From ead24ec6247577824cfce46ffcc9d179fb281fb2 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sun, 12 Apr 2020 14:25:46 +0100 Subject: Rebase GCCRS against SimplyTheOthers c++11 AST. We can use this as a common base to build upon. It contains a fully object orientated c++11 AST. --- gcc/rust/Make-lang.in | 309 +- gcc/rust/TO_notes.txt | 48 - gcc/rust/ast/clone-test.h | 90 + gcc/rust/ast/rust-ast-containers.h | 48 + gcc/rust/ast/rust-ast-full-decls.h | 265 + gcc/rust/ast/rust-ast-full-test.cc | 4610 +++++++ gcc/rust/ast/rust-ast-full.h | 13 + gcc/rust/ast/rust-ast-visitor.h | 224 + gcc/rust/ast/rust-ast.h | 1375 ++ gcc/rust/ast/rust-cond-compilation.h | 199 + gcc/rust/ast/rust-expr.h | 4614 +++++++ gcc/rust/ast/rust-item.h | 3385 +++++ gcc/rust/ast/rust-macro.h | 588 + gcc/rust/ast/rust-path.h | 803 ++ gcc/rust/ast/rust-pattern.h | 1163 ++ gcc/rust/ast/rust-stmt.h | 245 + gcc/rust/ast/rust-type.h | 828 ++ gcc/rust/backend.h | 764 ++ gcc/rust/config-lang.in | 2 +- gcc/rust/expand/rust-macro-expand.cc | 69 + gcc/rust/expand/rust-macro-expand.h | 47 + gcc/rust/lang.opt | 6 + gcc/rust/lex/rust-codepoint.h | 26 + gcc/rust/lex/rust-lex.cc | 2349 ++++ gcc/rust/lex/rust-lex.h | 125 + gcc/rust/lex/rust-token.cc | 100 + gcc/rust/lex/rust-token.h | 385 + gcc/rust/mrustc_parser/ast/ast.cpp | 440 - gcc/rust/mrustc_parser/ast/ast.hpp | 638 - gcc/rust/mrustc_parser/ast/attrs.hpp | 157 - gcc/rust/mrustc_parser/ast/crate.cpp | 209 - gcc/rust/mrustc_parser/ast/crate.hpp | 118 - gcc/rust/mrustc_parser/ast/dump.cpp | 1179 -- gcc/rust/mrustc_parser/ast/expr.cpp | 625 - gcc/rust/mrustc_parser/ast/expr.hpp | 719 - gcc/rust/mrustc_parser/ast/expr_ptr.hpp | 38 - gcc/rust/mrustc_parser/ast/generics.hpp | 181 - gcc/rust/mrustc_parser/ast/item.hpp | 40 - gcc/rust/mrustc_parser/ast/macro.hpp | 67 - gcc/rust/mrustc_parser/ast/path.cpp | 347 - gcc/rust/mrustc_parser/ast/path.hpp | 365 - gcc/rust/mrustc_parser/ast/pattern.cpp | 243 - gcc/rust/mrustc_parser/ast/pattern.hpp | 205 - gcc/rust/mrustc_parser/ast/types.cpp | 334 - gcc/rust/mrustc_parser/ast/types.hpp | 354 - .../gcc-interface-test/gcc-interface.cc | 434 - .../gcc-interface-test/rust-c-interface.h | 58 - gcc/rust/mrustc_parser/parse/common.hpp | 72 - gcc/rust/mrustc_parser/parse/eTokenType.enum.h | 154 - gcc/rust/mrustc_parser/parse/expr.cpp | 1338 -- .../mrustc_parser/parse/interpolated_fragment.cpp | 123 - .../mrustc_parser/parse/interpolated_fragment.hpp | 61 - gcc/rust/mrustc_parser/parse/lex.cpp | 1071 -- gcc/rust/mrustc_parser/parse/lex.hpp | 80 - gcc/rust/mrustc_parser/parse/parseerror.cpp | 91 - gcc/rust/mrustc_parser/parse/parseerror.hpp | 47 - gcc/rust/mrustc_parser/parse/paths.cpp | 254 - gcc/rust/mrustc_parser/parse/pattern.cpp | 526 - gcc/rust/mrustc_parser/parse/root.cpp | 1999 --- gcc/rust/mrustc_parser/parse/token.cpp | 512 - gcc/rust/mrustc_parser/parse/token.hpp | 158 - gcc/rust/mrustc_parser/parse/tokenstream.cpp | 153 - gcc/rust/mrustc_parser/parse/tokenstream.hpp | 105 - gcc/rust/mrustc_parser/parse/tokentree.cpp | 55 - gcc/rust/mrustc_parser/parse/tokentree.hpp | 61 - gcc/rust/mrustc_parser/parse/ttstream.cpp | 121 - gcc/rust/mrustc_parser/parse/ttstream.hpp | 57 - gcc/rust/mrustc_parser/parse/types.cpp | 340 - gcc/rust/old/lang-specs.h | 19 - gcc/rust/old/rdot-dataflow.cc | 883 -- gcc/rust/old/rdot-generic-compiler.cc | 1202 -- gcc/rust/old/rdot-impl.cc | 267 - gcc/rust/old/rdot-impl.h | 166 - gcc/rust/old/rdot-pretty-print.cc | 664 - gcc/rust/old/rs-lang.c | 326 - gcc/rust/old/rs-lexer.l | 161 - gcc/rust/old/rs-parser.cc | 838 -- gcc/rust/old/rs-pass-manager.cc | 118 - gcc/rust/old/rs-runtime-hooks.cc | 57 - gcc/rust/old/rsspec.cc | 401 - gcc/rust/old/rust.h | 99 - gcc/rust/old/y.rs.h | 58 - gcc/rust/operator.h | 66 + gcc/rust/parse/rust-parse-includes.h | 27 + gcc/rust/parse/rust-parse.cc | 13001 +++++++++++++++++++ gcc/rust/parse/rust-parse.h | 613 + gcc/rust/parse/rust-scope.cc | 43 + gcc/rust/parse/rust-scope.h | 61 + gcc/rust/parse/rust-symbol.h | 78 + gcc/rust/parse/rust-tree.h | 167 + gcc/rust/rust-buffered-queue.h | 130 + gcc/rust/rust-c.h | 45 - gcc/rust/rust-gcc.cc | 3758 +++--- gcc/rust/rust-lang.c | 567 - gcc/rust/rust-lang.cc | 385 + gcc/rust/rust-object-export.c | 193 + gcc/rust/rust-object-export.h | 9 + gcc/rust/rust-session-manager.cc | 654 + gcc/rust/rust-session-manager.h | 175 + gcc/rust/rust-system.h | 8 +- gcc/rust/rustc_parser/RustCNotes.txt | 28 - gcc/rust/rustc_parser/grammar/.gitignore | 3 - gcc/rust/rustc_parser/grammar/lexer.l | 350 - gcc/rust/rustc_parser/grammar/parser-lalr-main.c | 193 - gcc/rust/rustc_parser/grammar/parser-lalr.y | 1982 --- .../grammar/raw-string-literal-ambiguity.md | 64 - gcc/rust/rustc_parser/grammar/testparser.py | 66 - gcc/rust/rustc_parser/grammar/tokens.h | 99 - gcc/rust/rustc_parser/libsyntax/Cargo.toml | 23 - gcc/rust/rustc_parser/libsyntax/README.md | 9 - gcc/rust/rustc_parser/libsyntax/ast.rs | 2409 ---- gcc/rust/rustc_parser/libsyntax/attr/builtin.rs | 903 -- gcc/rust/rustc_parser/libsyntax/attr/mod.rs | 753 -- gcc/rust/rustc_parser/libsyntax/build.rs | 5 - gcc/rust/rustc_parser/libsyntax/config.rs | 369 - .../rustc_parser/libsyntax/diagnostics/macros.rs | 188 - .../rustc_parser/libsyntax/diagnostics/metadata.rs | 93 - .../rustc_parser/libsyntax/diagnostics/plugin.rs | 213 - .../rustc_parser/libsyntax/early_buffered_lints.rs | 28 - gcc/rust/rustc_parser/libsyntax/entry.rs | 35 - gcc/rust/rustc_parser/libsyntax/error_codes.rs | 450 - gcc/rust/rustc_parser/libsyntax/ext/base.rs | 1013 -- gcc/rust/rustc_parser/libsyntax/ext/build.rs | 1210 -- gcc/rust/rustc_parser/libsyntax/ext/derive.rs | 75 - gcc/rust/rustc_parser/libsyntax/ext/expand.rs | 1471 --- .../rustc_parser/libsyntax/ext/placeholders.rs | 203 - gcc/rust/rustc_parser/libsyntax/ext/source_util.rs | 187 - .../rustc_parser/libsyntax/ext/tt/macro_parser.rs | 954 -- .../rustc_parser/libsyntax/ext/tt/macro_rules.rs | 1206 -- gcc/rust/rustc_parser/libsyntax/ext/tt/quoted.rs | 418 - .../rustc_parser/libsyntax/ext/tt/transcribe.rs | 372 - gcc/rust/rustc_parser/libsyntax/feature_gate.rs | 2646 ---- gcc/rust/rustc_parser/libsyntax/json.rs | 412 - gcc/rust/rustc_parser/libsyntax/lib.rs | 189 - gcc/rust/rustc_parser/libsyntax/mut_visit.rs | 1334 -- gcc/rust/rustc_parser/libsyntax/parse/attr.rs | 305 - gcc/rust/rustc_parser/libsyntax/parse/classify.rs | 25 - .../rustc_parser/libsyntax/parse/diagnostics.rs | 1273 -- .../rustc_parser/libsyntax/parse/lexer/comments.rs | 433 - gcc/rust/rustc_parser/libsyntax/parse/lexer/mod.rs | 1609 --- .../libsyntax/parse/lexer/tokentrees.rs | 230 - .../libsyntax/parse/lexer/unicode_chars.rs | 393 - gcc/rust/rustc_parser/libsyntax/parse/literal.rs | 470 - gcc/rust/rustc_parser/libsyntax/parse/mod.rs | 680 - gcc/rust/rustc_parser/libsyntax/parse/parser.rs | 7852 ----------- gcc/rust/rustc_parser/libsyntax/parse/token.rs | 827 -- gcc/rust/rustc_parser/libsyntax/parse/unescape.rs | 602 - .../libsyntax/parse/unescape_error_reporting.rs | 210 - gcc/rust/rustc_parser/libsyntax/print/pp.rs | 661 - gcc/rust/rustc_parser/libsyntax/print/pprust.rs | 3069 ----- gcc/rust/rustc_parser/libsyntax/ptr.rs | 226 - gcc/rust/rustc_parser/libsyntax/show_span.rs | 75 - gcc/rust/rustc_parser/libsyntax/source_map.rs | 1244 -- gcc/rust/rustc_parser/libsyntax/std_inject.rs | 119 - gcc/rust/rustc_parser/libsyntax/test.rs | 437 - gcc/rust/rustc_parser/libsyntax/test_snippet.rs | 1164 -- gcc/rust/rustc_parser/libsyntax/tokenstream.rs | 665 - .../rustc_parser/libsyntax/util/lev_distance.rs | 136 - .../rustc_parser/libsyntax/util/map_in_place.rs | 102 - gcc/rust/rustc_parser/libsyntax/util/node_count.rs | 141 - gcc/rust/rustc_parser/libsyntax/util/parser.rs | 402 - .../rustc_parser/libsyntax/util/parser_testing.rs | 160 - gcc/rust/rustc_parser/libsyntax/visit.rs | 857 -- gcc/rust/rustc_parser/libsyntax_ext/Cargo.toml | 20 - gcc/rust/rustc_parser/libsyntax_ext/asm.rs | 282 - gcc/rust/rustc_parser/libsyntax_ext/assert.rs | 141 - gcc/rust/rustc_parser/libsyntax_ext/cfg.rs | 56 - .../rustc_parser/libsyntax_ext/compile_error.rs | 19 - gcc/rust/rustc_parser/libsyntax_ext/concat.rs | 65 - .../rustc_parser/libsyntax_ext/concat_idents.rs | 66 - .../rustc_parser/libsyntax_ext/deriving/bounds.rs | 27 - .../rustc_parser/libsyntax_ext/deriving/clone.rs | 216 - .../rustc_parser/libsyntax_ext/deriving/cmp/eq.rs | 83 - .../rustc_parser/libsyntax_ext/deriving/cmp/ord.rs | 118 - .../libsyntax_ext/deriving/cmp/partial_eq.rs | 103 - .../libsyntax_ext/deriving/cmp/partial_ord.rs | 301 - .../rustc_parser/libsyntax_ext/deriving/custom.rs | 119 - .../rustc_parser/libsyntax_ext/deriving/debug.rs | 138 - .../libsyntax_ext/deriving/decodable.rs | 205 - .../rustc_parser/libsyntax_ext/deriving/default.rs | 81 - .../libsyntax_ext/deriving/encodable.rs | 277 - .../libsyntax_ext/deriving/generic/mod.rs | 1831 --- .../libsyntax_ext/deriving/generic/ty.rs | 297 - .../rustc_parser/libsyntax_ext/deriving/hash.rs | 93 - .../rustc_parser/libsyntax_ext/deriving/mod.rs | 182 - gcc/rust/rustc_parser/libsyntax_ext/env.rs | 87 - gcc/rust/rustc_parser/libsyntax_ext/error_codes.rs | 123 - gcc/rust/rustc_parser/libsyntax_ext/format.rs | 1090 -- .../rustc_parser/libsyntax_ext/format_foreign.rs | 836 -- .../libsyntax_ext/format_foreign/printf/tests.rs | 151 - .../libsyntax_ext/format_foreign/shell/tests.rs | 59 - gcc/rust/rustc_parser/libsyntax_ext/global_asm.rs | 68 - gcc/rust/rustc_parser/libsyntax_ext/lib.rs | 168 - gcc/rust/rustc_parser/libsyntax_ext/log_syntax.rs | 14 - .../rustc_parser/libsyntax_ext/proc_macro_decls.rs | 432 - .../rustc_parser/libsyntax_ext/proc_macro_impl.rs | 68 - .../libsyntax_ext/proc_macro_server.rs | 717 - gcc/rust/rustc_parser/libsyntax_ext/test.rs | 309 - gcc/rust/rustc_parser/libsyntax_ext/test_case.rs | 51 - .../rustc_parser/libsyntax_ext/trace_macros.rs | 21 - gcc/rust/rustc_parser/libsyntax_pos/Cargo.toml | 19 - .../libsyntax_pos/analyze_source_file.rs | 425 - gcc/rust/rustc_parser/libsyntax_pos/edition.rs | 77 - gcc/rust/rustc_parser/libsyntax_pos/hygiene.rs | 763 -- gcc/rust/rustc_parser/libsyntax_pos/lib.rs | 1446 --- .../rustc_parser/libsyntax_pos/span_encoding.rs | 140 - gcc/rust/rustc_parser/libsyntax_pos/symbol.rs | 1380 -- gcc/rust/rustfrontend/backend.h | 778 -- gcc/rust/rustfrontend/main.cc | 14 - gcc/rust/rustfrontend/node.cc | 862 -- gcc/rust/rustfrontend/node.h | 378 - gcc/rust/rustfrontend/operator.h | 55 - gcc/rust/rustfrontend/rs-lexer.l | 350 - gcc/rust/rustfrontend/rs-parser.y | 1977 --- gcc/rust/rustfrontend/rustly.cc | 83 - gcc/rust/rustfrontend/rustly.h | 26 - gcc/rust/rustspec.cc | 46 +- gcc/rust/test/rustc_bison_test/lex.yy.c | 3389 ----- gcc/rust/test/rustc_bison_test/lex.yy.cc | 3151 ----- gcc/rust/test/rustc_bison_test/lexer.l | 350 - gcc/rust/test/rustc_bison_test/parser-interface.c | 200 - gcc/rust/test/rustc_bison_test/parser-lalr.y | 1982 --- gcc/rust/test/rustc_bison_test/parser.tab.c | 9173 ------------- gcc/rust/test/rustc_bison_test/token.h | 167 - gcc/rust/test/test1..s | 1 - gcc/rust/test/test1.rs | 4 - gcc/rust/test/test1.s | 17 - gcc/rust/test/test2-minimal.rs | 25 - gcc/rust/test/test2.rs | 18 - gcc/rust/test/test2.s | 17 - gcc/rust/test/test_jit.c | 331 - gcc/rust/test2/rust-c.h | 65 - gcc/rust/test2/rust-lang.c | 512 - gcc/rust/test2/rustfrontend/eTokenType.enum.h | 154 - .../test2/rustfrontend/rs-generic-converter.cc | 7 - gcc/rust/test2/rustfrontend/rs-lex.cc | 2884 ---- gcc/rust/test2/rustfrontend/rs-lex.h | 361 - gcc/rust/test2/rustfrontend/rs-token.h | 284 - gcc/rust/test2/rustfrontend/rust.cc | 179 - gcc/rust/test3-tiny/Make-lang.in | 226 - gcc/rust/test3-tiny/config-lang.in | 49 - gcc/rust/test3-tiny/lang-specs.h | 30 - gcc/rust/test3-tiny/lex/rust-lex.cc | 314 - gcc/rust/test3-tiny/lex/rust-lex.h | 98 - gcc/rust/test3-tiny/lex/rust-token.cc | 33 - gcc/rust/test3-tiny/lex/rust-token.h | 173 - gcc/rust/test3-tiny/parse/rust-misc-convert.cc | 37 - gcc/rust/test3-tiny/parse/rust-parse.cc | 1806 --- gcc/rust/test3-tiny/parse/rust-parse.h | 149 - gcc/rust/test3-tiny/parse/rust-scope.cc | 43 - gcc/rust/test3-tiny/parse/rust-scope.h | 112 - gcc/rust/test3-tiny/parse/rust-tree.h | 167 - gcc/rust/test3-tiny/rsspec.cc | 354 - gcc/rust/test3-tiny/rust-buffered-queue.h | 106 - gcc/rust/test3-tiny/rust-lang.cc | 262 - gcc/rust/test3/Make-lang.in | 240 - gcc/rust/test3/ast/clone-test.h | 90 - gcc/rust/test3/ast/rust-ast-containers.h | 48 - gcc/rust/test3/ast/rust-ast-full-decls.h | 265 - gcc/rust/test3/ast/rust-ast-full-test.cc | 4610 ------- gcc/rust/test3/ast/rust-ast-full.h | 13 - gcc/rust/test3/ast/rust-ast-visitor.h | 224 - gcc/rust/test3/ast/rust-ast.h | 1376 -- gcc/rust/test3/ast/rust-cond-compilation.h | 199 - gcc/rust/test3/ast/rust-expr.h | 4614 ------- gcc/rust/test3/ast/rust-item.h | 3385 ----- gcc/rust/test3/ast/rust-macro.h | 588 - gcc/rust/test3/ast/rust-path.h | 803 -- gcc/rust/test3/ast/rust-pattern.h | 1163 -- gcc/rust/test3/ast/rust-stmt.h | 245 - gcc/rust/test3/ast/rust-type.h | 828 -- gcc/rust/test3/config-lang.in | 49 - gcc/rust/test3/expand/rust-macro-expand.cc | 69 - gcc/rust/test3/expand/rust-macro-expand.h | 47 - gcc/rust/test3/lang-specs.h | 30 - gcc/rust/test3/lang.opt | 46 - gcc/rust/test3/lex/rust-codepoint.h | 26 - gcc/rust/test3/lex/rust-lex.cc | 2349 ---- gcc/rust/test3/lex/rust-lex.h | 125 - gcc/rust/test3/lex/rust-token.cc | 100 - gcc/rust/test3/lex/rust-token.h | 385 - gcc/rust/test3/parse/rust-misc-convert.cc | 37 - gcc/rust/test3/parse/rust-parse-includes.h | 27 - gcc/rust/test3/parse/rust-parse.cc | 13001 ------------------- gcc/rust/test3/parse/rust-parse.h | 613 - gcc/rust/test3/parse/rust-scope.cc | 43 - gcc/rust/test3/parse/rust-scope.h | 61 - gcc/rust/test3/parse/rust-symbol.h | 78 - gcc/rust/test3/parse/rust-tree.h | 167 - gcc/rust/test3/rsspec.cc | 358 - gcc/rust/test3/rust-buffered-queue.h | 130 - gcc/rust/test3/rust-lang.cc | 330 - gcc/rust/test3/rust-session-manager.cc | 654 - gcc/rust/test3/rust-session-manager.h | 180 - gcc/testsuite/rust.test/alias-uninit-value.rs | 23 - .../rust.test/alignment-gep-tup-like-1.rs | 42 - .../rust.test/alignment-gep-tup-like-2.rs | 61 - .../rust.test/alloca-from-derived-tydesc.rs | 17 - .../rust.test/anon-extern-mod-cross-crate-2.rs | 22 - gcc/testsuite/rust.test/anon-extern-mod.rs | 23 - .../rust.test/anon-trait-static-method.rs | 24 - .../rust.test/anon_trait_static_method_exe.rs | 20 - gcc/testsuite/rust.test/argument-passing.rs | 35 - gcc/testsuite/rust.test/arith-0.rs | 17 - gcc/testsuite/rust.test/arith-1.rs | 33 - gcc/testsuite/rust.test/arith-2.rs | 17 - gcc/testsuite/rust.test/arith-unsigned.rs | 35 - gcc/testsuite/rust.test/artificial-block.rs | 13 - gcc/testsuite/rust.test/asm-out-assign.rs | 32 - .../rust.test/assert-approx-eq-macro-success.rs | 16 - gcc/testsuite/rust.test/assert-eq-macro-success.rs | 20 - gcc/testsuite/rust.test/assign-assign.rs | 38 - gcc/testsuite/rust.test/assignability-trait.rs | 53 - gcc/testsuite/rust.test/attr-before-view-item.rs | 17 - gcc/testsuite/rust.test/attr-before-view-item2.rs | 19 - gcc/testsuite/rust.test/attr-main-2.rs | 19 - gcc/testsuite/rust.test/attr-main.rs | 15 - gcc/testsuite/rust.test/attr-no-drop-flag-size.rs | 25 - gcc/testsuite/rust.test/attr-start.rs | 16 - gcc/testsuite/rust.test/auto-encode.rs | 185 - gcc/testsuite/rust.test/auto-instantiate.rs | 24 - gcc/testsuite/rust.test/auto-loop.rs | 18 - .../rust.test/auto-ref-bounded-ty-param.rs | 40 - gcc/testsuite/rust.test/auto-ref-newtype.rs | 23 - gcc/testsuite/rust.test/auto-ref-slice-plus-ref.rs | 43 - gcc/testsuite/rust.test/auto-ref-sliceable.rs | 26 - gcc/testsuite/rust.test/auto-ref.rs | 28 - gcc/testsuite/rust.test/autobind.rs | 19 - .../autoderef-and-borrow-method-receiver.rs | 24 - .../rust.test/autoderef-method-newtype.rs | 24 - .../rust.test/autoderef-method-on-trait.rs | 22 - .../rust.test/autoderef-method-priority.rs | 26 - .../autoderef-method-twice-but-not-thrice.rs | 22 - gcc/testsuite/rust.test/autoderef-method-twice.rs | 22 - gcc/testsuite/rust.test/autoderef-method.rs | 22 - .../autoref-intermediate-types-issue-3585.rs | 30 - gcc/testsuite/rust.test/bare-static-string.rs | 14 - gcc/testsuite/rust.test/big-literals.rs | 21 - .../rust.test/binary-minus-without-space.rs | 16 - gcc/testsuite/rust.test/bind-by-move.rs | 23 - gcc/testsuite/rust.test/binops.rs | 101 - gcc/testsuite/rust.test/bitv-perf-test.rs | 24 - gcc/testsuite/rust.test/bitwise.rs | 45 - gcc/testsuite/rust.test/block-arg-call-as.rs | 26 - .../block-arg-can-be-followed-by-binop.rs | 18 - .../block-arg-can-be-followed-by-block-arg.rs | 16 - .../rust.test/block-arg-can-be-followed-by-call.rs | 16 - .../rust.test/block-arg-in-parentheses.rs | 35 - gcc/testsuite/rust.test/block-arg-used-as-any.rs | 18 - gcc/testsuite/rust.test/block-arg.rs | 62 - gcc/testsuite/rust.test/block-explicit-types.rs | 14 - gcc/testsuite/rust.test/block-expr-precedence.rs | 66 - gcc/testsuite/rust.test/block-fn-coerce.rs | 17 - gcc/testsuite/rust.test/block-iter-1.rs | 25 - gcc/testsuite/rust.test/block-iter-2.rs | 25 - gcc/testsuite/rust.test/bool-not.rs | 18 - .../rust.test/borrow-by-val-method-receiver.rs | 22 - gcc/testsuite/rust.test/borrowck-binding-mutbl.rs | 24 - .../rust.test/borrowck-borrow-from-at-vec.rs | 20 - .../rust.test/borrowck-borrow-from-expr-block.rs | 28 - .../rust.test/borrowck-fixed-length-vecs.rs | 15 - gcc/testsuite/rust.test/borrowck-lend-args.rs | 26 - .../borrowck-macro-interaction-issue-6304.rs | 31 - .../rust.test/borrowck-move-by-capture-ok.rs | 5 - gcc/testsuite/rust.test/borrowck-mut-uniq.rs | 39 - .../rust.test/borrowck-mut-vec-as-imm-slice.rs | 23 - gcc/testsuite/rust.test/borrowck-nested-calls.rs | 32 - gcc/testsuite/rust.test/borrowck-pat-enum.rs | 47 - .../rust.test/borrowck-pat-reassign-no-binding.rs | 22 - .../borrowck-preserve-box-in-arm-not-taken.rs | 27 - .../rust.test/borrowck-preserve-box-in-discr.rs | 32 - .../rust.test/borrowck-preserve-box-in-field.rs | 36 - .../rust.test/borrowck-preserve-box-in-pat.rs | 32 - .../rust.test/borrowck-preserve-box-in-uniq.rs | 36 - .../borrowck-preserve-box-sometimes-needed.rs | 25 - gcc/testsuite/rust.test/borrowck-preserve-box.rs | 34 - .../rust.test/borrowck-preserve-cond-box.rs | 43 - .../rust.test/borrowck-preserve-expl-deref.rs | 36 - .../rust.test/borrowck-root-while-cond-2.rs | 17 - .../rust.test/borrowck-root-while-cond.rs | 18 - .../rust.test/borrowck-rvalues-mutable.rs | 30 - .../borrowck-scope-of-deref-issue-4666.rs | 50 - .../rust.test/borrowck-static-item-in-fn.rs | 15 - gcc/testsuite/rust.test/borrowck-unary-move-2.rs | 32 - gcc/testsuite/rust.test/borrowck-uniq-via-ref.rs | 54 - .../rust.test/borrowck-univariant-enum.rs | 29 - ...oderef-and-autoborrowvec-combined-issue-6272.rs | 41 - .../rust.test/borrowck-wg-borrow-mut-to-imm-2.rs | 13 - .../rust.test/borrowck-wg-borrow-mut-to-imm-3.rs | 18 - .../rust.test/borrowck-wg-borrow-mut-to-imm.rs | 12 - gcc/testsuite/rust.test/borrowck-wg-simple.rs | 8 - .../rust.test/borrowck-wg-two-imm-borrows.rs | 14 - gcc/testsuite/rust.test/borrowed-ptr-pattern-2.rs | 21 - gcc/testsuite/rust.test/borrowed-ptr-pattern-3.rs | 21 - .../rust.test/borrowed-ptr-pattern-infallible.rs | 16 - .../rust.test/borrowed-ptr-pattern-option.rs | 23 - gcc/testsuite/rust.test/borrowed-ptr-pattern.rs | 21 - gcc/testsuite/rust.test/box-compare.rs | 17 - gcc/testsuite/rust.test/box-in-tup.rs | 14 - gcc/testsuite/rust.test/box-inside-if.rs | 25 - gcc/testsuite/rust.test/box-inside-if2.rs | 25 - gcc/testsuite/rust.test/box-pattern.rs | 19 - gcc/testsuite/rust.test/box-unbox.rs | 22 - gcc/testsuite/rust.test/box.rs | 13 - .../rust.test/boxed-class-type-substitution.rs | 34 - gcc/testsuite/rust.test/boxed-trait-with-vstore.rs | 24 - gcc/testsuite/rust.test/break-value.rs | 13 - gcc/testsuite/rust.test/break.rs | 33 - gcc/testsuite/rust.test/bug-7183-generics.rs | 43 - gcc/testsuite/rust.test/bug-7295.rs | 21 - .../builtin-superkinds-capabilities-transitive.rs | 33 - .../builtin-superkinds-capabilities-xc.rs | 36 - .../rust.test/builtin-superkinds-capabilities.rs | 29 - .../rust.test/builtin-superkinds-in-metadata.rs | 26 - .../builtin-superkinds-phantom-typaram.rs | 21 - .../rust.test/builtin-superkinds-self-type.rs | 28 - .../rust.test/builtin-superkinds-simple.rs | 17 - .../rust.test/builtin-superkinds-typaram.rs | 18 - gcc/testsuite/rust.test/c-stack-as-value.rs | 21 - gcc/testsuite/rust.test/c-stack-returning-int64.rs | 34 - .../rust.test/call-closure-from-overloaded-op.rs | 17 - .../cancel-clean-via-immediate-rvalue-ref.rs | 17 - gcc/testsuite/rust.test/cap-clause-move.rs | 23 - gcc/testsuite/rust.test/capture_nil.rs | 39 - gcc/testsuite/rust.test/cast-mutable-trait.rs | 34 - gcc/testsuite/rust.test/cast-region-to-uint.rs | 16 - gcc/testsuite/rust.test/cast.rs | 22 - gcc/testsuite/rust.test/cci_borrow.rs | 22 - gcc/testsuite/rust.test/cci_capture_clause.rs | 21 - gcc/testsuite/rust.test/cci_impl_exe.rs | 28 - gcc/testsuite/rust.test/cci_iter_exe.rs | 23 - gcc/testsuite/rust.test/cci_nested_exe.rs | 31 - gcc/testsuite/rust.test/cci_no_inline_exe.rs | 33 - gcc/testsuite/rust.test/cfg-family.rs | 17 - gcc/testsuite/rust.test/cfg-macros-foo.rs | 37 - gcc/testsuite/rust.test/cfg-macros-notfoo.rs | 37 - gcc/testsuite/rust.test/cfg-target-family.rs | 17 - gcc/testsuite/rust.test/cfg_inner_static.rs | 18 - gcc/testsuite/rust.test/cfgs-on-items.rs | 31 - gcc/testsuite/rust.test/char.rs | 23 - gcc/testsuite/rust.test/child-outlives-parent.rs | 19 - gcc/testsuite/rust.test/class-attributes-1.rs | 26 - gcc/testsuite/rust.test/class-attributes-2.rs | 37 - .../rust.test/class-cast-to-trait-cross-crate-2.rs | 26 - .../class-cast-to-trait-multiple-types.rs | 94 - gcc/testsuite/rust.test/class-cast-to-trait.rs | 61 - gcc/testsuite/rust.test/class-dtor.rs | 29 - gcc/testsuite/rust.test/class-exports.rs | 38 - .../class-impl-very-parameterized-trait.rs | 126 - .../rust.test/class-implement-trait-cross-crate.rs | 66 - gcc/testsuite/rust.test/class-implement-traits.rs | 72 - .../rust.test/class-method-cross-crate.rs | 22 - .../rust.test/class-methods-cross-crate.rs | 23 - gcc/testsuite/rust.test/class-methods.rs | 36 - .../rust.test/class-poly-methods-cross-crate.rs | 25 - gcc/testsuite/rust.test/class-poly-methods.rs | 42 - gcc/testsuite/rust.test/class-separate-impl.rs | 68 - gcc/testsuite/rust.test/class-str-field.rs | 25 - gcc/testsuite/rust.test/class-typarams.rs | 33 - gcc/testsuite/rust.test/classes-cross-crate.rs | 22 - .../rust.test/classes-self-referential.rs | 23 - .../rust.test/classes-simple-cross-crate.rs | 21 - gcc/testsuite/rust.test/classes-simple-method.rs | 34 - gcc/testsuite/rust.test/classes-simple.rs | 29 - gcc/testsuite/rust.test/classes.rs | 57 - gcc/testsuite/rust.test/cleanup-copy-mode.rs | 19 - gcc/testsuite/rust.test/clone-with-exterior.rs | 28 - .../rust.test/close-over-big-then-small-data.rs | 46 - .../rust.test/closure-bounds-can-capture-chan.rs | 23 - gcc/testsuite/rust.test/closure-inference.rs | 20 - gcc/testsuite/rust.test/closure-inference2.rs | 17 - gcc/testsuite/rust.test/cmp-default.rs | 56 - .../rust.test/coerce-reborrow-imm-ptr-arg.rs | 13 - .../rust.test/coerce-reborrow-imm-ptr-rcvr.rs | 16 - .../rust.test/coerce-reborrow-imm-vec-arg.rs | 15 - .../rust.test/coerce-reborrow-imm-vec-rcvr.rs | 13 - .../rust.test/coerce-reborrow-mut-ptr-arg.rs | 22 - .../rust.test/coerce-reborrow-mut-ptr-rcvr.rs | 24 - .../rust.test/coerce-reborrow-mut-vec-arg.rs | 15 - .../rust.test/coerce-reborrow-mut-vec-rcvr.rs | 11 - gcc/testsuite/rust.test/coherence-impl-in-fn.rs | 19 - gcc/testsuite/rust.test/comm.rs | 27 - gcc/testsuite/rust.test/compare-generic-enums.rs | 22 - gcc/testsuite/rust.test/complex.rs | 43 - .../rust.test/conditional-compile-arch.rs | 18 - gcc/testsuite/rust.test/conditional-compile.rs | 151 - .../rust.test/conditional-debug-macro-off.rs | 18 - .../rust.test/conditional-debug-macro-on.rs | 20 - gcc/testsuite/rust.test/const-autoderef-newtype.rs | 17 - gcc/testsuite/rust.test/const-autoderef.rs | 19 - gcc/testsuite/rust.test/const-big-enum.rs | 38 - gcc/testsuite/rust.test/const-binops.rs | 116 - gcc/testsuite/rust.test/const-bound.rs | 27 - gcc/testsuite/rust.test/const-cast-ptr-int.rs | 17 - gcc/testsuite/rust.test/const-cast.rs | 23 - gcc/testsuite/rust.test/const-const.rs | 16 - gcc/testsuite/rust.test/const-contents.rs | 27 - gcc/testsuite/rust.test/const-cross-crate-const.rs | 25 - .../rust.test/const-cross-crate-extern.rs | 20 - gcc/testsuite/rust.test/const-deref.rs | 20 - gcc/testsuite/rust.test/const-enum-byref-self.rs | 25 - gcc/testsuite/rust.test/const-enum-byref.rs | 23 - gcc/testsuite/rust.test/const-enum-cast.rs | 31 - gcc/testsuite/rust.test/const-enum-ptr.rs | 19 - gcc/testsuite/rust.test/const-enum-struct.rs | 19 - gcc/testsuite/rust.test/const-enum-struct2.rs | 19 - gcc/testsuite/rust.test/const-enum-structlike.rs | 25 - gcc/testsuite/rust.test/const-enum-tuple.rs | 18 - gcc/testsuite/rust.test/const-enum-tuple2.rs | 18 - gcc/testsuite/rust.test/const-enum-tuplestruct.rs | 19 - gcc/testsuite/rust.test/const-enum-tuplestruct2.rs | 19 - gcc/testsuite/rust.test/const-enum-vec-index.rs | 25 - gcc/testsuite/rust.test/const-enum-vec-ptr.rs | 23 - gcc/testsuite/rust.test/const-enum-vector.rs | 23 - .../rust.test/const-expr-in-fixed-length-vec.rs | 19 - .../rust.test/const-expr-in-vec-repeat.rs | 18 - gcc/testsuite/rust.test/const-extern-function.rs | 23 - .../rust.test/const-fields-and-indexing.rs | 34 - gcc/testsuite/rust.test/const-fn-val.rs | 21 - gcc/testsuite/rust.test/const-negative.rs | 17 - gcc/testsuite/rust.test/const-nullary-enum.rs | 30 - .../rust.test/const-nullary-univariant-enum.rs | 22 - gcc/testsuite/rust.test/const-rec-and-tup.rs | 25 - .../rust.test/const-region-ptrs-noncopy.rs | 20 - gcc/testsuite/rust.test/const-region-ptrs.rs | 22 - gcc/testsuite/rust.test/const-str-ptr.rs | 29 - gcc/testsuite/rust.test/const-struct-offsets.rs | 13 - gcc/testsuite/rust.test/const-struct.rs | 37 - gcc/testsuite/rust.test/const-tuple-struct.rs | 22 - gcc/testsuite/rust.test/const-unit-struct.rs | 19 - gcc/testsuite/rust.test/const-vec-of-fns.rs | 29 - gcc/testsuite/rust.test/const-vec-syntax.rs | 16 - gcc/testsuite/rust.test/const-vecs-and-slices.rs | 20 - gcc/testsuite/rust.test/const.rs | 15 - gcc/testsuite/rust.test/consts-in-patterns.rs | 22 - gcc/testsuite/rust.test/core-rt-smoke.rs | 20 - gcc/testsuite/rust.test/core-run-destroy.rs | 98 - .../rust.test/crate-method-reexport-grrrrrrr.rs | 27 - gcc/testsuite/rust.test/crateresolve1.rs | 20 - gcc/testsuite/rust.test/crateresolve2.rs | 35 - gcc/testsuite/rust.test/crateresolve3.rs | 31 - gcc/testsuite/rust.test/crateresolve4.rs | 30 - gcc/testsuite/rust.test/crateresolve5.rs | 24 - gcc/testsuite/rust.test/crateresolve6.rs | 23 - gcc/testsuite/rust.test/crateresolve7.rs | 21 - gcc/testsuite/rust.test/cross-crate-const-pat.rs | 22 - .../rust.test/cross-crate-newtype-struct-pat.rs | 21 - gcc/testsuite/rust.test/cycle-collection.rs | 23 - gcc/testsuite/rust.test/cycle-collection2.rs | 40 - gcc/testsuite/rust.test/dead-code-one-arm-if.rs | 15 - gcc/testsuite/rust.test/deep-vector.rs | 2012 --- gcc/testsuite/rust.test/deep-vector2.rs | 8012 ------------ gcc/testsuite/rust.test/deep.rs | 19 - gcc/testsuite/rust.test/default-method-parsing.rs | 15 - gcc/testsuite/rust.test/default-method-simple.rs | 33 - .../rust.test/default-method-supertrait-vtable.rs | 36 - gcc/testsuite/rust.test/deref-lval.rs | 13 - gcc/testsuite/rust.test/deref.rs | 16 - gcc/testsuite/rust.test/deriving-clone-enum.rs | 21 - .../rust.test/deriving-clone-generic-enum.rs | 21 - .../rust.test/deriving-clone-generic-struct.rs | 20 - .../deriving-clone-generic-tuple-struct.rs | 16 - gcc/testsuite/rust.test/deriving-clone-struct.rs | 33 - .../rust.test/deriving-clone-tuple-struct.rs | 14 - .../rust.test/deriving-cmp-generic-enum.rs | 56 - .../rust.test/deriving-cmp-generic-struct-enum.rs | 52 - .../rust.test/deriving-cmp-generic-struct.rs | 52 - .../rust.test/deriving-cmp-generic-tuple-struct.rs | 50 - .../rust.test/deriving-cmp-shortcircuit.rs | 46 - .../rust.test/deriving-encodable-decodable.rs | 79 - .../rust.test/deriving-enum-single-variant.rs | 8 - gcc/testsuite/rust.test/deriving-global.rs | 42 - .../rust.test/deriving-meta-empty-trait-list.rs | 21 - gcc/testsuite/rust.test/deriving-meta-multiple.rs | 27 - gcc/testsuite/rust.test/deriving-meta.rs | 25 - gcc/testsuite/rust.test/deriving-primitive.rs | 37 - gcc/testsuite/rust.test/deriving-rand.rs | 43 - .../deriving-self-lifetime-totalord-totaleq.rs | 32 - gcc/testsuite/rust.test/deriving-self-lifetime.rs | 34 - gcc/testsuite/rust.test/deriving-to-str.rs | 51 - .../rust.test/deriving-via-extension-c-enum.rs | 25 - .../rust.test/deriving-via-extension-enum.rs | 24 - .../deriving-via-extension-iter-bytes-enum.rs | 27 - .../deriving-via-extension-iter-bytes-struct.rs | 20 - .../deriving-via-extension-struct-empty.rs | 17 - ...iving-via-extension-struct-like-enum-variant.rs | 13 - .../deriving-via-extension-struct-tuple.rs | 26 - .../rust.test/deriving-via-extension-struct.rs | 25 - .../deriving-via-extension-type-params.rs | 28 - gcc/testsuite/rust.test/deriving-zero.rs | 39 - gcc/testsuite/rust.test/die-macro.rs | 13 - gcc/testsuite/rust.test/div-mod.rs | 28 - gcc/testsuite/rust.test/do-empty-args.rs | 23 - gcc/testsuite/rust.test/do-no-args.rs | 19 - gcc/testsuite/rust.test/do-pure.rs | 20 - gcc/testsuite/rust.test/do-stack.rs | 15 - gcc/testsuite/rust.test/do1.rs | 15 - gcc/testsuite/rust.test/do2.rs | 15 - gcc/testsuite/rust.test/do3.rs | 15 - gcc/testsuite/rust.test/double-unbox.rs | 18 - .../rust.test/drop-on-empty-block-exit.rs | 18 - gcc/testsuite/rust.test/drop-on-ret.rs | 23 - gcc/testsuite/rust.test/drop-trait-generic.rs | 24 - gcc/testsuite/rust.test/drop-trait.rs | 23 - gcc/testsuite/rust.test/duplicate-use.rs | 19 - gcc/testsuite/rust.test/early-ret-binop-add.rs | 12 - gcc/testsuite/rust.test/early-vtbl-resolution.rs | 23 - gcc/testsuite/rust.test/else-if.rs | 30 - gcc/testsuite/rust.test/empty-mutable-vec.rs | 13 - gcc/testsuite/rust.test/empty-tag.rs | 27 - gcc/testsuite/rust.test/enum-alignment.rs | 33 - gcc/testsuite/rust.test/enum-discr.rs | 20 - .../rust.test/enum-discrim-range-overflow.rs | 31 - .../rust.test/enum-discrim-width-stuff.rs | 25 - gcc/testsuite/rust.test/enum-disr-val-pretty.rs | 25 - gcc/testsuite/rust.test/enum-export-inheritance.rs | 21 - .../rust.test/enum-nullable-simplifycfg-misopt.rs | 24 - gcc/testsuite/rust.test/enum-variants.rs | 15 - gcc/testsuite/rust.test/enum-vec-initializer.rs | 24 - gcc/testsuite/rust.test/estr-shared.rs | 13 - gcc/testsuite/rust.test/estr-slice.rs | 58 - gcc/testsuite/rust.test/estr-uniq.rs | 20 - gcc/testsuite/rust.test/evec-internal-boxes.rs | 20 - gcc/testsuite/rust.test/evec-internal.rs | 53 - gcc/testsuite/rust.test/evec-slice.rs | 56 - gcc/testsuite/rust.test/exec-env.rs | 18 - gcc/testsuite/rust.test/explicit-i-suffix.rs | 19 - gcc/testsuite/rust.test/explicit-self-closures.rs | 26 - gcc/testsuite/rust.test/explicit-self-generic.rs | 42 - .../rust.test/explicit-self-objects-box.rs | 32 - .../rust.test/explicit-self-objects-simple.rs | 29 - .../rust.test/explicit-self-objects-uniq.rs | 29 - gcc/testsuite/rust.test/explicit-self.rs | 83 - .../rust.test/explicit_self_xcrate_exe.rs | 20 - gcc/testsuite/rust.test/export-abstract-tag.rs | 20 - .../rust.test/export-glob-imports-target.rs | 30 - gcc/testsuite/rust.test/export-multi.rs | 21 - gcc/testsuite/rust.test/export-non-interference.rs | 14 - .../rust.test/export-non-interference2.rs | 19 - .../rust.test/export-non-interference3.rs | 21 - gcc/testsuite/rust.test/export-tag-variant.rs | 15 - gcc/testsuite/rust.test/export-unexported-dep.rs | 30 - gcc/testsuite/rust.test/expr-block-box.rs | 15 - gcc/testsuite/rust.test/expr-block-fn.rs | 20 - gcc/testsuite/rust.test/expr-block-generic-box1.rs | 31 - gcc/testsuite/rust.test/expr-block-generic-box2.rs | 26 - .../rust.test/expr-block-generic-unique1.rs | 30 - .../rust.test/expr-block-generic-unique2.rs | 26 - gcc/testsuite/rust.test/expr-block-generic.rs | 41 - gcc/testsuite/rust.test/expr-block-ref.rs | 12 - gcc/testsuite/rust.test/expr-block-slot.rs | 21 - gcc/testsuite/rust.test/expr-block-unique.rs | 15 - gcc/testsuite/rust.test/expr-block.rs | 28 - gcc/testsuite/rust.test/expr-copy.rs | 27 - gcc/testsuite/rust.test/expr-elseif-ref.rs | 17 - gcc/testsuite/rust.test/expr-elseif-ref2.rs | 20 - gcc/testsuite/rust.test/expr-empty-ret.rs | 20 - gcc/testsuite/rust.test/expr-fn.rs | 68 - gcc/testsuite/rust.test/expr-if-box.rs | 27 - gcc/testsuite/rust.test/expr-if-fail-all.rs | 19 - gcc/testsuite/rust.test/expr-if-fail.rs | 23 - gcc/testsuite/rust.test/expr-if-generic-box1.rs | 27 - gcc/testsuite/rust.test/expr-if-generic-box2.rs | 26 - gcc/testsuite/rust.test/expr-if-generic.rs | 40 - gcc/testsuite/rust.test/expr-if-struct.rs | 39 - gcc/testsuite/rust.test/expr-if-unique.rs | 22 - gcc/testsuite/rust.test/expr-if.rs | 65 - gcc/testsuite/rust.test/expr-match-box.rs | 28 - gcc/testsuite/rust.test/expr-match-fail-all.rs | 22 - gcc/testsuite/rust.test/expr-match-fail.rs | 21 - gcc/testsuite/rust.test/expr-match-generic-box1.rs | 27 - gcc/testsuite/rust.test/expr-match-generic-box2.rs | 26 - .../rust.test/expr-match-generic-unique1.rs | 29 - .../rust.test/expr-match-generic-unique2.rs | 29 - gcc/testsuite/rust.test/expr-match-generic.rs | 39 - gcc/testsuite/rust.test/expr-match-struct.rs | 38 - gcc/testsuite/rust.test/expr-match-unique.rs | 22 - gcc/testsuite/rust.test/expr-match.rs | 54 - gcc/testsuite/rust.test/expr-repeat-vstore.rs | 22 - gcc/testsuite/rust.test/expr-scope.rs | 15 - gcc/testsuite/rust.test/exterior.rs | 26 - gcc/testsuite/rust.test/extern-1.rs | 15 - gcc/testsuite/rust.test/extern-call-deep.rs | 43 - gcc/testsuite/rust.test/extern-call-deep2.rs | 48 - gcc/testsuite/rust.test/extern-call-direct.rs | 20 - gcc/testsuite/rust.test/extern-call-indirect.rs | 43 - gcc/testsuite/rust.test/extern-call-scrub.rs | 52 - .../rust.test/extern-compare-with-return-type.rs | 32 - gcc/testsuite/rust.test/extern-crosscrate.rs | 28 - gcc/testsuite/rust.test/extern-mod-abi.rs | 15 - gcc/testsuite/rust.test/extern-mod-ordering-exe.rs | 10 - gcc/testsuite/rust.test/extern-mod-syntax.rs | 20 - gcc/testsuite/rust.test/extern-pass-TwoU16s.rs | 32 - gcc/testsuite/rust.test/extern-pass-TwoU32s.rs | 30 - gcc/testsuite/rust.test/extern-pass-TwoU64s-ref.rs | 30 - gcc/testsuite/rust.test/extern-pass-TwoU64s.rs | 35 - gcc/testsuite/rust.test/extern-pass-TwoU8s.rs | 32 - gcc/testsuite/rust.test/extern-pass-char.rs | 22 - gcc/testsuite/rust.test/extern-pass-double.rs | 20 - gcc/testsuite/rust.test/extern-pass-u32.rs | 22 - gcc/testsuite/rust.test/extern-pass-u64.rs | 22 - gcc/testsuite/rust.test/extern-pub.rs | 6 - gcc/testsuite/rust.test/extern-return-TwoU16s.rs | 26 - gcc/testsuite/rust.test/extern-return-TwoU32s.rs | 26 - gcc/testsuite/rust.test/extern-return-TwoU64s.rs | 28 - gcc/testsuite/rust.test/extern-return-TwoU8s.rs | 26 - gcc/testsuite/rust.test/extern-stress.rs | 49 - gcc/testsuite/rust.test/extern-take-value.rs | 24 - gcc/testsuite/rust.test/extern-yield.rs | 48 - .../rust.test/extoption_env-not-defined.rs | 13 - gcc/testsuite/rust.test/fact.rs | 38 - gcc/testsuite/rust.test/fat-arrow-match.rs | 25 - gcc/testsuite/rust.test/filter-block-view-items.rs | 15 - gcc/testsuite/rust.test/fixed_length_copy.rs | 16 - gcc/testsuite/rust.test/fixed_length_vec_glue.rs | 22 - gcc/testsuite/rust.test/float-literal-inference.rs | 22 - gcc/testsuite/rust.test/float-nan.rs | 94 - gcc/testsuite/rust.test/float-signature.rs | 18 - gcc/testsuite/rust.test/float.rs | 20 - gcc/testsuite/rust.test/float2.rs | 34 - gcc/testsuite/rust.test/floatlits.rs | 20 - gcc/testsuite/rust.test/fn-bare-assign.rs | 25 - gcc/testsuite/rust.test/fn-bare-coerce-to-block.rs | 17 - gcc/testsuite/rust.test/fn-bare-item.rs | 17 - gcc/testsuite/rust.test/fn-bare-size.rs | 16 - gcc/testsuite/rust.test/fn-bare-spawn.rs | 23 - gcc/testsuite/rust.test/fn-coerce-field.rs | 18 - gcc/testsuite/rust.test/fn-lval.rs | 19 - .../rust.test/fn-pattern-expected-type-2.rs | 17 - .../rust.test/fn-pattern-expected-type.rs | 17 - gcc/testsuite/rust.test/fn-type-infer.rs | 18 - gcc/testsuite/rust.test/for-destruct.rs | 20 - gcc/testsuite/rust.test/for-loop-fail.rs | 11 - .../rust.test/foreach-external-iterators-break.rs | 21 - ...ach-external-iterators-hashmap-break-restart.rs | 41 - .../foreach-external-iterators-hashmap.rs | 27 - .../rust.test/foreach-external-iterators-loop.rs | 21 - .../rust.test/foreach-external-iterators-nested.rs | 23 - .../rust.test/foreach-external-iterators.rs | 18 - gcc/testsuite/rust.test/foreach-nested.rs | 27 - gcc/testsuite/rust.test/foreach-put-structured.rs | 31 - .../rust.test/foreach-simple-outer-slot.rs | 26 - gcc/testsuite/rust.test/foreign-call-no-runtime.rs | 22 - gcc/testsuite/rust.test/foreign-dupe.rs | 38 - gcc/testsuite/rust.test/foreign-fn-linkname.rs | 36 - gcc/testsuite/rust.test/foreign-lib-path.rs | 26 - .../rust.test/foreign-mod-unused-const.rs | 21 - gcc/testsuite/rust.test/foreign-no-abi.rs | 26 - gcc/testsuite/rust.test/foreign-struct.rs | 24 - gcc/testsuite/rust.test/foreign2.rs | 35 - .../rust.test/format-no-uppercase-statics.rs | 15 - gcc/testsuite/rust.test/fun-call-variants.rs | 21 - gcc/testsuite/rust.test/fun-indirect-call.rs | 21 - .../rust.test/func-arg-incomplete-pattern.rs | 20 - gcc/testsuite/rust.test/func-arg-ref-pattern.rs | 24 - gcc/testsuite/rust.test/func-arg-wild-pattern.rs | 10 - gcc/testsuite/rust.test/functional-struct-upd.rs | 20 - gcc/testsuite/rust.test/generic-alias-box.rs | 20 - gcc/testsuite/rust.test/generic-alias-unique.rs | 20 - gcc/testsuite/rust.test/generic-box.rs | 20 - gcc/testsuite/rust.test/generic-derived-type.rs | 32 - gcc/testsuite/rust.test/generic-drop-glue.rs | 16 - gcc/testsuite/rust.test/generic-exterior-box.rs | 21 - gcc/testsuite/rust.test/generic-exterior-unique.rs | 19 - gcc/testsuite/rust.test/generic-fn-box.rs | 15 - gcc/testsuite/rust.test/generic-fn-infer.rs | 19 - gcc/testsuite/rust.test/generic-fn-twice.rs | 19 - gcc/testsuite/rust.test/generic-fn-unique.rs | 14 - gcc/testsuite/rust.test/generic-fn.rs | 36 - gcc/testsuite/rust.test/generic-ivec-leak.rs | 13 - gcc/testsuite/rust.test/generic-ivec.rs | 12 - gcc/testsuite/rust.test/generic-newtype-struct.rs | 6 - gcc/testsuite/rust.test/generic-object.rs | 29 - gcc/testsuite/rust.test/generic-recursive-tag.rs | 18 - gcc/testsuite/rust.test/generic-static-methods.rs | 27 - gcc/testsuite/rust.test/generic-tag-corruption.rs | 17 - gcc/testsuite/rust.test/generic-tag-local.rs | 15 - gcc/testsuite/rust.test/generic-tag-match.rs | 21 - gcc/testsuite/rust.test/generic-tag-values.rs | 31 - gcc/testsuite/rust.test/generic-tag.rs | 19 - gcc/testsuite/rust.test/generic-temporary.rs | 26 - gcc/testsuite/rust.test/generic-tup.rs | 17 - gcc/testsuite/rust.test/generic-type-synonym.rs | 21 - gcc/testsuite/rust.test/generic-type.rs | 19 - gcc/testsuite/rust.test/generic-unique.rs | 18 - gcc/testsuite/rust.test/getopts_ref.rs | 27 - gcc/testsuite/rust.test/glob-std.rs | 194 - gcc/testsuite/rust.test/global-scope.rs | 20 - gcc/testsuite/rust.test/guards-not-exhaustive.rs | 13 - gcc/testsuite/rust.test/guards.rs | 25 - gcc/testsuite/rust.test/hashmap-memory.rs | 96 - gcc/testsuite/rust.test/hello.rs | 14 - gcc/testsuite/rust.test/helloworld.rs | 4 - gcc/testsuite/rust.test/html-literals.rs | 102 - gcc/testsuite/rust.test/hygiene-dodging-1.rs | 21 - gcc/testsuite/rust.test/i32-sub.rs | 15 - gcc/testsuite/rust.test/i8-incr.rs | 21 - gcc/testsuite/rust.test/if-bot.rs | 16 - gcc/testsuite/rust.test/if-check.rs | 25 - gcc/testsuite/rust.test/if-ret.rs | 13 - gcc/testsuite/rust.test/ifmt.rs | 295 - gcc/testsuite/rust.test/impl-implicit-trait.rs | 30 - gcc/testsuite/rust.test/impl-privacy-xc-1.rs | 9 - gcc/testsuite/rust.test/impl-privacy-xc-2.rs | 10 - gcc/testsuite/rust.test/import-from.rs | 20 - gcc/testsuite/rust.test/import-glob-0.rs | 41 - gcc/testsuite/rust.test/import-glob-crate.rs | 23 - gcc/testsuite/rust.test/import-in-block.rs | 22 - gcc/testsuite/rust.test/import-trailing-comma.rs | 22 - gcc/testsuite/rust.test/import.rs | 23 - gcc/testsuite/rust.test/import2.rs | 20 - gcc/testsuite/rust.test/import3.rs | 24 - gcc/testsuite/rust.test/import4.rs | 20 - gcc/testsuite/rust.test/import5.rs | 21 - gcc/testsuite/rust.test/import6.rs | 26 - gcc/testsuite/rust.test/import7.rs | 29 - gcc/testsuite/rust.test/import8.rs | 21 - gcc/testsuite/rust.test/infer-fn-tail-expr.rs | 15 - .../rust.test/inferred-suffix-in-pattern-range.rs | 32 - gcc/testsuite/rust.test/infinite-loops.rs | 29 - gcc/testsuite/rust.test/init-res-into-things.rs | 94 - gcc/testsuite/rust.test/inner-module.rs | 22 - gcc/testsuite/rust.test/inner-static.rs | 23 - gcc/testsuite/rust.test/instantiable.rs | 21 - .../rust.test/int-conversion-coherence.rs | 25 - gcc/testsuite/rust.test/int.rs | 15 - .../rust.test/integer-literal-suffix-inference.rs | 67 - gcc/testsuite/rust.test/integral-indexing.rs | 30 - gcc/testsuite/rust.test/intrinsic-alignment.rs | 65 - gcc/testsuite/rust.test/intrinsic-atomics-cc.rs | 21 - gcc/testsuite/rust.test/intrinsic-atomics.rs | 78 - gcc/testsuite/rust.test/intrinsic-frame-address.rs | 25 - gcc/testsuite/rust.test/intrinsic-move-val.rs | 25 - gcc/testsuite/rust.test/intrinsic-uninit.rs | 18 - gcc/testsuite/rust.test/intrinsics-integer.rs | 123 - gcc/testsuite/rust.test/intrinsics-math.rs | 107 - gcc/testsuite/rust.test/invoke-external-foreign.rs | 25 - gcc/testsuite/rust.test/irrefutable-unit.rs | 13 - gcc/testsuite/rust.test/issue-1112.rs | 44 - gcc/testsuite/rust.test/issue-1251.rs | 21 - gcc/testsuite/rust.test/issue-1257.rs | 18 - gcc/testsuite/rust.test/issue-1458.rs | 22 - gcc/testsuite/rust.test/issue-1460.rs | 14 - gcc/testsuite/rust.test/issue-1516.rs | 13 - gcc/testsuite/rust.test/issue-1660.rs | 13 - gcc/testsuite/rust.test/issue-1696.rs | 19 - gcc/testsuite/rust.test/issue-1701.rs | 31 - gcc/testsuite/rust.test/issue-1821.rs | 15 - gcc/testsuite/rust.test/issue-1866.rs | 31 - gcc/testsuite/rust.test/issue-1974.rs | 18 - gcc/testsuite/rust.test/issue-2185.rs | 86 - gcc/testsuite/rust.test/issue-2190-1.rs | 24 - gcc/testsuite/rust.test/issue-2190-2.rs | 31 - gcc/testsuite/rust.test/issue-2190.rs | 18 - gcc/testsuite/rust.test/issue-2214.rs | 47 - gcc/testsuite/rust.test/issue-2216.rs | 32 - gcc/testsuite/rust.test/issue-2284.rs | 20 - gcc/testsuite/rust.test/issue-2288.rs | 38 - gcc/testsuite/rust.test/issue-2311-2.rs | 28 - gcc/testsuite/rust.test/issue-2311.rs | 16 - gcc/testsuite/rust.test/issue-2312.rs | 21 - gcc/testsuite/rust.test/issue-2316-c.rs | 20 - gcc/testsuite/rust.test/issue-2380-b.rs | 18 - gcc/testsuite/rust.test/issue-2383.rs | 20 - gcc/testsuite/rust.test/issue-2414-c.rs | 17 - gcc/testsuite/rust.test/issue-2428.rs | 20 - gcc/testsuite/rust.test/issue-2445-b.rs | 35 - gcc/testsuite/rust.test/issue-2445.rs | 33 - gcc/testsuite/rust.test/issue-2463.rs | 31 - gcc/testsuite/rust.test/issue-2472.rs | 22 - gcc/testsuite/rust.test/issue-2487-a.rs | 38 - gcc/testsuite/rust.test/issue-2502.rs | 27 - gcc/testsuite/rust.test/issue-2526-a.rs | 20 - gcc/testsuite/rust.test/issue-2550.rs | 26 - gcc/testsuite/rust.test/issue-2611-3.rs | 27 - gcc/testsuite/rust.test/issue-2631-b.rs | 24 - gcc/testsuite/rust.test/issue-2633-2.rs | 18 - gcc/testsuite/rust.test/issue-2633.rs | 35 - gcc/testsuite/rust.test/issue-2642.rs | 16 - gcc/testsuite/rust.test/issue-2708.rs | 32 - gcc/testsuite/rust.test/issue-2718.rs | 327 - gcc/testsuite/rust.test/issue-2723-b.rs | 21 - gcc/testsuite/rust.test/issue-2734.rs | 24 - gcc/testsuite/rust.test/issue-2735-2.rs | 33 - gcc/testsuite/rust.test/issue-2735-3.rs | 33 - gcc/testsuite/rust.test/issue-2735.rs | 24 - gcc/testsuite/rust.test/issue-2748-a.rs | 21 - gcc/testsuite/rust.test/issue-2748-b.rs | 19 - gcc/testsuite/rust.test/issue-2804-2.rs | 22 - gcc/testsuite/rust.test/issue-2804.rs | 75 - gcc/testsuite/rust.test/issue-2895.rs | 36 - gcc/testsuite/rust.test/issue-2904.rs | 87 - gcc/testsuite/rust.test/issue-2935.rs | 34 - gcc/testsuite/rust.test/issue-2936.rs | 38 - gcc/testsuite/rust.test/issue-2989.rs | 47 - gcc/testsuite/rust.test/issue-3012-2.rs | 21 - gcc/testsuite/rust.test/issue-3026.rs | 19 - gcc/testsuite/rust.test/issue-3037.rs | 21 - gcc/testsuite/rust.test/issue-3052.rs | 19 - gcc/testsuite/rust.test/issue-3091.rs | 15 - gcc/testsuite/rust.test/issue-3109.rs | 13 - gcc/testsuite/rust.test/issue-3121.rs | 27 - gcc/testsuite/rust.test/issue-3149.rs | 31 - gcc/testsuite/rust.test/issue-3168.rs | 35 - gcc/testsuite/rust.test/issue-3186.rs | 15 - gcc/testsuite/rust.test/issue-3211.rs | 8 - gcc/testsuite/rust.test/issue-3220.rs | 30 - gcc/testsuite/rust.test/issue-3250.rs | 5 - gcc/testsuite/rust.test/issue-3290.rs | 16 - gcc/testsuite/rust.test/issue-333.rs | 15 - gcc/testsuite/rust.test/issue-3389.rs | 32 - gcc/testsuite/rust.test/issue-3424.rs | 30 - gcc/testsuite/rust.test/issue-3429.rs | 15 - gcc/testsuite/rust.test/issue-3447.rs | 35 - gcc/testsuite/rust.test/issue-3461.rs | 17 - gcc/testsuite/rust.test/issue-3500.rs | 17 - gcc/testsuite/rust.test/issue-3556.rs | 45 - gcc/testsuite/rust.test/issue-3559.rs | 36 - gcc/testsuite/rust.test/issue-3563-2.rs | 21 - gcc/testsuite/rust.test/issue-3563-3.rs | 186 - gcc/testsuite/rust.test/issue-3574.rs | 30 - gcc/testsuite/rust.test/issue-3609.rs | 28 - gcc/testsuite/rust.test/issue-3656.rs | 31 - gcc/testsuite/rust.test/issue-3683.rs | 27 - gcc/testsuite/rust.test/issue-3702.rs | 20 - gcc/testsuite/rust.test/issue-3743.rs | 50 - gcc/testsuite/rust.test/issue-3753.rs | 39 - gcc/testsuite/rust.test/issue-3794.rs | 39 - gcc/testsuite/rust.test/issue-3796.rs | 19 - gcc/testsuite/rust.test/issue-3847.rs | 22 - gcc/testsuite/rust.test/issue-3860.rs | 24 - gcc/testsuite/rust.test/issue-3874.rs | 18 - gcc/testsuite/rust.test/issue-3878.rs | 16 - gcc/testsuite/rust.test/issue-3888-2.rs | 15 - gcc/testsuite/rust.test/issue-3895.rs | 18 - gcc/testsuite/rust.test/issue-3904.rs | 37 - gcc/testsuite/rust.test/issue-3907-2.rs | 30 - gcc/testsuite/rust.test/issue-3935.rs | 21 - gcc/testsuite/rust.test/issue-3979-2.rs | 25 - gcc/testsuite/rust.test/issue-3979-generics.rs | 40 - gcc/testsuite/rust.test/issue-3979-xcrate.rs | 33 - gcc/testsuite/rust.test/issue-3979.rs | 41 - gcc/testsuite/rust.test/issue-3991.rs | 21 - gcc/testsuite/rust.test/issue-4016.rs | 26 - gcc/testsuite/rust.test/issue-4025.rs | 32 - gcc/testsuite/rust.test/issue-4036.rs | 22 - gcc/testsuite/rust.test/issue-4092.rs | 16 - gcc/testsuite/rust.test/issue-4107.rs | 33 - gcc/testsuite/rust.test/issue-4120.rs | 21 - gcc/testsuite/rust.test/issue-4208.rs | 19 - gcc/testsuite/rust.test/issue-4228.rs | 23 - gcc/testsuite/rust.test/issue-4241.rs | 131 - gcc/testsuite/rust.test/issue-4252.rs | 37 - gcc/testsuite/rust.test/issue-4333.rs | 16 - gcc/testsuite/rust.test/issue-4387.rs | 13 - gcc/testsuite/rust.test/issue-4401.rs | 8 - gcc/testsuite/rust.test/issue-4446.rs | 19 - gcc/testsuite/rust.test/issue-4448.rs | 22 - gcc/testsuite/rust.test/issue-4464.rs | 13 - gcc/testsuite/rust.test/issue-4541.rs | 32 - gcc/testsuite/rust.test/issue-4542.rs | 20 - gcc/testsuite/rust.test/issue-4545.rs | 15 - gcc/testsuite/rust.test/issue-4735.rs | 28 - gcc/testsuite/rust.test/issue-4759-1.rs | 13 - gcc/testsuite/rust.test/issue-4759.rs | 25 - gcc/testsuite/rust.test/issue-4830.rs | 16 - gcc/testsuite/rust.test/issue-4875.rs | 21 - .../issue-5008-borrowed-traitobject-method-call.rs | 43 - gcc/testsuite/rust.test/issue-5060.rs | 30 - gcc/testsuite/rust.test/issue-5192.rs | 44 - gcc/testsuite/rust.test/issue-5239-2.rs | 17 - gcc/testsuite/rust.test/issue-5243.rs | 23 - gcc/testsuite/rust.test/issue-5275.rs | 29 - gcc/testsuite/rust.test/issue-5280.rs | 25 - gcc/testsuite/rust.test/issue-5315.rs | 16 - .../issue-5321-immediates-with-bare-self.rs | 25 - gcc/testsuite/rust.test/issue-5353.rs | 24 - gcc/testsuite/rust.test/issue-5517.rs | 14 - gcc/testsuite/rust.test/issue-5530.rs | 49 - gcc/testsuite/rust.test/issue-5550.rs | 17 - gcc/testsuite/rust.test/issue-5554.rs | 39 - gcc/testsuite/rust.test/issue-5572.rs | 3 - gcc/testsuite/rust.test/issue-5666.rs | 35 - gcc/testsuite/rust.test/issue-5688.rs | 26 - gcc/testsuite/rust.test/issue-5708.rs | 60 - gcc/testsuite/rust.test/issue-5741.rs | 18 - gcc/testsuite/rust.test/issue-5754.rs | 20 - gcc/testsuite/rust.test/issue-5791.rs | 20 - gcc/testsuite/rust.test/issue-5884.rs | 24 - gcc/testsuite/rust.test/issue-5917.rs | 15 - gcc/testsuite/rust.test/issue-5926.rs | 19 - gcc/testsuite/rust.test/issue-6117.rs | 16 - gcc/testsuite/rust.test/issue-6128.rs | 27 - gcc/testsuite/rust.test/issue-6130.rs | 20 - .../rust.test/issue-6141-leaking-owned-fn.rs | 8 - gcc/testsuite/rust.test/issue-6153.rs | 20 - gcc/testsuite/rust.test/issue-6318.rs | 26 - gcc/testsuite/rust.test/issue-6341.rs | 18 - gcc/testsuite/rust.test/issue-6344-let.rs | 21 - gcc/testsuite/rust.test/issue-6344-match.rs | 24 - gcc/testsuite/rust.test/issue-6470.rs | 22 - gcc/testsuite/rust.test/issue-6557.rs | 13 - gcc/testsuite/rust.test/issue-6898.rs | 40 - gcc/testsuite/rust.test/issue-6919.rs | 19 - gcc/testsuite/rust.test/issue-7012.rs | 27 - gcc/testsuite/rust.test/issue-7222.rs | 19 - gcc/testsuite/rust.test/issue-7344.rs | 28 - .../rust.test/issue-7519-match-unit-in-arg.rs | 19 - gcc/testsuite/rust.test/issue-7563.rs | 25 - ...ssue-7673-cast-generically-implemented-trait.rs | 28 - gcc/testsuite/rust.test/issue-7712.rs | 25 - gcc/testsuite/rust.test/issue-8044.rs | 19 - ...71-default-method-self-inherit-builtin-trait.rs | 25 - gcc/testsuite/rust.test/issue-8248.rs | 21 - gcc/testsuite/rust.test/issue-8249.rs | 25 - gcc/testsuite/rust.test/issue-8351-1.rs | 25 - gcc/testsuite/rust.test/issue-8351-2.rs | 25 - gcc/testsuite/rust.test/issue-8398.rs | 18 - gcc/testsuite/rust.test/issue-8401.rs | 16 - gcc/testsuite/rust.test/issue-8498.rs | 44 - gcc/testsuite/rust.test/issue-868.rs | 24 - gcc/testsuite/rust.test/issue-8898.rs | 32 - gcc/testsuite/rust.test/issue-9047.rs | 19 - gcc/testsuite/rust.test/issue-9110.rs | 24 - gcc/testsuite/rust.test/issue-912.rs | 18 - gcc/testsuite/rust.test/issue-9123.rs | 16 - gcc/testsuite/rust.test/issue-9188.rs | 21 - .../rust.test/issue-9394-inherited-trait-calls.rs | 70 - gcc/testsuite/rust.test/issue-9446.rs | 38 - gcc/testsuite/rust.test/issue-979.rs | 35 - gcc/testsuite/rust.test/issue-980.rs | 23 - gcc/testsuite/rust.test/issue2170exe.rs | 17 - gcc/testsuite/rust.test/issue2378c.rs | 24 - gcc/testsuite/rust.test/issue_3136_b.rs | 15 - gcc/testsuite/rust.test/issue_9155.rs | 20 - gcc/testsuite/rust.test/istr.rs | 72 - gcc/testsuite/rust.test/item-attributes.rs | 194 - gcc/testsuite/rust.test/item-name-overload.rs | 23 - gcc/testsuite/rust.test/iter-range.rs | 23 - gcc/testsuite/rust.test/ivec-add.rs | 23 - gcc/testsuite/rust.test/ivec-pass-by-value.rs | 12 - gcc/testsuite/rust.test/ivec-tag.rs | 14 - .../rust.test/keyword-changes-2012-07-31.rs | 25 - .../rust.test/kindck-owned-trait-contains-1.rs | 28 - gcc/testsuite/rust.test/labeled-break.rs | 23 - gcc/testsuite/rust.test/lambda-infer-unresolved.rs | 21 - gcc/testsuite/rust.test/large-records.rs | 44 - gcc/testsuite/rust.test/last-use-in-block.rs | 26 - gcc/testsuite/rust.test/last-use-in-cap-clause.rs | 24 - gcc/testsuite/rust.test/last-use-is-capture.rs | 20 - gcc/testsuite/rust.test/lazy-and-or.rs | 22 - gcc/testsuite/rust.test/lazy-init.rs | 15 - gcc/testsuite/rust.test/leak-box-as-tydesc.rs | 15 - gcc/testsuite/rust.test/leak-tag-copy.rs | 16 - gcc/testsuite/rust.test/leak-unique-as-tydesc.rs | 15 - gcc/testsuite/rust.test/let-assignability.rs | 19 - gcc/testsuite/rust.test/let-destruct-fresh-mem.rs | 27 - gcc/testsuite/rust.test/let-destruct-ref.rs | 5 - gcc/testsuite/rust.test/let-destruct.rs | 18 - gcc/testsuite/rust.test/let-var-hygiene.rs | 18 - gcc/testsuite/rust.test/linear-for-loop.rs | 32 - gcc/testsuite/rust.test/link-section.rs | 34 - gcc/testsuite/rust.test/lint-cstack.rs | 27 - ...mel-case-types-non-uppercase-statics-unicode.rs | 21 - ...int-non-camel-case-with-trailing-underscores.rs | 16 - ...-non-uppercase-statics-lowercase-mut-statics.rs | 17 - gcc/testsuite/rust.test/list.rs | 17 - .../liveness-assign-imm-local-after-loop.rs | 24 - .../liveness-assign-imm-local-after-ret.rs | 21 - gcc/testsuite/rust.test/liveness-loop-break.rs | 22 - gcc/testsuite/rust.test/liveness-move-in-loop.rs | 25 - gcc/testsuite/rust.test/log-err-phi.rs | 13 - .../log-knows-the-names-of-variants-in-std.rs | 32 - .../rust.test/log-knows-the-names-of-variants.rs | 26 - gcc/testsuite/rust.test/log-linearized.rs | 34 - gcc/testsuite/rust.test/log-poly.rs | 20 - gcc/testsuite/rust.test/log-str.rs | 19 - gcc/testsuite/rust.test/logging-right-crate.rs | 30 - .../rust.test/logging_before_rt_started.rs | 20 - gcc/testsuite/rust.test/long-while.rs | 19 - gcc/testsuite/rust.test/loop-break-cont-1.rs | 17 - gcc/testsuite/rust.test/loop-break-cont.rs | 48 - gcc/testsuite/rust.test/loop-diverges.rs | 20 - gcc/testsuite/rust.test/loop-scope.rs | 16 - gcc/testsuite/rust.test/lots-a-fail.rs | 28 - gcc/testsuite/rust.test/macro-2.rs | 25 - gcc/testsuite/rust.test/macro-attributes.rs | 35 - gcc/testsuite/rust.test/macro-interpolation.rs | 30 - gcc/testsuite/rust.test/macro-local-data-key.rs | 28 - gcc/testsuite/rust.test/macro-path.rs | 26 - gcc/testsuite/rust.test/macro-stmt.rs | 44 - gcc/testsuite/rust.test/macro-with-attrs1.rs | 24 - gcc/testsuite/rust.test/macro-with-attrs2.rs | 22 - gcc/testsuite/rust.test/match-borrowed_str.rs | 62 - gcc/testsuite/rust.test/match-bot-2.rs | 13 - gcc/testsuite/rust.test/match-bot.rs | 16 - .../rust.test/match-drop-strs-issue-4541.rs | 27 - gcc/testsuite/rust.test/match-enum-struct-0.rs | 26 - gcc/testsuite/rust.test/match-enum-struct-1.rs | 28 - .../rust.test/match-implicit-copy-unique.rs | 20 - gcc/testsuite/rust.test/match-in-macro.rs | 27 - gcc/testsuite/rust.test/match-join.rs | 31 - gcc/testsuite/rust.test/match-naked-record-expr.rs | 19 - gcc/testsuite/rust.test/match-naked-record.rs | 19 - gcc/testsuite/rust.test/match-path.rs | 19 - gcc/testsuite/rust.test/match-pattern-drop.rs | 45 - gcc/testsuite/rust.test/match-pattern-lit.rs | 21 - .../rust.test/match-pattern-no-type-params.rs | 20 - gcc/testsuite/rust.test/match-pattern-simple.rs | 15 - gcc/testsuite/rust.test/match-phi.rs | 25 - gcc/testsuite/rust.test/match-pipe-binding.rs | 68 - gcc/testsuite/rust.test/match-range-static.rs | 9 - gcc/testsuite/rust.test/match-range.rs | 41 - .../rust.test/match-ref-binding-in-guard-3256.rs | 23 - .../rust.test/match-ref-binding-mut-option.rs | 18 - gcc/testsuite/rust.test/match-ref-binding-mut.rs | 25 - gcc/testsuite/rust.test/match-ref-binding.rs | 20 - .../rust.test/match-static-const-rename.rs | 71 - gcc/testsuite/rust.test/match-str.rs | 31 - gcc/testsuite/rust.test/match-struct-0.rs | 29 - gcc/testsuite/rust.test/match-tag.rs | 38 - gcc/testsuite/rust.test/match-unique-bind.rs | 18 - .../rust.test/match-value-binding-in-guard-3291.rs | 24 - gcc/testsuite/rust.test/match-vec-rvalue.rs | 12 - gcc/testsuite/rust.test/match-with-ret-arm.rs | 23 - gcc/testsuite/rust.test/max-min-classes.rs | 39 - gcc/testsuite/rust.test/method-attributes.rs | 34 - gcc/testsuite/rust.test/mid-path-type-params.rs | 33 - gcc/testsuite/rust.test/mlist-cycle.rs | 27 - gcc/testsuite/rust.test/mlist.rs | 14 - gcc/testsuite/rust.test/mod-inside-fn.rs | 21 - gcc/testsuite/rust.test/mod-view-items.rs | 24 - gcc/testsuite/rust.test/mod_dir_implicit.rs | 18 - gcc/testsuite/rust.test/mod_dir_path.rs | 21 - gcc/testsuite/rust.test/mod_dir_path2.rs | 22 - gcc/testsuite/rust.test/mod_dir_path3.rs | 21 - gcc/testsuite/rust.test/mod_dir_path_multi.rs | 27 - gcc/testsuite/rust.test/mod_dir_recursive.rs | 24 - gcc/testsuite/rust.test/mod_dir_simple.rs | 20 - gcc/testsuite/rust.test/mod_file.rs | 19 - gcc/testsuite/rust.test/mod_file_aux.rs | 13 - gcc/testsuite/rust.test/mod_file_with_path_attr.rs | 20 - .../module-qualified-struct-destructure.rs | 21 - gcc/testsuite/rust.test/monad.rs | 51 - .../rust.test/monomorphize-abi-alignment.rs | 31 - .../monomorphized-callees-with-ty-params-3314.rs | 45 - gcc/testsuite/rust.test/morestack-address.rs | 24 - gcc/testsuite/rust.test/morestack1.rs | 21 - gcc/testsuite/rust.test/morestack2.rs | 26 - gcc/testsuite/rust.test/morestack3.rs | 54 - gcc/testsuite/rust.test/morestack4.rs | 109 - gcc/testsuite/rust.test/morestack5.rs | 31 - gcc/testsuite/rust.test/morestack6.rs | 76 - gcc/testsuite/rust.test/move-1-unique.rs | 31 - gcc/testsuite/rust.test/move-1.rs | 26 - gcc/testsuite/rust.test/move-2-unique.rs | 14 - gcc/testsuite/rust.test/move-2.rs | 14 - gcc/testsuite/rust.test/move-3-unique.rs | 33 - gcc/testsuite/rust.test/move-3.rs | 28 - gcc/testsuite/rust.test/move-4-unique.rs | 23 - gcc/testsuite/rust.test/move-4.rs | 28 - gcc/testsuite/rust.test/move-arg-2-unique.rs | 20 - gcc/testsuite/rust.test/move-arg-2.rs | 20 - gcc/testsuite/rust.test/move-arg.rs | 13 - gcc/testsuite/rust.test/move-nullary-fn.rs | 20 - gcc/testsuite/rust.test/move-out-of-field.rs | 21 - gcc/testsuite/rust.test/move-scalar.rs | 17 - gcc/testsuite/rust.test/move-self.rs | 18 - .../moves-based-on-type-capture-clause.rs | 8 - .../rust.test/moves-based-on-type-cross-crate.rs | 19 - gcc/testsuite/rust.test/multi-let.rs | 15 - gcc/testsuite/rust.test/multibyte.rs | 14 - gcc/testsuite/rust.test/multiline-comment.rs | 16 - gcc/testsuite/rust.test/multiple-trait-bounds.rs | 6 - gcc/testsuite/rust.test/mut-function-arguments.rs | 27 - gcc/testsuite/rust.test/mut-vstore-expr.rs | 13 - ...mutability-inherits-through-fixed-length-vec.rs | 26 - gcc/testsuite/rust.test/mutable-alias-vec.rs | 26 - gcc/testsuite/rust.test/mutable-vec-drop.rs | 19 - gcc/testsuite/rust.test/mutual-recursion-group.rs | 23 - gcc/testsuite/rust.test/negative.rs | 16 - gcc/testsuite/rust.test/nested-class.rs | 31 - gcc/testsuite/rust.test/nested-enum-same-names.rs | 33 - gcc/testsuite/rust.test/nested-exhaustive-match.rs | 20 - .../rust.test/nested-function-names-issue-8587.rs | 50 - gcc/testsuite/rust.test/nested-matchs.rs | 25 - gcc/testsuite/rust.test/nested-pattern.rs | 24 - gcc/testsuite/rust.test/nested-patterns.rs | 27 - gcc/testsuite/rust.test/nested_item_main.rs | 19 - gcc/testsuite/rust.test/new-impl-syntax.rs | 25 - gcc/testsuite/rust.test/new-import-syntax.rs | 15 - gcc/testsuite/rust.test/new-style-constants.rs | 17 - .../rust.test/new-style-fixed-length-vec.rs | 15 - .../rust.test/new-vstore-mut-box-syntax.rs | 14 - gcc/testsuite/rust.test/newlambdas-ret-infer.rs | 17 - gcc/testsuite/rust.test/newlambdas-ret-infer2.rs | 17 - gcc/testsuite/rust.test/newlambdas.rs | 22 - gcc/testsuite/rust.test/newtype-polymorphic.rs | 23 - gcc/testsuite/rust.test/newtype-struct-drop-run.rs | 28 - .../rust.test/newtype-struct-with-dtor.rs | 16 - gcc/testsuite/rust.test/newtype-struct-xc-2.rs | 13 - gcc/testsuite/rust.test/newtype-struct-xc.rs | 8 - gcc/testsuite/rust.test/newtype-temporary.rs | 19 - gcc/testsuite/rust.test/newtype.rs | 21 - gcc/testsuite/rust.test/nil-decl-in-foreign.rs | 19 - gcc/testsuite/rust.test/nil-pattern.rs | 11 - gcc/testsuite/rust.test/no-std-xcrate.rs | 21 - gcc/testsuite/rust.test/no-std-xcrate2.rs | 35 - gcc/testsuite/rust.test/non-boolean-pure-fns.rs | 34 - gcc/testsuite/rust.test/non-legacy-modes.rs | 30 - gcc/testsuite/rust.test/nul-characters.rs | 44 - .../rust.test/nullable-pointer-iotareduction.rs | 90 - gcc/testsuite/rust.test/nullable-pointer-size.rs | 48 - gcc/testsuite/rust.test/nullary-or-pattern.rs | 20 - .../rust.test/numeric-method-autoexport.rs | 41 - .../rust.test/objects-coerce-freeze-borrored.rs | 48 - .../objects-coerce-from-managed-to-borrowed.rs | 44 - .../objects-owned-object-borrowed-method-header.rs | 41 - ...ects-owned-object-borrowed-method-headerless.rs | 39 - .../rust.test/objects-owned-object-owned-method.rs | 32 - gcc/testsuite/rust.test/once-move-out-on-heap.rs | 30 - gcc/testsuite/rust.test/once-move-out-on-stack.rs | 30 - gcc/testsuite/rust.test/one-tuple.rs | 23 - gcc/testsuite/rust.test/opeq.rs | 29 - gcc/testsuite/rust.test/operator-associativity.rs | 15 - gcc/testsuite/rust.test/operator-overloading.rs | 74 - gcc/testsuite/rust.test/option-ext.rs | 18 - gcc/testsuite/rust.test/option-unwrap.rs | 40 - gcc/testsuite/rust.test/or-pattern.rs | 21 - gcc/testsuite/rust.test/output-slot-variants.rs | 72 - gcc/testsuite/rust.test/over-constrained-vregs.rs | 22 - gcc/testsuite/rust.test/overload-index-operator.rs | 56 - gcc/testsuite/rust.test/owned-implies-static.rs | 15 - .../rust.test/packed-struct-borrow-element.rs | 22 - .../rust.test/packed-struct-generic-layout.rs | 37 - .../rust.test/packed-struct-generic-size.rs | 27 - gcc/testsuite/rust.test/packed-struct-layout.rs | 36 - gcc/testsuite/rust.test/packed-struct-match.rs | 25 - gcc/testsuite/rust.test/packed-struct-size-xc.rs | 10 - gcc/testsuite/rust.test/packed-struct-size.rs | 65 - gcc/testsuite/rust.test/packed-struct-vec.rs | 34 - .../rust.test/packed-tuple-struct-layout.rs | 30 - .../rust.test/packed-tuple-struct-size.rs | 46 - gcc/testsuite/rust.test/paren-free.rs | 15 - gcc/testsuite/rust.test/parse-fail.rs | 16 - gcc/testsuite/rust.test/pass-by-copy.rs | 21 - gcc/testsuite/rust.test/path.rs | 17 - .../rust.test/pattern-bound-var-in-for-each.rs | 28 - gcc/testsuite/rust.test/pattern-in-closure.rs | 21 - gcc/testsuite/rust.test/placement-new-arena.rs | 22 - gcc/testsuite/rust.test/pred-not-bool.rs | 16 - gcc/testsuite/rust.test/preempt.rs | 41 - gcc/testsuite/rust.test/privacy1.rs | 29 - gcc/testsuite/rust.test/private-class-field.rs | 31 - gcc/testsuite/rust.test/private-method.rs | 38 - gcc/testsuite/rust.test/pub-extern-privacy.rs | 14 - gcc/testsuite/rust.test/pub-use-xcrate.rs | 23 - gcc/testsuite/rust.test/pub_use_mods_xcrate_exe.rs | 19 - gcc/testsuite/rust.test/pure-sum.rs | 56 - gcc/testsuite/rust.test/purity-infer.rs | 15 - gcc/testsuite/rust.test/raw-str.rs | Bin 1314 -> 0 bytes gcc/testsuite/rust.test/rcvr-borrowed-to-region.rs | 43 - gcc/testsuite/rust.test/rcvr-borrowed-to-slice.rs | 39 - gcc/testsuite/rust.test/readalias.rs | 19 - gcc/testsuite/rust.test/rec-align-u32.rs | 70 - gcc/testsuite/rust.test/rec-align-u64.rs | 92 - gcc/testsuite/rust.test/rec-auto.rs | 24 - gcc/testsuite/rust.test/rec-extend.rs | 27 - gcc/testsuite/rust.test/rec-tup.rs | 37 - gcc/testsuite/rust.test/rec.rs | 35 - gcc/testsuite/rust.test/record-pat.rs | 25 - gcc/testsuite/rust.test/recursion.rs | 34 - .../rust.test/reexport-should-still-link.rs | 18 - gcc/testsuite/rust.test/reexport-star.rs | 29 - .../reexported-static-methods-cross-crate.rs | 25 - gcc/testsuite/rust.test/reflect-visit-data.rs | 648 - gcc/testsuite/rust.test/reflect-visit-type.rs | 166 - .../rust.test/region-dependent-addr-of.rs | 118 - gcc/testsuite/rust.test/region-dependent-autofn.rs | 22 - .../rust.test/region-dependent-autoslice.rs | 23 - .../rust.test/region-return-interior-of-option.rs | 32 - .../regions-addr-of-interior-of-unique-box.rs | 28 - gcc/testsuite/rust.test/regions-addr-of-ret.rs | 18 - .../rust.test/regions-appearance-constraint.rs | 34 - gcc/testsuite/rust.test/regions-borrow-at.rs | 20 - .../rust.test/regions-borrow-estr-uniq.rs | 23 - gcc/testsuite/rust.test/regions-borrow-evec-at.rs | 19 - .../rust.test/regions-borrow-evec-fixed.rs | 18 - .../rust.test/regions-borrow-evec-uniq.rs | 23 - gcc/testsuite/rust.test/regions-borrow-uniq.rs | 19 - gcc/testsuite/rust.test/regions-bot.rs | 18 - gcc/testsuite/rust.test/regions-copy-closure.rs | 25 - gcc/testsuite/rust.test/regions-creating-enums2.rs | 21 - gcc/testsuite/rust.test/regions-creating-enums5.rs | 21 - .../rust.test/regions-escape-into-other-fn.rs | 17 - gcc/testsuite/rust.test/regions-expl-self.rs | 21 - gcc/testsuite/rust.test/regions-fn-subtyping-2.rs | 26 - gcc/testsuite/rust.test/regions-fn-subtyping.rs | 36 - .../regions-infer-borrow-scope-addr-of.rs | 31 - .../rust.test/regions-infer-borrow-scope-view.rs | 18 - .../regions-infer-borrow-scope-within-loop-ok.rs | 20 - .../rust.test/regions-infer-borrow-scope.rs | 21 - gcc/testsuite/rust.test/regions-infer-call-2.rs | 23 - gcc/testsuite/rust.test/regions-infer-call.rs | 19 - .../regions-infer-contravariance-due-to-ret.rs | 28 - gcc/testsuite/rust.test/regions-mock-trans.rs | 60 - gcc/testsuite/rust.test/regions-nullary-variant.rs | 19 - gcc/testsuite/rust.test/regions-params.rs | 27 - gcc/testsuite/rust.test/regions-self-impls.rs | 27 - gcc/testsuite/rust.test/regions-self-in-enums.rs | 23 - gcc/testsuite/rust.test/regions-simple.rs | 16 - gcc/testsuite/rust.test/regions-static-closure.rs | 26 - gcc/testsuite/rust.test/rename-directory.rs | 57 - gcc/testsuite/rust.test/repeat-expr-in-static.rs | 16 - gcc/testsuite/rust.test/repeated-vector-syntax.rs | 22 - gcc/testsuite/rust.test/resolve-issue-2428.rs | 13 - .../rust.test/resource-assign-is-not-copy.rs | 38 - gcc/testsuite/rust.test/resource-cycle.rs | 81 - gcc/testsuite/rust.test/resource-cycle2.rs | 69 - gcc/testsuite/rust.test/resource-cycle3.rs | 78 - gcc/testsuite/rust.test/resource-destruct.rs | 37 - gcc/testsuite/rust.test/resource-in-struct.rs | 43 - gcc/testsuite/rust.test/ret-bang.rs | 21 - gcc/testsuite/rust.test/ret-none.rs | 17 - gcc/testsuite/rust.test/return-nil.rs | 15 - gcc/testsuite/rust.test/rt-run-twice.rs | 26 - gcc/testsuite/rust.test/rt-start-main-thread.rs | 21 - gcc/testsuite/rust.test/rtio-processes.rs | 156 - gcc/testsuite/rust.test/select-macro.rs | 72 - gcc/testsuite/rust.test/self-shadowing-import.rs | 26 - gcc/testsuite/rust.test/self-type-param.rs | 15 - gcc/testsuite/rust.test/send-iloop.rs | 39 - gcc/testsuite/rust.test/send-resource.rs | 38 - gcc/testsuite/rust.test/send-type-inference.rs | 21 - gcc/testsuite/rust.test/send_str_hashmap.rs | 80 - gcc/testsuite/rust.test/send_str_treemap.rs | 73 - gcc/testsuite/rust.test/sendable-class.rs | 30 - gcc/testsuite/rust.test/sendfn-generic-fn.rs | 46 - gcc/testsuite/rust.test/sendfn-is-a-block.rs | 20 - .../rust.test/sendfn-spawn-with-fn-arg.rs | 30 - gcc/testsuite/rust.test/seq-compare.rs | 26 - gcc/testsuite/rust.test/shadow.rs | 31 - .../rust.test/shape_intrinsic_tag_then_rec.rs | 62 - gcc/testsuite/rust.test/shebang.rs | 14 - gcc/testsuite/rust.test/shift.rs | 81 - gcc/testsuite/rust.test/signed-shift-const-eval.rs | 14 - gcc/testsuite/rust.test/simd-binop.rs | 28 - gcc/testsuite/rust.test/simd-type.rs | 9 - gcc/testsuite/rust.test/simple-generic-match.rs | 15 - gcc/testsuite/rust.test/simple-generic-tag.rs | 15 - gcc/testsuite/rust.test/simple-infer.rs | 13 - .../rust.test/simple-match-generic-tag.rs | 18 - gcc/testsuite/rust.test/size-and-align.rs | 31 - gcc/testsuite/rust.test/sized-borrowed-pointer.rs | 15 - gcc/testsuite/rust.test/sized-owned-pointer.rs | 15 - gcc/testsuite/rust.test/smallest-hello-world.rs | 42 - gcc/testsuite/rust.test/spawn-fn.rs | 25 - gcc/testsuite/rust.test/spawn-types.rs | 28 - gcc/testsuite/rust.test/spawn.rs | 20 - gcc/testsuite/rust.test/spawn2.rs | 36 - gcc/testsuite/rust.test/stable-addr-of.rs | 18 - gcc/testsuite/rust.test/stat.rs | 37 - gcc/testsuite/rust.test/static-assert.rs | 14 - gcc/testsuite/rust.test/static-fn-inline-xc.rs | 20 - gcc/testsuite/rust.test/static-fn-trait-xc.rs | 10 - .../rust.test/static-function-pointer-xc.rs | 26 - gcc/testsuite/rust.test/static-function-pointer.rs | 24 - gcc/testsuite/rust.test/static-impl.rs | 68 - .../static-method-in-trait-with-tps-intracrate.rs | 35 - gcc/testsuite/rust.test/static-method-xcrate.rs | 23 - .../rust.test/static-methods-in-traits.rs | 34 - .../rust.test/static-methods-in-traits2.rs | 19 - gcc/testsuite/rust.test/static-mut-foreign.rs | 47 - gcc/testsuite/rust.test/static-mut-xc.rs | 46 - gcc/testsuite/rust.test/static-vec-autoref.rs | 21 - gcc/testsuite/rust.test/str-append.rs | 35 - gcc/testsuite/rust.test/str-concat.rs | 21 - gcc/testsuite/rust.test/str-growth.rs | 24 - gcc/testsuite/rust.test/str-idx.rs | 18 - gcc/testsuite/rust.test/str-multiline.rs | 26 - gcc/testsuite/rust.test/string-self-append.rs | 25 - gcc/testsuite/rust.test/struct-deref.rs | 16 - .../rust.test/struct-destructuring-cross-crate.rs | 21 - .../rust.test/struct-field-assignability.rs | 8 - .../rust.test/struct-like-variant-construct.rs | 26 - .../rust.test/struct-like-variant-match.rs | 42 - gcc/testsuite/rust.test/struct-literal-dtor.rs | 23 - .../rust.test/struct-new-as-field-name.rs | 8 - gcc/testsuite/rust.test/struct-order-of-eval-1.rs | 16 - gcc/testsuite/rust.test/struct-order-of-eval-2.rs | 16 - gcc/testsuite/rust.test/struct-pattern-matching.rs | 21 - gcc/testsuite/rust.test/struct-return.rs | 71 - .../rust.test/struct-update-moves-and-copies.rs | 101 - gcc/testsuite/rust.test/struct_variant_xc.rs | 19 - gcc/testsuite/rust.test/structured-compare.rs | 36 - gcc/testsuite/rust.test/super.rs | 11 - .../rust.test/supertrait-default-generics.rs | 42 - gcc/testsuite/rust.test/supported-cast.rs | 232 - gcc/testsuite/rust.test/swap-1.rs | 17 - gcc/testsuite/rust.test/swap-2.rs | 22 - gcc/testsuite/rust.test/swap-overlapping.rs | 49 - gcc/testsuite/rust.test/syntax-extension-bytes.rs | 24 - gcc/testsuite/rust.test/syntax-extension-cfg.rs | 35 - gcc/testsuite/rust.test/syntax-extension-minor.rs | 21 - gcc/testsuite/rust.test/syntax-extension-shell.rs | 15 - .../rust.test/syntax-extension-source-utils.rs | 41 - gcc/testsuite/rust.test/tag-align-dyn-u64.rs | 35 - gcc/testsuite/rust.test/tag-align-dyn-variants.rs | 72 - gcc/testsuite/rust.test/tag-align-shape.rs | 27 - gcc/testsuite/rust.test/tag-align-u64.rs | 35 - gcc/testsuite/rust.test/tag-disr-val-shape.rs | 25 - gcc/testsuite/rust.test/tag-exports.rs | 29 - gcc/testsuite/rust.test/tag-in-block.rs | 19 - .../rust.test/tag-variant-disr-type-mismatch.rs | 16 - gcc/testsuite/rust.test/tag-variant-disr-val.rs | 71 - gcc/testsuite/rust.test/tag.rs | 37 - gcc/testsuite/rust.test/tail-call-arg-leak.rs | 17 - gcc/testsuite/rust.test/tail-cps.rs | 29 - gcc/testsuite/rust.test/tail-direct.rs | 19 - gcc/testsuite/rust.test/task-comm-0.rs | 40 - gcc/testsuite/rust.test/task-comm-1.rs | 20 - gcc/testsuite/rust.test/task-comm-10.rs | 40 - gcc/testsuite/rust.test/task-comm-11.rs | 27 - gcc/testsuite/rust.test/task-comm-12.rs | 38 - gcc/testsuite/rust.test/task-comm-13.rs | 28 - gcc/testsuite/rust.test/task-comm-14.rs | 45 - gcc/testsuite/rust.test/task-comm-15.rs | 34 - gcc/testsuite/rust.test/task-comm-16.rs | 116 - gcc/testsuite/rust.test/task-comm-17.rs | 24 - gcc/testsuite/rust.test/task-comm-3.rs | 75 - gcc/testsuite/rust.test/task-comm-4.rs | 54 - gcc/testsuite/rust.test/task-comm-5.rs | 27 - gcc/testsuite/rust.test/task-comm-6.rs | 52 - gcc/testsuite/rust.test/task-comm-7.rs | 65 - gcc/testsuite/rust.test/task-comm-9.rs | 47 - gcc/testsuite/rust.test/task-comm-chan-nil.rs | 25 - gcc/testsuite/rust.test/task-killjoin-rsrc.rs | 87 - gcc/testsuite/rust.test/task-killjoin.rs | 37 - gcc/testsuite/rust.test/task-life-0.rs | 21 - .../rust.test/task-spawn-move-and-copy.rs | 27 - gcc/testsuite/rust.test/tempfile.rs | 151 - .../rust.test/terminate-in-initializer.rs | 41 - gcc/testsuite/rust.test/test-ignore-cfg.rs | 36 - gcc/testsuite/rust.test/test-runner-hides-main.rs | 18 - gcc/testsuite/rust.test/threads.rs | 22 - gcc/testsuite/rust.test/trait-bounds-basic.rs | 32 - gcc/testsuite/rust.test/trait-bounds-in-arc.rs | 105 - gcc/testsuite/rust.test/trait-bounds-recursion.rs | 27 - gcc/testsuite/rust.test/trait-bounds.rs | 35 - gcc/testsuite/rust.test/trait-cast.rs | 58 - .../rust.test/trait-composition-trivial.rs | 19 - .../rust.test/trait-default-method-bound-subst.rs | 26 - .../rust.test/trait-default-method-bound-subst2.rs | 24 - .../rust.test/trait-default-method-bound-subst3.rs | 25 - .../rust.test/trait-default-method-bound-subst4.rs | 25 - .../rust.test/trait-default-method-bound.rs | 24 - .../rust.test/trait-default-method-xc-2.rs | 25 - gcc/testsuite/rust.test/trait-default-method-xc.rs | 81 - gcc/testsuite/rust.test/trait-generic.rs | 52 - .../rust.test/trait-inheritance-auto-xc-2.rs | 32 - .../rust.test/trait-inheritance-auto-xc.rs | 33 - gcc/testsuite/rust.test/trait-inheritance-auto.rs | 36 - .../trait-inheritance-call-bound-inherited.rs | 27 - .../trait-inheritance-call-bound-inherited2.rs | 30 - ...-inheritance-cast-without-call-to-supertrait.rs | 40 - gcc/testsuite/rust.test/trait-inheritance-cast.rs | 42 - .../trait-inheritance-cross-trait-call-xc.rs | 29 - .../trait-inheritance-cross-trait-call.rs | 26 - .../rust.test/trait-inheritance-diamond.rs | 35 - .../trait-inheritance-multiple-inheritors.rs | 30 - .../rust.test/trait-inheritance-multiple-params.rs | 33 - gcc/testsuite/rust.test/trait-inheritance-num.rs | 25 - gcc/testsuite/rust.test/trait-inheritance-num0.rs | 28 - gcc/testsuite/rust.test/trait-inheritance-num1.rs | 20 - gcc/testsuite/rust.test/trait-inheritance-num2.rs | 102 - gcc/testsuite/rust.test/trait-inheritance-num3.rs | 24 - gcc/testsuite/rust.test/trait-inheritance-num5.rs | 25 - .../trait-inheritance-overloading-simple.rs | 34 - .../trait-inheritance-overloading-xc-exe.rs | 29 - .../rust.test/trait-inheritance-overloading.rs | 48 - .../trait-inheritance-self-in-supertype.rs | 63 - gcc/testsuite/rust.test/trait-inheritance-self.rs | 28 - .../rust.test/trait-inheritance-simple.rs | 31 - .../rust.test/trait-inheritance-static.rs | 34 - .../rust.test/trait-inheritance-static2.rs | 38 - gcc/testsuite/rust.test/trait-inheritance-subst.rs | 35 - .../rust.test/trait-inheritance-subst2.rs | 45 - .../rust.test/trait-inheritance-visibility.rs | 28 - gcc/testsuite/rust.test/trait-inheritance2.rs | 33 - gcc/testsuite/rust.test/trait-object-generics.rs | 46 - .../rust.test/trait-region-pointer-simple.rs | 30 - .../rust.test/trait-static-method-overwriting.rs | 46 - gcc/testsuite/rust.test/trait-to-str.rs | 40 - gcc/testsuite/rust.test/trait-typedef-cc.rs | 30 - .../rust.test/trait-with-bounds-default.rs | 40 - .../rust.test/traits-default-method-macro.rs | 28 - .../rust.test/traits-default-method-mut.rs | 18 - .../rust.test/traits-default-method-self.rs | 26 - .../rust.test/traits-default-method-trivial.rs | 29 - .../transmute-non-immediate-to-immediate.rs | 18 - gcc/testsuite/rust.test/trivial-message.rs | 23 - gcc/testsuite/rust.test/tup.rs | 28 - gcc/testsuite/rust.test/tuple-struct-construct.rs | 16 - .../rust.test/tuple-struct-constructor-pointer.rs | 21 - .../rust.test/tuple-struct-destructuring.rs | 19 - gcc/testsuite/rust.test/tuple-struct-matching.rs | 22 - gcc/testsuite/rust.test/tuple-struct-trivial.rs | 14 - gcc/testsuite/rust.test/tydesc-name.rs | 25 - gcc/testsuite/rust.test/type-in-nested-module.rs | 21 - gcc/testsuite/rust.test/type-namespace.rs | 15 - gcc/testsuite/rust.test/type-param-constraints.rs | 47 - gcc/testsuite/rust.test/type-param.rs | 15 - gcc/testsuite/rust.test/type-params-in-for-each.rs | 27 - gcc/testsuite/rust.test/type-ptr.rs | 15 - gcc/testsuite/rust.test/type-sizes.rs | 38 - gcc/testsuite/rust.test/type-use-i1-versus-i8.rs | 19 - .../typeck-macro-interaction-issue-8852.rs | 24 - .../rust.test/typeclasses-eq-example-static.rs | 65 - gcc/testsuite/rust.test/typeclasses-eq-example.rs | 64 - gcc/testsuite/rust.test/typestate-cfg-nesting.rs | 23 - gcc/testsuite/rust.test/typestate-multi-decl.rs | 15 - gcc/testsuite/rust.test/u32-decr.rs | 19 - gcc/testsuite/rust.test/u8-incr-decr.rs | 28 - gcc/testsuite/rust.test/u8-incr.rs | 24 - gcc/testsuite/rust.test/uint.rs | 15 - .../rust.test/unary-minus-suffix-inference.rs | 53 - gcc/testsuite/rust.test/unfold-cross-crate.rs | 34 - gcc/testsuite/rust.test/unify-return-ty.rs | 24 - gcc/testsuite/rust.test/uniq-cc-generic.rs | 38 - gcc/testsuite/rust.test/uniq-cc.rs | 33 - gcc/testsuite/rust.test/unique-assign-copy.rs | 20 - gcc/testsuite/rust.test/unique-assign-drop.rs | 19 - gcc/testsuite/rust.test/unique-assign-generic.rs | 21 - gcc/testsuite/rust.test/unique-assign.rs | 15 - gcc/testsuite/rust.test/unique-autoderef-field.rs | 18 - gcc/testsuite/rust.test/unique-autoderef-index.rs | 14 - gcc/testsuite/rust.test/unique-cmp.rs | 18 - gcc/testsuite/rust.test/unique-containing-tag.rs | 29 - gcc/testsuite/rust.test/unique-copy-box.rs | 23 - gcc/testsuite/rust.test/unique-create.rs | 17 - gcc/testsuite/rust.test/unique-decl-init-copy.rs | 19 - gcc/testsuite/rust.test/unique-decl-init.rs | 15 - gcc/testsuite/rust.test/unique-decl-move-temp.rs | 14 - gcc/testsuite/rust.test/unique-decl-move.rs | 15 - gcc/testsuite/rust.test/unique-decl.rs | 17 - gcc/testsuite/rust.test/unique-deref.rs | 14 - gcc/testsuite/rust.test/unique-destructure.rs | 16 - gcc/testsuite/rust.test/unique-drop-complex.rs | 13 - gcc/testsuite/rust.test/unique-fn-arg-move.rs | 18 - gcc/testsuite/rust.test/unique-fn-arg-mut.rs | 19 - gcc/testsuite/rust.test/unique-fn-arg.rs | 19 - gcc/testsuite/rust.test/unique-fn-ret.rs | 17 - gcc/testsuite/rust.test/unique-generic-assign.rs | 16 - gcc/testsuite/rust.test/unique-in-tag.rs | 26 - gcc/testsuite/rust.test/unique-in-vec-copy.rs | 23 - gcc/testsuite/rust.test/unique-in-vec.rs | 13 - gcc/testsuite/rust.test/unique-init.rs | 13 - gcc/testsuite/rust.test/unique-kinds.rs | 71 - gcc/testsuite/rust.test/unique-log.rs | 14 - gcc/testsuite/rust.test/unique-match-discrim.rs | 18 - gcc/testsuite/rust.test/unique-move-drop.rs | 18 - gcc/testsuite/rust.test/unique-move-temp.rs | 15 - gcc/testsuite/rust.test/unique-move.rs | 16 - gcc/testsuite/rust.test/unique-mutable.rs | 15 - gcc/testsuite/rust.test/unique-object-move.rs | 24 - gcc/testsuite/rust.test/unique-pat-2.rs | 21 - gcc/testsuite/rust.test/unique-pat-3.rs | 22 - gcc/testsuite/rust.test/unique-pat.rs | 20 - gcc/testsuite/rust.test/unique-pinned-nocopy-2.rs | 34 - gcc/testsuite/rust.test/unique-rec.rs | 17 - gcc/testsuite/rust.test/unique-send-2.rs | 36 - gcc/testsuite/rust.test/unique-send.rs | 16 - gcc/testsuite/rust.test/unique-swap.rs | 19 - .../rust.test/unit-like-struct-drop-run.rs | 28 - gcc/testsuite/rust.test/unit-like-struct.rs | 18 - gcc/testsuite/rust.test/unit.rs | 22 - gcc/testsuite/rust.test/unnamed_argument_mode.rs | 11 - gcc/testsuite/rust.test/unreachable-code-1.rs | 24 - gcc/testsuite/rust.test/unreachable-code.rs | 35 - .../rust.test/unsafe-fn-called-from-unsafe-blk.rs | 24 - .../rust.test/unsafe-fn-called-from-unsafe-fn.rs | 23 - .../rust.test/unsafe-pointer-assignability.rs | 19 - gcc/testsuite/rust.test/unused-move-capture.rs | 15 - gcc/testsuite/rust.test/unused-move.rs | 21 - gcc/testsuite/rust.test/unwind-box.rs | 22 - gcc/testsuite/rust.test/unwind-resource.rs | 48 - gcc/testsuite/rust.test/unwind-resource2.rs | 37 - gcc/testsuite/rust.test/unwind-unique.rs | 22 - gcc/testsuite/rust.test/use-crate-name-alias.rs | 14 - gcc/testsuite/rust.test/use-import-export.rs | 21 - gcc/testsuite/rust.test/use-trait-before-def.rs | 15 - gcc/testsuite/rust.test/use-uninit-match.rs | 24 - gcc/testsuite/rust.test/use-uninit-match2.rs | 24 - gcc/testsuite/rust.test/use.rs | 28 - gcc/testsuite/rust.test/utf8.rs | 58 - gcc/testsuite/rust.test/utf8_chars.rs | 53 - gcc/testsuite/rust.test/utf8_idents.rs | 47 - gcc/testsuite/rust.test/variant-attributes.rs | 39 - gcc/testsuite/rust.test/variant-structs-trivial.rs | 18 - gcc/testsuite/rust.test/vec-concat.rs | 20 - gcc/testsuite/rust.test/vec-drop.rs | 20 - gcc/testsuite/rust.test/vec-fixed-length.rs | 14 - gcc/testsuite/rust.test/vec-growth.rs | 24 - gcc/testsuite/rust.test/vec-ivec-deadlock.rs | 17 - gcc/testsuite/rust.test/vec-late-init.rs | 17 - gcc/testsuite/rust.test/vec-matching-autoslice.rs | 22 - gcc/testsuite/rust.test/vec-matching-fixed.rs | 28 - gcc/testsuite/rust.test/vec-matching-fold.rs | 31 - .../vec-matching-legal-tail-element-borrow.rs | 10 - gcc/testsuite/rust.test/vec-matching.rs | 75 - gcc/testsuite/rust.test/vec-push.rs | 11 - gcc/testsuite/rust.test/vec-self-append.rs | 58 - gcc/testsuite/rust.test/vec-slice-drop.rs | 36 - gcc/testsuite/rust.test/vec-slice.rs | 16 - gcc/testsuite/rust.test/vec-tail-matching.rs | 35 - gcc/testsuite/rust.test/vec-to_str.rs | 24 - gcc/testsuite/rust.test/vec-trailing-comma.rs | 20 - gcc/testsuite/rust.test/vec.rs | 25 - gcc/testsuite/rust.test/vector-no-ann-2.rs | 11 - gcc/testsuite/rust.test/warn-ctypes-inhibit.rs | 23 - gcc/testsuite/rust.test/weird-exprs.rs | 85 - gcc/testsuite/rust.test/while-cont.rs | 20 - gcc/testsuite/rust.test/while-flow-graph.rs | 13 - .../rust.test/while-loop-constraints-2.rs | 24 - gcc/testsuite/rust.test/while-prelude-drop.rs | 30 - gcc/testsuite/rust.test/while-with-break.rs | 19 - gcc/testsuite/rust.test/while.rs | 22 - gcc/testsuite/rust.test/writealias.rs | 28 - gcc/testsuite/rust.test/x86stdcall.rs | 35 - gcc/testsuite/rust.test/x86stdcall2.rs | 44 - gcc/testsuite/rust.test/xc_conditions_client.rs | 40 - gcc/testsuite/rust.test/xc_conditions_client_2.rs | 21 - gcc/testsuite/rust.test/xc_conditions_client_3.rs | 38 - gcc/testsuite/rust.test/xc_conditions_client_4.rs | 32 - .../rust.test/xcrate-address-insignificant.rs | 18 - gcc/testsuite/rust.test/xcrate-static-addresses.rs | 28 - gcc/testsuite/rust.test/xcrate-unit-struct.rs | 33 - gcc/testsuite/rust.test/yield.rs | 28 - gcc/testsuite/rust.test/yield1.rs | 23 - gcc/testsuite/rust.test/yield2.rs | 17 - 1640 files changed, 39856 insertions(+), 199089 deletions(-) delete mode 100644 gcc/rust/TO_notes.txt create mode 100644 gcc/rust/ast/clone-test.h create mode 100644 gcc/rust/ast/rust-ast-containers.h create mode 100644 gcc/rust/ast/rust-ast-full-decls.h create mode 100644 gcc/rust/ast/rust-ast-full-test.cc create mode 100644 gcc/rust/ast/rust-ast-full.h create mode 100644 gcc/rust/ast/rust-ast-visitor.h create mode 100644 gcc/rust/ast/rust-ast.h create mode 100644 gcc/rust/ast/rust-cond-compilation.h create mode 100644 gcc/rust/ast/rust-expr.h create mode 100644 gcc/rust/ast/rust-item.h create mode 100644 gcc/rust/ast/rust-macro.h create mode 100644 gcc/rust/ast/rust-path.h create mode 100644 gcc/rust/ast/rust-pattern.h create mode 100644 gcc/rust/ast/rust-stmt.h create mode 100644 gcc/rust/ast/rust-type.h create mode 100644 gcc/rust/backend.h create mode 100644 gcc/rust/expand/rust-macro-expand.cc create mode 100644 gcc/rust/expand/rust-macro-expand.h create mode 100644 gcc/rust/lex/rust-codepoint.h create mode 100644 gcc/rust/lex/rust-lex.cc create mode 100644 gcc/rust/lex/rust-lex.h create mode 100644 gcc/rust/lex/rust-token.cc create mode 100644 gcc/rust/lex/rust-token.h delete mode 100644 gcc/rust/mrustc_parser/ast/ast.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/ast.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/attrs.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/crate.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/crate.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/dump.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/expr.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/expr.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/expr_ptr.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/generics.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/item.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/macro.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/path.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/path.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/pattern.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/pattern.hpp delete mode 100644 gcc/rust/mrustc_parser/ast/types.cpp delete mode 100644 gcc/rust/mrustc_parser/ast/types.hpp delete mode 100644 gcc/rust/mrustc_parser/gcc-interface-test/gcc-interface.cc delete mode 100644 gcc/rust/mrustc_parser/gcc-interface-test/rust-c-interface.h delete mode 100644 gcc/rust/mrustc_parser/parse/common.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/eTokenType.enum.h delete mode 100644 gcc/rust/mrustc_parser/parse/expr.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/interpolated_fragment.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/interpolated_fragment.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/lex.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/lex.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/parseerror.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/parseerror.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/paths.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/pattern.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/root.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/token.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/token.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/tokenstream.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/tokenstream.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/tokentree.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/tokentree.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/ttstream.cpp delete mode 100644 gcc/rust/mrustc_parser/parse/ttstream.hpp delete mode 100644 gcc/rust/mrustc_parser/parse/types.cpp delete mode 100644 gcc/rust/old/lang-specs.h delete mode 100644 gcc/rust/old/rdot-dataflow.cc delete mode 100644 gcc/rust/old/rdot-generic-compiler.cc delete mode 100644 gcc/rust/old/rdot-impl.cc delete mode 100644 gcc/rust/old/rdot-impl.h delete mode 100644 gcc/rust/old/rdot-pretty-print.cc delete mode 100644 gcc/rust/old/rs-lang.c delete mode 100644 gcc/rust/old/rs-lexer.l delete mode 100644 gcc/rust/old/rs-parser.cc delete mode 100644 gcc/rust/old/rs-pass-manager.cc delete mode 100644 gcc/rust/old/rs-runtime-hooks.cc delete mode 100644 gcc/rust/old/rsspec.cc delete mode 100644 gcc/rust/old/rust.h delete mode 100644 gcc/rust/old/y.rs.h create mode 100644 gcc/rust/operator.h create mode 100644 gcc/rust/parse/rust-parse-includes.h create mode 100644 gcc/rust/parse/rust-parse.cc create mode 100644 gcc/rust/parse/rust-parse.h create mode 100644 gcc/rust/parse/rust-scope.cc create mode 100644 gcc/rust/parse/rust-scope.h create mode 100644 gcc/rust/parse/rust-symbol.h create mode 100644 gcc/rust/parse/rust-tree.h create mode 100644 gcc/rust/rust-buffered-queue.h delete mode 100644 gcc/rust/rust-c.h delete mode 100644 gcc/rust/rust-lang.c create mode 100644 gcc/rust/rust-lang.cc create mode 100644 gcc/rust/rust-object-export.c create mode 100644 gcc/rust/rust-object-export.h create mode 100644 gcc/rust/rust-session-manager.cc create mode 100644 gcc/rust/rust-session-manager.h delete mode 100644 gcc/rust/rustc_parser/RustCNotes.txt delete mode 100644 gcc/rust/rustc_parser/grammar/.gitignore delete mode 100644 gcc/rust/rustc_parser/grammar/lexer.l delete mode 100644 gcc/rust/rustc_parser/grammar/parser-lalr-main.c delete mode 100644 gcc/rust/rustc_parser/grammar/parser-lalr.y delete mode 100644 gcc/rust/rustc_parser/grammar/raw-string-literal-ambiguity.md delete mode 100755 gcc/rust/rustc_parser/grammar/testparser.py delete mode 100644 gcc/rust/rustc_parser/grammar/tokens.h delete mode 100644 gcc/rust/rustc_parser/libsyntax/Cargo.toml delete mode 100644 gcc/rust/rustc_parser/libsyntax/README.md delete mode 100644 gcc/rust/rustc_parser/libsyntax/ast.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/attr/builtin.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/attr/mod.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/build.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/config.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/diagnostics/macros.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/diagnostics/metadata.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/diagnostics/plugin.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/early_buffered_lints.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/entry.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/error_codes.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/base.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/build.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/derive.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/expand.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/placeholders.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/source_util.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/tt/macro_parser.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/tt/macro_rules.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/tt/quoted.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ext/tt/transcribe.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/feature_gate.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/json.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/lib.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/mut_visit.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/attr.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/classify.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/diagnostics.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/lexer/comments.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/lexer/mod.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/lexer/tokentrees.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/lexer/unicode_chars.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/literal.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/mod.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/parser.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/token.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/unescape.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/parse/unescape_error_reporting.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/print/pp.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/print/pprust.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/ptr.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/show_span.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/source_map.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/std_inject.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/test.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/test_snippet.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/tokenstream.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/util/lev_distance.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/util/map_in_place.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/util/node_count.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/util/parser.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/util/parser_testing.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax/visit.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/Cargo.toml delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/asm.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/assert.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/cfg.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/compile_error.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/concat.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/concat_idents.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/bounds.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/clone.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/eq.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/ord.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_eq.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_ord.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/custom.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/debug.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/decodable.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/default.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/encodable.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/mod.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/ty.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/hash.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/deriving/mod.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/env.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/error_codes.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/format.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/format_foreign.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/format_foreign/printf/tests.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/format_foreign/shell/tests.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/global_asm.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/lib.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/log_syntax.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/proc_macro_decls.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/proc_macro_impl.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/proc_macro_server.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/test.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/test_case.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_ext/trace_macros.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/Cargo.toml delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/analyze_source_file.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/edition.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/hygiene.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/lib.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/span_encoding.rs delete mode 100644 gcc/rust/rustc_parser/libsyntax_pos/symbol.rs delete mode 100644 gcc/rust/rustfrontend/backend.h delete mode 100644 gcc/rust/rustfrontend/main.cc delete mode 100644 gcc/rust/rustfrontend/node.cc delete mode 100644 gcc/rust/rustfrontend/node.h delete mode 100644 gcc/rust/rustfrontend/operator.h delete mode 100644 gcc/rust/rustfrontend/rs-lexer.l delete mode 100644 gcc/rust/rustfrontend/rs-parser.y delete mode 100644 gcc/rust/rustfrontend/rustly.cc delete mode 100644 gcc/rust/rustfrontend/rustly.h delete mode 100644 gcc/rust/test/rustc_bison_test/lex.yy.c delete mode 100644 gcc/rust/test/rustc_bison_test/lex.yy.cc delete mode 100644 gcc/rust/test/rustc_bison_test/lexer.l delete mode 100644 gcc/rust/test/rustc_bison_test/parser-interface.c delete mode 100644 gcc/rust/test/rustc_bison_test/parser-lalr.y delete mode 100644 gcc/rust/test/rustc_bison_test/parser.tab.c delete mode 100644 gcc/rust/test/rustc_bison_test/token.h delete mode 100644 gcc/rust/test/test1..s delete mode 100644 gcc/rust/test/test1.rs delete mode 100644 gcc/rust/test/test1.s delete mode 100644 gcc/rust/test/test2-minimal.rs delete mode 100644 gcc/rust/test/test2.rs delete mode 100644 gcc/rust/test/test2.s delete mode 100644 gcc/rust/test/test_jit.c delete mode 100644 gcc/rust/test2/rust-c.h delete mode 100644 gcc/rust/test2/rust-lang.c delete mode 100644 gcc/rust/test2/rustfrontend/eTokenType.enum.h delete mode 100644 gcc/rust/test2/rustfrontend/rs-generic-converter.cc delete mode 100644 gcc/rust/test2/rustfrontend/rs-lex.cc delete mode 100644 gcc/rust/test2/rustfrontend/rs-lex.h delete mode 100644 gcc/rust/test2/rustfrontend/rs-token.h delete mode 100644 gcc/rust/test2/rustfrontend/rust.cc delete mode 100644 gcc/rust/test3-tiny/Make-lang.in delete mode 100644 gcc/rust/test3-tiny/config-lang.in delete mode 100644 gcc/rust/test3-tiny/lang-specs.h delete mode 100644 gcc/rust/test3-tiny/lex/rust-lex.cc delete mode 100644 gcc/rust/test3-tiny/lex/rust-lex.h delete mode 100644 gcc/rust/test3-tiny/lex/rust-token.cc delete mode 100644 gcc/rust/test3-tiny/lex/rust-token.h delete mode 100644 gcc/rust/test3-tiny/parse/rust-misc-convert.cc delete mode 100644 gcc/rust/test3-tiny/parse/rust-parse.cc delete mode 100644 gcc/rust/test3-tiny/parse/rust-parse.h delete mode 100644 gcc/rust/test3-tiny/parse/rust-scope.cc delete mode 100644 gcc/rust/test3-tiny/parse/rust-scope.h delete mode 100644 gcc/rust/test3-tiny/parse/rust-tree.h delete mode 100644 gcc/rust/test3-tiny/rsspec.cc delete mode 100644 gcc/rust/test3-tiny/rust-buffered-queue.h delete mode 100644 gcc/rust/test3-tiny/rust-lang.cc delete mode 100644 gcc/rust/test3/Make-lang.in delete mode 100644 gcc/rust/test3/ast/clone-test.h delete mode 100644 gcc/rust/test3/ast/rust-ast-containers.h delete mode 100644 gcc/rust/test3/ast/rust-ast-full-decls.h delete mode 100644 gcc/rust/test3/ast/rust-ast-full-test.cc delete mode 100644 gcc/rust/test3/ast/rust-ast-full.h delete mode 100644 gcc/rust/test3/ast/rust-ast-visitor.h delete mode 100644 gcc/rust/test3/ast/rust-ast.h delete mode 100644 gcc/rust/test3/ast/rust-cond-compilation.h delete mode 100644 gcc/rust/test3/ast/rust-expr.h delete mode 100644 gcc/rust/test3/ast/rust-item.h delete mode 100644 gcc/rust/test3/ast/rust-macro.h delete mode 100644 gcc/rust/test3/ast/rust-path.h delete mode 100644 gcc/rust/test3/ast/rust-pattern.h delete mode 100644 gcc/rust/test3/ast/rust-stmt.h delete mode 100644 gcc/rust/test3/ast/rust-type.h delete mode 100644 gcc/rust/test3/config-lang.in delete mode 100644 gcc/rust/test3/expand/rust-macro-expand.cc delete mode 100644 gcc/rust/test3/expand/rust-macro-expand.h delete mode 100644 gcc/rust/test3/lang-specs.h delete mode 100644 gcc/rust/test3/lang.opt delete mode 100644 gcc/rust/test3/lex/rust-codepoint.h delete mode 100644 gcc/rust/test3/lex/rust-lex.cc delete mode 100644 gcc/rust/test3/lex/rust-lex.h delete mode 100644 gcc/rust/test3/lex/rust-token.cc delete mode 100644 gcc/rust/test3/lex/rust-token.h delete mode 100644 gcc/rust/test3/parse/rust-misc-convert.cc delete mode 100644 gcc/rust/test3/parse/rust-parse-includes.h delete mode 100644 gcc/rust/test3/parse/rust-parse.cc delete mode 100644 gcc/rust/test3/parse/rust-parse.h delete mode 100644 gcc/rust/test3/parse/rust-scope.cc delete mode 100644 gcc/rust/test3/parse/rust-scope.h delete mode 100644 gcc/rust/test3/parse/rust-symbol.h delete mode 100644 gcc/rust/test3/parse/rust-tree.h delete mode 100644 gcc/rust/test3/rsspec.cc delete mode 100644 gcc/rust/test3/rust-buffered-queue.h delete mode 100644 gcc/rust/test3/rust-lang.cc delete mode 100644 gcc/rust/test3/rust-session-manager.cc delete mode 100644 gcc/rust/test3/rust-session-manager.h delete mode 100644 gcc/testsuite/rust.test/alias-uninit-value.rs delete mode 100644 gcc/testsuite/rust.test/alignment-gep-tup-like-1.rs delete mode 100644 gcc/testsuite/rust.test/alignment-gep-tup-like-2.rs delete mode 100644 gcc/testsuite/rust.test/alloca-from-derived-tydesc.rs delete mode 100644 gcc/testsuite/rust.test/anon-extern-mod-cross-crate-2.rs delete mode 100644 gcc/testsuite/rust.test/anon-extern-mod.rs delete mode 100644 gcc/testsuite/rust.test/anon-trait-static-method.rs delete mode 100644 gcc/testsuite/rust.test/anon_trait_static_method_exe.rs delete mode 100644 gcc/testsuite/rust.test/argument-passing.rs delete mode 100644 gcc/testsuite/rust.test/arith-0.rs delete mode 100644 gcc/testsuite/rust.test/arith-1.rs delete mode 100644 gcc/testsuite/rust.test/arith-2.rs delete mode 100644 gcc/testsuite/rust.test/arith-unsigned.rs delete mode 100644 gcc/testsuite/rust.test/artificial-block.rs delete mode 100644 gcc/testsuite/rust.test/asm-out-assign.rs delete mode 100644 gcc/testsuite/rust.test/assert-approx-eq-macro-success.rs delete mode 100644 gcc/testsuite/rust.test/assert-eq-macro-success.rs delete mode 100644 gcc/testsuite/rust.test/assign-assign.rs delete mode 100644 gcc/testsuite/rust.test/assignability-trait.rs delete mode 100644 gcc/testsuite/rust.test/attr-before-view-item.rs delete mode 100644 gcc/testsuite/rust.test/attr-before-view-item2.rs delete mode 100644 gcc/testsuite/rust.test/attr-main-2.rs delete mode 100644 gcc/testsuite/rust.test/attr-main.rs delete mode 100644 gcc/testsuite/rust.test/attr-no-drop-flag-size.rs delete mode 100644 gcc/testsuite/rust.test/attr-start.rs delete mode 100644 gcc/testsuite/rust.test/auto-encode.rs delete mode 100644 gcc/testsuite/rust.test/auto-instantiate.rs delete mode 100644 gcc/testsuite/rust.test/auto-loop.rs delete mode 100644 gcc/testsuite/rust.test/auto-ref-bounded-ty-param.rs delete mode 100644 gcc/testsuite/rust.test/auto-ref-newtype.rs delete mode 100644 gcc/testsuite/rust.test/auto-ref-slice-plus-ref.rs delete mode 100644 gcc/testsuite/rust.test/auto-ref-sliceable.rs delete mode 100644 gcc/testsuite/rust.test/auto-ref.rs delete mode 100644 gcc/testsuite/rust.test/autobind.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-and-borrow-method-receiver.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method-newtype.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method-on-trait.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method-priority.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method-twice-but-not-thrice.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method-twice.rs delete mode 100644 gcc/testsuite/rust.test/autoderef-method.rs delete mode 100644 gcc/testsuite/rust.test/autoref-intermediate-types-issue-3585.rs delete mode 100644 gcc/testsuite/rust.test/bare-static-string.rs delete mode 100644 gcc/testsuite/rust.test/big-literals.rs delete mode 100644 gcc/testsuite/rust.test/binary-minus-without-space.rs delete mode 100644 gcc/testsuite/rust.test/bind-by-move.rs delete mode 100644 gcc/testsuite/rust.test/binops.rs delete mode 100644 gcc/testsuite/rust.test/bitv-perf-test.rs delete mode 100644 gcc/testsuite/rust.test/bitwise.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-call-as.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-can-be-followed-by-binop.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-can-be-followed-by-block-arg.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-can-be-followed-by-call.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-in-parentheses.rs delete mode 100644 gcc/testsuite/rust.test/block-arg-used-as-any.rs delete mode 100644 gcc/testsuite/rust.test/block-arg.rs delete mode 100644 gcc/testsuite/rust.test/block-explicit-types.rs delete mode 100644 gcc/testsuite/rust.test/block-expr-precedence.rs delete mode 100644 gcc/testsuite/rust.test/block-fn-coerce.rs delete mode 100644 gcc/testsuite/rust.test/block-iter-1.rs delete mode 100644 gcc/testsuite/rust.test/block-iter-2.rs delete mode 100644 gcc/testsuite/rust.test/bool-not.rs delete mode 100644 gcc/testsuite/rust.test/borrow-by-val-method-receiver.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-binding-mutbl.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-borrow-from-at-vec.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-borrow-from-expr-block.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-fixed-length-vecs.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-lend-args.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-macro-interaction-issue-6304.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-move-by-capture-ok.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-mut-uniq.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-mut-vec-as-imm-slice.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-nested-calls.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-pat-enum.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-pat-reassign-no-binding.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-in-arm-not-taken.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-in-discr.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-in-field.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-in-pat.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-in-uniq.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box-sometimes-needed.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-box.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-cond-box.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-preserve-expl-deref.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-root-while-cond-2.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-root-while-cond.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-rvalues-mutable.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-scope-of-deref-issue-4666.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-static-item-in-fn.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-unary-move-2.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-uniq-via-ref.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-univariant-enum.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-2.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-3.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-simple.rs delete mode 100644 gcc/testsuite/rust.test/borrowck-wg-two-imm-borrows.rs delete mode 100644 gcc/testsuite/rust.test/borrowed-ptr-pattern-2.rs delete mode 100644 gcc/testsuite/rust.test/borrowed-ptr-pattern-3.rs delete mode 100644 gcc/testsuite/rust.test/borrowed-ptr-pattern-infallible.rs delete mode 100644 gcc/testsuite/rust.test/borrowed-ptr-pattern-option.rs delete mode 100644 gcc/testsuite/rust.test/borrowed-ptr-pattern.rs delete mode 100644 gcc/testsuite/rust.test/box-compare.rs delete mode 100644 gcc/testsuite/rust.test/box-in-tup.rs delete mode 100644 gcc/testsuite/rust.test/box-inside-if.rs delete mode 100644 gcc/testsuite/rust.test/box-inside-if2.rs delete mode 100644 gcc/testsuite/rust.test/box-pattern.rs delete mode 100644 gcc/testsuite/rust.test/box-unbox.rs delete mode 100644 gcc/testsuite/rust.test/box.rs delete mode 100644 gcc/testsuite/rust.test/boxed-class-type-substitution.rs delete mode 100644 gcc/testsuite/rust.test/boxed-trait-with-vstore.rs delete mode 100644 gcc/testsuite/rust.test/break-value.rs delete mode 100644 gcc/testsuite/rust.test/break.rs delete mode 100644 gcc/testsuite/rust.test/bug-7183-generics.rs delete mode 100644 gcc/testsuite/rust.test/bug-7295.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-capabilities-transitive.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-capabilities-xc.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-capabilities.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-in-metadata.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-phantom-typaram.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-self-type.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-simple.rs delete mode 100644 gcc/testsuite/rust.test/builtin-superkinds-typaram.rs delete mode 100644 gcc/testsuite/rust.test/c-stack-as-value.rs delete mode 100644 gcc/testsuite/rust.test/c-stack-returning-int64.rs delete mode 100644 gcc/testsuite/rust.test/call-closure-from-overloaded-op.rs delete mode 100644 gcc/testsuite/rust.test/cancel-clean-via-immediate-rvalue-ref.rs delete mode 100644 gcc/testsuite/rust.test/cap-clause-move.rs delete mode 100644 gcc/testsuite/rust.test/capture_nil.rs delete mode 100644 gcc/testsuite/rust.test/cast-mutable-trait.rs delete mode 100644 gcc/testsuite/rust.test/cast-region-to-uint.rs delete mode 100644 gcc/testsuite/rust.test/cast.rs delete mode 100644 gcc/testsuite/rust.test/cci_borrow.rs delete mode 100644 gcc/testsuite/rust.test/cci_capture_clause.rs delete mode 100644 gcc/testsuite/rust.test/cci_impl_exe.rs delete mode 100644 gcc/testsuite/rust.test/cci_iter_exe.rs delete mode 100644 gcc/testsuite/rust.test/cci_nested_exe.rs delete mode 100644 gcc/testsuite/rust.test/cci_no_inline_exe.rs delete mode 100644 gcc/testsuite/rust.test/cfg-family.rs delete mode 100644 gcc/testsuite/rust.test/cfg-macros-foo.rs delete mode 100644 gcc/testsuite/rust.test/cfg-macros-notfoo.rs delete mode 100644 gcc/testsuite/rust.test/cfg-target-family.rs delete mode 100644 gcc/testsuite/rust.test/cfg_inner_static.rs delete mode 100644 gcc/testsuite/rust.test/cfgs-on-items.rs delete mode 100644 gcc/testsuite/rust.test/char.rs delete mode 100644 gcc/testsuite/rust.test/child-outlives-parent.rs delete mode 100644 gcc/testsuite/rust.test/class-attributes-1.rs delete mode 100644 gcc/testsuite/rust.test/class-attributes-2.rs delete mode 100644 gcc/testsuite/rust.test/class-cast-to-trait-cross-crate-2.rs delete mode 100644 gcc/testsuite/rust.test/class-cast-to-trait-multiple-types.rs delete mode 100644 gcc/testsuite/rust.test/class-cast-to-trait.rs delete mode 100644 gcc/testsuite/rust.test/class-dtor.rs delete mode 100644 gcc/testsuite/rust.test/class-exports.rs delete mode 100644 gcc/testsuite/rust.test/class-impl-very-parameterized-trait.rs delete mode 100644 gcc/testsuite/rust.test/class-implement-trait-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/class-implement-traits.rs delete mode 100644 gcc/testsuite/rust.test/class-method-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/class-methods-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/class-methods.rs delete mode 100644 gcc/testsuite/rust.test/class-poly-methods-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/class-poly-methods.rs delete mode 100644 gcc/testsuite/rust.test/class-separate-impl.rs delete mode 100644 gcc/testsuite/rust.test/class-str-field.rs delete mode 100644 gcc/testsuite/rust.test/class-typarams.rs delete mode 100644 gcc/testsuite/rust.test/classes-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/classes-self-referential.rs delete mode 100644 gcc/testsuite/rust.test/classes-simple-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/classes-simple-method.rs delete mode 100644 gcc/testsuite/rust.test/classes-simple.rs delete mode 100644 gcc/testsuite/rust.test/classes.rs delete mode 100644 gcc/testsuite/rust.test/cleanup-copy-mode.rs delete mode 100644 gcc/testsuite/rust.test/clone-with-exterior.rs delete mode 100644 gcc/testsuite/rust.test/close-over-big-then-small-data.rs delete mode 100644 gcc/testsuite/rust.test/closure-bounds-can-capture-chan.rs delete mode 100644 gcc/testsuite/rust.test/closure-inference.rs delete mode 100644 gcc/testsuite/rust.test/closure-inference2.rs delete mode 100644 gcc/testsuite/rust.test/cmp-default.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-arg.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-rcvr.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-imm-vec-arg.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-imm-vec-rcvr.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-arg.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-rcvr.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-mut-vec-arg.rs delete mode 100644 gcc/testsuite/rust.test/coerce-reborrow-mut-vec-rcvr.rs delete mode 100644 gcc/testsuite/rust.test/coherence-impl-in-fn.rs delete mode 100644 gcc/testsuite/rust.test/comm.rs delete mode 100644 gcc/testsuite/rust.test/compare-generic-enums.rs delete mode 100644 gcc/testsuite/rust.test/complex.rs delete mode 100644 gcc/testsuite/rust.test/conditional-compile-arch.rs delete mode 100644 gcc/testsuite/rust.test/conditional-compile.rs delete mode 100644 gcc/testsuite/rust.test/conditional-debug-macro-off.rs delete mode 100644 gcc/testsuite/rust.test/conditional-debug-macro-on.rs delete mode 100644 gcc/testsuite/rust.test/const-autoderef-newtype.rs delete mode 100644 gcc/testsuite/rust.test/const-autoderef.rs delete mode 100644 gcc/testsuite/rust.test/const-big-enum.rs delete mode 100644 gcc/testsuite/rust.test/const-binops.rs delete mode 100644 gcc/testsuite/rust.test/const-bound.rs delete mode 100644 gcc/testsuite/rust.test/const-cast-ptr-int.rs delete mode 100644 gcc/testsuite/rust.test/const-cast.rs delete mode 100644 gcc/testsuite/rust.test/const-const.rs delete mode 100644 gcc/testsuite/rust.test/const-contents.rs delete mode 100644 gcc/testsuite/rust.test/const-cross-crate-const.rs delete mode 100644 gcc/testsuite/rust.test/const-cross-crate-extern.rs delete mode 100644 gcc/testsuite/rust.test/const-deref.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-byref-self.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-byref.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-cast.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-ptr.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-struct.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-struct2.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-structlike.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-tuple.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-tuple2.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-tuplestruct.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-tuplestruct2.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-vec-index.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-vec-ptr.rs delete mode 100644 gcc/testsuite/rust.test/const-enum-vector.rs delete mode 100644 gcc/testsuite/rust.test/const-expr-in-fixed-length-vec.rs delete mode 100644 gcc/testsuite/rust.test/const-expr-in-vec-repeat.rs delete mode 100644 gcc/testsuite/rust.test/const-extern-function.rs delete mode 100644 gcc/testsuite/rust.test/const-fields-and-indexing.rs delete mode 100644 gcc/testsuite/rust.test/const-fn-val.rs delete mode 100644 gcc/testsuite/rust.test/const-negative.rs delete mode 100644 gcc/testsuite/rust.test/const-nullary-enum.rs delete mode 100644 gcc/testsuite/rust.test/const-nullary-univariant-enum.rs delete mode 100644 gcc/testsuite/rust.test/const-rec-and-tup.rs delete mode 100644 gcc/testsuite/rust.test/const-region-ptrs-noncopy.rs delete mode 100644 gcc/testsuite/rust.test/const-region-ptrs.rs delete mode 100644 gcc/testsuite/rust.test/const-str-ptr.rs delete mode 100644 gcc/testsuite/rust.test/const-struct-offsets.rs delete mode 100644 gcc/testsuite/rust.test/const-struct.rs delete mode 100644 gcc/testsuite/rust.test/const-tuple-struct.rs delete mode 100644 gcc/testsuite/rust.test/const-unit-struct.rs delete mode 100644 gcc/testsuite/rust.test/const-vec-of-fns.rs delete mode 100644 gcc/testsuite/rust.test/const-vec-syntax.rs delete mode 100644 gcc/testsuite/rust.test/const-vecs-and-slices.rs delete mode 100644 gcc/testsuite/rust.test/const.rs delete mode 100644 gcc/testsuite/rust.test/consts-in-patterns.rs delete mode 100644 gcc/testsuite/rust.test/core-rt-smoke.rs delete mode 100644 gcc/testsuite/rust.test/core-run-destroy.rs delete mode 100644 gcc/testsuite/rust.test/crate-method-reexport-grrrrrrr.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve1.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve2.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve3.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve4.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve5.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve6.rs delete mode 100644 gcc/testsuite/rust.test/crateresolve7.rs delete mode 100644 gcc/testsuite/rust.test/cross-crate-const-pat.rs delete mode 100644 gcc/testsuite/rust.test/cross-crate-newtype-struct-pat.rs delete mode 100644 gcc/testsuite/rust.test/cycle-collection.rs delete mode 100644 gcc/testsuite/rust.test/cycle-collection2.rs delete mode 100644 gcc/testsuite/rust.test/dead-code-one-arm-if.rs delete mode 100644 gcc/testsuite/rust.test/deep-vector.rs delete mode 100644 gcc/testsuite/rust.test/deep-vector2.rs delete mode 100644 gcc/testsuite/rust.test/deep.rs delete mode 100644 gcc/testsuite/rust.test/default-method-parsing.rs delete mode 100644 gcc/testsuite/rust.test/default-method-simple.rs delete mode 100644 gcc/testsuite/rust.test/default-method-supertrait-vtable.rs delete mode 100644 gcc/testsuite/rust.test/deref-lval.rs delete mode 100644 gcc/testsuite/rust.test/deref.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-generic-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-generic-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-generic-tuple-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-clone-tuple-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-cmp-generic-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-cmp-generic-struct-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-cmp-generic-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-cmp-generic-tuple-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-cmp-shortcircuit.rs delete mode 100644 gcc/testsuite/rust.test/deriving-encodable-decodable.rs delete mode 100644 gcc/testsuite/rust.test/deriving-enum-single-variant.rs delete mode 100644 gcc/testsuite/rust.test/deriving-global.rs delete mode 100644 gcc/testsuite/rust.test/deriving-meta-empty-trait-list.rs delete mode 100644 gcc/testsuite/rust.test/deriving-meta-multiple.rs delete mode 100644 gcc/testsuite/rust.test/deriving-meta.rs delete mode 100644 gcc/testsuite/rust.test/deriving-primitive.rs delete mode 100644 gcc/testsuite/rust.test/deriving-rand.rs delete mode 100644 gcc/testsuite/rust.test/deriving-self-lifetime-totalord-totaleq.rs delete mode 100644 gcc/testsuite/rust.test/deriving-self-lifetime.rs delete mode 100644 gcc/testsuite/rust.test/deriving-to-str.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-c-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-enum.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-struct-empty.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-struct-like-enum-variant.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-struct-tuple.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-struct.rs delete mode 100644 gcc/testsuite/rust.test/deriving-via-extension-type-params.rs delete mode 100644 gcc/testsuite/rust.test/deriving-zero.rs delete mode 100644 gcc/testsuite/rust.test/die-macro.rs delete mode 100644 gcc/testsuite/rust.test/div-mod.rs delete mode 100644 gcc/testsuite/rust.test/do-empty-args.rs delete mode 100644 gcc/testsuite/rust.test/do-no-args.rs delete mode 100644 gcc/testsuite/rust.test/do-pure.rs delete mode 100644 gcc/testsuite/rust.test/do-stack.rs delete mode 100644 gcc/testsuite/rust.test/do1.rs delete mode 100644 gcc/testsuite/rust.test/do2.rs delete mode 100644 gcc/testsuite/rust.test/do3.rs delete mode 100644 gcc/testsuite/rust.test/double-unbox.rs delete mode 100644 gcc/testsuite/rust.test/drop-on-empty-block-exit.rs delete mode 100644 gcc/testsuite/rust.test/drop-on-ret.rs delete mode 100644 gcc/testsuite/rust.test/drop-trait-generic.rs delete mode 100644 gcc/testsuite/rust.test/drop-trait.rs delete mode 100644 gcc/testsuite/rust.test/duplicate-use.rs delete mode 100644 gcc/testsuite/rust.test/early-ret-binop-add.rs delete mode 100644 gcc/testsuite/rust.test/early-vtbl-resolution.rs delete mode 100644 gcc/testsuite/rust.test/else-if.rs delete mode 100644 gcc/testsuite/rust.test/empty-mutable-vec.rs delete mode 100644 gcc/testsuite/rust.test/empty-tag.rs delete mode 100644 gcc/testsuite/rust.test/enum-alignment.rs delete mode 100644 gcc/testsuite/rust.test/enum-discr.rs delete mode 100644 gcc/testsuite/rust.test/enum-discrim-range-overflow.rs delete mode 100644 gcc/testsuite/rust.test/enum-discrim-width-stuff.rs delete mode 100644 gcc/testsuite/rust.test/enum-disr-val-pretty.rs delete mode 100644 gcc/testsuite/rust.test/enum-export-inheritance.rs delete mode 100644 gcc/testsuite/rust.test/enum-nullable-simplifycfg-misopt.rs delete mode 100644 gcc/testsuite/rust.test/enum-variants.rs delete mode 100644 gcc/testsuite/rust.test/enum-vec-initializer.rs delete mode 100644 gcc/testsuite/rust.test/estr-shared.rs delete mode 100644 gcc/testsuite/rust.test/estr-slice.rs delete mode 100644 gcc/testsuite/rust.test/estr-uniq.rs delete mode 100644 gcc/testsuite/rust.test/evec-internal-boxes.rs delete mode 100644 gcc/testsuite/rust.test/evec-internal.rs delete mode 100644 gcc/testsuite/rust.test/evec-slice.rs delete mode 100644 gcc/testsuite/rust.test/exec-env.rs delete mode 100644 gcc/testsuite/rust.test/explicit-i-suffix.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self-closures.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self-generic.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self-objects-box.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self-objects-simple.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self-objects-uniq.rs delete mode 100644 gcc/testsuite/rust.test/explicit-self.rs delete mode 100644 gcc/testsuite/rust.test/explicit_self_xcrate_exe.rs delete mode 100644 gcc/testsuite/rust.test/export-abstract-tag.rs delete mode 100644 gcc/testsuite/rust.test/export-glob-imports-target.rs delete mode 100644 gcc/testsuite/rust.test/export-multi.rs delete mode 100644 gcc/testsuite/rust.test/export-non-interference.rs delete mode 100644 gcc/testsuite/rust.test/export-non-interference2.rs delete mode 100644 gcc/testsuite/rust.test/export-non-interference3.rs delete mode 100644 gcc/testsuite/rust.test/export-tag-variant.rs delete mode 100644 gcc/testsuite/rust.test/export-unexported-dep.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-box.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-fn.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-generic-box1.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-generic-box2.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-generic-unique1.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-generic-unique2.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-generic.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-ref.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-slot.rs delete mode 100644 gcc/testsuite/rust.test/expr-block-unique.rs delete mode 100644 gcc/testsuite/rust.test/expr-block.rs delete mode 100644 gcc/testsuite/rust.test/expr-copy.rs delete mode 100644 gcc/testsuite/rust.test/expr-elseif-ref.rs delete mode 100644 gcc/testsuite/rust.test/expr-elseif-ref2.rs delete mode 100644 gcc/testsuite/rust.test/expr-empty-ret.rs delete mode 100644 gcc/testsuite/rust.test/expr-fn.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-box.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-fail-all.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-fail.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-generic-box1.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-generic-box2.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-generic.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-struct.rs delete mode 100644 gcc/testsuite/rust.test/expr-if-unique.rs delete mode 100644 gcc/testsuite/rust.test/expr-if.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-box.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-fail-all.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-fail.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-generic-box1.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-generic-box2.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-generic-unique1.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-generic-unique2.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-generic.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-struct.rs delete mode 100644 gcc/testsuite/rust.test/expr-match-unique.rs delete mode 100644 gcc/testsuite/rust.test/expr-match.rs delete mode 100644 gcc/testsuite/rust.test/expr-repeat-vstore.rs delete mode 100644 gcc/testsuite/rust.test/expr-scope.rs delete mode 100644 gcc/testsuite/rust.test/exterior.rs delete mode 100644 gcc/testsuite/rust.test/extern-1.rs delete mode 100644 gcc/testsuite/rust.test/extern-call-deep.rs delete mode 100644 gcc/testsuite/rust.test/extern-call-deep2.rs delete mode 100644 gcc/testsuite/rust.test/extern-call-direct.rs delete mode 100644 gcc/testsuite/rust.test/extern-call-indirect.rs delete mode 100644 gcc/testsuite/rust.test/extern-call-scrub.rs delete mode 100644 gcc/testsuite/rust.test/extern-compare-with-return-type.rs delete mode 100644 gcc/testsuite/rust.test/extern-crosscrate.rs delete mode 100644 gcc/testsuite/rust.test/extern-mod-abi.rs delete mode 100644 gcc/testsuite/rust.test/extern-mod-ordering-exe.rs delete mode 100644 gcc/testsuite/rust.test/extern-mod-syntax.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-TwoU16s.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-TwoU32s.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-TwoU64s-ref.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-TwoU64s.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-TwoU8s.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-char.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-double.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-u32.rs delete mode 100644 gcc/testsuite/rust.test/extern-pass-u64.rs delete mode 100644 gcc/testsuite/rust.test/extern-pub.rs delete mode 100644 gcc/testsuite/rust.test/extern-return-TwoU16s.rs delete mode 100644 gcc/testsuite/rust.test/extern-return-TwoU32s.rs delete mode 100644 gcc/testsuite/rust.test/extern-return-TwoU64s.rs delete mode 100644 gcc/testsuite/rust.test/extern-return-TwoU8s.rs delete mode 100644 gcc/testsuite/rust.test/extern-stress.rs delete mode 100644 gcc/testsuite/rust.test/extern-take-value.rs delete mode 100644 gcc/testsuite/rust.test/extern-yield.rs delete mode 100644 gcc/testsuite/rust.test/extoption_env-not-defined.rs delete mode 100644 gcc/testsuite/rust.test/fact.rs delete mode 100644 gcc/testsuite/rust.test/fat-arrow-match.rs delete mode 100644 gcc/testsuite/rust.test/filter-block-view-items.rs delete mode 100644 gcc/testsuite/rust.test/fixed_length_copy.rs delete mode 100644 gcc/testsuite/rust.test/fixed_length_vec_glue.rs delete mode 100644 gcc/testsuite/rust.test/float-literal-inference.rs delete mode 100644 gcc/testsuite/rust.test/float-nan.rs delete mode 100644 gcc/testsuite/rust.test/float-signature.rs delete mode 100644 gcc/testsuite/rust.test/float.rs delete mode 100644 gcc/testsuite/rust.test/float2.rs delete mode 100644 gcc/testsuite/rust.test/floatlits.rs delete mode 100644 gcc/testsuite/rust.test/fn-bare-assign.rs delete mode 100644 gcc/testsuite/rust.test/fn-bare-coerce-to-block.rs delete mode 100644 gcc/testsuite/rust.test/fn-bare-item.rs delete mode 100644 gcc/testsuite/rust.test/fn-bare-size.rs delete mode 100644 gcc/testsuite/rust.test/fn-bare-spawn.rs delete mode 100644 gcc/testsuite/rust.test/fn-coerce-field.rs delete mode 100644 gcc/testsuite/rust.test/fn-lval.rs delete mode 100644 gcc/testsuite/rust.test/fn-pattern-expected-type-2.rs delete mode 100644 gcc/testsuite/rust.test/fn-pattern-expected-type.rs delete mode 100644 gcc/testsuite/rust.test/fn-type-infer.rs delete mode 100644 gcc/testsuite/rust.test/for-destruct.rs delete mode 100644 gcc/testsuite/rust.test/for-loop-fail.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators-break.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators-hashmap-break-restart.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators-hashmap.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators-loop.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators-nested.rs delete mode 100644 gcc/testsuite/rust.test/foreach-external-iterators.rs delete mode 100644 gcc/testsuite/rust.test/foreach-nested.rs delete mode 100644 gcc/testsuite/rust.test/foreach-put-structured.rs delete mode 100644 gcc/testsuite/rust.test/foreach-simple-outer-slot.rs delete mode 100644 gcc/testsuite/rust.test/foreign-call-no-runtime.rs delete mode 100644 gcc/testsuite/rust.test/foreign-dupe.rs delete mode 100644 gcc/testsuite/rust.test/foreign-fn-linkname.rs delete mode 100644 gcc/testsuite/rust.test/foreign-lib-path.rs delete mode 100644 gcc/testsuite/rust.test/foreign-mod-unused-const.rs delete mode 100644 gcc/testsuite/rust.test/foreign-no-abi.rs delete mode 100644 gcc/testsuite/rust.test/foreign-struct.rs delete mode 100644 gcc/testsuite/rust.test/foreign2.rs delete mode 100644 gcc/testsuite/rust.test/format-no-uppercase-statics.rs delete mode 100644 gcc/testsuite/rust.test/fun-call-variants.rs delete mode 100644 gcc/testsuite/rust.test/fun-indirect-call.rs delete mode 100644 gcc/testsuite/rust.test/func-arg-incomplete-pattern.rs delete mode 100644 gcc/testsuite/rust.test/func-arg-ref-pattern.rs delete mode 100644 gcc/testsuite/rust.test/func-arg-wild-pattern.rs delete mode 100644 gcc/testsuite/rust.test/functional-struct-upd.rs delete mode 100644 gcc/testsuite/rust.test/generic-alias-box.rs delete mode 100644 gcc/testsuite/rust.test/generic-alias-unique.rs delete mode 100644 gcc/testsuite/rust.test/generic-box.rs delete mode 100644 gcc/testsuite/rust.test/generic-derived-type.rs delete mode 100644 gcc/testsuite/rust.test/generic-drop-glue.rs delete mode 100644 gcc/testsuite/rust.test/generic-exterior-box.rs delete mode 100644 gcc/testsuite/rust.test/generic-exterior-unique.rs delete mode 100644 gcc/testsuite/rust.test/generic-fn-box.rs delete mode 100644 gcc/testsuite/rust.test/generic-fn-infer.rs delete mode 100644 gcc/testsuite/rust.test/generic-fn-twice.rs delete mode 100644 gcc/testsuite/rust.test/generic-fn-unique.rs delete mode 100644 gcc/testsuite/rust.test/generic-fn.rs delete mode 100644 gcc/testsuite/rust.test/generic-ivec-leak.rs delete mode 100644 gcc/testsuite/rust.test/generic-ivec.rs delete mode 100644 gcc/testsuite/rust.test/generic-newtype-struct.rs delete mode 100644 gcc/testsuite/rust.test/generic-object.rs delete mode 100644 gcc/testsuite/rust.test/generic-recursive-tag.rs delete mode 100644 gcc/testsuite/rust.test/generic-static-methods.rs delete mode 100644 gcc/testsuite/rust.test/generic-tag-corruption.rs delete mode 100644 gcc/testsuite/rust.test/generic-tag-local.rs delete mode 100644 gcc/testsuite/rust.test/generic-tag-match.rs delete mode 100644 gcc/testsuite/rust.test/generic-tag-values.rs delete mode 100644 gcc/testsuite/rust.test/generic-tag.rs delete mode 100644 gcc/testsuite/rust.test/generic-temporary.rs delete mode 100644 gcc/testsuite/rust.test/generic-tup.rs delete mode 100644 gcc/testsuite/rust.test/generic-type-synonym.rs delete mode 100644 gcc/testsuite/rust.test/generic-type.rs delete mode 100644 gcc/testsuite/rust.test/generic-unique.rs delete mode 100644 gcc/testsuite/rust.test/getopts_ref.rs delete mode 100644 gcc/testsuite/rust.test/glob-std.rs delete mode 100644 gcc/testsuite/rust.test/global-scope.rs delete mode 100644 gcc/testsuite/rust.test/guards-not-exhaustive.rs delete mode 100644 gcc/testsuite/rust.test/guards.rs delete mode 100644 gcc/testsuite/rust.test/hashmap-memory.rs delete mode 100644 gcc/testsuite/rust.test/hello.rs delete mode 100644 gcc/testsuite/rust.test/helloworld.rs delete mode 100644 gcc/testsuite/rust.test/html-literals.rs delete mode 100644 gcc/testsuite/rust.test/hygiene-dodging-1.rs delete mode 100644 gcc/testsuite/rust.test/i32-sub.rs delete mode 100644 gcc/testsuite/rust.test/i8-incr.rs delete mode 100644 gcc/testsuite/rust.test/if-bot.rs delete mode 100644 gcc/testsuite/rust.test/if-check.rs delete mode 100644 gcc/testsuite/rust.test/if-ret.rs delete mode 100644 gcc/testsuite/rust.test/ifmt.rs delete mode 100644 gcc/testsuite/rust.test/impl-implicit-trait.rs delete mode 100644 gcc/testsuite/rust.test/impl-privacy-xc-1.rs delete mode 100644 gcc/testsuite/rust.test/impl-privacy-xc-2.rs delete mode 100644 gcc/testsuite/rust.test/import-from.rs delete mode 100644 gcc/testsuite/rust.test/import-glob-0.rs delete mode 100644 gcc/testsuite/rust.test/import-glob-crate.rs delete mode 100644 gcc/testsuite/rust.test/import-in-block.rs delete mode 100644 gcc/testsuite/rust.test/import-trailing-comma.rs delete mode 100644 gcc/testsuite/rust.test/import.rs delete mode 100644 gcc/testsuite/rust.test/import2.rs delete mode 100644 gcc/testsuite/rust.test/import3.rs delete mode 100644 gcc/testsuite/rust.test/import4.rs delete mode 100644 gcc/testsuite/rust.test/import5.rs delete mode 100644 gcc/testsuite/rust.test/import6.rs delete mode 100644 gcc/testsuite/rust.test/import7.rs delete mode 100644 gcc/testsuite/rust.test/import8.rs delete mode 100644 gcc/testsuite/rust.test/infer-fn-tail-expr.rs delete mode 100644 gcc/testsuite/rust.test/inferred-suffix-in-pattern-range.rs delete mode 100644 gcc/testsuite/rust.test/infinite-loops.rs delete mode 100644 gcc/testsuite/rust.test/init-res-into-things.rs delete mode 100644 gcc/testsuite/rust.test/inner-module.rs delete mode 100644 gcc/testsuite/rust.test/inner-static.rs delete mode 100644 gcc/testsuite/rust.test/instantiable.rs delete mode 100644 gcc/testsuite/rust.test/int-conversion-coherence.rs delete mode 100644 gcc/testsuite/rust.test/int.rs delete mode 100644 gcc/testsuite/rust.test/integer-literal-suffix-inference.rs delete mode 100644 gcc/testsuite/rust.test/integral-indexing.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-alignment.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-atomics-cc.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-atomics.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-frame-address.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-move-val.rs delete mode 100644 gcc/testsuite/rust.test/intrinsic-uninit.rs delete mode 100644 gcc/testsuite/rust.test/intrinsics-integer.rs delete mode 100644 gcc/testsuite/rust.test/intrinsics-math.rs delete mode 100644 gcc/testsuite/rust.test/invoke-external-foreign.rs delete mode 100644 gcc/testsuite/rust.test/irrefutable-unit.rs delete mode 100644 gcc/testsuite/rust.test/issue-1112.rs delete mode 100644 gcc/testsuite/rust.test/issue-1251.rs delete mode 100644 gcc/testsuite/rust.test/issue-1257.rs delete mode 100644 gcc/testsuite/rust.test/issue-1458.rs delete mode 100644 gcc/testsuite/rust.test/issue-1460.rs delete mode 100644 gcc/testsuite/rust.test/issue-1516.rs delete mode 100644 gcc/testsuite/rust.test/issue-1660.rs delete mode 100644 gcc/testsuite/rust.test/issue-1696.rs delete mode 100644 gcc/testsuite/rust.test/issue-1701.rs delete mode 100644 gcc/testsuite/rust.test/issue-1821.rs delete mode 100644 gcc/testsuite/rust.test/issue-1866.rs delete mode 100644 gcc/testsuite/rust.test/issue-1974.rs delete mode 100644 gcc/testsuite/rust.test/issue-2185.rs delete mode 100644 gcc/testsuite/rust.test/issue-2190-1.rs delete mode 100644 gcc/testsuite/rust.test/issue-2190-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-2190.rs delete mode 100644 gcc/testsuite/rust.test/issue-2214.rs delete mode 100644 gcc/testsuite/rust.test/issue-2216.rs delete mode 100644 gcc/testsuite/rust.test/issue-2284.rs delete mode 100644 gcc/testsuite/rust.test/issue-2288.rs delete mode 100644 gcc/testsuite/rust.test/issue-2311-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-2311.rs delete mode 100644 gcc/testsuite/rust.test/issue-2312.rs delete mode 100644 gcc/testsuite/rust.test/issue-2316-c.rs delete mode 100644 gcc/testsuite/rust.test/issue-2380-b.rs delete mode 100644 gcc/testsuite/rust.test/issue-2383.rs delete mode 100644 gcc/testsuite/rust.test/issue-2414-c.rs delete mode 100644 gcc/testsuite/rust.test/issue-2428.rs delete mode 100644 gcc/testsuite/rust.test/issue-2445-b.rs delete mode 100644 gcc/testsuite/rust.test/issue-2445.rs delete mode 100644 gcc/testsuite/rust.test/issue-2463.rs delete mode 100644 gcc/testsuite/rust.test/issue-2472.rs delete mode 100644 gcc/testsuite/rust.test/issue-2487-a.rs delete mode 100644 gcc/testsuite/rust.test/issue-2502.rs delete mode 100644 gcc/testsuite/rust.test/issue-2526-a.rs delete mode 100644 gcc/testsuite/rust.test/issue-2550.rs delete mode 100644 gcc/testsuite/rust.test/issue-2611-3.rs delete mode 100644 gcc/testsuite/rust.test/issue-2631-b.rs delete mode 100644 gcc/testsuite/rust.test/issue-2633-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-2633.rs delete mode 100644 gcc/testsuite/rust.test/issue-2642.rs delete mode 100644 gcc/testsuite/rust.test/issue-2708.rs delete mode 100644 gcc/testsuite/rust.test/issue-2718.rs delete mode 100644 gcc/testsuite/rust.test/issue-2723-b.rs delete mode 100644 gcc/testsuite/rust.test/issue-2734.rs delete mode 100644 gcc/testsuite/rust.test/issue-2735-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-2735-3.rs delete mode 100644 gcc/testsuite/rust.test/issue-2735.rs delete mode 100644 gcc/testsuite/rust.test/issue-2748-a.rs delete mode 100644 gcc/testsuite/rust.test/issue-2748-b.rs delete mode 100644 gcc/testsuite/rust.test/issue-2804-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-2804.rs delete mode 100644 gcc/testsuite/rust.test/issue-2895.rs delete mode 100644 gcc/testsuite/rust.test/issue-2904.rs delete mode 100644 gcc/testsuite/rust.test/issue-2935.rs delete mode 100644 gcc/testsuite/rust.test/issue-2936.rs delete mode 100644 gcc/testsuite/rust.test/issue-2989.rs delete mode 100644 gcc/testsuite/rust.test/issue-3012-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-3026.rs delete mode 100644 gcc/testsuite/rust.test/issue-3037.rs delete mode 100644 gcc/testsuite/rust.test/issue-3052.rs delete mode 100644 gcc/testsuite/rust.test/issue-3091.rs delete mode 100644 gcc/testsuite/rust.test/issue-3109.rs delete mode 100644 gcc/testsuite/rust.test/issue-3121.rs delete mode 100644 gcc/testsuite/rust.test/issue-3149.rs delete mode 100644 gcc/testsuite/rust.test/issue-3168.rs delete mode 100644 gcc/testsuite/rust.test/issue-3186.rs delete mode 100644 gcc/testsuite/rust.test/issue-3211.rs delete mode 100644 gcc/testsuite/rust.test/issue-3220.rs delete mode 100644 gcc/testsuite/rust.test/issue-3250.rs delete mode 100644 gcc/testsuite/rust.test/issue-3290.rs delete mode 100644 gcc/testsuite/rust.test/issue-333.rs delete mode 100644 gcc/testsuite/rust.test/issue-3389.rs delete mode 100644 gcc/testsuite/rust.test/issue-3424.rs delete mode 100644 gcc/testsuite/rust.test/issue-3429.rs delete mode 100644 gcc/testsuite/rust.test/issue-3447.rs delete mode 100644 gcc/testsuite/rust.test/issue-3461.rs delete mode 100644 gcc/testsuite/rust.test/issue-3500.rs delete mode 100644 gcc/testsuite/rust.test/issue-3556.rs delete mode 100644 gcc/testsuite/rust.test/issue-3559.rs delete mode 100644 gcc/testsuite/rust.test/issue-3563-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-3563-3.rs delete mode 100644 gcc/testsuite/rust.test/issue-3574.rs delete mode 100644 gcc/testsuite/rust.test/issue-3609.rs delete mode 100644 gcc/testsuite/rust.test/issue-3656.rs delete mode 100644 gcc/testsuite/rust.test/issue-3683.rs delete mode 100644 gcc/testsuite/rust.test/issue-3702.rs delete mode 100644 gcc/testsuite/rust.test/issue-3743.rs delete mode 100644 gcc/testsuite/rust.test/issue-3753.rs delete mode 100644 gcc/testsuite/rust.test/issue-3794.rs delete mode 100644 gcc/testsuite/rust.test/issue-3796.rs delete mode 100644 gcc/testsuite/rust.test/issue-3847.rs delete mode 100644 gcc/testsuite/rust.test/issue-3860.rs delete mode 100644 gcc/testsuite/rust.test/issue-3874.rs delete mode 100644 gcc/testsuite/rust.test/issue-3878.rs delete mode 100644 gcc/testsuite/rust.test/issue-3888-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-3895.rs delete mode 100644 gcc/testsuite/rust.test/issue-3904.rs delete mode 100644 gcc/testsuite/rust.test/issue-3907-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-3935.rs delete mode 100644 gcc/testsuite/rust.test/issue-3979-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-3979-generics.rs delete mode 100644 gcc/testsuite/rust.test/issue-3979-xcrate.rs delete mode 100644 gcc/testsuite/rust.test/issue-3979.rs delete mode 100644 gcc/testsuite/rust.test/issue-3991.rs delete mode 100644 gcc/testsuite/rust.test/issue-4016.rs delete mode 100644 gcc/testsuite/rust.test/issue-4025.rs delete mode 100644 gcc/testsuite/rust.test/issue-4036.rs delete mode 100644 gcc/testsuite/rust.test/issue-4092.rs delete mode 100644 gcc/testsuite/rust.test/issue-4107.rs delete mode 100644 gcc/testsuite/rust.test/issue-4120.rs delete mode 100644 gcc/testsuite/rust.test/issue-4208.rs delete mode 100644 gcc/testsuite/rust.test/issue-4228.rs delete mode 100644 gcc/testsuite/rust.test/issue-4241.rs delete mode 100644 gcc/testsuite/rust.test/issue-4252.rs delete mode 100644 gcc/testsuite/rust.test/issue-4333.rs delete mode 100644 gcc/testsuite/rust.test/issue-4387.rs delete mode 100644 gcc/testsuite/rust.test/issue-4401.rs delete mode 100644 gcc/testsuite/rust.test/issue-4446.rs delete mode 100644 gcc/testsuite/rust.test/issue-4448.rs delete mode 100644 gcc/testsuite/rust.test/issue-4464.rs delete mode 100644 gcc/testsuite/rust.test/issue-4541.rs delete mode 100644 gcc/testsuite/rust.test/issue-4542.rs delete mode 100644 gcc/testsuite/rust.test/issue-4545.rs delete mode 100644 gcc/testsuite/rust.test/issue-4735.rs delete mode 100644 gcc/testsuite/rust.test/issue-4759-1.rs delete mode 100644 gcc/testsuite/rust.test/issue-4759.rs delete mode 100644 gcc/testsuite/rust.test/issue-4830.rs delete mode 100644 gcc/testsuite/rust.test/issue-4875.rs delete mode 100644 gcc/testsuite/rust.test/issue-5008-borrowed-traitobject-method-call.rs delete mode 100644 gcc/testsuite/rust.test/issue-5060.rs delete mode 100644 gcc/testsuite/rust.test/issue-5192.rs delete mode 100644 gcc/testsuite/rust.test/issue-5239-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-5243.rs delete mode 100644 gcc/testsuite/rust.test/issue-5275.rs delete mode 100644 gcc/testsuite/rust.test/issue-5280.rs delete mode 100644 gcc/testsuite/rust.test/issue-5315.rs delete mode 100644 gcc/testsuite/rust.test/issue-5321-immediates-with-bare-self.rs delete mode 100644 gcc/testsuite/rust.test/issue-5353.rs delete mode 100644 gcc/testsuite/rust.test/issue-5517.rs delete mode 100644 gcc/testsuite/rust.test/issue-5530.rs delete mode 100644 gcc/testsuite/rust.test/issue-5550.rs delete mode 100644 gcc/testsuite/rust.test/issue-5554.rs delete mode 100644 gcc/testsuite/rust.test/issue-5572.rs delete mode 100644 gcc/testsuite/rust.test/issue-5666.rs delete mode 100644 gcc/testsuite/rust.test/issue-5688.rs delete mode 100644 gcc/testsuite/rust.test/issue-5708.rs delete mode 100644 gcc/testsuite/rust.test/issue-5741.rs delete mode 100644 gcc/testsuite/rust.test/issue-5754.rs delete mode 100644 gcc/testsuite/rust.test/issue-5791.rs delete mode 100644 gcc/testsuite/rust.test/issue-5884.rs delete mode 100644 gcc/testsuite/rust.test/issue-5917.rs delete mode 100644 gcc/testsuite/rust.test/issue-5926.rs delete mode 100644 gcc/testsuite/rust.test/issue-6117.rs delete mode 100644 gcc/testsuite/rust.test/issue-6128.rs delete mode 100644 gcc/testsuite/rust.test/issue-6130.rs delete mode 100644 gcc/testsuite/rust.test/issue-6141-leaking-owned-fn.rs delete mode 100644 gcc/testsuite/rust.test/issue-6153.rs delete mode 100644 gcc/testsuite/rust.test/issue-6318.rs delete mode 100644 gcc/testsuite/rust.test/issue-6341.rs delete mode 100644 gcc/testsuite/rust.test/issue-6344-let.rs delete mode 100644 gcc/testsuite/rust.test/issue-6344-match.rs delete mode 100644 gcc/testsuite/rust.test/issue-6470.rs delete mode 100644 gcc/testsuite/rust.test/issue-6557.rs delete mode 100644 gcc/testsuite/rust.test/issue-6898.rs delete mode 100644 gcc/testsuite/rust.test/issue-6919.rs delete mode 100644 gcc/testsuite/rust.test/issue-7012.rs delete mode 100644 gcc/testsuite/rust.test/issue-7222.rs delete mode 100644 gcc/testsuite/rust.test/issue-7344.rs delete mode 100644 gcc/testsuite/rust.test/issue-7519-match-unit-in-arg.rs delete mode 100644 gcc/testsuite/rust.test/issue-7563.rs delete mode 100644 gcc/testsuite/rust.test/issue-7673-cast-generically-implemented-trait.rs delete mode 100644 gcc/testsuite/rust.test/issue-7712.rs delete mode 100644 gcc/testsuite/rust.test/issue-8044.rs delete mode 100644 gcc/testsuite/rust.test/issue-8171-default-method-self-inherit-builtin-trait.rs delete mode 100644 gcc/testsuite/rust.test/issue-8248.rs delete mode 100644 gcc/testsuite/rust.test/issue-8249.rs delete mode 100644 gcc/testsuite/rust.test/issue-8351-1.rs delete mode 100644 gcc/testsuite/rust.test/issue-8351-2.rs delete mode 100644 gcc/testsuite/rust.test/issue-8398.rs delete mode 100644 gcc/testsuite/rust.test/issue-8401.rs delete mode 100644 gcc/testsuite/rust.test/issue-8498.rs delete mode 100644 gcc/testsuite/rust.test/issue-868.rs delete mode 100644 gcc/testsuite/rust.test/issue-8898.rs delete mode 100644 gcc/testsuite/rust.test/issue-9047.rs delete mode 100644 gcc/testsuite/rust.test/issue-9110.rs delete mode 100644 gcc/testsuite/rust.test/issue-912.rs delete mode 100644 gcc/testsuite/rust.test/issue-9123.rs delete mode 100644 gcc/testsuite/rust.test/issue-9188.rs delete mode 100644 gcc/testsuite/rust.test/issue-9394-inherited-trait-calls.rs delete mode 100644 gcc/testsuite/rust.test/issue-9446.rs delete mode 100644 gcc/testsuite/rust.test/issue-979.rs delete mode 100644 gcc/testsuite/rust.test/issue-980.rs delete mode 100644 gcc/testsuite/rust.test/issue2170exe.rs delete mode 100644 gcc/testsuite/rust.test/issue2378c.rs delete mode 100644 gcc/testsuite/rust.test/issue_3136_b.rs delete mode 100644 gcc/testsuite/rust.test/issue_9155.rs delete mode 100644 gcc/testsuite/rust.test/istr.rs delete mode 100644 gcc/testsuite/rust.test/item-attributes.rs delete mode 100644 gcc/testsuite/rust.test/item-name-overload.rs delete mode 100644 gcc/testsuite/rust.test/iter-range.rs delete mode 100644 gcc/testsuite/rust.test/ivec-add.rs delete mode 100644 gcc/testsuite/rust.test/ivec-pass-by-value.rs delete mode 100644 gcc/testsuite/rust.test/ivec-tag.rs delete mode 100644 gcc/testsuite/rust.test/keyword-changes-2012-07-31.rs delete mode 100644 gcc/testsuite/rust.test/kindck-owned-trait-contains-1.rs delete mode 100644 gcc/testsuite/rust.test/labeled-break.rs delete mode 100644 gcc/testsuite/rust.test/lambda-infer-unresolved.rs delete mode 100644 gcc/testsuite/rust.test/large-records.rs delete mode 100644 gcc/testsuite/rust.test/last-use-in-block.rs delete mode 100644 gcc/testsuite/rust.test/last-use-in-cap-clause.rs delete mode 100644 gcc/testsuite/rust.test/last-use-is-capture.rs delete mode 100644 gcc/testsuite/rust.test/lazy-and-or.rs delete mode 100644 gcc/testsuite/rust.test/lazy-init.rs delete mode 100644 gcc/testsuite/rust.test/leak-box-as-tydesc.rs delete mode 100644 gcc/testsuite/rust.test/leak-tag-copy.rs delete mode 100644 gcc/testsuite/rust.test/leak-unique-as-tydesc.rs delete mode 100644 gcc/testsuite/rust.test/let-assignability.rs delete mode 100644 gcc/testsuite/rust.test/let-destruct-fresh-mem.rs delete mode 100644 gcc/testsuite/rust.test/let-destruct-ref.rs delete mode 100644 gcc/testsuite/rust.test/let-destruct.rs delete mode 100644 gcc/testsuite/rust.test/let-var-hygiene.rs delete mode 100644 gcc/testsuite/rust.test/linear-for-loop.rs delete mode 100644 gcc/testsuite/rust.test/link-section.rs delete mode 100644 gcc/testsuite/rust.test/lint-cstack.rs delete mode 100644 gcc/testsuite/rust.test/lint-non-camel-case-types-non-uppercase-statics-unicode.rs delete mode 100644 gcc/testsuite/rust.test/lint-non-camel-case-with-trailing-underscores.rs delete mode 100644 gcc/testsuite/rust.test/lint-non-uppercase-statics-lowercase-mut-statics.rs delete mode 100644 gcc/testsuite/rust.test/list.rs delete mode 100644 gcc/testsuite/rust.test/liveness-assign-imm-local-after-loop.rs delete mode 100644 gcc/testsuite/rust.test/liveness-assign-imm-local-after-ret.rs delete mode 100644 gcc/testsuite/rust.test/liveness-loop-break.rs delete mode 100644 gcc/testsuite/rust.test/liveness-move-in-loop.rs delete mode 100644 gcc/testsuite/rust.test/log-err-phi.rs delete mode 100644 gcc/testsuite/rust.test/log-knows-the-names-of-variants-in-std.rs delete mode 100644 gcc/testsuite/rust.test/log-knows-the-names-of-variants.rs delete mode 100644 gcc/testsuite/rust.test/log-linearized.rs delete mode 100644 gcc/testsuite/rust.test/log-poly.rs delete mode 100644 gcc/testsuite/rust.test/log-str.rs delete mode 100644 gcc/testsuite/rust.test/logging-right-crate.rs delete mode 100644 gcc/testsuite/rust.test/logging_before_rt_started.rs delete mode 100644 gcc/testsuite/rust.test/long-while.rs delete mode 100644 gcc/testsuite/rust.test/loop-break-cont-1.rs delete mode 100644 gcc/testsuite/rust.test/loop-break-cont.rs delete mode 100644 gcc/testsuite/rust.test/loop-diverges.rs delete mode 100644 gcc/testsuite/rust.test/loop-scope.rs delete mode 100644 gcc/testsuite/rust.test/lots-a-fail.rs delete mode 100644 gcc/testsuite/rust.test/macro-2.rs delete mode 100644 gcc/testsuite/rust.test/macro-attributes.rs delete mode 100644 gcc/testsuite/rust.test/macro-interpolation.rs delete mode 100644 gcc/testsuite/rust.test/macro-local-data-key.rs delete mode 100644 gcc/testsuite/rust.test/macro-path.rs delete mode 100644 gcc/testsuite/rust.test/macro-stmt.rs delete mode 100644 gcc/testsuite/rust.test/macro-with-attrs1.rs delete mode 100644 gcc/testsuite/rust.test/macro-with-attrs2.rs delete mode 100644 gcc/testsuite/rust.test/match-borrowed_str.rs delete mode 100644 gcc/testsuite/rust.test/match-bot-2.rs delete mode 100644 gcc/testsuite/rust.test/match-bot.rs delete mode 100644 gcc/testsuite/rust.test/match-drop-strs-issue-4541.rs delete mode 100644 gcc/testsuite/rust.test/match-enum-struct-0.rs delete mode 100644 gcc/testsuite/rust.test/match-enum-struct-1.rs delete mode 100644 gcc/testsuite/rust.test/match-implicit-copy-unique.rs delete mode 100644 gcc/testsuite/rust.test/match-in-macro.rs delete mode 100644 gcc/testsuite/rust.test/match-join.rs delete mode 100644 gcc/testsuite/rust.test/match-naked-record-expr.rs delete mode 100644 gcc/testsuite/rust.test/match-naked-record.rs delete mode 100644 gcc/testsuite/rust.test/match-path.rs delete mode 100644 gcc/testsuite/rust.test/match-pattern-drop.rs delete mode 100644 gcc/testsuite/rust.test/match-pattern-lit.rs delete mode 100644 gcc/testsuite/rust.test/match-pattern-no-type-params.rs delete mode 100644 gcc/testsuite/rust.test/match-pattern-simple.rs delete mode 100644 gcc/testsuite/rust.test/match-phi.rs delete mode 100644 gcc/testsuite/rust.test/match-pipe-binding.rs delete mode 100644 gcc/testsuite/rust.test/match-range-static.rs delete mode 100644 gcc/testsuite/rust.test/match-range.rs delete mode 100644 gcc/testsuite/rust.test/match-ref-binding-in-guard-3256.rs delete mode 100644 gcc/testsuite/rust.test/match-ref-binding-mut-option.rs delete mode 100644 gcc/testsuite/rust.test/match-ref-binding-mut.rs delete mode 100644 gcc/testsuite/rust.test/match-ref-binding.rs delete mode 100644 gcc/testsuite/rust.test/match-static-const-rename.rs delete mode 100644 gcc/testsuite/rust.test/match-str.rs delete mode 100644 gcc/testsuite/rust.test/match-struct-0.rs delete mode 100644 gcc/testsuite/rust.test/match-tag.rs delete mode 100644 gcc/testsuite/rust.test/match-unique-bind.rs delete mode 100644 gcc/testsuite/rust.test/match-value-binding-in-guard-3291.rs delete mode 100644 gcc/testsuite/rust.test/match-vec-rvalue.rs delete mode 100644 gcc/testsuite/rust.test/match-with-ret-arm.rs delete mode 100644 gcc/testsuite/rust.test/max-min-classes.rs delete mode 100644 gcc/testsuite/rust.test/method-attributes.rs delete mode 100644 gcc/testsuite/rust.test/mid-path-type-params.rs delete mode 100644 gcc/testsuite/rust.test/mlist-cycle.rs delete mode 100644 gcc/testsuite/rust.test/mlist.rs delete mode 100644 gcc/testsuite/rust.test/mod-inside-fn.rs delete mode 100644 gcc/testsuite/rust.test/mod-view-items.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_implicit.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_path.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_path2.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_path3.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_path_multi.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_recursive.rs delete mode 100644 gcc/testsuite/rust.test/mod_dir_simple.rs delete mode 100644 gcc/testsuite/rust.test/mod_file.rs delete mode 100644 gcc/testsuite/rust.test/mod_file_aux.rs delete mode 100644 gcc/testsuite/rust.test/mod_file_with_path_attr.rs delete mode 100644 gcc/testsuite/rust.test/module-qualified-struct-destructure.rs delete mode 100644 gcc/testsuite/rust.test/monad.rs delete mode 100644 gcc/testsuite/rust.test/monomorphize-abi-alignment.rs delete mode 100644 gcc/testsuite/rust.test/monomorphized-callees-with-ty-params-3314.rs delete mode 100644 gcc/testsuite/rust.test/morestack-address.rs delete mode 100644 gcc/testsuite/rust.test/morestack1.rs delete mode 100644 gcc/testsuite/rust.test/morestack2.rs delete mode 100644 gcc/testsuite/rust.test/morestack3.rs delete mode 100644 gcc/testsuite/rust.test/morestack4.rs delete mode 100644 gcc/testsuite/rust.test/morestack5.rs delete mode 100644 gcc/testsuite/rust.test/morestack6.rs delete mode 100644 gcc/testsuite/rust.test/move-1-unique.rs delete mode 100644 gcc/testsuite/rust.test/move-1.rs delete mode 100644 gcc/testsuite/rust.test/move-2-unique.rs delete mode 100644 gcc/testsuite/rust.test/move-2.rs delete mode 100644 gcc/testsuite/rust.test/move-3-unique.rs delete mode 100644 gcc/testsuite/rust.test/move-3.rs delete mode 100644 gcc/testsuite/rust.test/move-4-unique.rs delete mode 100644 gcc/testsuite/rust.test/move-4.rs delete mode 100644 gcc/testsuite/rust.test/move-arg-2-unique.rs delete mode 100644 gcc/testsuite/rust.test/move-arg-2.rs delete mode 100644 gcc/testsuite/rust.test/move-arg.rs delete mode 100644 gcc/testsuite/rust.test/move-nullary-fn.rs delete mode 100644 gcc/testsuite/rust.test/move-out-of-field.rs delete mode 100644 gcc/testsuite/rust.test/move-scalar.rs delete mode 100644 gcc/testsuite/rust.test/move-self.rs delete mode 100644 gcc/testsuite/rust.test/moves-based-on-type-capture-clause.rs delete mode 100644 gcc/testsuite/rust.test/moves-based-on-type-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/multi-let.rs delete mode 100644 gcc/testsuite/rust.test/multibyte.rs delete mode 100644 gcc/testsuite/rust.test/multiline-comment.rs delete mode 100644 gcc/testsuite/rust.test/multiple-trait-bounds.rs delete mode 100644 gcc/testsuite/rust.test/mut-function-arguments.rs delete mode 100644 gcc/testsuite/rust.test/mut-vstore-expr.rs delete mode 100644 gcc/testsuite/rust.test/mutability-inherits-through-fixed-length-vec.rs delete mode 100644 gcc/testsuite/rust.test/mutable-alias-vec.rs delete mode 100644 gcc/testsuite/rust.test/mutable-vec-drop.rs delete mode 100644 gcc/testsuite/rust.test/mutual-recursion-group.rs delete mode 100644 gcc/testsuite/rust.test/negative.rs delete mode 100644 gcc/testsuite/rust.test/nested-class.rs delete mode 100644 gcc/testsuite/rust.test/nested-enum-same-names.rs delete mode 100644 gcc/testsuite/rust.test/nested-exhaustive-match.rs delete mode 100644 gcc/testsuite/rust.test/nested-function-names-issue-8587.rs delete mode 100644 gcc/testsuite/rust.test/nested-matchs.rs delete mode 100644 gcc/testsuite/rust.test/nested-pattern.rs delete mode 100644 gcc/testsuite/rust.test/nested-patterns.rs delete mode 100644 gcc/testsuite/rust.test/nested_item_main.rs delete mode 100644 gcc/testsuite/rust.test/new-impl-syntax.rs delete mode 100644 gcc/testsuite/rust.test/new-import-syntax.rs delete mode 100644 gcc/testsuite/rust.test/new-style-constants.rs delete mode 100644 gcc/testsuite/rust.test/new-style-fixed-length-vec.rs delete mode 100644 gcc/testsuite/rust.test/new-vstore-mut-box-syntax.rs delete mode 100644 gcc/testsuite/rust.test/newlambdas-ret-infer.rs delete mode 100644 gcc/testsuite/rust.test/newlambdas-ret-infer2.rs delete mode 100644 gcc/testsuite/rust.test/newlambdas.rs delete mode 100644 gcc/testsuite/rust.test/newtype-polymorphic.rs delete mode 100644 gcc/testsuite/rust.test/newtype-struct-drop-run.rs delete mode 100644 gcc/testsuite/rust.test/newtype-struct-with-dtor.rs delete mode 100644 gcc/testsuite/rust.test/newtype-struct-xc-2.rs delete mode 100644 gcc/testsuite/rust.test/newtype-struct-xc.rs delete mode 100644 gcc/testsuite/rust.test/newtype-temporary.rs delete mode 100644 gcc/testsuite/rust.test/newtype.rs delete mode 100644 gcc/testsuite/rust.test/nil-decl-in-foreign.rs delete mode 100644 gcc/testsuite/rust.test/nil-pattern.rs delete mode 100644 gcc/testsuite/rust.test/no-std-xcrate.rs delete mode 100644 gcc/testsuite/rust.test/no-std-xcrate2.rs delete mode 100644 gcc/testsuite/rust.test/non-boolean-pure-fns.rs delete mode 100644 gcc/testsuite/rust.test/non-legacy-modes.rs delete mode 100644 gcc/testsuite/rust.test/nul-characters.rs delete mode 100644 gcc/testsuite/rust.test/nullable-pointer-iotareduction.rs delete mode 100644 gcc/testsuite/rust.test/nullable-pointer-size.rs delete mode 100644 gcc/testsuite/rust.test/nullary-or-pattern.rs delete mode 100644 gcc/testsuite/rust.test/numeric-method-autoexport.rs delete mode 100644 gcc/testsuite/rust.test/objects-coerce-freeze-borrored.rs delete mode 100644 gcc/testsuite/rust.test/objects-coerce-from-managed-to-borrowed.rs delete mode 100644 gcc/testsuite/rust.test/objects-owned-object-borrowed-method-header.rs delete mode 100644 gcc/testsuite/rust.test/objects-owned-object-borrowed-method-headerless.rs delete mode 100644 gcc/testsuite/rust.test/objects-owned-object-owned-method.rs delete mode 100644 gcc/testsuite/rust.test/once-move-out-on-heap.rs delete mode 100644 gcc/testsuite/rust.test/once-move-out-on-stack.rs delete mode 100644 gcc/testsuite/rust.test/one-tuple.rs delete mode 100644 gcc/testsuite/rust.test/opeq.rs delete mode 100644 gcc/testsuite/rust.test/operator-associativity.rs delete mode 100644 gcc/testsuite/rust.test/operator-overloading.rs delete mode 100644 gcc/testsuite/rust.test/option-ext.rs delete mode 100644 gcc/testsuite/rust.test/option-unwrap.rs delete mode 100644 gcc/testsuite/rust.test/or-pattern.rs delete mode 100644 gcc/testsuite/rust.test/output-slot-variants.rs delete mode 100644 gcc/testsuite/rust.test/over-constrained-vregs.rs delete mode 100644 gcc/testsuite/rust.test/overload-index-operator.rs delete mode 100644 gcc/testsuite/rust.test/owned-implies-static.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-borrow-element.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-generic-layout.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-generic-size.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-layout.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-match.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-size-xc.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-size.rs delete mode 100644 gcc/testsuite/rust.test/packed-struct-vec.rs delete mode 100644 gcc/testsuite/rust.test/packed-tuple-struct-layout.rs delete mode 100644 gcc/testsuite/rust.test/packed-tuple-struct-size.rs delete mode 100644 gcc/testsuite/rust.test/paren-free.rs delete mode 100644 gcc/testsuite/rust.test/parse-fail.rs delete mode 100644 gcc/testsuite/rust.test/pass-by-copy.rs delete mode 100644 gcc/testsuite/rust.test/path.rs delete mode 100644 gcc/testsuite/rust.test/pattern-bound-var-in-for-each.rs delete mode 100644 gcc/testsuite/rust.test/pattern-in-closure.rs delete mode 100644 gcc/testsuite/rust.test/placement-new-arena.rs delete mode 100644 gcc/testsuite/rust.test/pred-not-bool.rs delete mode 100644 gcc/testsuite/rust.test/preempt.rs delete mode 100644 gcc/testsuite/rust.test/privacy1.rs delete mode 100644 gcc/testsuite/rust.test/private-class-field.rs delete mode 100644 gcc/testsuite/rust.test/private-method.rs delete mode 100644 gcc/testsuite/rust.test/pub-extern-privacy.rs delete mode 100644 gcc/testsuite/rust.test/pub-use-xcrate.rs delete mode 100644 gcc/testsuite/rust.test/pub_use_mods_xcrate_exe.rs delete mode 100644 gcc/testsuite/rust.test/pure-sum.rs delete mode 100644 gcc/testsuite/rust.test/purity-infer.rs delete mode 100644 gcc/testsuite/rust.test/raw-str.rs delete mode 100644 gcc/testsuite/rust.test/rcvr-borrowed-to-region.rs delete mode 100644 gcc/testsuite/rust.test/rcvr-borrowed-to-slice.rs delete mode 100644 gcc/testsuite/rust.test/readalias.rs delete mode 100644 gcc/testsuite/rust.test/rec-align-u32.rs delete mode 100644 gcc/testsuite/rust.test/rec-align-u64.rs delete mode 100644 gcc/testsuite/rust.test/rec-auto.rs delete mode 100644 gcc/testsuite/rust.test/rec-extend.rs delete mode 100644 gcc/testsuite/rust.test/rec-tup.rs delete mode 100644 gcc/testsuite/rust.test/rec.rs delete mode 100644 gcc/testsuite/rust.test/record-pat.rs delete mode 100644 gcc/testsuite/rust.test/recursion.rs delete mode 100644 gcc/testsuite/rust.test/reexport-should-still-link.rs delete mode 100644 gcc/testsuite/rust.test/reexport-star.rs delete mode 100644 gcc/testsuite/rust.test/reexported-static-methods-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/reflect-visit-data.rs delete mode 100644 gcc/testsuite/rust.test/reflect-visit-type.rs delete mode 100644 gcc/testsuite/rust.test/region-dependent-addr-of.rs delete mode 100644 gcc/testsuite/rust.test/region-dependent-autofn.rs delete mode 100644 gcc/testsuite/rust.test/region-dependent-autoslice.rs delete mode 100644 gcc/testsuite/rust.test/region-return-interior-of-option.rs delete mode 100644 gcc/testsuite/rust.test/regions-addr-of-interior-of-unique-box.rs delete mode 100644 gcc/testsuite/rust.test/regions-addr-of-ret.rs delete mode 100644 gcc/testsuite/rust.test/regions-appearance-constraint.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-at.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-estr-uniq.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-evec-at.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-evec-fixed.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-evec-uniq.rs delete mode 100644 gcc/testsuite/rust.test/regions-borrow-uniq.rs delete mode 100644 gcc/testsuite/rust.test/regions-bot.rs delete mode 100644 gcc/testsuite/rust.test/regions-copy-closure.rs delete mode 100644 gcc/testsuite/rust.test/regions-creating-enums2.rs delete mode 100644 gcc/testsuite/rust.test/regions-creating-enums5.rs delete mode 100644 gcc/testsuite/rust.test/regions-escape-into-other-fn.rs delete mode 100644 gcc/testsuite/rust.test/regions-expl-self.rs delete mode 100644 gcc/testsuite/rust.test/regions-fn-subtyping-2.rs delete mode 100644 gcc/testsuite/rust.test/regions-fn-subtyping.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-borrow-scope-addr-of.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-borrow-scope-view.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-borrow-scope-within-loop-ok.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-borrow-scope.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-call-2.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-call.rs delete mode 100644 gcc/testsuite/rust.test/regions-infer-contravariance-due-to-ret.rs delete mode 100644 gcc/testsuite/rust.test/regions-mock-trans.rs delete mode 100644 gcc/testsuite/rust.test/regions-nullary-variant.rs delete mode 100644 gcc/testsuite/rust.test/regions-params.rs delete mode 100644 gcc/testsuite/rust.test/regions-self-impls.rs delete mode 100644 gcc/testsuite/rust.test/regions-self-in-enums.rs delete mode 100644 gcc/testsuite/rust.test/regions-simple.rs delete mode 100644 gcc/testsuite/rust.test/regions-static-closure.rs delete mode 100644 gcc/testsuite/rust.test/rename-directory.rs delete mode 100644 gcc/testsuite/rust.test/repeat-expr-in-static.rs delete mode 100644 gcc/testsuite/rust.test/repeated-vector-syntax.rs delete mode 100644 gcc/testsuite/rust.test/resolve-issue-2428.rs delete mode 100644 gcc/testsuite/rust.test/resource-assign-is-not-copy.rs delete mode 100644 gcc/testsuite/rust.test/resource-cycle.rs delete mode 100644 gcc/testsuite/rust.test/resource-cycle2.rs delete mode 100644 gcc/testsuite/rust.test/resource-cycle3.rs delete mode 100644 gcc/testsuite/rust.test/resource-destruct.rs delete mode 100644 gcc/testsuite/rust.test/resource-in-struct.rs delete mode 100644 gcc/testsuite/rust.test/ret-bang.rs delete mode 100644 gcc/testsuite/rust.test/ret-none.rs delete mode 100644 gcc/testsuite/rust.test/return-nil.rs delete mode 100644 gcc/testsuite/rust.test/rt-run-twice.rs delete mode 100644 gcc/testsuite/rust.test/rt-start-main-thread.rs delete mode 100644 gcc/testsuite/rust.test/rtio-processes.rs delete mode 100644 gcc/testsuite/rust.test/select-macro.rs delete mode 100644 gcc/testsuite/rust.test/self-shadowing-import.rs delete mode 100644 gcc/testsuite/rust.test/self-type-param.rs delete mode 100644 gcc/testsuite/rust.test/send-iloop.rs delete mode 100644 gcc/testsuite/rust.test/send-resource.rs delete mode 100644 gcc/testsuite/rust.test/send-type-inference.rs delete mode 100644 gcc/testsuite/rust.test/send_str_hashmap.rs delete mode 100644 gcc/testsuite/rust.test/send_str_treemap.rs delete mode 100644 gcc/testsuite/rust.test/sendable-class.rs delete mode 100644 gcc/testsuite/rust.test/sendfn-generic-fn.rs delete mode 100644 gcc/testsuite/rust.test/sendfn-is-a-block.rs delete mode 100644 gcc/testsuite/rust.test/sendfn-spawn-with-fn-arg.rs delete mode 100644 gcc/testsuite/rust.test/seq-compare.rs delete mode 100644 gcc/testsuite/rust.test/shadow.rs delete mode 100644 gcc/testsuite/rust.test/shape_intrinsic_tag_then_rec.rs delete mode 100644 gcc/testsuite/rust.test/shebang.rs delete mode 100644 gcc/testsuite/rust.test/shift.rs delete mode 100644 gcc/testsuite/rust.test/signed-shift-const-eval.rs delete mode 100644 gcc/testsuite/rust.test/simd-binop.rs delete mode 100644 gcc/testsuite/rust.test/simd-type.rs delete mode 100644 gcc/testsuite/rust.test/simple-generic-match.rs delete mode 100644 gcc/testsuite/rust.test/simple-generic-tag.rs delete mode 100644 gcc/testsuite/rust.test/simple-infer.rs delete mode 100644 gcc/testsuite/rust.test/simple-match-generic-tag.rs delete mode 100644 gcc/testsuite/rust.test/size-and-align.rs delete mode 100644 gcc/testsuite/rust.test/sized-borrowed-pointer.rs delete mode 100644 gcc/testsuite/rust.test/sized-owned-pointer.rs delete mode 100644 gcc/testsuite/rust.test/smallest-hello-world.rs delete mode 100644 gcc/testsuite/rust.test/spawn-fn.rs delete mode 100644 gcc/testsuite/rust.test/spawn-types.rs delete mode 100644 gcc/testsuite/rust.test/spawn.rs delete mode 100644 gcc/testsuite/rust.test/spawn2.rs delete mode 100644 gcc/testsuite/rust.test/stable-addr-of.rs delete mode 100644 gcc/testsuite/rust.test/stat.rs delete mode 100644 gcc/testsuite/rust.test/static-assert.rs delete mode 100644 gcc/testsuite/rust.test/static-fn-inline-xc.rs delete mode 100644 gcc/testsuite/rust.test/static-fn-trait-xc.rs delete mode 100644 gcc/testsuite/rust.test/static-function-pointer-xc.rs delete mode 100644 gcc/testsuite/rust.test/static-function-pointer.rs delete mode 100644 gcc/testsuite/rust.test/static-impl.rs delete mode 100644 gcc/testsuite/rust.test/static-method-in-trait-with-tps-intracrate.rs delete mode 100644 gcc/testsuite/rust.test/static-method-xcrate.rs delete mode 100644 gcc/testsuite/rust.test/static-methods-in-traits.rs delete mode 100644 gcc/testsuite/rust.test/static-methods-in-traits2.rs delete mode 100644 gcc/testsuite/rust.test/static-mut-foreign.rs delete mode 100644 gcc/testsuite/rust.test/static-mut-xc.rs delete mode 100644 gcc/testsuite/rust.test/static-vec-autoref.rs delete mode 100644 gcc/testsuite/rust.test/str-append.rs delete mode 100644 gcc/testsuite/rust.test/str-concat.rs delete mode 100644 gcc/testsuite/rust.test/str-growth.rs delete mode 100644 gcc/testsuite/rust.test/str-idx.rs delete mode 100644 gcc/testsuite/rust.test/str-multiline.rs delete mode 100644 gcc/testsuite/rust.test/string-self-append.rs delete mode 100644 gcc/testsuite/rust.test/struct-deref.rs delete mode 100644 gcc/testsuite/rust.test/struct-destructuring-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/struct-field-assignability.rs delete mode 100644 gcc/testsuite/rust.test/struct-like-variant-construct.rs delete mode 100644 gcc/testsuite/rust.test/struct-like-variant-match.rs delete mode 100644 gcc/testsuite/rust.test/struct-literal-dtor.rs delete mode 100644 gcc/testsuite/rust.test/struct-new-as-field-name.rs delete mode 100644 gcc/testsuite/rust.test/struct-order-of-eval-1.rs delete mode 100644 gcc/testsuite/rust.test/struct-order-of-eval-2.rs delete mode 100644 gcc/testsuite/rust.test/struct-pattern-matching.rs delete mode 100644 gcc/testsuite/rust.test/struct-return.rs delete mode 100644 gcc/testsuite/rust.test/struct-update-moves-and-copies.rs delete mode 100644 gcc/testsuite/rust.test/struct_variant_xc.rs delete mode 100644 gcc/testsuite/rust.test/structured-compare.rs delete mode 100644 gcc/testsuite/rust.test/super.rs delete mode 100644 gcc/testsuite/rust.test/supertrait-default-generics.rs delete mode 100644 gcc/testsuite/rust.test/supported-cast.rs delete mode 100644 gcc/testsuite/rust.test/swap-1.rs delete mode 100644 gcc/testsuite/rust.test/swap-2.rs delete mode 100644 gcc/testsuite/rust.test/swap-overlapping.rs delete mode 100644 gcc/testsuite/rust.test/syntax-extension-bytes.rs delete mode 100644 gcc/testsuite/rust.test/syntax-extension-cfg.rs delete mode 100644 gcc/testsuite/rust.test/syntax-extension-minor.rs delete mode 100644 gcc/testsuite/rust.test/syntax-extension-shell.rs delete mode 100644 gcc/testsuite/rust.test/syntax-extension-source-utils.rs delete mode 100644 gcc/testsuite/rust.test/tag-align-dyn-u64.rs delete mode 100644 gcc/testsuite/rust.test/tag-align-dyn-variants.rs delete mode 100644 gcc/testsuite/rust.test/tag-align-shape.rs delete mode 100644 gcc/testsuite/rust.test/tag-align-u64.rs delete mode 100644 gcc/testsuite/rust.test/tag-disr-val-shape.rs delete mode 100644 gcc/testsuite/rust.test/tag-exports.rs delete mode 100644 gcc/testsuite/rust.test/tag-in-block.rs delete mode 100644 gcc/testsuite/rust.test/tag-variant-disr-type-mismatch.rs delete mode 100644 gcc/testsuite/rust.test/tag-variant-disr-val.rs delete mode 100644 gcc/testsuite/rust.test/tag.rs delete mode 100644 gcc/testsuite/rust.test/tail-call-arg-leak.rs delete mode 100644 gcc/testsuite/rust.test/tail-cps.rs delete mode 100644 gcc/testsuite/rust.test/tail-direct.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-0.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-1.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-10.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-11.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-12.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-13.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-14.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-15.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-16.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-17.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-3.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-4.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-5.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-6.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-7.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-9.rs delete mode 100644 gcc/testsuite/rust.test/task-comm-chan-nil.rs delete mode 100644 gcc/testsuite/rust.test/task-killjoin-rsrc.rs delete mode 100644 gcc/testsuite/rust.test/task-killjoin.rs delete mode 100644 gcc/testsuite/rust.test/task-life-0.rs delete mode 100644 gcc/testsuite/rust.test/task-spawn-move-and-copy.rs delete mode 100644 gcc/testsuite/rust.test/tempfile.rs delete mode 100644 gcc/testsuite/rust.test/terminate-in-initializer.rs delete mode 100644 gcc/testsuite/rust.test/test-ignore-cfg.rs delete mode 100644 gcc/testsuite/rust.test/test-runner-hides-main.rs delete mode 100644 gcc/testsuite/rust.test/threads.rs delete mode 100644 gcc/testsuite/rust.test/trait-bounds-basic.rs delete mode 100644 gcc/testsuite/rust.test/trait-bounds-in-arc.rs delete mode 100644 gcc/testsuite/rust.test/trait-bounds-recursion.rs delete mode 100644 gcc/testsuite/rust.test/trait-bounds.rs delete mode 100644 gcc/testsuite/rust.test/trait-cast.rs delete mode 100644 gcc/testsuite/rust.test/trait-composition-trivial.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-bound-subst.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-bound-subst2.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-bound-subst3.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-bound-subst4.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-bound.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-xc-2.rs delete mode 100644 gcc/testsuite/rust.test/trait-default-method-xc.rs delete mode 100644 gcc/testsuite/rust.test/trait-generic.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-auto-xc-2.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-auto-xc.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-auto.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited2.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-cast-without-call-to-supertrait.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-cast.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-cross-trait-call-xc.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-cross-trait-call.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-diamond.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-multiple-inheritors.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-multiple-params.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num0.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num1.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num2.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num3.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-num5.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-overloading-simple.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-overloading-xc-exe.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-overloading.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-self-in-supertype.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-self.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-simple.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-static.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-static2.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-subst.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-subst2.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance-visibility.rs delete mode 100644 gcc/testsuite/rust.test/trait-inheritance2.rs delete mode 100644 gcc/testsuite/rust.test/trait-object-generics.rs delete mode 100644 gcc/testsuite/rust.test/trait-region-pointer-simple.rs delete mode 100644 gcc/testsuite/rust.test/trait-static-method-overwriting.rs delete mode 100644 gcc/testsuite/rust.test/trait-to-str.rs delete mode 100644 gcc/testsuite/rust.test/trait-typedef-cc.rs delete mode 100644 gcc/testsuite/rust.test/trait-with-bounds-default.rs delete mode 100644 gcc/testsuite/rust.test/traits-default-method-macro.rs delete mode 100644 gcc/testsuite/rust.test/traits-default-method-mut.rs delete mode 100644 gcc/testsuite/rust.test/traits-default-method-self.rs delete mode 100644 gcc/testsuite/rust.test/traits-default-method-trivial.rs delete mode 100644 gcc/testsuite/rust.test/transmute-non-immediate-to-immediate.rs delete mode 100644 gcc/testsuite/rust.test/trivial-message.rs delete mode 100644 gcc/testsuite/rust.test/tup.rs delete mode 100644 gcc/testsuite/rust.test/tuple-struct-construct.rs delete mode 100644 gcc/testsuite/rust.test/tuple-struct-constructor-pointer.rs delete mode 100644 gcc/testsuite/rust.test/tuple-struct-destructuring.rs delete mode 100644 gcc/testsuite/rust.test/tuple-struct-matching.rs delete mode 100644 gcc/testsuite/rust.test/tuple-struct-trivial.rs delete mode 100644 gcc/testsuite/rust.test/tydesc-name.rs delete mode 100644 gcc/testsuite/rust.test/type-in-nested-module.rs delete mode 100644 gcc/testsuite/rust.test/type-namespace.rs delete mode 100644 gcc/testsuite/rust.test/type-param-constraints.rs delete mode 100644 gcc/testsuite/rust.test/type-param.rs delete mode 100644 gcc/testsuite/rust.test/type-params-in-for-each.rs delete mode 100644 gcc/testsuite/rust.test/type-ptr.rs delete mode 100644 gcc/testsuite/rust.test/type-sizes.rs delete mode 100644 gcc/testsuite/rust.test/type-use-i1-versus-i8.rs delete mode 100644 gcc/testsuite/rust.test/typeck-macro-interaction-issue-8852.rs delete mode 100644 gcc/testsuite/rust.test/typeclasses-eq-example-static.rs delete mode 100644 gcc/testsuite/rust.test/typeclasses-eq-example.rs delete mode 100644 gcc/testsuite/rust.test/typestate-cfg-nesting.rs delete mode 100644 gcc/testsuite/rust.test/typestate-multi-decl.rs delete mode 100644 gcc/testsuite/rust.test/u32-decr.rs delete mode 100644 gcc/testsuite/rust.test/u8-incr-decr.rs delete mode 100644 gcc/testsuite/rust.test/u8-incr.rs delete mode 100644 gcc/testsuite/rust.test/uint.rs delete mode 100644 gcc/testsuite/rust.test/unary-minus-suffix-inference.rs delete mode 100644 gcc/testsuite/rust.test/unfold-cross-crate.rs delete mode 100644 gcc/testsuite/rust.test/unify-return-ty.rs delete mode 100644 gcc/testsuite/rust.test/uniq-cc-generic.rs delete mode 100644 gcc/testsuite/rust.test/uniq-cc.rs delete mode 100644 gcc/testsuite/rust.test/unique-assign-copy.rs delete mode 100644 gcc/testsuite/rust.test/unique-assign-drop.rs delete mode 100644 gcc/testsuite/rust.test/unique-assign-generic.rs delete mode 100644 gcc/testsuite/rust.test/unique-assign.rs delete mode 100644 gcc/testsuite/rust.test/unique-autoderef-field.rs delete mode 100644 gcc/testsuite/rust.test/unique-autoderef-index.rs delete mode 100644 gcc/testsuite/rust.test/unique-cmp.rs delete mode 100644 gcc/testsuite/rust.test/unique-containing-tag.rs delete mode 100644 gcc/testsuite/rust.test/unique-copy-box.rs delete mode 100644 gcc/testsuite/rust.test/unique-create.rs delete mode 100644 gcc/testsuite/rust.test/unique-decl-init-copy.rs delete mode 100644 gcc/testsuite/rust.test/unique-decl-init.rs delete mode 100644 gcc/testsuite/rust.test/unique-decl-move-temp.rs delete mode 100644 gcc/testsuite/rust.test/unique-decl-move.rs delete mode 100644 gcc/testsuite/rust.test/unique-decl.rs delete mode 100644 gcc/testsuite/rust.test/unique-deref.rs delete mode 100644 gcc/testsuite/rust.test/unique-destructure.rs delete mode 100644 gcc/testsuite/rust.test/unique-drop-complex.rs delete mode 100644 gcc/testsuite/rust.test/unique-fn-arg-move.rs delete mode 100644 gcc/testsuite/rust.test/unique-fn-arg-mut.rs delete mode 100644 gcc/testsuite/rust.test/unique-fn-arg.rs delete mode 100644 gcc/testsuite/rust.test/unique-fn-ret.rs delete mode 100644 gcc/testsuite/rust.test/unique-generic-assign.rs delete mode 100644 gcc/testsuite/rust.test/unique-in-tag.rs delete mode 100644 gcc/testsuite/rust.test/unique-in-vec-copy.rs delete mode 100644 gcc/testsuite/rust.test/unique-in-vec.rs delete mode 100644 gcc/testsuite/rust.test/unique-init.rs delete mode 100644 gcc/testsuite/rust.test/unique-kinds.rs delete mode 100644 gcc/testsuite/rust.test/unique-log.rs delete mode 100644 gcc/testsuite/rust.test/unique-match-discrim.rs delete mode 100644 gcc/testsuite/rust.test/unique-move-drop.rs delete mode 100644 gcc/testsuite/rust.test/unique-move-temp.rs delete mode 100644 gcc/testsuite/rust.test/unique-move.rs delete mode 100644 gcc/testsuite/rust.test/unique-mutable.rs delete mode 100644 gcc/testsuite/rust.test/unique-object-move.rs delete mode 100644 gcc/testsuite/rust.test/unique-pat-2.rs delete mode 100644 gcc/testsuite/rust.test/unique-pat-3.rs delete mode 100644 gcc/testsuite/rust.test/unique-pat.rs delete mode 100644 gcc/testsuite/rust.test/unique-pinned-nocopy-2.rs delete mode 100644 gcc/testsuite/rust.test/unique-rec.rs delete mode 100644 gcc/testsuite/rust.test/unique-send-2.rs delete mode 100644 gcc/testsuite/rust.test/unique-send.rs delete mode 100644 gcc/testsuite/rust.test/unique-swap.rs delete mode 100644 gcc/testsuite/rust.test/unit-like-struct-drop-run.rs delete mode 100644 gcc/testsuite/rust.test/unit-like-struct.rs delete mode 100644 gcc/testsuite/rust.test/unit.rs delete mode 100644 gcc/testsuite/rust.test/unnamed_argument_mode.rs delete mode 100644 gcc/testsuite/rust.test/unreachable-code-1.rs delete mode 100644 gcc/testsuite/rust.test/unreachable-code.rs delete mode 100644 gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-blk.rs delete mode 100644 gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-fn.rs delete mode 100644 gcc/testsuite/rust.test/unsafe-pointer-assignability.rs delete mode 100644 gcc/testsuite/rust.test/unused-move-capture.rs delete mode 100644 gcc/testsuite/rust.test/unused-move.rs delete mode 100644 gcc/testsuite/rust.test/unwind-box.rs delete mode 100644 gcc/testsuite/rust.test/unwind-resource.rs delete mode 100644 gcc/testsuite/rust.test/unwind-resource2.rs delete mode 100644 gcc/testsuite/rust.test/unwind-unique.rs delete mode 100644 gcc/testsuite/rust.test/use-crate-name-alias.rs delete mode 100644 gcc/testsuite/rust.test/use-import-export.rs delete mode 100644 gcc/testsuite/rust.test/use-trait-before-def.rs delete mode 100644 gcc/testsuite/rust.test/use-uninit-match.rs delete mode 100644 gcc/testsuite/rust.test/use-uninit-match2.rs delete mode 100644 gcc/testsuite/rust.test/use.rs delete mode 100644 gcc/testsuite/rust.test/utf8.rs delete mode 100644 gcc/testsuite/rust.test/utf8_chars.rs delete mode 100644 gcc/testsuite/rust.test/utf8_idents.rs delete mode 100644 gcc/testsuite/rust.test/variant-attributes.rs delete mode 100644 gcc/testsuite/rust.test/variant-structs-trivial.rs delete mode 100644 gcc/testsuite/rust.test/vec-concat.rs delete mode 100644 gcc/testsuite/rust.test/vec-drop.rs delete mode 100644 gcc/testsuite/rust.test/vec-fixed-length.rs delete mode 100644 gcc/testsuite/rust.test/vec-growth.rs delete mode 100644 gcc/testsuite/rust.test/vec-ivec-deadlock.rs delete mode 100644 gcc/testsuite/rust.test/vec-late-init.rs delete mode 100644 gcc/testsuite/rust.test/vec-matching-autoslice.rs delete mode 100644 gcc/testsuite/rust.test/vec-matching-fixed.rs delete mode 100644 gcc/testsuite/rust.test/vec-matching-fold.rs delete mode 100644 gcc/testsuite/rust.test/vec-matching-legal-tail-element-borrow.rs delete mode 100644 gcc/testsuite/rust.test/vec-matching.rs delete mode 100644 gcc/testsuite/rust.test/vec-push.rs delete mode 100644 gcc/testsuite/rust.test/vec-self-append.rs delete mode 100644 gcc/testsuite/rust.test/vec-slice-drop.rs delete mode 100644 gcc/testsuite/rust.test/vec-slice.rs delete mode 100644 gcc/testsuite/rust.test/vec-tail-matching.rs delete mode 100644 gcc/testsuite/rust.test/vec-to_str.rs delete mode 100644 gcc/testsuite/rust.test/vec-trailing-comma.rs delete mode 100644 gcc/testsuite/rust.test/vec.rs delete mode 100644 gcc/testsuite/rust.test/vector-no-ann-2.rs delete mode 100644 gcc/testsuite/rust.test/warn-ctypes-inhibit.rs delete mode 100644 gcc/testsuite/rust.test/weird-exprs.rs delete mode 100644 gcc/testsuite/rust.test/while-cont.rs delete mode 100644 gcc/testsuite/rust.test/while-flow-graph.rs delete mode 100644 gcc/testsuite/rust.test/while-loop-constraints-2.rs delete mode 100644 gcc/testsuite/rust.test/while-prelude-drop.rs delete mode 100644 gcc/testsuite/rust.test/while-with-break.rs delete mode 100644 gcc/testsuite/rust.test/while.rs delete mode 100644 gcc/testsuite/rust.test/writealias.rs delete mode 100644 gcc/testsuite/rust.test/x86stdcall.rs delete mode 100644 gcc/testsuite/rust.test/x86stdcall2.rs delete mode 100644 gcc/testsuite/rust.test/xc_conditions_client.rs delete mode 100644 gcc/testsuite/rust.test/xc_conditions_client_2.rs delete mode 100644 gcc/testsuite/rust.test/xc_conditions_client_3.rs delete mode 100644 gcc/testsuite/rust.test/xc_conditions_client_4.rs delete mode 100644 gcc/testsuite/rust.test/xcrate-address-insignificant.rs delete mode 100644 gcc/testsuite/rust.test/xcrate-static-addresses.rs delete mode 100644 gcc/testsuite/rust.test/xcrate-unit-struct.rs delete mode 100644 gcc/testsuite/rust.test/yield.rs delete mode 100644 gcc/testsuite/rust.test/yield1.rs delete mode 100644 gcc/testsuite/rust.test/yield2.rs (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 551eb63..e5b4d3d 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -1,6 +1,6 @@ -# Make-lang.in -- Top level -*- makefile -*- fragment for gcc Go frontend. +# Make-lang.in -- Top level -*- makefile -*- fragment for GCC Rust frontend. -# Copyright (C) 2009-2019 Free Software Foundation, Inc. +# Copyright (C) 2009-2013 Free Software Foundation, Inc. # This file is part of GCC. @@ -20,189 +20,171 @@ # This file provides the language dependent support in the main Makefile. -# Installation name. +#RUST_EXES = rust -RSFLEXFLAGS= -RSBISONFLAGS=-v --debug +# Use strict warnings for this front end. +rust-warn = $(STRICT_WARN) -GCCRUST_INSTALL_NAME := $(shell echo gccrust|sed '$(program_transform_name)') -GCCRUST_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrust|sed '$(program_transform_name)') +# Installation name. Useful for cross compilers and used during install. +GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)') +GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)') -# The name for selecting rust in LANGUAGES. -rust: rust1$(exeext) +# Define the names for selecting rust in LANGUAGES. +rust: gccrs$(exeext) grs1$(exeext) +# Tell GNU make to ignore files by these names if they exist. .PHONY: rust -CFLAGS-rust/rustspec.o += $(DRIVER_DEFINES) - -GCCRUST_OBJS = $(GCC_OBJS) rust/rustspec.o -gccrust$(exeext): $(GCCRUST_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) - +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GCCRUST_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ - $(EXTRA_GCC_LIBS) $(LIBS) +# removed GRS_CFLAGS from here -# The cross-compiler version. This is built mainly as a signal to the -# rust.install-common target. If this executable exists, it means that -# rust.all.cross was run. -gccrust-cross$(exeext): gccrust$(exeext) - -rm -f gccrust-cross$(exeext) - cp gccrust$(exeext) gccrust-cross$(exeext) +CFLAGS-rust/rustspec.o += $(DRIVER_DEFINES) -# Use strict warnings. -rust-warn = $(STRICT_WARN) +# Create the compiler driver gccrs. +# A compiler driver is the program that interprets command argument and can be called from the command +# line - e.g. gcc or g++, and not cc1, which is the actual compiler -RUST_OBJS = \ - rust/rust-lang.o \ - rust/rust-backend.o \ - rust/rust-linemap.o \ - rust/rust-gcc-diagnostics.o \ - rust/rust-gcc.o \ - rust/node.o \ - rust/rs-parser.o \ - rust/rs-lexer.o \ - rust/rustly.o +# Create driver objects +GCCRS_D_OBJS = \ + $(GCC_OBJS) \ + rust/rustspec.o \ + $(END) -rust_OBJS = $(RUST_OBJS) rust/rustspec.o +gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) -rust1$(exeext): $(RUST_OBJS) attribs.o $(BACKEND) $(LIBDEPS) +# List of host object files used by the rust language - files for translation from the parse tree +# to GENERIC +# The compiler proper, not driver +GRS_OBJS = \ + rust/rust-lang.o \ + rust/rust-object-export.o \ + rust/rust-linemap.o \ + rust/rust-gcc-diagnostics.o \ + rust/rust-gcc.o \ + rust/rust-token.o \ + rust/rust-lex.o \ + rust/rust-parse.o \ + rust/rust-scope.o \ + rust/rust-ast-full-test.o \ + rust/rust-session-manager.o \ + $(END) +# removed object files from here + +# The compiler itself is called grs1 +grs1$(exeext): $(GRS_OBJS) attribs.o $(BACKEND) $(LIBDEPS) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(RUST_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) + $(GRS_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) -# Documentation. +# Build hooks. -RUST_TEXI_FILES = \ - rust/gccrust.texi \ - $(gcc_docdir)/include/fdl.texi \ - $(gcc_docdir)/include/gpl_v3.texi \ - $(gcc_docdir)/include/gcc-common.texi \ - gcc-vers.texi +# Copies its dependencies into the source directory. This generally should be used for generated files +# such as Bison output files which are not version-controlled, but should be included in any release +# tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’ +# was specified as a configure option. +rust.srcextra: -doc/gccrust.info: $(RUST_TEXI_FILES) - if test "x$(BUILD_INFO)" = xinfo; then \ - rm -f doc/gccrust.info*; \ - $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \ - -I $(gcc_docdir)/include -o $@ $<; \ - else true; fi +rust.all.cross: -doc/gccrust.dvi: $(RUST_TEXI_FILES) - $(TEXI2DVI) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $< +# idk what this does but someone used it +rust.start.encap: gccrs$(exeext) +rust.rest.encap: -doc/gccrust.pdf: $(RUST_TEXI_FILES) - $(TEXI2PDF) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $< +# Build generated man pages for the front end from Texinfo manuals (see Man Page Generation), in the +# build directory. This target is only called if the necessary tools are available, but should ignore +# errors so as not to stop the build if errors occur; man pages are optional and the tools involved +# may be installed in a broken way. +rust.man: -$(build_htmldir)/rust/index.html: $(RUST_TEXI_FILES) - $(mkinstalldirs) $(@D) - rm -f $(@D)/* - $(TEXI2HTML) -I $(gcc_docdir) -I $(gcc_docdir)/include \ - -I $(srcdir)/rust -o $(@D) $< +# Copies its dependencies into the source directory. These targets will be executed during a bootstrap +# if ‘--enable-generated-files-in-srcdir’ was specified as a configure option. +rust.srcman: -# .INTERMEDIATE: gccrust.pod +# Clean hooks. -# gccrust.pod: rust/gccrust.texi -# -$(TEXI2POD) -D gccrust < $< > $@ +rust.mostlyclean: +# cd $(srcdir)/rust; rm -f *.o y.tab.h y.tab.c lex.yy.c -# Build hooks. +rust.clean: rust.mostlyclean -rust.all.cross: gccrust-cross$(exeext) -rust.start.encap: gccrust$(exeext) -rust.rest.encap: -rust.info: doc/gccrust.info -rust.dvi: doc/gccrust.dvi -rust.pdf: doc/gccrust.pdf -rust.html: $(build_htmldir)/rust/index.html -rust.srcinfo: doc/gccrust.info - -cp -p $^ $(srcdir)/doc -rust.srcextra: +# Builds an etags TAGS file in the language subdirectory in the source tree. +# TODO: add more directories if I add more rust.tags: force cd $(srcdir)/rust; \ - etags -o TAGS.sub *.c *.h rustfrontend/*.h rustfrontend/*.cc; \ + etags -o TAGS.sub *.y *.l *.cc *.h ast/*.h ast/*.cc lex/*.h lex/*.cc parse/*.h parse/*.cc; \ etags --include TAGS.sub --include ../TAGS.sub -rust.man: -# rust.man: doc/gccrust.1 -# rust.srcman: doc/gccrust.1 -# -cp -p $^ $(srcdir)/doc -lang_checks += check-rust -lang_checks_parallelized += check-rust -check_rust_parallelize = 10 +# Build documentation hooks. -# No rust-specific selftests -selftest-rust: +# Build info documentation for the front end, in the build directory. This target is only called by +# ‘make bootstrap’ if a suitable version of makeinfo is available, so does not need to check for this, +# and should fail if an error occurs. +rust.info: + +rust.srcinfo: + +# Build DVI documentation for the front end, in the build directory. This should be done using +# $(TEXI2DVI), with appropriate -I arguments pointing to directories of included files. +rust.dvi: + +# Build PDF documentation for the front end, in the build directory. This should be done using +# $(TEXI2PDF), with appropriate -I arguments pointing to directories of included files. +rust.pdf: + +doc/rust.info: +doc/rust.dvi: +doc/rust.pdf: + +# Build HTML documentation for the front end, in the build directory. +rust.html: # Install hooks. +# Install everything that is part of the front end, apart from the compiler executables listed in +# compilers in config-lang.in. rust.install-common: installdirs - -rm -f $(DESTDIR)$(bindir)/$(GCCRUST_INSTALL_NAME)$(exeext) - $(INSTALL_PROGRAM) gccrust$(exeext) $(DESTDIR)$(bindir)/$(GCCRUST_INSTALL_NAME)$(exeext) - -if test -f rust1$(exeext); then \ - if test -f gccrust-cross$(exeext); then \ - :; \ - else \ - rm -f $(DESTDIR)$(bindir)/$(GCCRUST_TARGET_INSTALL_NAME)$(exeext); \ - ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(GCCRUST_INSTALL_NAME)$(exeext) $(GCCRUST_TARGET_INSTALL_NAME)$(exeext) ); \ - fi; \ - fi - +# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) +# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext) +# $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) +# if test -f $(DESTDIR)$(bindir)$(GCCRS_TARGET_INSTALL_NAME)$(exeext); then \ +# :; \ +# else \ +# cd $(DESTDIR)$(bindir) && \ +# $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ +# fi + -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) + $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) + rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ + ( cd $(DESTDIR)$(bindir) && \ + $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext) ); \ + +# Install headers needed for plugins. rust.install-plugin: -# rust.install-info: $(DESTDIR)$(infodir)/gccrust.info -rust.install-info: - -# rust.install-pdf: doc/gccrust.pdf -# @$(NORMAL_INSTALL) -# test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc" -# @for p in doc/gccrust.pdf; do \ -# if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ -# f=$(pdf__strip_dir) \ -# echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \ -# $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \ -# done -rust.install-pdf: - -# rust.install-html: $(build_htmldir)/rust -# @$(NORMAL_INSTALL) -# test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)" -# @for p in $(build_htmldir)/rust; do \ -# if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \ -# f=$(html__strip_dir) \ -# if test -d "$$d$$p"; then \ -# echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \ -# $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ -# echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ -# $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \ -# else \ -# echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \ -# $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \ -# fi; \ -# done - -# rust.install-man: $(DESTDIR)$(man1dir)/$(GCCRUST_INSTALL_NAME)$(man1ext) -rust.install-man: +# Uninstall files installed by installing the compiler. This is currently documented not to be +# supported, so the hook need not do anything. +rust.uninstall: +# -rm -rf $(DESTDIR)/$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) + -rm -f gccrs$(exeext) grs1$(exeext) + -rm -f $(GRS_OBJS) +# ^those two are a maybe -# $(DESTDIR)$(man1dir)/$(GCCRUST_INSTALL_NAME)$(man1ext): doc/gccrust.1 installdirs -# -rm -f $@ -# -$(INSTALL_DATA) $< $@ -# -chmod a-x $@ +# No rust-specific selftests +selftest-rust: -rust.uninstall: - rm -rf $(DESTDIR)$(bindir)/$(GCCRUST_INSTALL_NAME)$(exeext) - rm -rf $(DESTDIR)$(man1dir)/$(GCCRUST_INSTALL_NAME)$(man1ext) - rm -rf $(DESTDIR)$(bindir)/$(GCCRUST_TARGET_INSTALL_NAME)$(exeext) - rm -rf $(DESTDIR)$(infodir)/gccrust.info* +# Install info documentation for the front end, if it is present in the source directory. This target +# should have dependencies on info files that should be installed. +rust.install-info: -# Clean hooks. +rust.install-pdf: -rust.mostlyclean: - -rm -f rust/*$(objext) - -rm -f rust/*$(coverageexts) - -rm -f gccrust$(exeext) gccrust-cross$(exeext) rust1$(exeext) -rust.clean: -rust.distclean: -rust.maintainer-clean: - -rm -f $(docobjdir)/gccrust.1 +# Install man pages for the front end. This target should ignore errors. +rust.install-man: -# Stage hooks. +# Stage hooks: +# The toplevel makefile has already created stage?/rust at this point. +# Used for handling bootstrap rust.stage1: stage1-start -mv rust/*$(objext) stage1/rust @@ -220,27 +202,28 @@ rust.stagefeedback: stagefeedback-start CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" -RUSTINCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/rustfrontend - -CFLAGS-rust/rust-gcc.o += $(RUSTINCLUDES) -CFLAGS-rust/rust-linemap.o += $(RUSTINCLUDES) -CFLAGS-rust/rust-gcc-diagnostics.o += $(RUSTINCLUDES) -CFLAGS-rust/rust-encode-id.o += $(RUSTINCLUDES) +# cross-folder includes - add new folders later +RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse -I $(srcdir)/rust/ast -rust/rs-parser.cc: rust/rustfrontend/rs-parser.y - $(BISON) $(RSBISONFLAGS) --defines=rust/rs-parser.h -o $@ $< +# add files that require cross-folder includes - currently rust-lang.o, rust-lex.o +CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) +CFLAGS-rust/rust-lex.o += $(RUST_INCLUDES) +CFLAGS-rust/rust-parse.o += $(RUST_INCLUDES) +CFLAGS-rust/rust-session-manager.o += $(RUST_INCLUDES) -rust/rs-lexer.cc: rust/rustfrontend/rs-lexer.l - $(FLEX) $(RSFLEXFLAGS) -o $@ $< +# TODO: possibly find a way to ensure C++11 compilation level here? -rust/rs-parser.o: rust/rs-parser.cc - $(COMPILE) $(RUSTINCLUDES) $< +# build all rust/lex files in rust folder, add cross-folder includes +rust/%.o: rust/lex/%.cc + $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< $(POSTCOMPILE) -rust/rs-lexer.o: rust/rs-lexer.cc - $(COMPILE) $(RUSTINCLUDES) $< +# build all rust/parse files in rust folder, add cross-folder includes +rust/%.o: rust/parse/%.cc + $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< $(POSTCOMPILE) -rust/%.o: rust/rustfrontend/%.cc - $(COMPILE) $(RUSTINCLUDES) $< +# build rust/ast files in rust folder +rust/%.o: rust/ast/%.cc + $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< $(POSTCOMPILE) diff --git a/gcc/rust/TO_notes.txt b/gcc/rust/TO_notes.txt deleted file mode 100644 index 2e29028..0000000 --- a/gcc/rust/TO_notes.txt +++ /dev/null @@ -1,48 +0,0 @@ -TO notes: - -This is the actual compiler frontend. - -What needs to occur in a frontend according to GCC docs: - -Parsing pass: --Language frontend is only invoked once via lang_hooks.parse_file (which parses any input) --Frontend may use any intermediate language representation deemed appropriate (i.e. could use MIR like in actual Rust, but GENERIC trees would probably be used) --At some point, the frontend must translate the intermediate language representation used inside it to a representation understood by the rest of the compiler (GIMPLE or maybe GENERIC). There are two current ways of doing this: - -C frontend manually invokes gimplifier on each function, and uses gimplifier callbacks to convert language-specific tree nodes directly to GIMPLE before passing function off to be compiled. - -Fortran frontend converts from private representation to GENERIC, which is later lowered to GIMPLE when the function is compiled. - -Also, a front end could generate GIMPLE directly, which is a "moderately complex process" but would maybe mean that more of the Rust LLVM frontend could be used without modification. - -Which route to choose depends on how well GENERIC (plus extensions) can be made to match up with the source language and necessary parsing data structures. The easiest seems to be the Fortran method, i.e. just make GENERIC. --Note that each function (and top level declaration) must be passed separately to the middle end or something. Function and data definitions must be passed to the middle-end, and for debug info, data and type declarations should also be passed. --Front end needs complete top-level function or data declaration, and each data definition should be passed to rest_of_decl_compilation . Each complete type definition should be passed to rest_of_type_compilation . Each function definition should be passed to cgraph_finalize_function . --Middle-end will either emit the function and data definitions immediately or queue them for later processing. - -Gimplification pass: --Consists of conversion of frontend's intermediate representation to GIMPLE --Main entry point is gimplify_function_tree in gimplify.c . From here, the entire function is processed, gimplifying each statement in turn. Main workhorse for this pass is gimplify_expr . Approximately everything passes through here at least once, and it is from here that we invoke lang_hooks.gimplify_expr callback. --Callback should examine the expression and return GS_UNHANDLED if the expression is not a language-specific construct that requires attention. Otherwise it should alter the expression in some way to progress towards it being valid GIMPLE. If callback is certain that transformation is complete and expression is valid GIMPLE, should return GS_ALL_DONE . Otherwise, return GS_OK , which causes expression to be processed again. If callback encounters error during transformation (because frontend relies on gimplification to finish semantic checks), return GS_ERROR . - -Pass manager: --Pass manager is located in passes.c, tree-optimize.c, and tree-pass.h . It processes passes as defined in passes.def . It runs all passes in correct order. etc. more stuff - -After this, the AST should be built in GIMPLE or whatever, so the middle-end and back-end of GCC take care of the rest of compilation, I hope. - - - -Notes on GENERIC: --A language-independent way of representing an entire _function_ in trees. If you can express it with gcc/tree.def, it's GENERIC. --A statement is defined as an expression whose value, if any, is ignored. A statement will always have TREE_SIDE_EFFECTS set, but a non-statement expression may also have side effects, e.g. CALL_EXPR (probably a function call). --Implication that frontends lower GENERIC to GIMPLE. - -Trees: --The central data structure, tree, is a node of C type tree. It is a pointer type, but the object it points to may be a variety of types. --Can tell what kind of a node a tree is by using TREE_CODE macro. Many macros take trees as input and return trees as output. Most require a certain kind of tree node as input, i.e. there is a particular type system for trees not reflected in C's type system. --For safety, useful to configure GCC with --enable-checking . All tree types are checked at runtime as a result, destroying performance but aiding debugging. --Many macros behave as predicates (a function used to test something about a supplied argument - e.g. lambda expression LINQ), and many, though not all, of these end in _P . Don't rely on result type of macros being of any particular type, but may rely on fact that type can be compared to 0, so statements like "int i = (TEST_P(t) != 0);" are legal. Macros that return int values now may be changed to return tree values, or other pointers in the future. Thus, should not write code like "if (TEST_P(t) == 1)". -- - - - -Notes on basic outline: --rustc and mrustc appear to use a hand-written recursive-descent parser, not a bison-generated LALR parser. --I don't know if redbrain's original parser was bison LALR or handwritten recursive-descent - it seemed to have aspects of both. However, he mentioned using a bison-generated parser initially and then moving to a handwritten one later. --As such, own parser should probably be hand-written recursive-descent. \ No newline at end of file diff --git a/gcc/rust/ast/clone-test.h b/gcc/rust/ast/clone-test.h new file mode 100644 index 0000000..0c71c82 --- /dev/null +++ b/gcc/rust/ast/clone-test.h @@ -0,0 +1,90 @@ +#ifndef CLONE_TEST_H +#define CLONE_TEST_H +// Potential fancy deep cloning test for use with unique_ptr + +// disable by default +#if 0 +#include + +namespace clone_code { + template + class abstract_method {}; + + template + class virtual_inherit_from : virtual public T { + using T::T; + }; + + template + class clone_inherit : public Bases... { + public: + virtual ~clone_inherit() = default; + + std::unique_ptr clone() const { + return std::unique_ptr(static_cast(this->clone_impl())); + } + + protected: + private: + virtual clone_inherit* clone_impl() const override { + return new Derived(static_cast(*this)); + } + }; + + template + class clone_inherit, Bases...> : public Bases... { + public: + virtual ~clone_inherit() = default; + + std::unique_ptr clone() const { + return std::unique_ptr(static_cast(this->clone_impl())); + } + + protected: + private: + virtual clone_inherit* clone_impl() const = 0; + }; + + template + class clone_inherit { + public: + virtual ~clone_inherit() = default; + + std::unique_ptr clone() const { + return std::unique_ptr(static_cast(this->clone_impl())); + } + + private: + virtual clone_inherit* clone_impl() const override { + return new Derived(static_cast(*this)); + } + }; + + template + class clone_inherit > { + public: + virtual ~clone_inherit() = default; + + std::unique_ptr clone() const { + return std::unique_ptr(static_cast(this->clone_impl())); + } + + private: + virtual clone_inherit* clone_impl() const = 0; + }; +} + +namespace user_code { + using namespace clone_code; + + class cloneable : public clone_inherit > {}; + + class foo : public clone_inherit, virtual_inherit_from > {}; + + class bar : public clone_inherit, virtual_inherit_from > {}; + + class concrete : public clone_inherit {}; +} +#endif + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-ast-containers.h b/gcc/rust/ast/rust-ast-containers.h new file mode 100644 index 0000000..81b0187 --- /dev/null +++ b/gcc/rust/ast/rust-ast-containers.h @@ -0,0 +1,48 @@ +#ifndef RUST_AST_CONTAINERS_H +#define RUST_AST_CONTAINERS_H +// crappy redefined AST maybe. may move + +/* This is mainly the "logical", more "abstract" representation of the code, while the "AST" itself is + * more high-level and matches the language better. */ + +// this is now deprecated and replaced with the proper AST +#error "rust-ast-containers.h was included by accident. Don't use." + +namespace Rust { + namespace AST { + struct Module { + public: + }; + + struct Crate { + public: + Module root_module; + }; + + // replace with rust-types.h version + struct AttributeList { + public: + //::std::vector attribs; + }; + + // replace with rust-types.h version + struct Visibility {}; + + /*enum VisibilityType { + Private, + PublicFull, + PublicInPath, + PublicCrate, + PublicSuper, + PublicSelfModule + }; + + // Represents visibility - maybe make into an enum or union or something + struct Visibility { + }; + + */ + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h new file mode 100644 index 0000000..a76a599 --- /dev/null +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -0,0 +1,265 @@ +#ifndef RUST_AST_FULL_DECLS_H +#define RUST_AST_FULL_DECLS_H +// Forward declarations for all AST classes. Useful for not having to include all definitions. + +namespace Rust { + namespace AST { + // rust-ast.h + class AttrInput; + class TokenTree; + class MacroMatch; + class Token; + struct Literal; + class DelimTokenTree; + class PathSegment; + class SimplePathSegment; + class SimplePath; + struct Attribute; + class MetaItemInner; + class AttrInputMetaItemContainer; + class MetaItem; + class Stmt; + class Item; + class Expr; + class ExprWithoutBlock; + class IdentifierExpr; + class Pattern; + class Type; + class TypeNoBounds; + class TypeParamBound; + class Lifetime; + class GenericParam; + class LifetimeParam; + class MacroItem; + class TraitItem; + class InherentImplItem; + class TraitImplItem; + class MacroInvocationSemi; + struct Crate; + class PathExpr; + + // rust-path.h + class PathIdentSegment; + struct GenericArgsBinding; + struct GenericArgs; + class PathExprSegment; + class PathPattern; + class PathInExpression; + class TypePathSegment; + class TypePathSegmentGeneric; + struct TypePathFunction; + class TypePathSegmentFunction; + class TypePath; + struct QualifiedPathType; + class QualifiedPathInExpression; + class QualifiedPathInType; + + // rust-expr.h + class ExprWithBlock; + class LiteralExpr; + class AttrInputLiteral; + class MetaItemLitExpr; + class MetaItemPathLit; + class OperatorExpr; + class BorrowExpr; + class DereferenceExpr; + class ErrorPropagationExpr; + class NegationExpr; + class ArithmeticOrLogicalExpr; + class ComparisonExpr; + class LazyBooleanExpr; + class TypeCastExpr; + class AssignmentExpr; + class CompoundAssignmentExpr; + class GroupedExpr; + class ArrayElems; + class ArrayElemsValues; + class ArrayElemsCopied; + class ArrayExpr; + class ArrayIndexExpr; + class TupleExpr; + class TupleIndexExpr; + class StructExpr; + class StructExprStruct; + struct StructBase; + class StructExprField; + class StructExprFieldIdentifier; + class StructExprFieldWithVal; + class StructExprFieldIdentifierValue; + class StructExprFieldIndexValue; + class StructExprStructFields; + class StructExprStructBase; + class StructExprTuple; + class StructExprUnit; + class EnumVariantExpr; + class EnumExprField; + class EnumExprFieldIdentifier; + class EnumExprFieldWithVal; + class EnumExprFieldIdentifierValue; + class EnumExprFieldIndexValue; + class EnumExprStruct; + class EnumExprTuple; + class EnumExprFieldless; + class CallExpr; + class MethodCallExpr; + class FieldAccessExpr; + struct ClosureParam; + class ClosureExpr; + class ClosureExprInner; + class BlockExpr; + class ClosureExprInnerTyped; + class ContinueExpr; + class BreakExpr; + class RangeExpr; + class RangeFromToExpr; + class RangeFromExpr; + class RangeToExpr; + class RangeFullExpr; + class RangeFromToInclExpr; + class RangeToInclExpr; + class ReturnExpr; + class UnsafeBlockExpr; + class LoopLabel; + class BaseLoopExpr; + class LoopExpr; + class WhileLoopExpr; + class WhileLetLoopExpr; + class ForLoopExpr; + class IfExpr; + class IfExprConseqElse; + class IfExprConseqIf; + class IfLetExpr; + class IfExprConseqIfLet; + class IfLetExprConseqElse; + class IfLetExprConseqIf; + class IfLetExprConseqIfLet; + struct MatchArm; + class MatchCase; + class MatchCaseBlockExpr; + class MatchCaseExpr; + class MatchExpr; + class AwaitExpr; + class AsyncBlockExpr; + + // rust-stmt.h + class EmptyStmt; + class LetStmt; + class ExprStmt; + class ExprStmtWithoutBlock; + class ExprStmtWithBlock; + + // rust-item.h + class TypeParam; + class WhereClauseItem; + class LifetimeWhereClauseItem; + class TypeBoundWhereClauseItem; + struct WhereClause; + struct SelfParam; + struct FunctionQualifiers; + struct FunctionParam; + struct Visibility; + class Method; + class VisItem; + class Module; + class ModuleBodied; + class ModuleNoBody; + class ExternCrate; + class UseTree; + class UseTreeGlob; + class UseTreeList; + class UseTreeRebind; + class UseDeclaration; + class Function; + class TypeAlias; + class Struct; + struct StructField; + class StructStruct; + struct TupleField; + class TupleStruct; + class EnumItem; + class EnumItemTuple; + class EnumItemStruct; + class EnumItemDiscriminant; + class Enum; + class Union; + class ConstantItem; + class StaticItem; + struct TraitFunctionDecl; + class TraitItemFunc; + struct TraitMethodDecl; + class TraitItemMethod; + class TraitItemConst; + class TraitItemType; + class Trait; + class Impl; + class InherentImpl; + class TraitImpl; + class ExternalItem; + class ExternalStaticItem; + struct NamedFunctionParam; + class ExternalFunctionItem; + class ExternBlock; + + // rust-macro.h + class MacroMatchFragment; + class MacroMatchRepetition; + class MacroMatcher; + struct MacroTranscriber; + struct MacroRule; + class MacroRulesDefinition; + class MacroInvocation; + class MetaItemPath; + class MetaItemSeq; + class MetaWord; + class MetaNameValueStr; + class MetaListPaths; + class MetaListNameValueStr; + + // rust-pattern.h + class LiteralPattern; + class IdentifierPattern; + class WildcardPattern; + class RangePatternBound; + class RangePatternBoundLiteral; + class RangePatternBoundPath; + class RangePatternBoundQualPath; + class RangePattern; + class ReferencePattern; + struct StructPatternEtc; + class StructPatternField; + class StructPatternFieldTuplePat; + class StructPatternFieldIdentPat; + class StructPatternFieldIdent; + struct StructPatternElements; + class StructPattern; + class TupleStructItems; + class TupleStructItemsNoRange; + class TupleStructItemsRange; + class TupleStructPattern; + class TuplePatternItems; + class TuplePatternItemsMultiple; + class TuplePatternItemsRanged; + class TuplePattern; + class GroupedPattern; + class SlicePattern; + + // rust-type.h + class TraitBound; + class ImplTraitType; + class TraitObjectType; + class ParenthesisedType; + class ImplTraitTypeOneBound; + class TraitObjectTypeOneBound; + class TupleType; + class NeverType; + class RawPointerType; + class ReferenceType; + class ArrayType; + class SliceType; + class InferredType; + struct MaybeNamedParam; + class BareFunctionType; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc new file mode 100644 index 0000000..216299d --- /dev/null +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -0,0 +1,4610 @@ +#include "rust-ast-full.h" +#include "diagnostic.h" + +#include "rust-ast-visitor.h" + +#include "rust-session-manager.h" + +/* Compilation unit used for various AST-related functions that would make the headers too long if + * they were defined inline and don't receive any benefits from being defined inline because they are + * virtual. Also used for various other stuff. */ + +namespace Rust { + namespace AST { + // Gets a string in a certain delim type. + ::std::string get_string_in_delims(::std::string str_input, DelimType delim_type) { + switch (delim_type) { + case PARENS: + return "(" + str_input + ")"; + case SQUARE: + return "[" + str_input + "]"; + case CURLY: + return "{" + str_input + "}"; + default: + return "ERROR-MARK-STRING (delims)"; + } + gcc_unreachable(); + } + + // Converts a frag spec enum item to a string form. + ::std::string frag_spec_to_str(MacroFragSpec frag_spec) { + switch (frag_spec) { + case BLOCK: + return "block"; + case EXPR: + return "expr"; + case IDENT: + return "ident"; + case ITEM: + return "item"; + case LIFETIME: + return "lifetime"; + case LITERAL: + return "literal"; + case META: + return "meta"; + case PAT: + return "pat"; + case PATH: + return "path"; + case STMT: + return "stmt"; + case TT: + return "tt"; + case TY: + return "ty"; + case VIS: + return "vis"; + case INVALID: + return "INVALID_FRAG_SPEC"; + default: + return "ERROR_MARK_STRING - unknown frag spec"; + } + } + + ::std::string Crate::as_string() const { + fprintf(stderr, "beginning crate recursive as-string\n"); + + ::std::string str("Crate: "); + // add utf8bom and shebang + if (has_utf8bom) { + str += "\n has utf8bom"; + } + if (has_shebang) { + str += "\n has shebang"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + // items + str += "\n items: "; + if (items.empty()) { + str += "none"; + } else { + for (const auto& item : items) { + // DEBUG: null pointer check + if (item == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer item in crate."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + item->as_string(); + } + } + + return str + "\n"; + } + + ::std::string Attribute::as_string() const { + ::std::string path_str = path.as_string(); + if (attr_input == NULL) { + return path_str; + } else { + return path_str + attr_input->as_string(); + } + } + + ::std::string DelimTokenTree::as_string() const { + ::std::string start_delim; + ::std::string end_delim; + switch (delim_type) { + case PARENS: + start_delim = "("; + end_delim = ")"; + break; + case SQUARE: + start_delim = "["; + end_delim = "]"; + break; + case CURLY: + start_delim = "{"; + end_delim = "}"; + break; + default: + // error + return ""; + } + ::std::string str = start_delim; + if (token_trees.empty()) { + str += "none"; + } else { + for (const auto& tree : token_trees) { + // DEBUG: null pointer check + if (tree == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "token tree in delim token tree."); + return "NULL_POINTER_MARK"; + } + + str += tree->as_string() + ", "; + } + } + str += end_delim; + + return str; + } + + ::std::string Token::as_string() const { + /* FIXME: only works when not identifier or literal or whatever, i.e. when doesn't store + * string value */ + // return get_token_description(token_id); + + // maybe fixed - stores everything as string though, so storage-inefficient + return str; + } + + ::std::string SimplePathSegment::as_string() const { + return segment_name; + } + + ::std::string SimplePath::as_string() const { + ::std::string path; + if (has_opening_scope_resolution) { + path = "::"; + } + + // crappy hack because doing proper for loop would be more code + bool first_time = true; + for (const auto& segment : segments) { + if (first_time) { + path += segment.as_string(); + first_time = false; + } else { + path += "::" + segment.as_string(); + } + + // DEBUG: remove later. Checks for path error. + if (segment.is_error()) { + fprintf(stderr, + "segment in path is error - this should've been filtered out. first segment " + "was '%s' \n", + segments.at(0).as_string().c_str()); + } + } + + return path; + } + + ::std::string Visibility::as_string() const { + switch (public_vis_type) { + case NONE: + return ::std::string("pub"); + case CRATE: + return ::std::string("ub(crate)"); + case SELF: + return ::std::string("pub(self)"); + case SUPER: + return ::std::string("pub(super)"); + case IN_PATH: + return ::std::string("pub(in ") + in_path.as_string() + ::std::string(")"); + default: + gcc_unreachable(); + } + } + + // Creates a string that reflects the visibility stored. + ::std::string VisItem::as_string() const { + // FIXME: can't do formatting on string to make identation occur. + ::std::string str = Item::as_string(); + + if (has_visibility()) { + str = visibility.as_string() + " "; + } + + return str; + } + + // Creates a string that reflects the outer attributes stored. + ::std::string Item::as_string() const { + ::std::string str; + + if (!outer_attrs.empty()) { + for (const auto& attr : outer_attrs) { + str += attr.as_string() + "\n"; + } + } + + return str; + } + + ::std::string Module::as_string() const { + ::std::string vis_item = VisItem::as_string(); + + return vis_item + "mod " + module_name; + } + + ::std::string ModuleBodied::as_string() const { + // get module string for "[vis] mod [name]" + ::std::string str = Module::as_string(); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + // items + str += "\n items: "; + if (items.empty()) { + str += "none"; + } else { + for (const auto& item : items) { + // DEBUG: null pointer check + if (item == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer item in crate."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + item->as_string(); + } + } + + return str + "\n"; + } + + ::std::string ModuleNoBody::as_string() const { + ::std::string str = Module::as_string(); + + str += "\n no body (reference to external file)"; + + return str + "\n"; + } + + ::std::string StaticItem::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "static"; + + if (has_mut) { + str += " mut"; + } + + str += name; + + // DEBUG: null pointer check + if (type == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer type in static item."); + return "NULL_POINTER_MARK"; + } + str += "\n Type: " + type->as_string(); + + // DEBUG: null pointer check + if (expr == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer expr in static item."); + return "NULL_POINTER_MARK"; + } + str += "\n Expression: " + expr->as_string(); + + return str + "\n"; + } + + ::std::string ExternCrate::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "extern crate " + referenced_crate; + + if (has_as_clause()) { + str += " as " + as_clause_name; + } + + return str; + } + + ::std::string TupleStruct::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + // tuple fields + str += "\n Tuple fields: "; + if (fields.empty()) { + str += "none"; + } else { + for (const auto& field : fields) { + str += "\n " + field.as_string(); + } + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string ConstantItem::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "const " + identifier; + + // DEBUG: null pointer check + if (type == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer type in const item."); + return "NULL_POINTER_MARK"; + } + str += "\n Type: " + type->as_string(); + + // DEBUG: null pointer check + if (const_expr == NULL) { + fprintf(stderr, + "something really terrible has gone wrong - null pointer expr in const item."); + return "NULL_POINTER_MARK"; + } + str += "\n Expression: " + const_expr->as_string(); + + return str + "\n"; + } + + ::std::string InherentImpl::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in inherent impl."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Type: " + trait_type->as_string(); + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + // inherent impl items + str += "\n Inherent impl items: "; + if (!has_impl_items()) { + str += "none"; + } else { + for (const auto& item : impl_items) { + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string Method::as_string() const { + ::std::string str("Method: \n "); + + str += vis.as_string() + " " + qualifiers.as_string(); + + str += " fn " + method_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in method."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Self param: " + self_param.as_string(); + + str += "\n Function params: "; + if (function_params.empty()) { + str += "none"; + } else { + for (const auto& param : function_params) { + str += "\n " + param.as_string(); + } + } + + str += "\n Return type: "; + if (has_return_type()) { + str += return_type->as_string(); + } else { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + str += "\n Block expr (body): \n "; + str += expr->as_string(); + + return str; + } + + ::std::string StructStruct::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + // struct fields + str += "\n Struct fields: "; + if (is_unit) { + str += "none (unit)"; + } else if (fields.empty()) { + str += "none (non-unit)"; + } else { + for (const auto& field : fields) { + str += "\n " + field.as_string(); + } + } + + return str; + } + + ::std::string UseDeclaration::as_string() const { + ::std::string str = VisItem::as_string(); + + // DEBUG: null pointer check + if (use_tree == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer use tree in " + "use declaration."); + return "NULL_POINTER_MARK"; + } + + str += "use " + use_tree->as_string(); + + return str; + } + + ::std::string UseTreeGlob::as_string() const { + switch (glob_type) { + case NO_PATH: + return "*"; + case GLOBAL: + return "::*"; + case PATH_PREFIXED: { + ::std::string path_str = path.as_string(); + return path_str + "::*"; + } + default: + // some kind of error + return "ERROR-PATH"; + } + gcc_unreachable(); + } + + ::std::string UseTreeList::as_string() const { + ::std::string path_str; + switch (path_type) { + case NO_PATH: + path_str = "{"; + break; + case GLOBAL: + path_str = "::{"; + break; + case PATH_PREFIXED: { + path_str = path.as_string() + "::{"; + break; + } + default: + // some kind of error + return "ERROR-PATH-LIST"; + } + + if (has_trees()) { + for (const auto& tree : trees) { + // DEBUG: null pointer check + if (tree == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "tree in use tree list."); + return "NULL_POINTER_MARK"; + } + + path_str += tree->as_string() + ", "; + } + } else { + path_str += "none"; + } + + return path_str + "}"; + } + + ::std::string UseTreeRebind::as_string() const { + ::std::string path_str = path.as_string(); + + switch (bind_type) { + case NONE: + // nothing to add, just path + break; + case IDENTIFIER: + path_str += " as " + identifier; + break; + case WILDCARD: + path_str += " as _"; + break; + default: + // error + return "ERROR-PATH-REBIND"; + } + + return path_str; + } + + ::std::string Enum::as_string() const { + ::std::string str = VisItem::as_string(); + str += enum_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + // items + str += "\n Items: "; + if (items.empty()) { + str += "none"; + } else { + for (const auto& item : items) { + // DEBUG: null pointer check + if (item == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "enum item in enum."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string Trait::as_string() const { + ::std::string str = VisItem::as_string(); + + if (has_unsafe) { + str += "unsafe "; + } + + str += "trait " + name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in trait."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Type param bounds: "; + if (!has_type_param_bounds()) { + str += "none"; + } else { + for (const auto& bound : type_param_bounds) { + // DEBUG: null pointer check + if (bound == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "type param bound in trait."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + bound->as_string(); + } + } + + str += "\n Where clause: "; + if (!has_where_clause()) { + str += "none"; + } else { + str += where_clause.as_string(); + } + + str += "\n Trait items: "; + if (!has_trait_items()) { + str += "none"; + } else { + for (const auto& item : trait_items) { + // DEBUG: null pointer check + if (item == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "trait item in trait."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string Union::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "union " + union_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in union."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + // struct fields + str += "\n Struct fields (variants): "; + if (variants.empty()) { + str += "none"; + } else { + for (const auto& field : variants) { + str += "\n " + field.as_string(); + } + } + + return str; + } + + ::std::string Function::as_string() const { + ::std::string str = VisItem::as_string() + "Function: "; + ::std::string qualifiers_str = "Qualifiers: " + qualifiers.as_string(); + + ::std::string generic_params_str("Generic params: "); + if (has_generics()) { + for (const auto& generic_param : generic_params) { + // DEBUG: null pointer check + if (generic_param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in function item."); + return "NULL_POINTER_MARK"; + } + + generic_params_str += generic_param->as_string() + ", "; + } + } else { + generic_params_str += "none"; + } + + ::std::string function_params_str("Function params: "); + if (has_function_params()) { + for (const auto& param : function_params) { + function_params_str += param.as_string() + ", "; + } + } else { + function_params_str += "none"; + } + + ::std::string return_type_str("Return type: "); + if (has_function_return_type()) { + // DEBUG: null pointer check + if (return_type == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer return " + "type in function."); + return "NULL_POINTER_MARK"; + } + + return_type_str += return_type->as_string(); + } else { + return_type_str += "none (void)"; + } + + ::std::string where_clause_str("Where clause: "); + if (has_where_clause()) { + where_clause_str += where_clause.as_string(); + } else { + where_clause_str += "none"; + } + + // DEBUG: null pointer check + if (function_body == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer function " + "body in function."); + return "NULL_POINTER_MARK"; + } + ::std::string body_str = "Body: " + function_body->as_string(); + + str += "\n " + qualifiers_str + "\n " + generic_params_str + "\n " + + function_params_str + "\n " + return_type_str + "\n " + where_clause_str + + "\n " + body_str; + + return str; + } + + ::std::string WhereClause::as_string() const { + // just print where clause items, don't mention "where" or "where clause" + ::std::string str; + + if (where_clause_items.empty()) { + str = "none"; + } else { + for (const auto& item : where_clause_items) { + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string BlockExpr::as_string() const { + ::std::string str = "BlockExpr: "; + + // get outer attributes + str += "\n " + Expr::as_string(); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + // statements + str += "\n statements: "; + if (statements.empty()) { + str += "none"; + } else { + for (const auto& stmt : statements) { + // DEBUG: null pointer check + if (stmt == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "stmt in block expr."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + stmt->as_string(); + } + } + + // final expression + str += "\n final expression: "; + if (expr == NULL) { + str += "none"; + } else { + str += "\n " + expr->as_string(); + } + + return str; + } + + ::std::string TraitImpl::as_string() const { + ::std::string str = VisItem::as_string(); + + if (has_unsafe) { + str += "unsafe "; + } + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (!has_generics()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + str += "\n " + param->as_string(); + } + } + + str += "\n Has exclam: "; + if (has_exclam) { + str += "true"; + } else { + str += "false"; + } + + str += "\n TypePath (to trait): " + trait_path.as_string(); + + str += "\n Type (struct to impl on): " + trait_type->as_string(); + + str += "\n Where clause: "; + if (!has_where_clause()) { + str += "none"; + } else { + str += where_clause.as_string(); + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n trait impl items: "; + if (!has_impl_items()) { + str += "none"; + } else { + for (const auto& item : impl_items) { + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string TypeAlias::as_string() const { + ::std::string str = VisItem::as_string(); + + str += " " + new_type_name; + + // generic params + str += "\n Generic params: "; + if (!has_generics()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + str += param->as_string() + ", "; + } + } + + str += "\n Where clause: "; + if (!has_where_clause()) { + str += "none"; + } else { + str += where_clause.as_string(); + } + + str += "\n Type: " + existing_type->as_string(); + + return str; + } + + ::std::string MacroInvocationSemi::as_string() const { + // get outer attrs + ::std::string str = MacroItem::as_string(); + + str += "\n" + path.as_string() + "!"; + + ::std::string tok_trees; + if (token_trees.empty()) { + tok_trees = "none"; + } else { + for (const auto& tree : token_trees) { + // DEBUG: null pointer check + if (tree == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "token tree in macro invocation semi."); + return "NULL_POINTER_MARK"; + } + + tok_trees += tree->as_string() + ", "; + } + } + + return str + get_string_in_delims(::std::move(tok_trees), delim_type); + } + + ::std::string ExternBlock::as_string() const { + ::std::string str = VisItem::as_string(); + + str += "extern "; + if (has_abi()) { + str += "\"" + abi + "\" "; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n external items: "; + if (!has_extern_items()) { + str += "none"; + } else { + for (const auto& item : extern_items) { + str += "\n " + item->as_string(); + } + } + + return str; + } + + ::std::string MacroRule::as_string() const { + ::std::string str("Macro rule: "); + + str += "\n Matcher: \n "; + str += matcher.as_string(); + + str += "\n Transcriber: \n "; + str += transcriber.as_string(); + + return str; + } + + ::std::string MacroRulesDefinition::as_string() const { + ::std::string str("macro_rules!"); + + str += rule_name; + + str += "\n Macro rules: "; + if (rules.empty()) { + str += "none"; + } else { + for (const auto& rule : rules) { + str += "\n " + rule.as_string(); + } + } + + str += "\n Delim type: "; + switch (delim_type) { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - delim type in macro invocation"; + } + + return str; + } + + ::std::string MacroInvocation::as_string() const { + return path.as_string() + "!" + token_tree.as_string(); + } + + ::std::string PathInExpression::as_string() const { + ::std::string str; + + if (has_opening_scope_resolution) { + str = "::"; + } + + return str + PathPattern::as_string(); + } + + ::std::string ExprStmtWithBlock::as_string() const { + ::std::string str("ExprStmtWithBlock: \n "); + + if (expr == NULL) { + str += "none (this should not happen and is an error)"; + } else { + str += expr->as_string(); + } + + return str; + } + + ::std::string ClosureParam::as_string() const { + ::std::string str(pattern->as_string()); + + if (has_type_given()) { + str += " : " + type->as_string(); + } + + return str; + } + + ::std::string ClosureExpr::as_string() const { + ::std::string str("ClosureExpr:\n Has move: "); + if (has_move) { + str += "true"; + } else { + str += "false"; + } + + str += "\n Params: "; + if (params.empty()) { + str += "none"; + } else { + for (const auto& param : params) { + str += "\n " + param.as_string(); + } + } + + return str; + } + + ::std::string ClosureExprInnerTyped::as_string() const { + ::std::string str = ClosureExpr::as_string(); + + str += "\n Return type: " + return_type->as_string(); + + str += "\n Body: " + expr->as_string(); + + return str; + } + + ::std::string PathPattern::as_string() const { + ::std::string str; + + for (const auto& segment : segments) { + str += segment.as_string() + "::"; + } + + // basically a hack - remove last two characters of string (remove final ::) + str.erase(str.length() - 2); + + return str; + } + + ::std::string QualifiedPathType::as_string() const { + ::std::string str("<"); + str += type_to_invoke_on->as_string(); + + if (has_as_clause()) { + str += " as " + trait_path.as_string(); + } + + return str + ">"; + } + + ::std::string QualifiedPathInExpression::as_string() const { + return path_type.as_string() + "::" + PathPattern::as_string(); + } + + ::std::string BorrowExpr::as_string() const { + ::std::string str("&"); + + if (double_borrow) { + str += "&"; + } + + if (is_mut) { + str += "mut "; + } + + str += main_or_left_expr->as_string(); + + return str; + } + + ::std::string ReturnExpr::as_string() const { + ::std::string str("return "); + + if (has_return_expr()) { + str += return_expr->as_string(); + } + + return str; + } + + ::std::string GroupedExpr::as_string() const { + ::std::string str("Grouped expr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n Expr in parens: " + expr_in_parens->as_string(); + + return str; + } + + ::std::string RangeToExpr::as_string() const { + return ".." + to->as_string(); + } + + ::std::string ContinueExpr::as_string() const { + ::std::string str("continue "); + + if (has_label()) { + str += label.as_string(); + } + + return str; + } + + ::std::string NegationExpr::as_string() const { + ::std::string str; + + switch (negation_type) { + case NEGATE: + str = "-"; + break; + case NOT: + str = "!"; + break; + default: + return "ERROR_MARK_STRING - negation expr"; + } + + str += main_or_left_expr->as_string(); + + return str; + } + + ::std::string RangeFromExpr::as_string() const { + return from->as_string() + ".."; + } + + ::std::string RangeFullExpr::as_string() const { + return ".."; + } + + ::std::string ArrayIndexExpr::as_string() const { + return array_expr->as_string() + "[" + index_expr->as_string() + "]"; + } + + ::std::string AssignmentExpr::as_string() const { + ::std::string str("AssignmentExpr: "); + + if (main_or_left_expr == NULL || right_expr == NULL) { + str += "error (either or both expressions are null)"; + } else { + // left expr + str += "\n left: " + main_or_left_expr->as_string(); + + // right expr + str += "\n right: " + right_expr->as_string(); + } + + return str; + } + + ::std::string AsyncBlockExpr::as_string() const { + ::std::string str = "AsyncBlockExpr: "; + + // get outer attributes + str += "\n " + Expr::as_string(); + + str += "\n Has move: "; + str += has_move ? "true" : "false"; + + return str + "\n" + block_expr->as_string(); + } + + ::std::string ComparisonExpr::as_string() const { + ::std::string str(main_or_left_expr->as_string()); + + switch (expr_type) { + case EQUAL: + str += " == "; + break; + case NOT_EQUAL: + str += " != "; + break; + case GREATER_THAN: + str += " > "; + break; + case LESS_THAN: + str += " < "; + break; + case GREATER_OR_EQUAL: + str += " >= "; + break; + case LESS_OR_EQUAL: + str += " <= "; + break; + default: + return "ERROR_MARK_STRING - comparison expr"; + } + + str += right_expr->as_string(); + + return str; + } + + ::std::string MethodCallExpr::as_string() const { + ::std::string str("MethodCallExpr: \n Object (receiver) expr: "); + + str += receiver->as_string(); + + str += "\n Method path segment: \n"; + + str += method_name.as_string(); + + str += "\n Call params:"; + if (params.empty()) { + str += "none"; + } else { + for (const auto& param : params) { + if (param == NULL) { + return "ERROR_MARK_STRING - method call expr param is null"; + } + + str += "\n " + param->as_string(); + } + } + + return str; + } + + ::std::string TupleIndexExpr::as_string() const { + return tuple_expr->as_string() + "." + ::std::to_string(tuple_index); + } + + ::std::string DereferenceExpr::as_string() const { + return "*" + main_or_left_expr->as_string(); + } + + ::std::string FieldAccessExpr::as_string() const { + return receiver->as_string() + "." + field; + } + + ::std::string LazyBooleanExpr::as_string() const { + ::std::string str(main_or_left_expr->as_string()); + + switch (expr_type) { + case LOGICAL_OR: + str += " || "; + break; + case LOGICAL_AND: + str += " && "; + break; + default: + return "ERROR_MARK_STRING - lazy boolean expr out of bounds"; + } + + str += right_expr->as_string(); + + return str; + } + + ::std::string RangeFromToExpr::as_string() const { + return from->as_string() + ".." + to->as_string(); + } + + ::std::string RangeToInclExpr::as_string() const { + return "..=" + to->as_string(); + } + + ::std::string UnsafeBlockExpr::as_string() const { + ::std::string str = "UnsafeBlockExpr: "; + + // get outer attributes + str += "\n " + Expr::as_string(); + + return str + "\n" + expr->as_string(); + } + + ::std::string ClosureExprInner::as_string() const { + ::std::string str = ClosureExpr::as_string(); + + str += "\n Expression: " + closure_inner->as_string(); + + return str; + } + + ::std::string IfExpr::as_string() const { + ::std::string str("IfExpr: "); + + str += "\n Condition expr: " + condition->as_string(); + + str += "\n If block expr: " + if_block->as_string(); + + return str; + } + + ::std::string IfExprConseqElse::as_string() const { + ::std::string str = IfExpr::as_string(); + + str += "\n Else block expr: " + else_block->as_string(); + + return str; + } + + ::std::string IfExprConseqIf::as_string() const { + ::std::string str = IfExpr::as_string(); + + str += "\n Else if expr: \n " + if_expr->as_string(); + + return str; + } + + ::std::string IfExprConseqIfLet::as_string() const { + ::std::string str = IfExpr::as_string(); + + str += "\n Else if let expr: \n " + if_let_expr->as_string(); + + return str; + } + + ::std::string IfLetExpr::as_string() const { + ::std::string str("IfLetExpr: "); + + str += "\n Condition match arm patterns: "; + if (match_arm_patterns.empty()) { + str += "none"; + } else { + for (const auto& pattern : match_arm_patterns) { + str += "\n " + pattern->as_string(); + } + } + + str += "\n Scrutinee expr: " + value->as_string(); + + str += "\n If let block expr: " + if_block->as_string(); + + return str; + } + + ::std::string IfLetExprConseqElse::as_string() const { + ::std::string str = IfLetExpr::as_string(); + + str += "\n Else block expr: " + else_block->as_string(); + + return str; + } + + ::std::string IfLetExprConseqIf::as_string() const { + ::std::string str = IfLetExpr::as_string(); + + str += "\n Else if expr: \n " + if_expr->as_string(); + + return str; + } + + ::std::string IfLetExprConseqIfLet::as_string() const { + ::std::string str = IfLetExpr::as_string(); + + str += "\n Else if let expr: \n " + if_let_expr->as_string(); + + return str; + } + + ::std::string RangeFromToInclExpr::as_string() const { + return from->as_string() + "..=" + to->as_string(); + } + + ::std::string ErrorPropagationExpr::as_string() const { + return main_or_left_expr->as_string() + "?"; + } + + ::std::string CompoundAssignmentExpr::as_string() const { + ::std::string operator_str; + operator_str.reserve(1); + + // get operator string + switch (expr_type) { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + operator_str += "="; + + ::std::string str("CompoundAssignmentExpr: "); + if (main_or_left_expr == NULL || right_expr == NULL) { + str += "error. this is probably a parsing failure."; + } else { + str += "\n left: " + main_or_left_expr->as_string(); + str += "\n right: " + right_expr->as_string(); + str += "\n operator: " + operator_str; + } + + return str; + } + + ::std::string ArithmeticOrLogicalExpr::as_string() const { + ::std::string operator_str; + operator_str.reserve(1); + + // get operator string + switch (expr_type) { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + ::std::string str("ArithmeticOrLogicalExpr: "); + if (main_or_left_expr == NULL || right_expr == NULL) { + str += "error. this is probably a parsing failure."; + } else { + str += "\n left: " + main_or_left_expr->as_string(); + str += "\n right: " + right_expr->as_string(); + str += "\n operator: " + operator_str; + } + + return str; + } + + ::std::string CallExpr::as_string() const { + ::std::string str("CallExpr: \n Function expr: "); + + str += function->as_string(); + + str += "\n Call params:"; + if (!has_params()) { + str += "none"; + } else { + for (const auto& param : params) { + if (param == NULL) { + return "ERROR_MARK_STRING - call expr param is null"; + } + + str += "\n " + param->as_string(); + } + } + + return str; + } + + ::std::string WhileLoopExpr::as_string() const { + ::std::string str("WhileLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label()) { + str += "none"; + } else { + str += loop_label.as_string(); + } + + str += "\n Conditional expr: " + condition->as_string(); + + str += "\n Loop block: " + loop_block->as_string(); + + return str; + } + + ::std::string WhileLetLoopExpr::as_string() const { + ::std::string str("WhileLetLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label()) { + str += "none"; + } else { + str += loop_label.as_string(); + } + + str += "\n Match arm patterns: "; + if (match_arm_patterns.empty()) { + str += "none"; + } else { + for (const auto& pattern : match_arm_patterns) { + str += "\n " + pattern->as_string(); + } + } + + str += "\n Scrutinee expr: " + condition->as_string(); + + str += "\n Loop block: " + loop_block->as_string(); + + return str; + } + + ::std::string LoopExpr::as_string() const { + ::std::string str("LoopExpr: (infinite loop)"); + + str += "\n Label: "; + if (!has_loop_label()) { + str += "none"; + } else { + str += loop_label.as_string(); + } + + str += "\n Loop block: " + loop_block->as_string(); + + return str; + } + + ::std::string ArrayExpr::as_string() const { + ::std::string str("ArrayExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n Array elems: "; + if (!has_array_elems()) { + str += "none"; + } else { + str += internal_elements->as_string(); + } + + return str; + } + + ::std::string AwaitExpr::as_string() const { + return awaited_expr->as_string() + ".await"; + } + + ::std::string BreakExpr::as_string() const { + ::std::string str("break "); + + if (has_label()) { + str += label.as_string() + " "; + } + + if (has_break_expr()) { + str += break_expr->as_string(); + } + + return str; + } + + ::std::string LoopLabel::as_string() const { + return label.as_string() + ": (label) "; + } + + ::std::string MatchArm::as_string() const { + // outer attributes + ::std::string str = "Outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\nPatterns: "; + if (match_arm_patterns.empty()) { + str += "none"; + } else { + for (const auto& pattern : match_arm_patterns) { + str += "\n " + pattern->as_string(); + } + } + + str += "\nGuard expr: "; + if (!has_match_arm_guard()) { + str += "none"; + } else { + str += guard_expr->as_string(); + } + + return str; + } + + ::std::string MatchCase::as_string() const { + ::std::string str("MatchCase: (match arm) "); + + str += "\n Match arm matcher: \n" + arm.as_string(); + + return str; + } + + ::std::string MatchCaseBlockExpr::as_string() const { + ::std::string str = MatchCase::as_string(); + + str += "\n Block expr: " + block_expr->as_string(); + + return str; + } + + ::std::string MatchCaseExpr::as_string() const { + ::std::string str = MatchCase::as_string(); + + str += "\n Expr: " + expr->as_string(); + + return str; + } + + ::std::string MatchExpr::as_string() const { + ::std::string str("MatchExpr:"); + + str += "\n Scrutinee expr: " + branch_value->as_string(); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + // match arms + str += "\n Match arms: "; + if (match_arms.empty()) { + str += "none"; + } else { + for (const auto& arm : match_arms) { + str += "\n " + arm->as_string(); + } + } + + return str; + } + + ::std::string TupleExpr::as_string() const { + ::std::string str("TupleExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n Tuple elements: "; + if (tuple_elems.empty()) { + str += "none"; + } else { + for (const auto& elem : tuple_elems) { + str += "\n " + elem->as_string(); + } + } + + return str; + } + + ::std::string ExprStmtWithoutBlock::as_string() const { + ::std::string str("ExprStmtWithoutBlock: \n "); + + if (expr == NULL) { + str += "none (this shouldn't happen and is probably an error)"; + } else { + str += expr->as_string(); + } + + return str; + } + + ::std::string FunctionParam::as_string() const { + return param_name->as_string() + " : " + type->as_string(); + } + + ::std::string FunctionQualifiers::as_string() const { + ::std::string str; + + switch (const_status) { + case NONE: + // do nothing + break; + case CONST: + str += "const "; + break; + case ASYNC: + str += "async "; + break; + default: + return "ERROR_MARK_STRING: async-const status failure"; + } + + if (has_unsafe) { + str += "unsafe "; + } + + if (has_extern) { + str += "extern"; + if (extern_abi != "") { + str += " \"" + extern_abi + "\""; + } + } + + return str; + } + + ::std::string TraitBound::as_string() const { + ::std::string str("TraitBound:"); + + str += "\n Has opening question mark: "; + if (opening_question_mark) { + str += "true"; + } else { + str += "false"; + } + + str += "\n For lifetimes: "; + if (!has_for_lifetimes()) { + str += "none"; + } else { + for (const auto& lifetime : for_lifetimes) { + str += "\n " + lifetime.as_string(); + } + } + + str += "\n Type path: " + type_path.as_string(); + + return str; + } + + ::std::string MacroMatcher::as_string() const { + ::std::string str("Macro matcher: "); + + str += "\n Delim type: "; + + switch (delim_type) { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - macro matcher delim"; + } + + str += "\n Matches: "; + + if (matches.empty()) { + str += "none"; + } else { + for (const auto& match : matches) { + str += "\n " + match->as_string(); + } + } + + return str; + } + + ::std::string LifetimeParam::as_string() const { + ::std::string str("LifetimeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute()) { + str += "none"; + } else { + str += outer_attr.as_string(); + } + + str += "\n Lifetime: " + lifetime.as_string(); + + str += "\n Lifetime bounds: "; + if (!has_lifetime_bounds()) { + str += "none"; + } else { + for (const auto& bound : lifetime_bounds) { + str += "\n " + bound.as_string(); + } + } + + return str; + } + + ::std::string MacroMatchFragment::as_string() const { + return "$" + ident + ": " + frag_spec_to_str(frag_spec); + } + + ::std::string QualifiedPathInType::as_string() const { + ::std::string str = path_type.as_string(); + + for (const auto& segment : segments) { + str += "::" + segment->as_string(); + } + + return str; + } + + ::std::string MacroMatchRepetition::as_string() const { + ::std::string str("Macro match repetition: "); + + str += "\n Matches: "; + if (matches.empty()) { + str += "none"; + } else { + for (const auto& match : matches) { + str += "\n " + match->as_string(); + } + } + + str += "\n Sep: "; + if (!has_sep()) { + str += "none"; + } else { + str += sep->as_string(); + } + + str += "\n Op: "; + switch (op) { + case ASTERISK: + str += "*"; + break; + case PLUS: + str += "+"; + break; + case QUESTION_MARK: + str += "?"; + break; + case NONE: + str += "no op? shouldn't be allowed"; + break; + default: + return "ERROR_MARK_STRING - unknown op in macro match repetition"; + } + + return str; + } + + ::std::string Lifetime::as_string() const { + if (is_error()) { + return "error lifetime"; + } + + switch (lifetime_type) { + case NAMED: + return "'" + lifetime_name; + case STATIC: + return "'static"; + case WILDCARD: + return "'_"; + default: + return "ERROR-MARK-STRING: lifetime type failure"; + } + } + + ::std::string TypePath::as_string() const { + ::std::string str; + + if (has_opening_scope_resolution) { + str = "::"; + } + + for (const auto& segment : segments) { + str += segment->as_string() + "::"; + } + + // kinda hack - remove last 2 '::' characters + str.erase(str.length() - 2); + + return str; + } + + ::std::string TypeParam::as_string() const { + ::std::string str("TypeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute()) { + str += "none"; + } else { + str += outer_attr.as_string(); + } + + str += "\n Identifier: " + type_representation; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds()) { + str += "none"; + } else { + for (const auto& bound : type_param_bounds) { + str += "\n " + bound->as_string(); + } + } + + str += "\n Type: "; + if (!has_type()) { + str += "none"; + } else { + str += type->as_string(); + } + + return str; + } + + SimplePath PathPattern::convert_to_simple_path(bool with_opening_scope_resolution) const { + if (!has_segments()) { + return SimplePath::create_empty(); + } + + // create vector of reserved size (to minimise reallocations) + ::std::vector simple_segments; + simple_segments.reserve(segments.size()); + + for (const auto& segment : segments) { + // return empty path if doesn't meet simple path segment requirements + if (segment.is_error() || segment.has_generic_args() + || segment.as_string() == "Self") { + return SimplePath::create_empty(); + } + + // create segment and add to vector + ::std::string segment_str = segment.as_string(); + simple_segments.push_back( + SimplePathSegment(::std::move(segment_str), segment.get_locus())); + } + + // kind of a HACK to get locus depending on opening scope resolution + location_t locus = UNKNOWN_LOCATION; + if (with_opening_scope_resolution) { + locus = simple_segments[0].get_locus() - 2; // minus 2 chars for :: + } else { + locus = simple_segments[0].get_locus(); + } + + return SimplePath(::std::move(simple_segments), with_opening_scope_resolution, locus); + } + + SimplePath TypePath::as_simple_path() const { + if (segments.empty()) { + return SimplePath::create_empty(); + } + + // create vector of reserved size (to minimise reallocations) + ::std::vector simple_segments; + simple_segments.reserve(segments.size()); + + for (const auto& segment : segments) { + // return empty path if doesn't meet simple path segment requirements + if (segment == NULL || segment->is_error() || !segment->is_ident_only() + || segment->as_string() == "Self") { + return SimplePath::create_empty(); + } + + // create segment and add to vector + ::std::string segment_str = segment->as_string(); + simple_segments.push_back( + SimplePathSegment(::std::move(segment_str), segment->get_locus())); + } + + return SimplePath(::std::move(simple_segments), has_opening_scope_resolution, locus); + } + + ::std::string PathExprSegment::as_string() const { + ::std::string ident_str = segment_name.as_string(); + if (has_generic_args()) { + ident_str += "::<" + generic_args.as_string() + ">"; + } + + return ident_str; + } + + ::std::string GenericArgs::as_string() const { + ::std::string args; + + // lifetime args + if (!lifetime_args.empty()) { + for (const auto& lifetime_arg : lifetime_args) { + args += lifetime_arg.as_string() + ", "; + } + } + + // type args + if (!type_args.empty()) { + for (const auto& type_arg : type_args) { + args += type_arg->as_string() + ", "; + } + } + + // binding args + if (!binding_args.empty()) { + for (const auto& binding_arg : binding_args) { + args += binding_arg.as_string() + ", "; + } + } + + return args; + } + + ::std::string GenericArgsBinding::as_string() const { + return identifier + " = " + type->as_string(); + } + + ::std::string ForLoopExpr::as_string() const { + ::std::string str("ForLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label()) { + str += "none"; + } else { + str += loop_label.as_string(); + } + + str += "\n Pattern: " + pattern->as_string(); + + str += "\n Iterator expr: " + iterator_expr->as_string(); + + str += "\n Loop block: " + loop_block->as_string(); + + return str; + } + + ::std::string RangePattern::as_string() const { + if (has_ellipsis_syntax) { + return lower->as_string() + "..." + upper->as_string(); + } else { + return lower->as_string() + "..=" + upper->as_string(); + } + } + + ::std::string RangePatternBoundLiteral::as_string() const { + ::std::string str; + + if (has_minus) { + str += "-"; + } + + str += literal.as_string(); + + return str; + } + + ::std::string SlicePattern::as_string() const { + ::std::string str("SlicePattern: "); + + for (const auto& pattern : items) { + str += "\n " + pattern->as_string(); + } + + return str; + } + + ::std::string TuplePatternItemsMultiple::as_string() const { + ::std::string str; + + for (const auto& pattern : patterns) { + str += "\n " + pattern->as_string(); + } + + return str; + } + + ::std::string TuplePatternItemsRanged::as_string() const { + ::std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty()) { + str += "none"; + } else { + for (const auto& lower : lower_patterns) { + str += "\n " + lower->as_string(); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty()) { + str += "none"; + } else { + for (const auto& upper : upper_patterns) { + str += "\n " + upper->as_string(); + } + } + + return str; + } + + ::std::string TuplePattern::as_string() const { + return "TuplePattern: " + items->as_string(); + } + + ::std::string StructPatternField::as_string() const { + // outer attributes + ::std::string str("Outer attributes: "); + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + return str; + } + + ::std::string StructPatternFieldIdent::as_string() const { + ::std::string str = StructPatternField::as_string(); + + str += "\n"; + + if (has_ref) { + str += "ref "; + } + + if (has_mut) { + str += "mut "; + } + + str += ident; + + return str; + } + + ::std::string StructPatternFieldTuplePat::as_string() const { + ::std::string str = StructPatternField::as_string(); + + str += "\n"; + + str += ::std::to_string(index) + " : " + tuple_pattern->as_string(); + + return str; + } + + ::std::string StructPatternFieldIdentPat::as_string() const { + ::std::string str = StructPatternField::as_string(); + + str += "\n"; + + str += ident + " : " + ident_pattern->as_string(); + + return str; + } + + ::std::string StructPatternElements::as_string() const { + ::std::string str("\n Fields: "); + + if (!has_struct_pattern_fields()) { + str += "none"; + } else { + for (const auto& field : fields) { + str += "\n " + field->as_string(); + } + } + + str += "\n Etc: "; + if (has_struct_pattern_etc) { + str += "true"; + } else { + str += "false"; + } + + return str; + } + + ::std::string StructPattern::as_string() const { + ::std::string str("StructPattern: \n Path: "); + + str += path.as_string(); + + str += "\n Struct pattern elems: "; + if (!has_struct_pattern_elems()) { + str += "none"; + } else { + str += elems.as_string(); + } + + return str; + } + + ::std::string LiteralPattern::as_string() const { + ::std::string str; + + if (has_minus) { + str += "-"; + } + + return str + lit.as_string(); + } + + ::std::string ReferencePattern::as_string() const { + ::std::string str("&"); + + if (has_two_amps) { + str += "&"; + } + + if (is_mut) { + str += "mut "; + } + + str += pattern->as_string(); + + return str; + } + + ::std::string IdentifierPattern::as_string() const { + ::std::string str; + + if (is_ref) { + str += "ref "; + } + + if (is_mut) { + str += "mut "; + } + + str += variable_ident; + + if (has_pattern_to_bind()) { + str += " @ " + to_bind->as_string(); + } + + return str; + } + + ::std::string TupleStructItemsNoRange::as_string() const { + ::std::string str; + + for (const auto& pattern : patterns) { + str += "\n " + pattern->as_string(); + } + + return str; + } + + ::std::string TupleStructItemsRange::as_string() const { + ::std::string str("\n Lower patterns: "); + + if (lower_patterns.empty()) { + str += "none"; + } else { + for (const auto& lower : lower_patterns) { + str += "\n " + lower->as_string(); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty()) { + str += "none"; + } else { + for (const auto& upper : upper_patterns) { + str += "\n " + upper->as_string(); + } + } + + return str; + } + + ::std::string TupleStructPattern::as_string() const { + ::std::string str("TupleStructPattern: \n Path: "); + + str += path.as_string(); + + str += "\n Tuple struct items: " + items->as_string(); + + return str; + } + + ::std::string LetStmt::as_string() const { + // outer attributes + ::std::string str = "Outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\nlet " + variables_pattern->as_string(); + + if (has_type()) { + str += " : " + type->as_string(); + } + + if (has_init_expr()) { + str += " = " + init_expr->as_string(); + } + + return str; + } + + // Used to get outer attributes for expressions. + ::std::string Expr::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + return str; + } + + // hopefully definition here will prevent circular dependency issue + TraitBound* TypePath::to_trait_bound(bool in_parens) const { + // create clone FIXME is this required? or is copy constructor automatically called? + TypePath copy(*this); + return new TraitBound(::std::move(copy), in_parens); + } + + ::std::string InferredType::as_string() const { + return "_ (inferred)"; + } + + ::std::string TypeCastExpr::as_string() const { + return main_or_left_expr->as_string() + " as " + type_to_convert_to->as_string(); + } + + ::std::string ImplTraitType::as_string() const { + ::std::string str("ImplTraitType: \n TypeParamBounds: "); + + if (type_param_bounds.empty()) { + str += "none"; + } else { + for (const auto& bound : type_param_bounds) { + str += "\n " + bound->as_string(); + } + } + + return str; + } + + ::std::string ReferenceType::as_string() const { + ::std::string str("&"); + + if (has_lifetime()) { + str += lifetime.as_string() + " "; + } + + if (has_mut) { + str += "mut "; + } + + str += type->as_string(); + + return str; + } + + ::std::string RawPointerType::as_string() const { + ::std::string str("*"); + + switch (pointer_type) { + case MUT: + str += "mut "; + break; + case CONST: + str += "const "; + break; + default: + return "ERROR_MARK_STRING - unknown pointer type in raw pointer type"; + } + + str += type->as_string(); + + return str; + } + + ::std::string TraitObjectType::as_string() const { + ::std::string str("TraitObjectType: \n Has dyn dispatch: "); + + if (has_dyn) { + str += "true"; + } else { + str += "false"; + } + + str += "\n TypeParamBounds: "; + if (type_param_bounds.empty()) { + str += "none"; + } else { + for (const auto& bound : type_param_bounds) { + str += "\n " + bound->as_string(); + } + } + + return str; + } + + ::std::string BareFunctionType::as_string() const { + ::std::string str("BareFunctionType: \n For lifetimes: "); + + if (!has_for_lifetimes()) { + str += "none"; + } else { + for (const auto& for_lifetime : for_lifetimes) { + str += "\n " + for_lifetime.as_string(); + } + } + + str += "\n Qualifiers: " + function_qualifiers.as_string(); + + str += "\n Params: "; + if (params.empty()) { + str += "none"; + } else { + for (const auto& param : params) { + str += "\n " + param.as_string(); + } + } + + str += "\n Is variadic: "; + if (is_variadic) { + str += "true"; + } else { + str += "false"; + } + + str += "\n Return type: "; + if (!has_return_type()) { + str += "none (void)"; + } else { + str += return_type->as_string(); + } + + return str; + } + + ::std::string ImplTraitTypeOneBound::as_string() const { + ::std::string str("ImplTraitTypeOneBound: \n TraitBound: "); + + return str + trait_bound.as_string(); + } + + ::std::string TypePathSegmentGeneric::as_string() const { + return TypePathSegment::as_string() + "<" + generic_args.as_string() + ">"; + } + + ::std::string TraitObjectTypeOneBound::as_string() const { + ::std::string str("TraitObjectTypeOneBound: \n Has dyn dispatch: "); + + if (has_dyn) { + str += "true"; + } else { + str += "false"; + } + + str += "\n TraitBound: " + trait_bound.as_string(); + + return str; + } + + ::std::string TypePathFunction::as_string() const { + ::std::string str("("); + + if (has_inputs()) { + for (const auto& param : inputs) { + str += param->as_string() + ", "; + } + } + + str += ")"; + + if (has_return_type()) { + str += " -> " + return_type->as_string(); + } + + return str; + } + + ::std::string TypePathSegmentFunction::as_string() const { + return TypePathSegment::as_string() + function_path.as_string(); + } + + ::std::string ArrayType::as_string() const { + return "[" + elem_type->as_string() + "; " + size->as_string() + "]"; + } + + ::std::string SliceType::as_string() const { + return "[" + elem_type->as_string() + "]"; + } + + ::std::string TupleType::as_string() const { + ::std::string str("("); + + if (!is_unit_type()) { + for (const auto& elem : elems) { + str += elem->as_string() + ", "; + } + } + + str += ")"; + + return str; + } + + ::std::string StructExpr::as_string() const { + ::std::string str = ExprWithoutBlock::as_string(); + + str += "\nStructExpr"; + + str += "\n PathInExpr: " + struct_name.as_string(); + + return str; + } + + ::std::string StructExprTuple::as_string() const { + ::std::string str = StructExpr::as_string(); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n Tuple fields: "; + if (exprs.empty()) { + str += "none"; + } else { + for (const auto& field : exprs) { + // debug - null pointer check + if (field == NULL) { + return "ERROR_MARK_STRING - nullptr struct expr tuple field"; + } + + str += "\n " + field->as_string(); + } + } + + return str; + } + + ::std::string StructExprStruct::as_string() const { + ::std::string str("StructExprStruct (or subclass): "); + + str += "\n Path: " + get_struct_name().as_string(); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "inner attribute" syntax - just the body + for (const auto& attr : inner_attrs) { + str += "\n " + attr.as_string(); + } + } + + return str; + } + + ::std::string StructBase::as_string() const { + if (base_struct != NULL) { + return base_struct->as_string(); + } else { + return "ERROR_MARK_STRING - invalid struct base had as string applied"; + } + } + + ::std::string StructExprFieldWithVal::as_string() const { + // used to get value string + return value->as_string(); + } + + ::std::string StructExprFieldIdentifierValue::as_string() const { + return field_name + " : " + StructExprFieldWithVal::as_string(); + } + + ::std::string StructExprFieldIndexValue::as_string() const { + return ::std::to_string(index) + " : " + StructExprFieldWithVal::as_string(); + } + + ::std::string StructExprStructFields::as_string() const { + ::std::string str = StructExprStruct::as_string(); + + str += "\n Fields: "; + if (fields.empty()) { + str += "none"; + } else { + for (const auto& field : fields) { + str += "\n " + field->as_string(); + } + } + + str += "\n Struct base: "; + if (!has_struct_base()) { + str += "none"; + } else { + str += struct_base.as_string(); + } + + return str; + } + + ::std::string EnumItem::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n" + variant_name; + + return str; + } + + ::std::string EnumItemTuple::as_string() const { + ::std::string str = EnumItem::as_string(); + + // add tuple opening parens + str += "("; + + // tuple fields + if (has_tuple_fields()) { + for (const auto& field : tuple_fields) { + str += field.as_string() + ", "; + } + } + + // add tuple closing parens + str += ")"; + + return str; + } + + ::std::string TupleField::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + if (has_visibility()) { + str += "\n" + visibility.as_string(); + } + + str += " " + field_type->as_string(); + + return str; + } + + ::std::string EnumItemStruct::as_string() const { + ::std::string str = EnumItem::as_string(); + + // add struct opening parens + str += "{"; + + // tuple fields + if (has_struct_fields()) { + for (const auto& field : struct_fields) { + str += field.as_string() + ", "; + } + } + + // add struct closing parens + str += "}"; + + return str; + } + + ::std::string StructField::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + if (has_visibility()) { + str += "\n" + visibility.as_string(); + } + + str += " " + field_name + " : " + field_type->as_string(); + + return str; + } + + ::std::string EnumItemDiscriminant::as_string() const { + ::std::string str = EnumItem::as_string(); + + // add equal and expression + str += " = " + expression->as_string(); + + return str; + } + + ::std::string ExternalItem::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + // start visibility on new line and with a space + str += "\n" + visibility.as_string() + " "; + + return str; + } + + ::std::string ExternalStaticItem::as_string() const { + ::std::string str = ExternalItem::as_string(); + + str += "static "; + + if (has_mut) { + str += "mut "; + } + + // add name + str += get_item_name(); + + // add type on new line + str += "\n Type: " + item_type->as_string(); + + return str; + } + + ::std::string ExternalFunctionItem::as_string() const { + ::std::string str = ExternalItem::as_string(); + + str += "fn "; + + // add name + str += get_item_name(); + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in external function item."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + // function params + str += "\n Function params: "; + if (function_params.empty()) { + str += "none"; + } else { + for (const auto& param : function_params) { + str += "\n " + param.as_string(); + } + if (has_variadics) { + str += "\n .. (variadic)"; + } + } + + // add type on new line + str += "\n (return) Type: " + return_type->as_string(); + + // where clause + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string NamedFunctionParam::as_string() const { + ::std::string str = name; + + str += "\n Type: " + param_type->as_string(); + + return str; + } + + /*::std::string TraitItem::as_string() const { + // outer attributes + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + return str; + }*/ + + ::std::string TraitItemFunc::as_string() const { + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n" + decl.as_string(); + + str += "\n Definition (block expr): "; + if (has_definition()) { + str += block_expr->as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string TraitFunctionDecl::as_string() const { + ::std::string str = qualifiers.as_string() + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Function params: "; + if (has_params()) { + for (const auto& param : function_params) { + str += "\n " + param.as_string(); + } + } else { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type()) { + str += return_type->as_string(); + } else { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string TraitItemMethod::as_string() const { + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\n" + decl.as_string(); + + str += "\n Definition (block expr): "; + if (has_definition()) { + str += block_expr->as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string TraitMethodDecl::as_string() const { + ::std::string str = qualifiers.as_string() + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty()) { + str += "none"; + } else { + for (const auto& param : generic_params) { + // DEBUG: null pointer check + if (param == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + param->as_string(); + } + } + + str += "\n Self param: " + self_param.as_string(); + + str += "\n Function params: "; + if (has_params()) { + for (const auto& param : function_params) { + str += "\n " + param.as_string(); + } + } else { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type()) { + str += return_type->as_string(); + } else { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause()) { + str += where_clause.as_string(); + } else { + str += "none"; + } + + return str; + } + + ::std::string TraitItemConst::as_string() const { + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\nconst " + name + " : " + type->as_string(); + + if (has_expression()) { + str += " = " + expr->as_string(); + } + + return str; + } + + ::std::string TraitItemType::as_string() const { + ::std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - just the body + for (const auto& attr : outer_attrs) { + str += "\n " + attr.as_string(); + } + } + + str += "\ntype " + name; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds()) { + str += "none"; + } else { + for (const auto& bound : type_param_bounds) { + // DEBUG: null pointer check + if (bound == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "type param bound in trait item type."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + bound->as_string(); + } + } + + return str; + } + + ::std::string SelfParam::as_string() const { + if (is_error()) { + return "error"; + } else { + if (has_type()) { + // type (i.e. not ref, no lifetime) + ::std::string str; + + if (is_mut) { + str += "mut "; + } + + str += "self : "; + + str += type->as_string(); + + return str; + } else if (has_lifetime()) { + // ref and lifetime + ::std::string str = "&" + lifetime.as_string() + " "; + + if (is_mut) { + str += "mut "; + } + + str += "self"; + + return str; + } else if (has_ref) { + // ref with no lifetime + ::std::string str = "&"; + + if (is_mut) { + str += " mut "; + } + + str += "self"; + + return str; + } else { + // no ref, no type + ::std::string str; + + if (is_mut) { + str += "mut "; + } + + str += "self"; + + return str; + } + } + } + + ::std::string ArrayElemsCopied::as_string() const { + return elem_to_copy->as_string() + "; " + num_copies->as_string(); + } + + ::std::string LifetimeWhereClauseItem::as_string() const { + ::std::string str("Lifetime: "); + + str += lifetime.as_string(); + + str += "\nLifetime bounds: "; + + for (const auto& bound : lifetime_bounds) { + str += "\n " + bound.as_string(); + } + + return str; + } + + ::std::string TypeBoundWhereClauseItem::as_string() const { + ::std::string str("For lifetimes: "); + + if (!has_for_lifetimes()) { + str += "none"; + } else { + for (const auto& for_lifetime : for_lifetimes) { + str += "\n " + for_lifetime.as_string(); + } + } + + str += "\nType: " + bound_type->as_string(); + + str += "\nType param bounds bounds: "; + + for (const auto& bound : type_param_bounds) { + // debug null pointer check + if (bound == NULL) { + return "NULL_POINTER_MARK - type param bounds"; + } + + str += "\n " + bound->as_string(); + } + + return str; + } + + ::std::string ArrayElemsValues::as_string() const { + ::std::string str; + + for (const auto& expr : values) { + // DEBUG: null pointer check + if (expr == NULL) { + fprintf(stderr, "something really terrible has gone wrong - null pointer " + "expr in array elems values."); + return "NULL_POINTER_MARK"; + } + + str += "\n " + expr->as_string(); + } + + return str; + } + + ::std::string MaybeNamedParam::as_string() const { + ::std::string str; + + switch (param_kind) { + case UNNAMED: + break; + case IDENTIFIER: + str = name + " : "; + break; + case WILDCARD: + str = "_ : "; + break; + default: + return "ERROR_MARK_STRING - maybe named param unrecognised param kind"; + } + + str += param_type->as_string(); + + return str; + } + + ::std::string MetaItemSeq::as_string() const { + ::std::string path_str = path.as_string() + "("; + + for (const auto& item : seq) { + path_str += item->as_string() + ", "; + } + + return path_str + ")"; + } + + ::std::string MetaListPaths::as_string() const { + ::std::string str = ident + "("; + + for (const auto& path : paths) { + str += path.as_string() + ", "; + } + + return str + ")"; + } + + ::std::string MetaListNameValueStr::as_string() const { + ::std::string str = ident + "("; + + for (const auto& elem : strs) { + str += elem.as_string() + ", "; + } + + return str + ")"; + } + + ::std::string AttrInputMetaItemContainer::as_string() const { + ::std::string str = "("; + + for (const auto& item : items) { + str += item->as_string() + ", "; + } + + return str + ")"; + } + + // Override that calls the function recursively on all items contained within the module. + void ModuleBodied::add_crate_name(::std::vector< ::std::string>& names) const { + /* TODO: test whether module has been 'cfg'-ed out to determine whether to exclude it + * from search */ + + for (const auto& item : items) { + item->add_crate_name(names); + } + } + + void Attribute::parse_attr_to_meta_item() { + // only parse if has attribute input + if (!has_attr_input()) { + return; + } + + ::std::unique_ptr converted_input(attr_input->parse_to_meta_item()); + + if (converted_input != NULL) { + attr_input = ::std::move(converted_input); + } + } + + AttrInput* DelimTokenTree::parse_to_meta_item() const { + // must have token trees + if (token_trees.empty()) { + return NULL; + } + + // assume top-level delim token tree in attribute - convert all nested ones to token + // stream + ::std::vector< ::std::unique_ptr > token_stream = to_token_stream(); + + // TODO: replace this with a specialised converter that the token stream is moved into + /*int i = 0; + ::std::vector< ::std::unique_ptr > meta_items( + parse_meta_item_seq(token_stream, i));*/ + // something like: + MacroParser parser(::std::move(token_stream)); + ::std::vector< ::std::unique_ptr > meta_items( + parser.parse_meta_item_seq()); + + return new AttrInputMetaItemContainer(::std::move(meta_items)); + } + + ::std::unique_ptr MacroParser::parse_meta_item_inner() { + // if first tok not identifier, not a "special" case one + if (peek_token()->get_id() != IDENTIFIER) { + switch (peek_token()->get_id()) { + case CHAR_LITERAL: + case STRING_LITERAL: + case BYTE_CHAR_LITERAL: + case BYTE_STRING_LITERAL: + case INT_LITERAL: + case FLOAT_LITERAL: + case TRUE_LITERAL: + case FALSE_LITERAL: + // stream_pos++; + return parse_meta_item_lit(); + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: { + return parse_path_meta_item(); + } + default: + error_at(peek_token()->get_locus(), "unrecognised token '%s' in meta item", + get_token_description(peek_token()->get_id())); + return NULL; + } + } + + // else, check for path + if (peek_token(1)->get_id() == SCOPE_RESOLUTION) { + // path + return parse_path_meta_item(); + } + + Identifier ident = peek_token()->as_string(); + if (is_end_meta_item_tok(peek_token(1)->get_id())) { + // meta word syntax + skip_token(); + return ::std::unique_ptr(new MetaWord(::std::move(ident))); + } + + if (peek_token(1)->get_id() == EQUAL) { + // maybe meta name value str syntax - check next 2 tokens + if (peek_token(2)->get_id() == STRING_LITERAL + && is_end_meta_item_tok(peek_token(3)->get_id())) { + // meta name value str syntax + ::std::string value = peek_token(2)->as_string(); + + skip_token(2); + + return ::std::unique_ptr( + new MetaNameValueStr(::std::move(ident), ::std::move(value))); + } else { + // just interpret as path-based meta item + return parse_path_meta_item(); + } + } + + if (peek_token(1)->get_id() != LEFT_PAREN) { + error_at(peek_token(1)->get_locus(), + "unexpected token '%s' after identifier in attribute", + get_token_description(peek_token(1)->get_id())); + return NULL; + } + + // HACK: parse parenthesised sequence, and then try conversions to other stuff + ::std::vector< ::std::unique_ptr > meta_items = parse_meta_item_seq(); + + // pass for meta name value str + ::std::vector meta_name_value_str_items; + for (const auto& item : meta_items) { + ::std::unique_ptr converted_item(item->to_meta_name_value_str()); + if (converted_item == NULL) { + meta_name_value_str_items.clear(); + break; + } + meta_name_value_str_items.push_back(::std::move(*converted_item)); + } + // if valid, return this + if (!meta_name_value_str_items.empty()) { + return ::std::unique_ptr(new MetaListNameValueStr( + ::std::move(ident), ::std::move(meta_name_value_str_items))); + } + + // pass for meta list idents + /*::std::vector ident_items; + for (const auto& item : meta_items) { + ::std::unique_ptr converted_ident(item->to_ident_item()); + if (converted_ident == NULL) { + ident_items.clear(); + break; + } + ident_items.push_back(::std::move(*converted_ident)); + } + // if valid return this + if (!ident_items.empty()) { + return ::std::unique_ptr(new MetaListIdents(::std::move(ident), + ::std::move(ident_items))); + }*/ + // as currently no meta list ident, currently no path. may change in future + + // pass for meta list paths + ::std::vector path_items; + for (const auto& item : meta_items) { + SimplePath converted_path(item->to_path_item()); + if (converted_path.is_empty()) { + path_items.clear(); + break; + } + path_items.push_back(::std::move(converted_path)); + } + if (!path_items.empty()) { + return ::std::unique_ptr( + new MetaListPaths(::std::move(ident), ::std::move(path_items))); + } + + error_at(UNKNOWN_LOCATION, "failed to parse any meta item inner"); + return NULL; + } + + bool MacroParser::is_end_meta_item_tok(TokenId id) const { + return id == COMMA || id == RIGHT_PAREN; + } + + ::std::unique_ptr MacroParser::parse_path_meta_item() { + SimplePath path = parse_simple_path(); + if (path.is_empty()) { + error_at(peek_token()->get_locus(), "failed to parse simple path in attribute"); + return NULL; + } + + switch (peek_token()->get_id()) { + case LEFT_PAREN: { + ::std::vector< ::std::unique_ptr > meta_items + = parse_meta_item_seq(); + + return ::std::unique_ptr( + new MetaItemSeq(::std::move(path), ::std::move(meta_items))); + } + case EQUAL: { + skip_token(); + + location_t locus = peek_token()->get_locus(); + Literal lit = parse_literal(); + if (lit.is_error()) { + error_at(peek_token()->get_locus(), "failed to parse literal in attribute"); + return NULL; + } + LiteralExpr expr(::std::move(lit), locus); + // stream_pos++; + // shouldn't be required anymore due to parsing literal actually skipping the + // token + return ::std::unique_ptr( + new MetaItemPathLit(::std::move(path), ::std::move(expr))); + } + case COMMA: + // just simple path + return ::std::unique_ptr(new MetaItemPath(::std::move(path))); + default: + error_at(peek_token()->get_locus(), "unrecognised token '%s' in meta item", + get_token_description(peek_token()->get_id())); + return NULL; + } + } + + // Parses a parenthesised sequence of meta item inners. Parentheses are required here. + ::std::vector< ::std::unique_ptr > MacroParser::parse_meta_item_seq() { + if (stream_pos != 0) { + // warning? + fprintf(stderr, "WARNING: stream pos for parse_meta_item_seq is not 0!\n"); + } + + // int i = 0; + int vec_length = token_stream.size(); + ::std::vector< ::std::unique_ptr > meta_items; + + if (peek_token()->get_id() != LEFT_PAREN) { + error_at(peek_token()->get_locus(), "missing left paren in delim token tree"); + return {}; + } + skip_token(); + + while (stream_pos < vec_length && peek_token()->get_id() != RIGHT_PAREN) { + ::std::unique_ptr inner = parse_meta_item_inner(); + if (inner == NULL) { + error_at( + peek_token()->get_locus(), "failed to parse inner meta item in attribute"); + return {}; + } + meta_items.push_back(::std::move(inner)); + + if (peek_token()->get_id() != COMMA) { + break; + } + skip_token(); + } + + if (peek_token()->get_id() != RIGHT_PAREN) { + error_at(peek_token()->get_locus(), "missing right paren in delim token tree"); + return {}; + } + skip_token(); + + return meta_items; + } + + // Collects any nested token trees into a flat token stream, suitable for parsing. + ::std::vector< ::std::unique_ptr > DelimTokenTree::to_token_stream() const { + ::std::vector< ::std::unique_ptr > tokens; + + // simulate presence of delimiters + tokens.push_back(::std::unique_ptr( + new Token(LEFT_PAREN, UNKNOWN_LOCATION, "", CORETYPE_UNKNOWN))); + + for (const auto& tree : token_trees) { + ::std::vector< ::std::unique_ptr > stream = tree->to_token_stream(); + + tokens.insert(tokens.end(), ::std::make_move_iterator(stream.begin()), + ::std::make_move_iterator(stream.end())); + } + + tokens.push_back(::std::unique_ptr( + new Token(RIGHT_PAREN, UNKNOWN_LOCATION, "", CORETYPE_UNKNOWN))); + + tokens.shrink_to_fit(); + + return tokens; + } + + Literal MacroParser::parse_literal() { + const ::std::unique_ptr& tok = peek_token(); + switch (tok->get_id()) { + case CHAR_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::CHAR); + case STRING_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::STRING); + case BYTE_CHAR_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::BYTE); + case BYTE_STRING_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::BYTE_STRING); + case INT_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::INT); + case FLOAT_LITERAL: + skip_token(); + return Literal(tok->as_string(), Literal::FLOAT); + case TRUE_LITERAL: + skip_token(); + return Literal("true", Literal::BOOL); + case FALSE_LITERAL: + skip_token(); + return Literal("false", Literal::BOOL); + default: + error_at(tok->get_locus(), "expected literal - found '%s'", + get_token_description(tok->get_id())); + return Literal::create_error(); + } + } + + SimplePath MacroParser::parse_simple_path() { + bool has_opening_scope_res = false; + if (peek_token()->get_id() == SCOPE_RESOLUTION) { + has_opening_scope_res = true; + skip_token(); + } + + ::std::vector segments; + + SimplePathSegment segment = parse_simple_path_segment(); + if (segment.is_error()) { + error_at(peek_token()->get_locus(), + "failed to parse simple path segment in attribute simple path"); + return SimplePath::create_empty(); + } + segments.push_back(::std::move(segment)); + + while (peek_token()->get_id() == SCOPE_RESOLUTION) { + skip_token(); + + SimplePathSegment segment = parse_simple_path_segment(); + if (segment.is_error()) { + error_at(peek_token()->get_locus(), + "failed to parse simple path segment in attribute simple path"); + return SimplePath::create_empty(); + } + segments.push_back(::std::move(segment)); + } + segments.shrink_to_fit(); + + return SimplePath(::std::move(segments), has_opening_scope_res); + } + + SimplePathSegment MacroParser::parse_simple_path_segment() { + const ::std::unique_ptr& tok = peek_token(); + switch (tok->get_id()) { + case IDENTIFIER: + skip_token(); + return SimplePathSegment(tok->as_string(), tok->get_locus()); + case SUPER: + skip_token(); + return SimplePathSegment("super", tok->get_locus()); + case SELF: + skip_token(); + return SimplePathSegment("self", tok->get_locus()); + case CRATE: + skip_token(); + return SimplePathSegment("crate", tok->get_locus()); + case DOLLAR_SIGN: + if (peek_token(1)->get_id() == CRATE) { + skip_token(1); + return SimplePathSegment("$crate", tok->get_locus()); + } + gcc_fallthrough(); + default: + error_at(tok->get_locus(), "unexpected token '%s' in simple path segment", + get_token_description(tok->get_id())); + return SimplePathSegment::create_error(); + } + } + + ::std::unique_ptr MacroParser::parse_meta_item_lit() { + location_t locus = peek_token()->get_locus(); + LiteralExpr lit_expr(parse_literal(), locus); + return ::std::unique_ptr(new MetaItemLitExpr(::std::move(lit_expr))); + } + + bool AttrInputMetaItemContainer::check_cfg_predicate(const Session& session) const { + // cfg value of container is purely based on cfg of each inner item - all must be true + for (const auto& inner_item : items) { + if (!inner_item->check_cfg_predicate(session)) { + return false; + } + } + + /* TODO: as far as I can tell, there should only be a single element to check here, so + * ensure there is only a single element in items too? */ + + return true; + } + + bool MetaItemLitExpr::check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const { + // as far as I can tell, a literal expr can never be a valid cfg body, so false + return false; + } + + bool MetaListNameValueStr::check_cfg_predicate(const Session& session) const { + if (ident == "all") { + for (const auto& str : strs) { + if (!str.check_cfg_predicate(session)) { + return false; + } + } + return true; + } else if (ident == "any") { + for (const auto& str : strs) { + if (str.check_cfg_predicate(session)) { + return true; + } + } + return false; + } else if (ident == "not") { + if (strs.size() != 1) { + // HACK: convert vector platform-dependent size_type to string to use in printf + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaListNameValueStr with ident of " + "'not' because there are '%s' elements, not '1'", + ::std::to_string(strs.size()).c_str()); + return false; + } + + return !strs[0].check_cfg_predicate(session); + } else { + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaListNameValueStr with ident of " + "'%s' - ident must be 'all' or 'any'", + ident.c_str()); + return false; + } + } + + bool MetaListPaths::check_cfg_predicate(const Session& session) const { + if (ident == "all") { + for (const auto& path : paths) { + if (!check_path_exists_in_cfg(session, path)) { + return false; + } + } + return true; + } else if (ident == "any") { + for (const auto& path : paths) { + if (check_path_exists_in_cfg(session, path)) { + return true; + } + } + return false; + } else if (ident == "not") { + if (paths.size() != 1) { + // HACK: convert vector platform-dependent size_type to string to use in printf + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaListPaths with ident of 'not' " + "because there are '%s' elements, not '1'", + ::std::to_string(paths.size()).c_str()); + return false; + } + + return !check_path_exists_in_cfg(session, paths[0]); + } else { + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaListNameValueStr with ident of " + "'%s' - ident must be 'all' or 'any'", + ident.c_str()); + return false; + } + } + + bool MetaListPaths::check_path_exists_in_cfg( + const Session& session, const SimplePath& path) const { + auto it = session.options.target_data.features.find(path.as_string()); + if (it != session.options.target_data.features.end()) { + return true; + } + return false; + } + + bool MetaItemSeq::check_cfg_predicate(const Session& session) const { + if (path.as_string() == "all") { + for (const auto& item : seq) { + if (!item->check_cfg_predicate(session)) { + return false; + } + } + return true; + } else if (path.as_string() == "any") { + for (const auto& item : seq) { + if (item->check_cfg_predicate(session)) { + return true; + } + } + return false; + } else if (path.as_string() == "not") { + if (seq.size() != 1) { + // HACK: convert vector platform-dependent size_type to string to use in printf + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaItemSeq with ident of 'not' " + "because there are '%s' elements, not '1'", + ::std::to_string(seq.size()).c_str()); + return false; + } + + return !seq[0]->check_cfg_predicate(session); + } else { + error_at(UNKNOWN_LOCATION, + "cfg predicate could not be checked for MetaItemSeq with path of " + "'%s' - path must be 'all' or 'any'", + path.as_string().c_str()); + return false; + } + } + + bool MetaWord::check_cfg_predicate(const Session& session) const { + auto it = session.options.target_data.features.find(ident); + if (it != session.options.target_data.features.end()) { + return true; + } + return false; + } + + bool MetaItemPath::check_cfg_predicate(const Session& session) const { + /* Strictly speaking, this should always be false, but maybe do check relating to + * SimplePath being identifier. Currently, it would return true if path as identifier + * existed, and if the path in string form existed (though this shouldn't occur). */ + auto it = session.options.target_data.features.find(path.as_string()); + if (it != session.options.target_data.features.end()) { + return true; + } + return false; + } + + bool MetaNameValueStr::check_cfg_predicate(const Session& session) const { + auto it = session.options.target_data.features.find(ident); + if (it != session.options.target_data.features.end()) { + // value must also be the same, not just the name existing + if (it->second.find(str) != it->second.end()) { + return true; + } + } + return false; + } + + bool MetaItemPathLit::check_cfg_predicate(const Session& session) const { + auto it = session.options.target_data.features.find(path.as_string()); + if (it != session.options.target_data.features.end()) { + // value must also be the same, not just the name existing + if (it->second.find(lit.as_string()) != it->second.end()) { + return true; + } + } + return false; + } + + ::std::vector< ::std::unique_ptr > Token::to_token_stream() const { + // initialisation list doesn't work as it needs copy constructor, so have to do this + ::std::vector< ::std::unique_ptr > dummy_vector; + dummy_vector.reserve(1); + dummy_vector.push_back(::std::unique_ptr(clone_token_impl())); + return dummy_vector; + } + + /* Visitor implementations - these are short but inlining can't happen anyway due to virtual + * functions and I didn't want to make the ast header includes any longer than they already + * are. */ + + void Token::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void DelimTokenTree::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IdentifierExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Lifetime::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LifetimeParam::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroInvocationSemi::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void PathInExpression::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypePathSegment::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypePathSegmentGeneric::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypePathSegmentFunction::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypePath::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void QualifiedPathInExpression::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void QualifiedPathInType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LiteralExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void AttrInputLiteral::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaItemLitExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaItemPathLit::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void BorrowExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void DereferenceExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ErrorPropagationExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void NegationExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArithmeticOrLogicalExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ComparisonExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LazyBooleanExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypeCastExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void AssignmentExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void CompoundAssignmentExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void GroupedExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArrayElemsValues::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArrayElemsCopied::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArrayExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArrayIndexExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleIndexExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprStruct::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprFieldIdentifier::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprFieldIdentifierValue::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprFieldIndexValue::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprStructFields::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprStructBase::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprTuple::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructExprUnit::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprFieldIdentifier::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprFieldIdentifierValue::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprFieldIndexValue::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprStruct::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprTuple::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumExprFieldless::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void CallExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MethodCallExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void FieldAccessExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ClosureExprInner::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void BlockExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ClosureExprInnerTyped::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ContinueExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void BreakExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeFromToExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeFromExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeToExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeFullExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeFromToInclExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangeToInclExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ReturnExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void UnsafeBlockExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LoopExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void WhileLoopExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void WhileLetLoopExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ForLoopExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfExprConseqElse::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfExprConseqIf::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfExprConseqIfLet::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfLetExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfLetExprConseqElse::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfLetExprConseqIf::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IfLetExprConseqIfLet::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MatchCaseBlockExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MatchCaseExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MatchExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void AwaitExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void AsyncBlockExpr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypeParam::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LifetimeWhereClauseItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypeBoundWhereClauseItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Method::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ModuleBodied::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ModuleNoBody::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExternCrate::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void UseTreeGlob::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void UseTreeList::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void UseTreeRebind::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void UseDeclaration::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Function::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TypeAlias::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructStruct::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleStruct::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumItemTuple::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumItemStruct::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EnumItemDiscriminant::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Enum::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Union::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ConstantItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StaticItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitItemFunc::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitItemMethod::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitItemConst::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitItemType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void Trait::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void InherentImpl::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitImpl::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExternalStaticItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExternalFunctionItem::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExternBlock::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroMatchFragment::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroMatchRepetition::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroMatcher::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroRulesDefinition::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MacroInvocation::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LiteralPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void IdentifierPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void WildcardPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangePatternBoundLiteral::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangePatternBoundPath::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangePatternBoundQualPath::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RangePattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ReferencePattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructPatternFieldTuplePat::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructPatternFieldIdentPat::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructPatternFieldIdent::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void StructPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleStructItemsNoRange::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleStructItemsRange::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleStructPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TuplePatternItemsMultiple::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TuplePatternItemsRanged::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TuplePattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void GroupedPattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void SlicePattern::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void EmptyStmt::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void LetStmt::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExprStmtWithoutBlock::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ExprStmtWithBlock::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitBound::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ImplTraitType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitObjectType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ParenthesisedType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ImplTraitTypeOneBound::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TraitObjectTypeOneBound::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void TupleType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void NeverType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void RawPointerType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ReferenceType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void ArrayType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void SliceType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void InferredType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void BareFunctionType::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaItemSeq::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaItemPath::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaListPaths::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaNameValueStr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaListNameValueStr::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void AttrInputMetaItemContainer::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + + void MetaWord::accept_vis(ASTVisitor& vis) { + vis.visit(*this); + } + } +} diff --git a/gcc/rust/ast/rust-ast-full.h b/gcc/rust/ast/rust-ast-full.h new file mode 100644 index 0000000..5378236 --- /dev/null +++ b/gcc/rust/ast/rust-ast-full.h @@ -0,0 +1,13 @@ +#ifndef RUST_AST_FULL_H +#define RUST_AST_FULL_H +// Use as a fast way of including all aspects of the AST (i.e. all headers) +#include "rust-ast.h" +#include "rust-expr.h" +#include "rust-item.h" +#include "rust-path.h" +#include "rust-pattern.h" +#include "rust-stmt.h" +#include "rust-type.h" +#include "rust-macro.h" + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h new file mode 100644 index 0000000..b8e92c2 --- /dev/null +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -0,0 +1,224 @@ +#ifndef RUST_AST_VISITOR_H +#define RUST_AST_VISITOR_H +// Visitor base for AST + +// full include not required - only forward decls +#include "rust-ast-full-decls.h" + +namespace Rust { + namespace AST { + // Pure abstract class that provides an interface for accessing different classes of the AST. + class ASTVisitor { + public: + // only concrete class overloads are required + + // rust-ast.h + //virtual void visit(AttrInput& attr_input) = 0; + //virtual void visit(TokenTree& token_tree) = 0; + //virtual void visit(MacroMatch& macro_match) = 0; + virtual void visit(Token& tok) = 0; + virtual void visit(DelimTokenTree& delim_tok_tree) = 0; + virtual void visit(AttrInputMetaItemContainer& input) = 0; + //virtual void visit(MetaItem& meta_item) = 0; + //virtual void visit(Stmt& stmt) = 0; + //virtual void visit(Expr& expr) = 0; + virtual void visit(IdentifierExpr& ident_expr) = 0; + //virtual void visit(Pattern& pattern) = 0; + //virtual void visit(Type& type) = 0; + //virtual void visit(TypeParamBound& type_param_bound) = 0; + virtual void visit(Lifetime& lifetime) = 0; + //virtual void visit(GenericParam& generic_param) = 0; + virtual void visit(LifetimeParam& lifetime_param) = 0; + //virtual void visit(TraitItem& trait_item) = 0; + //virtual void visit(InherentImplItem& inherent_impl_item) = 0; + //virtual void visit(TraitImplItem& trait_impl_item) = 0; + virtual void visit(MacroInvocationSemi& macro) = 0; + + // rust-path.h + virtual void visit(PathInExpression& path) = 0; + virtual void visit(TypePathSegment& segment) = 0; + virtual void visit(TypePathSegmentGeneric& segment) = 0; + virtual void visit(TypePathSegmentFunction& segment) = 0; + virtual void visit(TypePath& path) = 0; + virtual void visit(QualifiedPathInExpression& path) = 0; + virtual void visit(QualifiedPathInType& path) = 0; + + // rust-expr.h + virtual void visit(LiteralExpr& expr) = 0; + virtual void visit(AttrInputLiteral& attr_input) = 0; + virtual void visit(MetaItemLitExpr& meta_item) = 0; + virtual void visit(MetaItemPathLit& meta_item) = 0; + virtual void visit(BorrowExpr& expr) = 0; + virtual void visit(DereferenceExpr& expr) = 0; + virtual void visit(ErrorPropagationExpr& expr) = 0; + virtual void visit(NegationExpr& expr) = 0; + virtual void visit(ArithmeticOrLogicalExpr& expr) = 0; + virtual void visit(ComparisonExpr& expr) = 0; + virtual void visit(LazyBooleanExpr& expr) = 0; + virtual void visit(TypeCastExpr& expr) = 0; + virtual void visit(AssignmentExpr& expr) = 0; + virtual void visit(CompoundAssignmentExpr& expr) = 0; + virtual void visit(GroupedExpr& expr) = 0; + //virtual void visit(ArrayElems& elems) = 0; + virtual void visit(ArrayElemsValues& elems) = 0; + virtual void visit(ArrayElemsCopied& elems) = 0; + virtual void visit(ArrayExpr& expr) = 0; + virtual void visit(ArrayIndexExpr& expr) = 0; + virtual void visit(TupleExpr& expr) = 0; + virtual void visit(TupleIndexExpr& expr) = 0; + virtual void visit(StructExprStruct& expr) = 0; + //virtual void visit(StructExprField& field) = 0; + virtual void visit(StructExprFieldIdentifier& field) = 0; + virtual void visit(StructExprFieldIdentifierValue& field) = 0; + virtual void visit(StructExprFieldIndexValue& field) = 0; + virtual void visit(StructExprStructFields& expr) = 0; + virtual void visit(StructExprStructBase& expr) = 0; + virtual void visit(StructExprTuple& expr) = 0; + virtual void visit(StructExprUnit& expr) = 0; + //virtual void visit(EnumExprField& field) = 0; + virtual void visit(EnumExprFieldIdentifier& field) = 0; + virtual void visit(EnumExprFieldIdentifierValue& field) = 0; + virtual void visit(EnumExprFieldIndexValue& field) = 0; + virtual void visit(EnumExprStruct& expr) = 0; + virtual void visit(EnumExprTuple& expr) = 0; + virtual void visit(EnumExprFieldless& expr) = 0; + virtual void visit(CallExpr& expr) = 0; + virtual void visit(MethodCallExpr& expr) = 0; + virtual void visit(FieldAccessExpr& expr) = 0; + virtual void visit(ClosureExprInner& expr) = 0; + virtual void visit(BlockExpr& expr) = 0; + virtual void visit(ClosureExprInnerTyped& expr) = 0; + virtual void visit(ContinueExpr& expr) = 0; + virtual void visit(BreakExpr& expr) = 0; + virtual void visit(RangeFromToExpr& expr) = 0; + virtual void visit(RangeFromExpr& expr) = 0; + virtual void visit(RangeToExpr& expr) = 0; + virtual void visit(RangeFullExpr& expr) = 0; + virtual void visit(RangeFromToInclExpr& expr) = 0; + virtual void visit(RangeToInclExpr& expr) = 0; + virtual void visit(ReturnExpr& expr) = 0; + virtual void visit(UnsafeBlockExpr& expr) = 0; + virtual void visit(LoopExpr& expr) = 0; + virtual void visit(WhileLoopExpr& expr) = 0; + virtual void visit(WhileLetLoopExpr& expr) = 0; + virtual void visit(ForLoopExpr& expr) = 0; + virtual void visit(IfExpr& expr) = 0; + virtual void visit(IfExprConseqElse& expr) = 0; + virtual void visit(IfExprConseqIf& expr) = 0; + virtual void visit(IfExprConseqIfLet& expr) = 0; + virtual void visit(IfLetExpr& expr) = 0; + virtual void visit(IfLetExprConseqElse& expr) = 0; + virtual void visit(IfLetExprConseqIf& expr) = 0; + virtual void visit(IfLetExprConseqIfLet& expr) = 0; + //virtual void visit(MatchCase& match_case) = 0; + virtual void visit(MatchCaseBlockExpr& match_case) = 0; + virtual void visit(MatchCaseExpr& match_case) = 0; + virtual void visit(MatchExpr& expr) = 0; + virtual void visit(AwaitExpr& expr) = 0; + virtual void visit(AsyncBlockExpr& expr) = 0; + + // rust-item.h + virtual void visit(TypeParam& param) = 0; + //virtual void visit(WhereClauseItem& item) = 0; + virtual void visit(LifetimeWhereClauseItem& item) = 0; + virtual void visit(TypeBoundWhereClauseItem& item) = 0; + virtual void visit(Method& method) = 0; + virtual void visit(ModuleBodied& module) = 0; + virtual void visit(ModuleNoBody& module) = 0; + virtual void visit(ExternCrate& crate) = 0; + //virtual void visit(UseTree& use_tree) = 0; + virtual void visit(UseTreeGlob& use_tree) = 0; + virtual void visit(UseTreeList& use_tree) = 0; + virtual void visit(UseTreeRebind& use_tree) = 0; + virtual void visit(UseDeclaration& use_decl) = 0; + virtual void visit(Function& function) = 0; + virtual void visit(TypeAlias& type_alias) = 0; + virtual void visit(StructStruct& struct_item) = 0; + virtual void visit(TupleStruct& tuple_struct) = 0; + virtual void visit(EnumItem& item) = 0; + virtual void visit(EnumItemTuple& item) = 0; + virtual void visit(EnumItemStruct& item) = 0; + virtual void visit(EnumItemDiscriminant& item) = 0; + virtual void visit(Enum& enum_item) = 0; + virtual void visit(Union& union_item) = 0; + virtual void visit(ConstantItem& const_item) = 0; + virtual void visit(StaticItem& static_item) = 0; + virtual void visit(TraitItemFunc& item) = 0; + virtual void visit(TraitItemMethod& item) = 0; + virtual void visit(TraitItemConst& item) = 0; + virtual void visit(TraitItemType& item) = 0; + virtual void visit(Trait& trait) = 0; + virtual void visit(InherentImpl& impl) = 0; + virtual void visit(TraitImpl& impl) = 0; + //virtual void visit(ExternalItem& item) = 0; + virtual void visit(ExternalStaticItem& item) = 0; + virtual void visit(ExternalFunctionItem& item) = 0; + virtual void visit(ExternBlock& block) = 0; + + // rust-macro.h + virtual void visit(MacroMatchFragment& match) = 0; + virtual void visit(MacroMatchRepetition& match) = 0; + virtual void visit(MacroMatcher& matcher) = 0; + virtual void visit(MacroRulesDefinition& rules_def) = 0; + virtual void visit(MacroInvocation& macro_invoc) = 0; + virtual void visit(MetaItemPath& meta_item) = 0; + virtual void visit(MetaItemSeq& meta_item) = 0; + virtual void visit(MetaWord& meta_item) = 0; + virtual void visit(MetaNameValueStr& meta_item) = 0; + virtual void visit(MetaListPaths& meta_item) = 0; + virtual void visit(MetaListNameValueStr& meta_item) = 0; + + // rust-pattern.h + virtual void visit(LiteralPattern& pattern) = 0; + virtual void visit(IdentifierPattern& pattern) = 0; + virtual void visit(WildcardPattern& pattern) = 0; + //virtual void visit(RangePatternBound& bound) = 0; + virtual void visit(RangePatternBoundLiteral& bound) = 0; + virtual void visit(RangePatternBoundPath& bound) = 0; + virtual void visit(RangePatternBoundQualPath& bound) = 0; + virtual void visit(RangePattern& pattern) = 0; + virtual void visit(ReferencePattern& pattern) = 0; + //virtual void visit(StructPatternField& field) = 0; + virtual void visit(StructPatternFieldTuplePat& field) = 0; + virtual void visit(StructPatternFieldIdentPat& field) = 0; + virtual void visit(StructPatternFieldIdent& field) = 0; + virtual void visit(StructPattern& pattern) = 0; + //virtual void visit(TupleStructItems& tuple_items) = 0; + virtual void visit(TupleStructItemsNoRange& tuple_items) = 0; + virtual void visit(TupleStructItemsRange& tuple_items) = 0; + virtual void visit(TupleStructPattern& pattern) = 0; + //virtual void visit(TuplePatternItems& tuple_items) = 0; + virtual void visit(TuplePatternItemsMultiple& tuple_items) = 0; + virtual void visit(TuplePatternItemsRanged& tuple_items) = 0; + virtual void visit(TuplePattern& pattern) = 0; + virtual void visit(GroupedPattern& pattern) = 0; + virtual void visit(SlicePattern& pattern) = 0; + + // rust-stmt.h + virtual void visit(EmptyStmt& stmt) = 0; + virtual void visit(LetStmt& stmt) = 0; + virtual void visit(ExprStmtWithoutBlock& stmt) = 0; + virtual void visit(ExprStmtWithBlock& stmt) = 0; + + // rust-type.h + virtual void visit(TraitBound& bound) = 0; + virtual void visit(ImplTraitType& type) = 0; + virtual void visit(TraitObjectType& type) = 0; + virtual void visit(ParenthesisedType& type) = 0; + virtual void visit(ImplTraitTypeOneBound& type) = 0; + virtual void visit(TraitObjectTypeOneBound& type) = 0; + virtual void visit(TupleType& type) = 0; + virtual void visit(NeverType& type) = 0; + virtual void visit(RawPointerType& type) = 0; + virtual void visit(ReferenceType& type) = 0; + virtual void visit(ArrayType& type) = 0; + virtual void visit(SliceType& type) = 0; + virtual void visit(InferredType& type) = 0; + virtual void visit(BareFunctionType& type) = 0; + + // TODO: rust-cond-compilation.h visiting? not currently used + }; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h new file mode 100644 index 0000000..ebcbd25 --- /dev/null +++ b/gcc/rust/ast/rust-ast.h @@ -0,0 +1,1375 @@ +#ifndef RUST_AST_BASE_H +#define RUST_AST_BASE_H +// Base for AST used in gccrs, basically required by all specific ast things + +// GCC imports +#include "config.h" +//#define INCLUDE_UNIQUE_PTR +// should allow including the gcc emulation of std::unique_ptr +#include "system.h" +#include "coretypes.h" // order: config, INCLUDE, system, coretypes + +// STL imports +#include "rust-system.h" +// with C++11, now can use actual std::unique_ptr +#include + +// gccrs imports +// required for AST::Token +#include "rust-token.h" + +namespace Rust { + // TODO: remove typedefs and make actual types for these + // typedef int location_t; + // typedef ::std::string SimplePath; + typedef ::std::string Identifier; + typedef int TupleIndex; + + struct Session; + + namespace AST { + // foward decl: ast visitor + class ASTVisitor; + + // Delimiter types - used in macros and whatever. + enum DelimType { PARENS, SQUARE, CURLY }; + + // Base AST node object - TODO is this really required or useful? Where to draw line? + /*class Node { + public: + // Gets node's location_t. + location_t get_locus() const { + return loc; + } + + // Sets node's location_t. + void set_locus(location_t loc_) { + loc = loc_; + } + + // Get node output as a string. Pure virtual. + virtual ::std::string as_string() const = 0; + + virtual ~Node() {} + + // TODO: constructor including location_t? Make all derived classes have location_t? + + private: + // The node's location. + location_t loc; + };*/ + // decided to not have node as a "node" would never need to be stored + + // Attribute body - abstract base class + class AttrInput { + public: + virtual ~AttrInput() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_attr_input() const { + return ::std::unique_ptr(clone_attr_input_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + virtual bool check_cfg_predicate(const Session& session) const = 0; + + // Parse attribute input to meta item, if possible + virtual AttrInput* parse_to_meta_item() const { + return NULL; + } + + protected: + // pure virtual clone implementation + virtual AttrInput* clone_attr_input_impl() const = 0; + }; + + // forward decl for use in token tree method + class Token; + + // A tree of tokens (or a single token) - abstract base class + class TokenTree { + public: + virtual ~TokenTree() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_token_tree() const { + return ::std::unique_ptr(clone_token_tree_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + /* Converts token tree to a flat token stream. Tokens must be pointer to avoid mutual + * dependency with Token. */ + virtual ::std::vector< ::std::unique_ptr > to_token_stream() const = 0; + + protected: + // pure virtual clone implementation + virtual TokenTree* clone_token_tree_impl() const = 0; + }; + + // Abstract base class for a macro match + class MacroMatch { + public: + virtual ~MacroMatch() {} + + virtual ::std::string as_string() const = 0; + + // Unique pointer custom clone function + ::std::unique_ptr clone_macro_match() const { + return ::std::unique_ptr(clone_macro_match_impl()); + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual clone implementation + virtual MacroMatch* clone_macro_match_impl() const = 0; + }; + + // A token is a kind of token tree (except delimiter tokens) + class Token + : public TokenTree + , public MacroMatch { + // A token is a kind of token tree (except delimiter tokens) + // A token is a kind of MacroMatch (except $ and delimiter tokens) + // TODO: improve member variables - current ones are the same as lexer token + // Token kind. + TokenId token_id; + // Token location. + location_t locus; + // Associated text (if any) of token. + std::string str; + // Token type hint (if any). + PrimitiveCoreType type_hint; + + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_token() const { + return ::std::unique_ptr(clone_token_impl()); + } + + // constructor from general text - avoid using if lexer const_TokenPtr is available + Token( + TokenId token_id, location_t locus, ::std::string str, PrimitiveCoreType type_hint) : + token_id(token_id), + locus(locus), str(::std::move(str)), type_hint(type_hint) {} + + // Constructor from lexer const_TokenPtr + /* TODO: find workaround for std::string being NULL - probably have to introduce new + * method in lexer Token, or maybe make conversion method there*/ + Token(const_TokenPtr lexer_token_ptr) : + token_id(lexer_token_ptr->get_id()), locus(lexer_token_ptr->get_locus()), str(""), + type_hint(lexer_token_ptr->get_type_hint()) { + // FIXME: change to "should have str" later? + if (lexer_token_ptr->has_str()) { + str = lexer_token_ptr->get_str(); + + // DEBUG + fprintf(stderr, "ast token created with str '%s'\n", str.c_str()); + } else { + // FIXME: is this returning correct thing? + str = lexer_token_ptr->get_token_description(); + + // DEBUG + fprintf(stderr, "ast token created with string '%s'\n", str.c_str()); + } + + // DEBUG + if (lexer_token_ptr->should_have_str() && !lexer_token_ptr->has_str()) { + fprintf(stderr, "BAD: for token '%s', should have string but does not!\n", + lexer_token_ptr->get_token_description()); + } + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // Return copy of itself but in token stream form. + virtual ::std::vector< ::std::unique_ptr > to_token_stream() const OVERRIDE; + + TokenId get_id() const { + return token_id; + } + + location_t get_locus() const { + return locus; + } + + protected: + // No virtual for now as not polymorphic but can be in future + /*virtual*/ Token* clone_token_impl() const { + return new Token(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual Token* clone_token_tree_impl() const OVERRIDE { + return new Token(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual Token* clone_macro_match_impl() const OVERRIDE { + return new Token(*this); + } + }; + + // A literal - value with a type. Used in LiteralExpr and LiteralPattern. + struct Literal { + public: + enum LitType { + CHAR, + STRING, + RAW_STRING, + BYTE, + BYTE_STRING, + RAW_BYTE_STRING, + INT, + FLOAT, + BOOL + }; + + private: + // TODO: maybe make subclasses of each type of literal with their typed values (or + // generics) + ::std::string value_as_string; + LitType type; + + public: + ::std::string as_string() const { + return value_as_string; + } + + inline LitType get_lit_type() const { + return type; + } + + Literal(::std::string value_as_string, LitType type) : + value_as_string(::std::move(value_as_string)), type(type) {} + + static Literal create_error() { + return Literal("", CHAR); + } + + // Returns whether literal is in an invalid state. + bool is_error() const { + return value_as_string == ""; + } + }; + + // A token tree with delimiters + class DelimTokenTree + : public TokenTree + , public AttrInput { + DelimType delim_type; + ::std::vector< ::std::unique_ptr > token_trees; + + location_t locus; + + // TODO: move all the "parse" functions into a separate class that has the token stream + // reference - will be cleaner Parse a meta item inner. + //::std::unique_ptr parse_meta_item_inner(const ::std::vector< + //::std::unique_ptr >& token_stream, int& i) const; SimplePath + // parse_simple_path(const ::std::vector< ::std::unique_ptr >& token_stream, int& i) + // const; SimplePathSegment parse_simple_path_segment(const ::std::vector< + // ::std::unique_ptr >& token_stream, int& i) const; + //::std::unique_ptr parse_meta_item_lit(const ::std::unique_ptr& + //tok) const; + //::std::vector< ::std::unique_ptr > parse_meta_item_seq(const + //::std::vector< ::std::unique_ptr >& token_stream, int& i) const; Literal + // parse_literal(const ::std::unique_ptr& tok) const; + //::std::unique_ptr parse_path_meta_item(const ::std::vector< + //::std::unique_ptr >& token_stream, int& i) const; bool + // is_end_meta_item_tok(TokenId tok) const; + + protected: + // Use covariance to implement clone function as returning a DelimTokenTree object + virtual DelimTokenTree* clone_attr_input_impl() const OVERRIDE { + return new DelimTokenTree(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual DelimTokenTree* clone_token_tree_impl() const OVERRIDE { + return new DelimTokenTree(*this); + } + + public: + DelimTokenTree(DelimType delim_type, + ::std::vector< ::std::unique_ptr > token_trees + = ::std::vector< ::std::unique_ptr >(), + location_t locus = UNKNOWN_LOCATION) : + delim_type(delim_type), + token_trees(::std::move(token_trees)), locus(locus) {} + + // Copy constructor with vector clone + DelimTokenTree(DelimTokenTree const& other) : + delim_type(other.delim_type), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + token_trees.reserve(other.token_trees.size()); + + for (const auto& e : other.token_trees) { + token_trees.push_back(e->clone_token_tree()); + } + } + + // overloaded assignment operator with vector clone + DelimTokenTree& operator=(DelimTokenTree const& other) { + delim_type = other.delim_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + token_trees.reserve(other.token_trees.size()); + + for (const auto& e : other.token_trees) { + token_trees.push_back(e->clone_token_tree()); + } + + return *this; + } + + // move constructors + DelimTokenTree(DelimTokenTree&& other) = default; + DelimTokenTree& operator=(DelimTokenTree&& other) = default; + + static DelimTokenTree create_empty() { + return DelimTokenTree(PARENS); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { + // this should never be called - should be converted first + return false; + } + + virtual AttrInput* parse_to_meta_item() const OVERRIDE; + + virtual ::std::vector< ::std::unique_ptr > to_token_stream() const OVERRIDE; + }; + + // Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to be defined + class AttrInputLiteral; + + // TODO: move applicable stuff into here or just don't include it because nothing uses it + // A segment of a path (maybe) + class PathSegment { + public: + virtual ~PathSegment() {} + + virtual ::std::string as_string() const = 0; + + // TODO: add visitor here? + }; + + // A segment of a simple path without generic or type arguments + class SimplePathSegment : public PathSegment { + ::std::string segment_name; + location_t locus; + + // only allow identifiers, "super", "self", "crate", or "$crate" + public: + // TODO: put checks in constructor to enforce this rule? + SimplePathSegment(::std::string segment_name, location_t locus = UNKNOWN_LOCATION) : + segment_name(::std::move(segment_name)), locus(locus) {} + + // Returns whether simple path segment is in an invalid state (currently, if empty). + inline bool is_error() const { + return segment_name.empty(); + } + + // Creates an error SimplePathSegment + static SimplePathSegment create_error() { + return SimplePathSegment(::std::string("")); + } + + ::std::string as_string() const; + + inline location_t get_locus() const { + return locus; + } + + // TODO: visitor pattern? + }; + + // A simple path without generic or type arguments + class SimplePath { + bool has_opening_scope_resolution; + ::std::vector segments; + location_t locus; + + public: + // Constructor + SimplePath(::std::vector path_segments, + bool has_opening_scope_resolution = false, location_t locus = UNKNOWN_LOCATION) : + has_opening_scope_resolution(has_opening_scope_resolution), + segments(::std::move(path_segments)), locus(locus) {} + + // Creates an empty SimplePath. + static SimplePath create_empty() { + return SimplePath(::std::vector()); + } + + // Returns whether the SimplePath is empty, i.e. has path segments. + inline bool is_empty() const { + return segments.empty(); + } + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + // does this need visitor if not polymorphic? probably not + + // path-to-string comparison operator + bool operator==(const ::std::string& rhs) { + return !has_opening_scope_resolution && segments.size() == 1 + && segments[0].as_string() == rhs; + } + + /* Creates a single-segment SimplePath from a string. This will not check to ensure that + * this is a valid identifier in path, so be careful. Also, this will have no location + * data. + * TODO have checks? */ + static SimplePath from_str(::std::string str) { + ::std::vector single_segments + = { AST::SimplePathSegment(::std::move(str)) }; + return SimplePath(::std::move(single_segments)); + } + }; + + // aka Attr + // Attribute AST representation + struct Attribute { + private: + SimplePath path; + + // bool has_attr_input; + // AttrInput* attr_input; + ::std::unique_ptr attr_input; + + location_t locus; + + // TODO: maybe a variable storing whether attr input is parsed or not + + public: + // Returns whether Attribute has AttrInput + inline bool has_attr_input() const { + return attr_input != NULL; + } + + // Constructor has pointer AttrInput for polymorphism reasons + Attribute(SimplePath path, ::std::unique_ptr input, + location_t locus = UNKNOWN_LOCATION) : + path(::std::move(path)), + attr_input(::std::move(input)), locus(locus) {} + + // Copy constructor must deep copy attr_input as unique pointer + Attribute(Attribute const& other) : path(other.path), locus(other.locus) { + // guard to protect from null pointer dereference + if (other.attr_input != NULL) { + attr_input = other.attr_input->clone_attr_input(); + } + } + + // default destructor + ~Attribute() = default; + + // overload assignment operator to use custom clone method + Attribute& operator=(Attribute const& other) { + path = other.path; + locus = other.locus; + // guard to protect from null pointer dereference + if (other.attr_input != NULL) { + attr_input = other.attr_input->clone_attr_input(); + } + + return *this; + } + + // default move semantics + Attribute(Attribute&& other) = default; + Attribute& operator=(Attribute&& other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr clone_attribute() const { + return ::std::unique_ptr(clone_attribute_impl()); + } + + /*~Attribute() { + delete attr_input; + }*/ + + // Creates an empty attribute (which is invalid) + static Attribute create_empty() { + return Attribute(SimplePath::create_empty(), NULL); + } + + // Returns whether the attribute is considered an "empty" attribute. + inline bool is_empty() const { + return attr_input == NULL && path.is_empty(); + } + + /* e.g.: + #![crate_type = "lib"] + #[test] + #[cfg(target_os = "linux")] + #[allow(non_camel_case_types)] + #![allow(unused_variables)] + */ + + // Full built-in attribute list: + /* cfg + * cfg_attr + * test + * ignore + * should_panic + * derive + * macro_export + * macro_use + * proc_macro + * proc_macro_derive + * proc_macro_attribute + * allow + * warn + * deny + * forbid + * deprecated + * must_use + * link + * link_name + * no_link + * repr + * crate_type + * no_main + * export_name + * link_section + * no_mangle + * used + * crate_name + * inline + * cold + * no_builtins + * target_feature + * doc + * no_std + * no_implicit_prelude + * path + * recursion_limit + * type_length_limit + * panic_handler + * global_allocator + * windows_subsystem + * feature */ + + ::std::string as_string() const; + + // TODO: does this require visitor pattern as not polymorphic? + + // Maybe change to const-reference in future + SimplePath get_path() const { + return path; + } + + // Call to parse attribute body to meta item syntax. + void parse_attr_to_meta_item(); + + // Determines whether cfg predicate is true and item with attribute should not be + // stripped. + bool check_cfg_predicate(const Session& session) { + // assume that cfg predicate actually can exist, i.e. attribute has cfg or cfg_attr + // path + + if (!has_attr_input()) { + return false; + } + + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item(); + // can't be const because of this anyway + + return attr_input->check_cfg_predicate(session); + } + + protected: + // not virtual as currently no subclasses of Attribute, but could be in future + /*virtual*/ Attribute* clone_attribute_impl() const { + return new Attribute(*this); + } + }; + + // Forward decl - defined in rust-macro.h + class MetaNameValueStr; + + // abstract base meta item inner class + class MetaItemInner { + protected: + // pure virtual as MetaItemInner + virtual MetaItemInner* clone_meta_item_inner_impl() const = 0; + + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_meta_item_inner() const { + return ::std::unique_ptr(clone_meta_item_inner_impl()); + } + + virtual ~MetaItemInner() {} + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + // HACK: used to simplify parsing - creates a copy of that type, or returns null + virtual MetaNameValueStr* to_meta_name_value_str() const { + return NULL; + } + + // HACK: used to simplify parsing - same thing + virtual SimplePath to_path_item() const { + return SimplePath::create_empty(); + } + + virtual bool check_cfg_predicate(const Session& session) const = 0; + }; + + // Container used to store MetaItems as AttrInput (bridge-ish kinda thing) + class AttrInputMetaItemContainer : public AttrInput { + ::std::vector< ::std::unique_ptr > items; + + public: + AttrInputMetaItemContainer(::std::vector< ::std::unique_ptr > items) : + items(::std::move(items)) {} + + // copy constructor with vector clone + AttrInputMetaItemContainer(const AttrInputMetaItemContainer& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_meta_item_inner()); + } + } + + // no destructor definition required + + // copy assignment operator with vector clone + AttrInputMetaItemContainer& operator=(const AttrInputMetaItemContainer& other) { + AttrInput::operator=(other); + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_meta_item_inner()); + } + + return *this; + } + + // default move constructors + AttrInputMetaItemContainer(AttrInputMetaItemContainer&& other) = default; + AttrInputMetaItemContainer& operator=(AttrInputMetaItemContainer&& other) = default; + + ::std::string as_string() const OVERRIDE; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual AttrInputMetaItemContainer* clone_attr_input_impl() const OVERRIDE { + return new AttrInputMetaItemContainer(*this); + } + }; + + // abstract base meta item class + class MetaItem : public MetaItemInner {}; + + // Forward decl - defined in rust-expr.h + class MetaItemLitExpr; + + // Forward decl - defined in rust-expr.h + class MetaItemPathLit; + + // Forward decl - defined in rust-macro.h + class MetaItemPath; + + // Forward decl - defined in rust-macro.h + class MetaItemSeq; + + // Forward decl - defined in rust-macro.h + class MetaWord; + + // Forward decl - defined in rust-macro.h + class MetaListPaths; + + // Forward decl - defined in rust-macro.h + struct MetaListNameValueStr; + + /* Base statement abstract class. Note that most "statements" are not allowed in top-level + * module scope - only a subclass of statements called "items" are. */ + class Stmt { + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_stmt() const { + return ::std::unique_ptr(clone_stmt_impl()); + } + + virtual ~Stmt() {} + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual Stmt* clone_stmt_impl() const = 0; + }; + + // Rust "item" AST node (declaration of top-level/module-level allowed stuff) + class Item : public Stmt { + ::std::vector outer_attrs; + + // TODO: should outer attrs be defined here or in each derived class? + + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_item() const { + return ::std::unique_ptr(clone_item_impl()); + } + + ::std::string as_string() const; + + // Adds crate names to the vector passed by reference, if it can (polymorphism). + virtual void add_crate_name(::std::vector< ::std::string>& names ATTRIBUTE_UNUSED) const { + } + + protected: + // Constructor + Item(::std::vector outer_attribs = ::std::vector()) : + outer_attrs(::std::move(outer_attribs)) {} + + // Clone function implementation as pure virtual method + virtual Item* clone_item_impl() const = 0; + + /* Save having to specify two clone methods in derived classes by making statement clone + * return item clone. Hopefully won't affect performance too much. */ + virtual Item* clone_stmt_impl() const OVERRIDE { + return clone_item_impl(); + } + }; + + // forward decl of ExprWithoutBlock + class ExprWithoutBlock; + + // Base expression AST node - abstract + class Expr { + // TODO: move outer attribute data to derived classes? + ::std::vector outer_attrs; + + public: + inline const ::std::vector& get_outer_attrs() const { + return outer_attrs; + } + + // Unique pointer custom clone function + ::std::unique_ptr clone_expr() const { + return ::std::unique_ptr(clone_expr_impl()); + } + + /* TODO: public methods that could be useful: + * - get_type() - returns type of expression. set_type() may also be useful for some? + * - evaluate() - evaluates expression if constant? can_evaluate()? */ + + // HACK: downcasting without dynamic_cast (if possible) via polymorphism - overrided in + // subclasses of ExprWithoutBlock + virtual ExprWithoutBlock* as_expr_without_block() const { + // DEBUG + fprintf(stderr, "clone expr without block returns null and has not been overriden\n"); + + return NULL; + } + + // TODO: make pure virtual if move out outer attributes to derived classes + virtual ::std::string as_string() const; + + virtual ~Expr() {} + + // HACK: slow way of getting location from base expression through virtual methods. + virtual location_t get_locus_slow() const { + return UNKNOWN_LOCATION; + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Constructor + Expr(::std::vector outer_attribs = ::std::vector()) : + outer_attrs(::std::move(outer_attribs)) {} + + // Clone function implementation as pure virtual method + virtual Expr* clone_expr_impl() const = 0; + + // TODO: think of less hacky way to implement this kind of thing + // Sets outer attributes. + void set_outer_attrs(::std::vector outer_attrs_to_set) { + outer_attrs = ::std::move(outer_attrs_to_set); + } + }; + + // AST node for an expression without an accompanying block - abstract + class ExprWithoutBlock : public Expr { + protected: + // Constructor + ExprWithoutBlock(::std::vector outer_attribs = ::std::vector()) : + Expr(::std::move(outer_attribs)) {} + + // pure virtual clone implementation + virtual ExprWithoutBlock* clone_expr_without_block_impl() const = 0; + + /* Save having to specify two clone methods in derived classes by making expr clone + * return exprwithoutblock clone. Hopefully won't affect performance too much. */ + virtual ExprWithoutBlock* clone_expr_impl() const OVERRIDE { + return clone_expr_without_block_impl(); + } + + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_expr_without_block() const { + return ::std::unique_ptr(clone_expr_without_block_impl()); + } + + // downcasting hack from expr to use pratt parsing with parse_expr_without_block + virtual ExprWithoutBlock* as_expr_without_block() const OVERRIDE { + // DEBUG + fprintf(stderr, "about to call the impl for clone expr without block\n"); + + return clone_expr_without_block_impl(); + } + }; + + // HACK: IdentifierExpr, delete when figure out identifier vs expr problem in Pratt parser + // Alternatively, identifiers could just be represented as single-segment paths + class IdentifierExpr : public ExprWithoutBlock { + Identifier ident; + + location_t locus; + + public: + IdentifierExpr(Identifier ident, location_t locus = UNKNOWN_LOCATION, + ::std::vector outer_attrs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attrs)), + ident(::std::move(ident)), locus(locus) {} + + ::std::string as_string() const OVERRIDE { + return ident; + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone method implementation + virtual IdentifierExpr* clone_expr_without_block_impl() const OVERRIDE { + return new IdentifierExpr(*this); + } + }; + + // Pattern base AST node + class Pattern { + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_pattern() const { + return ::std::unique_ptr(clone_pattern_impl()); + } + + // possible virtual methods: is_refutable() + + virtual ~Pattern() {} + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone pattern implementation as pure virtual method + virtual Pattern* clone_pattern_impl() const = 0; + }; + + // forward decl for Type + class TraitBound; + + // Base class for types as represented in AST - abstract + class Type { + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_type() const { + return ::std::unique_ptr(clone_type_impl()); + } + + // virtual destructor + virtual ~Type() {} + + virtual ::std::string as_string() const = 0; + + // HACK: convert to trait bound. Virtual method overriden by classes that enable this. + virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const { + return NULL; + } + // as pointer, shouldn't require definition beforehand, only forward declaration. + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual Type* clone_type_impl() const = 0; + }; + + // A type without parentheses? - abstract + class TypeNoBounds : public Type { + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_type_no_bounds() const { + return ::std::unique_ptr(clone_type_no_bounds_impl()); + } + + protected: + // Clone function implementation as pure virtual method + virtual TypeNoBounds* clone_type_no_bounds_impl() const = 0; + + /* Save having to specify two clone methods in derived classes by making type clone + * return typenobounds clone. Hopefully won't affect performance too much. */ + virtual TypeNoBounds* clone_type_impl() const OVERRIDE { + return clone_type_no_bounds_impl(); + } + }; + + // Abstract base class representing a type param bound - Lifetime and TraitBound extends it + class TypeParamBound { + public: + virtual ~TypeParamBound() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_type_param_bound() const { + return ::std::unique_ptr(clone_type_param_bound_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual TypeParamBound* clone_type_param_bound_impl() const = 0; + }; + + // Represents a lifetime (and is also a kind of type param bound) + class Lifetime : public TypeParamBound { + public: + enum LifetimeType { + NAMED, // corresponds to LIFETIME_OR_LABEL + STATIC, // corresponds to 'static + WILDCARD // corresponds to '_ + }; + + private: + LifetimeType lifetime_type; + + // TODO: LIFETIME_OR_LABEL (aka lifetime token) is only field + // find way of enclosing token or something + ::std::string lifetime_name; + // only applies for NAMED lifetime_type + + location_t locus; + + public: + // Constructor + Lifetime(LifetimeType type, ::std::string name = ::std::string(), + location_t locus = UNKNOWN_LOCATION) : + lifetime_type(type), + lifetime_name(::std::move(name)), locus(locus) {} + + // Creates an "error" lifetime. + static Lifetime error() { + return Lifetime(NAMED, ::std::string("")); + } + + // Returns true if the lifetime is in an error state. + inline bool is_error() const { + return lifetime_type == NAMED && lifetime_name.empty(); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Lifetime* clone_type_param_bound_impl() const OVERRIDE { + return new Lifetime(*this); + } + }; + + // Base generic parameter in AST. Abstract - can be represented by a Lifetime or Type param + class GenericParam { + public: + virtual ~GenericParam() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_generic_param() const { + return ::std::unique_ptr(clone_generic_param_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual GenericParam* clone_generic_param_impl() const = 0; + }; + + // A lifetime generic parameter (as opposed to a type generic parameter) + class LifetimeParam : public GenericParam { + Lifetime lifetime; + + // bool has_lifetime_bounds; + // LifetimeBounds lifetime_bounds; + ::std::vector lifetime_bounds; // inlined LifetimeBounds + + // bool has_outer_attribute; + //::std::unique_ptr outer_attr; + Attribute outer_attr; + + location_t locus; + + public: + // Returns whether the lifetime param has any lifetime bounds. + inline bool has_lifetime_bounds() const { + return !lifetime_bounds.empty(); + } + + // Returns whether the lifetime param has an outer attribute. + inline bool has_outer_attribute() const { + return !outer_attr.is_empty(); + } + + // Creates an error state lifetime param. + static LifetimeParam create_error() { + return LifetimeParam(Lifetime::error()); + } + + // Returns whether the lifetime param is in an error state. + inline bool is_error() const { + return lifetime.is_error(); + } + + // Constructor + LifetimeParam(Lifetime lifetime, location_t locus = UNKNOWN_LOCATION, + ::std::vector lifetime_bounds = ::std::vector(), + Attribute outer_attr = Attribute::create_empty()) : + lifetime(::std::move(lifetime)), + lifetime_bounds(::std::move(lifetime_bounds)), outer_attr(::std::move(outer_attr)), + locus(locus) {} + + // TODO: remove copy and assignment operator definitions - not required + + // Copy constructor with clone + LifetimeParam(LifetimeParam const& other) : + lifetime(other.lifetime), lifetime_bounds(other.lifetime_bounds), + outer_attr(other.outer_attr), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone attribute + LifetimeParam& operator=(LifetimeParam const& other) { + lifetime = other.lifetime; + lifetime_bounds = other.lifetime_bounds; + outer_attr = other.outer_attr; + locus = other.locus; + + return *this; + } + + // move constructors + LifetimeParam(LifetimeParam&& other) = default; + LifetimeParam& operator=(LifetimeParam&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LifetimeParam* clone_generic_param_impl() const OVERRIDE { + return new LifetimeParam(*this); + } + }; + + // A macro item AST node - potentially abstract base class + class MacroItem : public Item { + /*public: + ::std::string as_string() const;*/ + protected: + MacroItem(::std::vector outer_attribs) : Item(::std::move(outer_attribs)) {} + }; + + // Item used in trait declarations - abstract base class + class TraitItem { + // bool has_outer_attrs; + // TODO: remove and rely on virtual functions and VisItem-derived attributes? + //::std::vector outer_attrs; + + // NOTE: all children should have outer attributes + + protected: + // Constructor + /*TraitItem(::std::vector outer_attrs = ::std::vector()) : + outer_attrs(::std::move(outer_attrs)) {}*/ + + // Clone function implementation as pure virtual method + virtual TraitItem* clone_trait_item_impl() const = 0; + + public: + virtual ~TraitItem() {} + + // Returns whether TraitItem has outer attributes. + /*inline bool has_outer_attrs() const { + return !outer_attrs.empty(); + }*/ + + // Unique pointer custom clone function + ::std::unique_ptr clone_trait_item() const { + return ::std::unique_ptr(clone_trait_item_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + }; + + // Abstract base class for items used within an inherent impl block (the impl name {} one) + class InherentImplItem { + protected: + // Clone function implementation as pure virtual method + virtual InherentImplItem* clone_inherent_impl_item_impl() const = 0; + + public: + virtual ~InherentImplItem() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_inherent_impl_item() const { + return ::std::unique_ptr(clone_inherent_impl_item_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + }; + + // Abstract base class for items used in a trait impl + class TraitImplItem { + protected: + virtual TraitImplItem* clone_trait_impl_item_impl() const = 0; + + public: + virtual ~TraitImplItem(){}; + + // Unique pointer custom clone function + ::std::unique_ptr clone_trait_impl_item() const { + return ::std::unique_ptr(clone_trait_impl_item_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + }; + + // A macro invocation item (or statement) AST node (i.e. semi-coloned macro invocation) + class MacroInvocationSemi + : public MacroItem + , public TraitItem + , public InherentImplItem + , public TraitImplItem + /*, public Statement*/ { + // already inherits from statement indirectly via item as item is a subclass of statement + SimplePath path; + // all delim types except curly must have invocation end with a semicolon + DelimType delim_type; + //::std::vector token_trees; + ::std::vector< ::std::unique_ptr > token_trees; + + location_t locus; + + public: + ::std::string as_string() const; + + MacroInvocationSemi(SimplePath macro_path, DelimType delim_type, + ::std::vector< ::std::unique_ptr > token_trees, + ::std::vector outer_attribs, location_t locus) : + MacroItem(::std::move(outer_attribs)), + path(::std::move(macro_path)), delim_type(delim_type), + token_trees(::std::move(token_trees)), locus(locus) {} + /* TODO: possible issue with Item and TraitItem hierarchies both having outer attributes + * - storage inefficiency at least. + * Best current idea is to make Item preferred and have TraitItem get virtual functions + * for attributes or something. + * Or just redo the "composition" approach, but then this prevents polymorphism and would + * entail redoing quite a bit of the parser. */ + + // Copy constructor with vector clone + MacroInvocationSemi(MacroInvocationSemi const& other) : + MacroItem(other), TraitItem(other), InherentImplItem(other), TraitImplItem(other), + path(other.path), delim_type(other.delim_type), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + token_trees.reserve(other.token_trees.size()); + + for (const auto& e : other.token_trees) { + token_trees.push_back(e->clone_token_tree()); + } + } + + // Overloaded assignment operator to vector clone + MacroInvocationSemi& operator=(MacroInvocationSemi const& other) { + MacroItem::operator=(other); + TraitItem::operator=(other); + InherentImplItem::operator=(other); + TraitImplItem::operator=(other); + path = other.path; + delim_type = other.delim_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + token_trees.reserve(other.token_trees.size()); + + for (const auto& e : other.token_trees) { + token_trees.push_back(e->clone_token_tree()); + } + + return *this; + } + + // Move constructors + MacroInvocationSemi(MacroInvocationSemi&& other) = default; + MacroInvocationSemi& operator=(MacroInvocationSemi&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocationSemi* clone_item_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocationSemi* clone_inherent_impl_item_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocationSemi* clone_trait_impl_item_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + } + + // FIXME: remove if item impl virtual override works properly + // Use covariance to implement clone function as returning this object rather than base + /*virtual MacroInvocationSemi* clone_statement_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + }*/ + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocationSemi* clone_trait_item_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + } + }; + + // A crate AST object - holds all the data for a single compilation unit + struct Crate { + bool has_utf8bom; + bool has_shebang; + + ::std::vector inner_attrs; + //::std::vector items; + // dodgy spacing required here + // TODO: is it better to have a vector of items here or a module (implicit top-level one)? + ::std::vector< ::std::unique_ptr > items; + + public: + // Constructor + Crate(::std::vector< ::std::unique_ptr > items, + ::std::vector inner_attrs, bool has_utf8bom = false, + bool has_shebang = false) : + has_utf8bom(has_utf8bom), + has_shebang(has_shebang), inner_attrs(::std::move(inner_attrs)), + items(::std::move(items)) {} + + // Copy constructor with vector clone + Crate(Crate const& other) : + has_utf8bom(other.has_utf8bom), has_shebang(other.has_shebang), + inner_attrs(other.inner_attrs) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_item()); + } + } + + ~Crate() = default; + + // Overloaded assignment operator with vector clone + Crate& operator=(Crate const& other) { + inner_attrs = other.inner_attrs; + has_shebang = other.has_shebang; + has_utf8bom = other.has_utf8bom; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_item()); + } + + return *this; + } + + // Move constructors + Crate(Crate&& other) = default; + Crate& operator=(Crate&& other) = default; + + // Get crate representation as string (e.g. for debugging). + ::std::string as_string() const; + }; + + // Base path expression AST node - abstract + class PathExpr : public ExprWithoutBlock { + protected: + PathExpr(::std::vector outer_attribs) : + ExprWithoutBlock(::std::move(outer_attribs)) {} + + public: + // TODO: think of a better and less hacky way to allow this + + // Replaces the outer attributes of this path expression with the given outer attributes. + void replace_outer_attrs(::std::vector outer_attrs) { + set_outer_attrs(::std::move(outer_attrs)); + } + }; + } +} + +#endif diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h new file mode 100644 index 0000000..4fa6a0b --- /dev/null +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -0,0 +1,199 @@ +#ifndef RUST_AST_CONDCOMPILATION +#define RUST_AST_CONDCOMPILATION +// Conditional compilation-related AST stuff + +#include "rust-ast.h" + +namespace Rust { + namespace AST { + // Base conditional compilation configuration predicate thing - abstract + class ConfigurationPredicate { + public: + virtual ~ConfigurationPredicate() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_configuration_predicate() const { + return ::std::unique_ptr( + clone_configuration_predicate_impl()); + } + + // not sure if I'll use this but here anyway + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function impl to be overriden in base classes + virtual ConfigurationPredicate* clone_configuration_predicate_impl() const = 0; + }; + + // A configuration option - true if option is set, false if option is not set. + class ConfigurationOption : public ConfigurationPredicate { + Identifier option_name; + + // bool has_string_literal_option_body; + ::std::string option_value; // technically a string or raw string literal + + public: + // Returns whether the configuration option has a "value" part of the key-value pair. + inline bool has_option_value() const { + return !option_value.empty(); + } + + // Key-value pair constructor + ConfigurationOption(Identifier option_name, ::std::string option_value) : + option_name(option_name), option_value(option_value) {} + + // Name-only constructor + ConfigurationOption(Identifier option_name) : option_name(option_name) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ConfigurationOption* clone_configuration_predicate_impl() const OVERRIDE { + return new ConfigurationOption(*this); + } + }; + + // TODO: inline + struct ConfigurationPredicateList { + ::std::vector< ::std::unique_ptr > predicate_list; + }; + + // Predicate that returns true if all of the supplied predicates return true. + class ConfigurationAll : public ConfigurationPredicate { + ::std::vector< ::std::unique_ptr > predicate_list; // inlined form + + public: + ConfigurationAll( + ::std::vector< ::std::unique_ptr > predicate_list) : + predicate_list(predicate_list) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ConfigurationAll* clone_configuration_predicate_impl() const OVERRIDE { + return new ConfigurationAll(*this); + } + }; + + // Predicate that returns true if any of the supplied predicates are true. + class ConfigurationAny : public ConfigurationPredicate { + ::std::vector< ::std::unique_ptr > predicate_list; // inlined form + + public: + ConfigurationAny( + ::std::vector< ::std::unique_ptr > predicate_list) : + predicate_list(predicate_list) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ConfigurationAny* clone_configuration_predicate_impl() const OVERRIDE { + return new ConfigurationAny(*this); + } + }; + + // Predicate that produces the negation of a supplied other configuration predicate. + class ConfigurationNot : public ConfigurationPredicate { + ::std::unique_ptr config_to_negate; + + public: + ConfigurationNot(ConfigurationPredicate* config_to_negate) : + config_to_negate(config_to_negate) {} + + // Copy constructor with clone + ConfigurationNot(ConfigurationNot const& other) : + config_to_negate(other.config_to_negate->clone_configuration_predicate()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ConfigurationNot& operator=(ConfigurationNot const& other) { + config_to_negate = other.config_to_negate->clone_configuration_predicate(); + + return *this; + } + + // move constructors + ConfigurationNot(ConfigurationNot&& other) = default; + ConfigurationNot& operator=(ConfigurationNot&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ConfigurationNot* clone_configuration_predicate_impl() const OVERRIDE { + return new ConfigurationNot(*this); + } + }; + + // TODO: relationship to other attributes? + class CfgAttribute { + ::std::unique_ptr config_to_include; + + public: + CfgAttribute(ConfigurationPredicate* config_to_include) : + config_to_include(config_to_include) {} + + // Copy constructor with clone + CfgAttribute(CfgAttribute const& other) : + config_to_include(other.config_to_include->clone_configuration_predicate()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + CfgAttribute& operator=(CfgAttribute const& other) { + config_to_include = other.config_to_include->clone_configuration_predicate(); + + return *this; + } + + // move constructors + CfgAttribute(CfgAttribute&& other) = default; + CfgAttribute& operator=(CfgAttribute&& other) = default; + }; + /* TODO: ok, best thing to do would be eliminating this class, making Attribute has a "is_cfg()" + * method, and having attribute path as "cfg" and AttrInput as ConfigurationPredicate (so make + * ConfigurationPredicate a subclass of AttrInput?). Would need special handling in parser, however. */ + + // TODO: inline + struct CfgAttrs { + ::std::vector cfg_attrs; + }; + + // TODO: relationship to other attributes? + class CfgAttrAttribute { + ::std::unique_ptr config_to_include; + ::std::vector cfg_attrs; + + public: + CfgAttrAttribute( + ConfigurationPredicate* config_to_include, ::std::vector cfg_attrs) : + config_to_include(config_to_include), + cfg_attrs(cfg_attrs) {} + + // Copy constructor with clone + CfgAttrAttribute(CfgAttrAttribute const& other) : + config_to_include(other.config_to_include->clone_configuration_predicate()), + cfg_attrs(cfg_attrs) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + CfgAttrAttribute& operator=(CfgAttrAttribute const& other) { + config_to_include = other.config_to_include->clone_configuration_predicate(); + cfg_attrs = other.cfg_attrs; + + return *this; + } + + // move constructors + CfgAttrAttribute(CfgAttrAttribute&& other) = default; + CfgAttrAttribute& operator=(CfgAttrAttribute&& other) = default; + }; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h new file mode 100644 index 0000000..1842da9 --- /dev/null +++ b/gcc/rust/ast/rust-expr.h @@ -0,0 +1,4614 @@ +#ifndef RUST_AST_EXPR_H +#define RUST_AST_EXPR_H + +#include "rust-ast.h" +#include "rust-path.h" + +namespace Rust { + namespace AST { + /* TODO: if GCC moves to C++17 or allows boost, replace some boolean "has_whatever" pairs with + * optional types (std::optional or boost::optional)? */ + + // forward decls: defined in rust-path.h, rust-type.h, rust-pattern.h, and rust-stmt.h + /*class PathInExpression; + class QualifiedPathInExpression; + class PathExprSegment;*/ // decls no longer required as "rust-path.h" is included + /*class Type; + class TypeNoBounds; + class Lifetime; + class Pattern; + class Statement;*/ // decls no longer required as definitions moved to rust-ast.h + + // Decl as definition moved to rust-ast.h + class ExprWithoutBlock; + + // AST node for an expression with an accompanying block - abstract + class ExprWithBlock : public Expr { + // TODO: should this mean that a BlockExpr should be a member variable? + protected: + ExprWithBlock(::std::vector outer_attrs = ::std::vector()) : + Expr(::std::move(outer_attrs)) {} + + // pure virtual clone implementation + virtual ExprWithBlock* clone_expr_with_block_impl() const = 0; + + // prevent having to define multiple clone expressions + virtual ExprWithBlock* clone_expr_impl() const OVERRIDE { + return clone_expr_with_block_impl(); + } + + public: + // Unique pointer custom clone function + ::std::unique_ptr clone_expr_with_block() const { + return ::std::unique_ptr(clone_expr_with_block_impl()); + } + }; + + // Literals? Or literal base? + class LiteralExpr : public ExprWithoutBlock { + /*public: + enum LitType { + CHAR, + STRING, + RAW_STRING, + BYTE, + BYTE_STRING, + RAW_BYTE_STRING, + INT, + FLOAT, + BOOL + }; + + private: + // TODO: maybe make subclasses of each type of literal with their typed values (or + // generics) + ::std::string value_as_string; + LitType type;*/ + // moved to Literal + Literal literal; + + location_t locus; + + public: + ::std::string as_string() const { + return literal.as_string(); + } + + inline Literal::LitType get_lit_type() const { + return literal.get_lit_type(); + } + + LiteralExpr(::std::string value_as_string, Literal::LitType type, location_t locus, + ::std::vector outer_attrs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attrs)), + literal(::std::move(value_as_string), type), locus(locus) {} + + LiteralExpr(Literal literal, location_t locus, + ::std::vector outer_attrs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attrs)), + literal(::std::move(literal)), locus(locus) {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_literal_expr() const { + return ::std::unique_ptr(clone_literal_expr_impl()); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LiteralExpr* clone_expr_impl() const OVERRIDE { + return new LiteralExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual LiteralExpr* clone_expr_without_block_impl() const OVERRIDE { + return new LiteralExpr(*this); + } + + // not virtual as currently no subclasses of LiteralExpr, but could be in future + /*virtual*/ LiteralExpr* clone_literal_expr_impl() const { + return new LiteralExpr(*this); + } + }; + + // Literal expression attribute body (non-macro attribute) + class AttrInputLiteral : public AttrInput { + // Literal expression WITHOUT SUFFIX + // LiteralExpr* literal_expr; + //::std::unique_ptr literal_expr; + LiteralExpr literal_expr; // as not using polymorphic behaviour, doesn't require pointer + // TODO: will require pointer if LiteralExpr is changed to have subclassing + + // TODO: should this store location data? + + public: + AttrInputLiteral(LiteralExpr lit_expr) : literal_expr(::std::move(lit_expr)) {} + /*~AttrInputLiteral() { + delete literal_expr; + }*/ + + ::std::string as_string() const { + return " = " + literal_expr.as_string(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // this can never be a cfg predicate - cfg and cfg_attr require a token-tree cfg + virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { + // TODO: ensure this is true + // DEBUG + fprintf( + stderr, "check_cfg_predicate call went to AttrInputLiteral - should not happen?\n"); + + return false; + } + + protected: + // Use covariance to implement clone function as returning an AttrInputLiteral object + virtual AttrInputLiteral* clone_attr_input_impl() const OVERRIDE { + return new AttrInputLiteral(*this); + } + }; + + // literal expr only meta item inner - TODO possibly replace with inheritance of LiteralExpr + // itself? + class MetaItemLitExpr : public MetaItemInner { + LiteralExpr lit_expr; + + public: + MetaItemLitExpr(LiteralExpr lit_expr) : lit_expr(::std::move(lit_expr)) {} + + ::std::string as_string() const OVERRIDE { + return lit_expr.as_string(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemLitExpr* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaItemLitExpr(*this); + } + }; + + // more generic meta item "path = lit" form + class MetaItemPathLit : public MetaItem { + SimplePath path; + LiteralExpr lit; + + public: + MetaItemPathLit(SimplePath path, LiteralExpr lit_expr) : + path(::std::move(path)), lit(::std::move(lit_expr)) {} + + ::std::string as_string() const OVERRIDE { + return path.as_string() + " = " + lit.as_string(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + // TODO: return true if "ident" is defined and value of it is "lit", return false otherwise + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemPathLit* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaItemPathLit(*this); + } + }; + + // AST node for a non-qualified path expression - FIXME: should this be inheritance instead? + /*class PathExprNonQual : public PathExpr { + PathInExpression path; + + public: + ::std::string as_string() const { + return path.as_string(); + } + + PathExprNonQual(PathInExpression path, ::std::vector outer_attribs) : + PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual PathExprNonQual* clone_expr_impl() const OVERRIDE { + return new PathExprNonQual(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual PathExprNonQual* clone_expr_without_block_impl() const OVERRIDE { + return new PathExprNonQual(*this); + } + };*/ + // converted to inheritance + + // AST node for a qualified path expression - FIXME: should this be inheritance instead? + /*class PathExprQual : public PathExpr { + QualifiedPathInExpression path; + + public: + ::std::string as_string() const { + return path.as_string(); + } + + PathExprQual(QualifiedPathInExpression path, ::std::vector outer_attribs) : + PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual PathExprQual* clone_expr_impl() const OVERRIDE { + return new PathExprQual(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual PathExprQual* clone_expr_without_block_impl() const OVERRIDE { + return new PathExprQual(*this); + } + };*/ + // replaced with inheritance + + // Represents an expression using unary or binary operators as AST node. Can be overloaded. + class OperatorExpr : public ExprWithoutBlock { + // TODO: create binary and unary operator subclasses? + + location_t locus; + + protected: + // Variable must be protected to allow derived classes to use it as a first class citizen + // Expr* main_or_left_expr; + ::std::unique_ptr main_or_left_expr; + + // Constructor (only for initialisation of expr purposes) + OperatorExpr(::std::unique_ptr main_or_left_expr, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + locus(locus), main_or_left_expr(::std::move(main_or_left_expr)) {} + + // Copy constructor (only for initialisation of expr purposes) + OperatorExpr(OperatorExpr const& other) : + ExprWithoutBlock(other), + locus(other.locus) /*, main_or_left_expr(other.main_or_left_expr->clone_expr())*/ { + // DEBUG: moved main_or_left_expr into body - move back later + + if (other.main_or_left_expr == NULL) { + fprintf(stderr, "other operator expr's main_or_left_expr is null!\n"); + } + + fprintf(stderr, + "called operator expr copy constructor - about to clone main_or_left_expr\n"); + main_or_left_expr = other.main_or_left_expr->clone_expr(); + fprintf(stderr, "successfully cloned main_or_left_expr\n"); + // this occurred successfully, so something else must be the issue + } + + // Overload assignment operator to deep copy expr + OperatorExpr& operator=(OperatorExpr const& other) { + ExprWithoutBlock::operator=(other); + main_or_left_expr = other.main_or_left_expr->clone_expr(); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + OperatorExpr(OperatorExpr&& other) = default; + OperatorExpr& operator=(OperatorExpr&& other) = default; + + public: + /*virtual ~OperatorExpr() { + delete main_or_left_expr; + }*/ + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + }; + + // Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be overloaded. + class BorrowExpr : public OperatorExpr { + bool is_mut; + bool double_borrow; + + public: + ::std::string as_string() const; + + BorrowExpr(::std::unique_ptr borrow_lvalue, bool is_mut_borrow, + bool is_double_borrow, ::std::vector outer_attribs, location_t locus) : + OperatorExpr(::std::move(borrow_lvalue), ::std::move(outer_attribs), locus), + is_mut(is_mut_borrow), double_borrow(is_double_borrow) {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual BorrowExpr* clone_expr_impl() const OVERRIDE { + return new BorrowExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual BorrowExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on borrowexpr\n"); + + return new BorrowExpr(*this); + } + }; + + // Unary prefix * deference operator + class DereferenceExpr : public OperatorExpr { + public: + ::std::string as_string() const; + + // Constructor calls OperatorExpr's protected constructor + DereferenceExpr(::std::unique_ptr deref_lvalue, + ::std::vector outer_attribs, location_t locus) : + OperatorExpr(::std::move(deref_lvalue), ::std::move(outer_attribs), locus) {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual DereferenceExpr* clone_expr_impl() const OVERRIDE { + return new DereferenceExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual DereferenceExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on dereferenceexpr\n"); + + return new DereferenceExpr(*this); + } + }; + + // Unary postfix ? error propogation operator. Cannot be overloaded. + class ErrorPropagationExpr : public OperatorExpr { + public: + ::std::string as_string() const; + + // Constructor calls OperatorExpr's protected constructor + ErrorPropagationExpr(::std::unique_ptr potential_error_value, + ::std::vector outer_attribs, location_t locus) : + OperatorExpr(::std::move(potential_error_value), ::std::move(outer_attribs), locus) {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ErrorPropagationExpr* clone_expr_impl() const OVERRIDE { + return new ErrorPropagationExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ErrorPropagationExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on errorpropagationexpr\n"); + + return new ErrorPropagationExpr(*this); + } + }; + + // Unary prefix - or ! negation or NOT operators. + class NegationExpr : public OperatorExpr { + public: + enum NegationType { NEGATE, NOT }; + + private: + // Note: overload negation via std::ops::Neg and not via std::ops::Not + // Negation only works for signed integer and floating-point types, NOT only works for + // boolean and integer types (via bitwise NOT) + NegationType negation_type; + + public: + ::std::string as_string() const; + + inline NegationType get_negation_type() const { + return negation_type; + } + + // Constructor calls OperatorExpr's protected constructor + NegationExpr(::std::unique_ptr negated_value, NegationType negation_kind, + ::std::vector outer_attribs, location_t locus) : + OperatorExpr(::std::move(negated_value), ::std::move(outer_attribs), locus), + negation_type(negation_kind) {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual NegationExpr* clone_expr_impl() const OVERRIDE { + return new NegationExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual NegationExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on negationexpr\n"); + + return new NegationExpr(*this); + } + }; + + // Infix binary operators. +, -, *, /, %, &, |, ^, <<, >> + class ArithmeticOrLogicalExpr : public OperatorExpr { + public: + enum ExprType { + ADD, // std::ops::Add + SUBTRACT, // std::ops::Sub + MULTIPLY, // std::ops::Mul + DIVIDE, // std::ops::Div + MODULUS, // std::ops::Rem + BITWISE_AND, // std::ops::BitAnd + BITWISE_OR, // std::ops::BitOr + BITWISE_XOR, // std::ops::BitXor + LEFT_SHIFT, // std::ops::Shl + RIGHT_SHIFT // std::ops::Shr + }; + + private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr right_expr; + + public: + /*~ArithmeticOrLogicalExpr() { + delete right_expr; + }*/ + + ::std::string as_string() const; + + inline ExprType get_expr_type() const { + return expr_type; + } + + // Constructor calls OperatorExpr's protected constructor + ArithmeticOrLogicalExpr(::std::unique_ptr left_value, + ::std::unique_ptr right_value, ExprType expr_kind, location_t locus) : + OperatorExpr(::std::move(left_value), ::std::vector(), locus), + expr_type(expr_kind), right_expr(::std::move(right_value)) {} + // outer attributes not allowed + + // Copy constructor - probably required due to unique pointer + ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr const& other) : + OperatorExpr(other), expr_type(other.expr_type), + right_expr(other.right_expr->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator + ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr(); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr&& other) = default; + ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ArithmeticOrLogicalExpr* clone_expr_impl() const OVERRIDE { + return new ArithmeticOrLogicalExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ArithmeticOrLogicalExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf( + stderr, "called clone_expr_without_block_impl() on arithmeticorlogicalexpr\n"); + + return new ArithmeticOrLogicalExpr(*this); + } + }; + + // Infix binary comparison operators. ==, !=, <, <=, >, >= + class ComparisonExpr : public OperatorExpr { + public: + enum ExprType { + EQUAL, // std::cmp::PartialEq::eq + NOT_EQUAL, // std::cmp::PartialEq::ne + GREATER_THAN, // std::cmp::PartialEq::gt + LESS_THAN, // std::cmp::PartialEq::lt + GREATER_OR_EQUAL, // std::cmp::PartialEq::ge + LESS_OR_EQUAL // std::cmp::PartialEq::le + }; + + private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr right_expr; + + public: + /*~ComparisonExpr() { + delete right_expr; + }*/ + + ::std::string as_string() const; + + inline ExprType get_expr_type() const { + return expr_type; + } + + // Constructor requires pointers for polymorphism + ComparisonExpr(::std::unique_ptr left_value, ::std::unique_ptr right_value, + ExprType comparison_kind, location_t locus) : + OperatorExpr(::std::move(left_value), ::std::vector(), locus), + expr_type(comparison_kind), right_expr(::std::move(right_value)) {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + ComparisonExpr(ComparisonExpr const& other) : + OperatorExpr(other), expr_type(other.expr_type), + right_expr(other.right_expr->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + ComparisonExpr& operator=(ComparisonExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr(); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ComparisonExpr(ComparisonExpr&& other) = default; + ComparisonExpr& operator=(ComparisonExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) maybe? + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ComparisonExpr* clone_expr_impl() const OVERRIDE { + return new ComparisonExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ComparisonExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on comparisonexpr\n"); + + return new ComparisonExpr(*this); + } + }; + + // Infix binary lazy boolean logical operators && and ||. + class LazyBooleanExpr : public OperatorExpr { + public: + enum ExprType { LOGICAL_OR, LOGICAL_AND }; + + private: + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr right_expr; + + public: + /*~LazyBooleanExpr() { + delete right_expr; + }*/ + + // Constructor calls OperatorExpr's protected constructor + LazyBooleanExpr(::std::unique_ptr left_bool_expr, + ::std::unique_ptr right_bool_expr, ExprType expr_kind, location_t locus) : + OperatorExpr(::std::move(left_bool_expr), ::std::vector(), locus), + expr_type(expr_kind), right_expr(::std::move(right_bool_expr)) {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + LazyBooleanExpr(LazyBooleanExpr const& other) : + OperatorExpr(other), expr_type(other.expr_type), + right_expr(other.right_expr->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + LazyBooleanExpr& operator=(LazyBooleanExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr(); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + LazyBooleanExpr(LazyBooleanExpr&& other) = default; + LazyBooleanExpr& operator=(LazyBooleanExpr&& other) = default; + + ::std::string as_string() const; + + inline ExprType get_expr_type() const { + return expr_type; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LazyBooleanExpr* clone_expr_impl() const OVERRIDE { + return new LazyBooleanExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual LazyBooleanExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on lazybooleanexpr\n"); + + return new LazyBooleanExpr(*this); + } + }; + + // Binary infix "as" cast expression. + class TypeCastExpr : public OperatorExpr { + // TypeNoBounds type_to_convert_to; + ::std::unique_ptr type_to_convert_to; + + // Note: only certain type casts allowed, outlined in reference + public: + ::std::string as_string() const; + + // Constructor requires calling protected constructor of OperatorExpr + TypeCastExpr(::std::unique_ptr expr_to_cast, + ::std::unique_ptr type_to_cast_to, location_t locus) : + OperatorExpr(::std::move(expr_to_cast), ::std::vector(), locus), + type_to_convert_to(::std::move(type_to_cast_to)) {} + // outer attributes not allowed + + // Copy constructor also requires calling protected constructor + TypeCastExpr(TypeCastExpr const& other) : + OperatorExpr(other), + type_to_convert_to(other.type_to_convert_to->clone_type_no_bounds()) {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + TypeCastExpr& operator=(TypeCastExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds(); + + return *this; + } + + // move constructors as not supported in c++03 + TypeCastExpr(TypeCastExpr&& other) = default; + TypeCastExpr& operator=(TypeCastExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TypeCastExpr* clone_expr_impl() const OVERRIDE { + return new TypeCastExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TypeCastExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on typecastexpr\n"); + + return new TypeCastExpr(*this); + } + }; + + // Binary assignment expression. + class AssignmentExpr : public OperatorExpr { + // Expr* right_expr; + ::std::unique_ptr right_expr; + + public: + /*~AssignmentExpr() { + delete right_expr; + }*/ + + ::std::string as_string() const; + + // Call OperatorExpr constructor to initialise left_expr + AssignmentExpr(::std::unique_ptr value_to_assign_to, + ::std::unique_ptr value_to_assign, location_t locus) : + OperatorExpr(::std::move(value_to_assign_to), ::std::vector(), locus), + right_expr(::std::move(value_to_assign)) {} + // outer attributes not allowed + + // Call OperatorExpr constructor in copy constructor, as well as clone + AssignmentExpr(AssignmentExpr const& other) : + OperatorExpr(other) /*, right_expr(other.right_expr->clone_expr())*/ { + // DEBUG: moved cloning right expr into body + fprintf(stderr, + "assignment expr copy constructor successfully cloned base operator expr\n"); + if (other.right_expr == NULL) { + fprintf(stderr, "other expr's right expr (in assignment) is null!!!"); + } + fprintf(stderr, "test other's right expr as string: %s\n", + other.right_expr->as_string().c_str()); + // apparently, despite not being null, cloning still fails + right_expr = other.right_expr->clone_expr(); + fprintf(stderr, "assignment expr copy constructor successfully cloned right expr\n"); + + // DEBUG + fprintf(stderr, "assignment expr copy constructor called successfully\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr right_expr + AssignmentExpr& operator=(AssignmentExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr(); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + AssignmentExpr(AssignmentExpr&& other) = default; + AssignmentExpr& operator=(AssignmentExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual AssignmentExpr* clone_expr_impl() const OVERRIDE { + return new AssignmentExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual AssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on assignmentexpr\n"); + + return new AssignmentExpr(*this); + } + }; + + // Binary infix compound assignment (arithmetic or logic then assignment) expressions. + class CompoundAssignmentExpr : public OperatorExpr { + public: + enum ExprType { + ADD, // std::ops::AddAssign + SUBTRACT, // std::ops::SubAssign + MULTIPLY, // std::ops::MulAssign + DIVIDE, // std::ops::DivAssign + MODULUS, // std::ops::RemAssign + BITWISE_AND, // std::ops::BitAndAssign + BITWISE_OR, // std::ops::BitOrAssign + BITWISE_XOR, // std::ops::BitXorAssign + LEFT_SHIFT, // std::ops::ShlAssign + RIGHT_SHIFT // std::ops::ShrAssign + }; + + private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr right_expr; + + public: + /*~CompoundAssignmentExpr() { + delete right_expr; + }*/ + + ::std::string as_string() const; + + inline ExprType get_expr_type() const { + return expr_type; + } + + // Use pointers in constructor to enable polymorphism + CompoundAssignmentExpr(::std::unique_ptr value_to_assign_to, + ::std::unique_ptr value_to_assign, ExprType expr_kind, location_t locus) : + OperatorExpr(::std::move(value_to_assign_to), ::std::vector(), locus), + expr_type(expr_kind), right_expr(::std::move(value_to_assign)) {} + // outer attributes not allowed + + // Have clone in copy constructor + CompoundAssignmentExpr(CompoundAssignmentExpr const& other) : + OperatorExpr(other), expr_type(other.expr_type), + right_expr(other.right_expr->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + CompoundAssignmentExpr& operator=(CompoundAssignmentExpr const& other) { + OperatorExpr::operator=(other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr(); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + CompoundAssignmentExpr(CompoundAssignmentExpr&& other) = default; + CompoundAssignmentExpr& operator=(CompoundAssignmentExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual CompoundAssignmentExpr* clone_expr_impl() const OVERRIDE { + return new CompoundAssignmentExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual CompoundAssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called clone_expr_without_block_impl() on compoundassignmentexpr\n"); + + return new CompoundAssignmentExpr(*this); + } + }; + + // Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) + class GroupedExpr : public ExprWithoutBlock { + ::std::vector inner_attrs; + // Expr* expr_in_parens; + ::std::unique_ptr expr_in_parens; + + location_t locus; + + public: + /*~GroupedExpr() { + delete expr_in_parens; + }*/ + + ::std::string as_string() const; + + inline ::std::vector get_inner_attrs() const { + return inner_attrs; + } + + GroupedExpr(::std::unique_ptr parenthesised_expr, + ::std::vector inner_attribs, ::std::vector outer_attribs, + location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), + expr_in_parens(::std::move(parenthesised_expr)), locus(locus) {} + + // Copy constructor includes clone for expr_in_parens + GroupedExpr(GroupedExpr const& other) : + ExprWithoutBlock(other), inner_attrs(other.inner_attrs), + expr_in_parens(other.expr_in_parens->clone_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone expr_in_parens + GroupedExpr& operator=(GroupedExpr const& other) { + ExprWithoutBlock::operator=(other); + inner_attrs = other.inner_attrs; + expr_in_parens = other.expr_in_parens->clone_expr(); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + GroupedExpr(GroupedExpr&& other) = default; + GroupedExpr& operator=(GroupedExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual GroupedExpr* clone_expr_impl() const OVERRIDE { + return new GroupedExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual GroupedExpr* clone_expr_without_block_impl() const OVERRIDE { + return new GroupedExpr(*this); + } + }; + + // Base array initialisation internal element representation thing (abstract) + // aka ArrayElements + class ArrayElems { + public: + virtual ~ArrayElems() {} + + // Unique pointer custom clone ArrayElems function + ::std::unique_ptr clone_array_elems() const { + return ::std::unique_ptr(clone_array_elems_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual clone implementation + virtual ArrayElems* clone_array_elems_impl() const = 0; + }; + + // Value array elements + class ArrayElemsValues : public ArrayElems { + //::std::vector values; + ::std::vector< ::std::unique_ptr > values; + + // TODO: should this store location data? + + public: + /*inline ::std::vector< ::std::unique_ptr > get_values() const { + return values; + }*/ + + ArrayElemsValues(::std::vector< ::std::unique_ptr > elems) : + values(::std::move(elems)) {} + + // copy constructor with vector clone + ArrayElemsValues(ArrayElemsValues const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + values.reserve(other.values.size()); + + for (const auto& e : other.values) { + values.push_back(e->clone_expr()); + } + } + + // overloaded assignment operator with vector clone + ArrayElemsValues& operator=(ArrayElemsValues const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + values.reserve(other.values.size()); + + for (const auto& e : other.values) { + values.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + ArrayElemsValues(ArrayElemsValues&& other) = default; + ArrayElemsValues& operator=(ArrayElemsValues&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + virtual ArrayElemsValues* clone_array_elems_impl() const OVERRIDE { + return new ArrayElemsValues(*this); + } + }; + + // Copied array element and number of copies + class ArrayElemsCopied : public ArrayElems { + // Expr* elem_to_copy; + ::std::unique_ptr elem_to_copy; + // Expr* num_copies; + ::std::unique_ptr num_copies; + + // TODO: should this store location data? + + public: + /*~ArrayElemsCopied() { + delete num_copies; + delete elem_to_copy; + }*/ + + // Constructor requires pointers for polymorphism + ArrayElemsCopied( + ::std::unique_ptr copied_elem, ::std::unique_ptr copy_amount) : + elem_to_copy(::std::move(copied_elem)), + num_copies(::std::move(copy_amount)) {} + + // Copy constructor required due to unique_ptr - uses custom clone + ArrayElemsCopied(ArrayElemsCopied const& other) : + elem_to_copy(other.elem_to_copy->clone_expr()), + num_copies(other.num_copies->clone_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator for deep copying + ArrayElemsCopied& operator=(ArrayElemsCopied const& other) { + elem_to_copy = other.elem_to_copy->clone_expr(); + num_copies = other.num_copies->clone_expr(); + + return *this; + } + + // move constructors + ArrayElemsCopied(ArrayElemsCopied&& other) = default; + ArrayElemsCopied& operator=(ArrayElemsCopied&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + virtual ArrayElemsCopied* clone_array_elems_impl() const OVERRIDE { + return new ArrayElemsCopied(*this); + } + }; + + // Array definition-ish expression + class ArrayExpr : public ExprWithoutBlock { + ::std::vector inner_attrs; + // ArrayElems internal_elements; + ::std::unique_ptr internal_elements; + + location_t locus; + + public: + ::std::string as_string() const; + + inline ::std::vector get_inner_attrs() const { + return inner_attrs; + } + + // Returns whether array expr has array elems or if it is just empty. + inline bool has_array_elems() const { + return internal_elements != NULL; + } + + // Constructor requires ArrayElems pointer + ArrayExpr(::std::unique_ptr array_elems, + ::std::vector inner_attribs, ::std::vector outer_attribs, + location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), internal_elements(::std::move(array_elems)), + locus(locus) {} + + // Copy constructor requires cloning ArrayElems for polymorphism to hold + ArrayExpr(ArrayExpr const& other) : + ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { + if (other.has_array_elems()) { + internal_elements = other.internal_elements->clone_array_elems(); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone internal_elements + ArrayExpr& operator=(ArrayExpr const& other) { + ExprWithoutBlock::operator=(other); + inner_attrs = other.inner_attrs; + if (other.has_array_elems()) { + internal_elements = other.internal_elements->clone_array_elems(); + } + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ArrayExpr(ArrayExpr&& other) = default; + ArrayExpr& operator=(ArrayExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayExpr* clone_expr_impl() const OVERRIDE { + return new ArrayExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayExpr* clone_expr_without_block_impl() const OVERRIDE { + return new ArrayExpr(*this); + } + }; + + // Aka IndexExpr (also applies to slices) + // Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or + // *std::ops::Index::index_mut(&mut a, b) + // Also apparently deref operations on a will be repeatedly applied to find an implementation + class ArrayIndexExpr : public ExprWithoutBlock { + /*Expr* array_expr; + Expr* index_expr;*/ + ::std::unique_ptr array_expr; + ::std::unique_ptr index_expr; + + location_t locus; + + public: + /*~ArrayIndexExpr() { + delete index_expr; + delete array_expr; + }*/ + + ::std::string as_string() const; + + ArrayIndexExpr(::std::unique_ptr array_expr, + ::std::unique_ptr array_index_expr, ::std::vector outer_attribs, + location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + array_expr(::std::move(array_expr)), index_expr(::std::move(array_index_expr)), + locus(locus) {} + + // Copy constructor requires special cloning due to unique_ptr + ArrayIndexExpr(ArrayIndexExpr const& other) : + ExprWithoutBlock(other), array_expr(other.array_expr->clone_expr()), + index_expr(other.index_expr->clone_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptrs + ArrayIndexExpr& operator=(ArrayIndexExpr const& other) { + ExprWithoutBlock::operator=(other); + array_expr = other.array_expr->clone_expr(); + index_expr = other.index_expr->clone_expr(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ArrayIndexExpr(ArrayIndexExpr&& other) = default; + ArrayIndexExpr& operator=(ArrayIndexExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayIndexExpr* clone_expr_impl() const OVERRIDE { + return new ArrayIndexExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayIndexExpr* clone_expr_without_block_impl() const OVERRIDE { + return new ArrayIndexExpr(*this); + } + }; + + // AST representation of a tuple + class TupleExpr : public ExprWithoutBlock { + ::std::vector inner_attrs; + + //::std::vector tuple_elems; + ::std::vector< ::std::unique_ptr > tuple_elems; + // replaces (inlined version of) TupleElements + + location_t locus; + + public: + ::std::string as_string() const; + + inline ::std::vector get_inner_attrs() const { + return inner_attrs; + } + + TupleExpr(::std::vector< ::std::unique_ptr > tuple_elements, + ::std::vector inner_attribs, ::std::vector outer_attribs, + location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), tuple_elems(::std::move(tuple_elements)), + locus(locus) {} + + // copy constructor with vector clone + TupleExpr(TupleExpr const& other) : + ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + tuple_elems.reserve(other.tuple_elems.size()); + + for (const auto& e : other.tuple_elems) { + tuple_elems.push_back(e->clone_expr()); + } + } + + // overloaded assignment operator to vector clone + TupleExpr& operator=(TupleExpr const& other) { + ExprWithoutBlock::operator=(other); + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + tuple_elems.reserve(other.tuple_elems.size()); + + for (const auto& e : other.tuple_elems) { + tuple_elems.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + TupleExpr(TupleExpr&& other) = default; + TupleExpr& operator=(TupleExpr&& other) = default; + + // Note: syntactically, can disambiguate single-element tuple from parens with comma, i.e. + // (0,) rather than (0) + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleExpr* clone_expr_impl() const OVERRIDE { + return new TupleExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TupleExpr* clone_expr_without_block_impl() const OVERRIDE { + return new TupleExpr(*this); + } + }; + + // aka TupleIndexingExpr + // AST representation of a tuple indexing expression + class TupleIndexExpr : public ExprWithoutBlock { + // Expr* tuple_expr; + ::std::unique_ptr tuple_expr; + // TupleIndex is a decimal int literal with no underscores or suffix + TupleIndex tuple_index; + + location_t locus; + + // i.e. pair.0 + + public: + /*~TupleIndexExpr() { + delete tuple_expr; + }*/ + + ::std::string as_string() const; + + inline TupleIndex get_tuple_index() const { + return tuple_index; + } + + TupleIndexExpr(::std::unique_ptr tuple_expr, TupleIndex index, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + tuple_expr(::std::move(tuple_expr)), tuple_index(index), locus(locus) {} + + // Copy constructor requires a clone for tuple_expr + TupleIndexExpr(TupleIndexExpr const& other) : + ExprWithoutBlock(other), tuple_expr(other.tuple_expr->clone_expr()), + tuple_index(other.tuple_index), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator in order to clone + TupleIndexExpr& operator=(TupleIndexExpr const& other) { + ExprWithoutBlock::operator=(other); + tuple_expr = other.tuple_expr->clone_expr(); + tuple_index = other.tuple_index; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + TupleIndexExpr(TupleIndexExpr&& other) = default; + TupleIndexExpr& operator=(TupleIndexExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleIndexExpr* clone_expr_impl() const OVERRIDE { + return new TupleIndexExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TupleIndexExpr* clone_expr_without_block_impl() const OVERRIDE { + return new TupleIndexExpr(*this); + } + }; + + // Base struct/tuple/union value creator AST node (abstract) + class StructExpr : public ExprWithoutBlock { + PathInExpression struct_name; + + protected: + // Protected constructor to allow initialising struct_name + StructExpr(PathInExpression struct_path, ::std::vector outer_attribs) : + ExprWithoutBlock(::std::move(outer_attribs)), struct_name(::std::move(struct_path)) {} + + public: + inline const PathInExpression& get_struct_name() const { + return struct_name; + } + + virtual ::std::string as_string() const; + }; + + // Actual AST node of the struct creator (with no fields). Not abstract! + class StructExprStruct : public StructExpr { + ::std::vector inner_attrs; + + location_t locus; + + public: + ::std::string as_string() const; + + inline ::std::vector get_inner_attrs() const { + return inner_attrs; + } + + // Constructor has to call protected constructor of base class + StructExprStruct(PathInExpression struct_path, ::std::vector inner_attribs, + ::std::vector outer_attribs, location_t locus) : + StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), locus(locus) {} + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStruct* clone_expr_impl() const OVERRIDE { + return new StructExprStruct(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStruct* clone_expr_without_block_impl() const OVERRIDE { + return new StructExprStruct(*this); + } + }; + + // AST node representing expression used to fill a struct's fields from another struct + struct StructBase { + private: + // Expr* base_struct; + ::std::unique_ptr base_struct; + + // TODO: should this store location data? + + public: + StructBase(::std::unique_ptr base_struct_ptr) : + base_struct(::std::move(base_struct_ptr)) {} + + // Copy constructor requires clone + StructBase(StructBase const& other) { + // HACK: gets around base_struct pointer being null (e.g. if no struct base exists) + if (other.base_struct != NULL) { + other.base_struct->clone_expr(); + } + + // DEBUG: + fprintf(stderr, "struct base copy constructor called successfully\n"); + } + + // Destructor + ~StructBase() = default; + + // Overload assignment operator to clone base_struct + StructBase& operator=(StructBase const& other) { + base_struct = other.base_struct->clone_expr(); + + return *this; + } + + // move constructors + StructBase(StructBase&& other) = default; + StructBase& operator=(StructBase&& other) = default; + + /*~StructBase() { + delete base_struct; + }*/ + + // Returns a null expr-ed StructBase - error state + static StructBase error() { + return StructBase(NULL); + } + + // Returns whether StructBase is in error state + inline bool is_invalid() const { + return base_struct == NULL; + } + + ::std::string as_string() const; + }; + + // Base AST node for a single struct expression field (in struct instance creation) - abstract + class StructExprField { + public: + virtual ~StructExprField() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_struct_expr_field() const { + return ::std::unique_ptr(clone_struct_expr_field_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual clone implementation + virtual StructExprField* clone_struct_expr_field_impl() const = 0; + }; + + // Identifier-only variant of StructExprField AST node + class StructExprFieldIdentifier : public StructExprField { + Identifier field_name; + + // TODO: should this store location data? + + public: + StructExprFieldIdentifier(Identifier field_identifier) : + field_name(::std::move(field_identifier)) {} + + ::std::string as_string() const { + return field_name; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this rather than base + virtual StructExprFieldIdentifier* clone_struct_expr_field_impl() const OVERRIDE { + return new StructExprFieldIdentifier(*this); + } + }; + + // Base AST node for a single struct expression field with an assigned value - abstract + class StructExprFieldWithVal : public StructExprField { + // Expr* value; + ::std::unique_ptr value; + + protected: + StructExprFieldWithVal(::std::unique_ptr field_value) : + value(::std::move(field_value)) {} + + // Copy constructor requires clone + StructExprFieldWithVal(StructExprFieldWithVal const& other) : + value(other.value->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + StructExprFieldWithVal& operator=(StructExprFieldWithVal const& other) { + value = other.value->clone_expr(); + + return *this; + } + + // move constructors + StructExprFieldWithVal(StructExprFieldWithVal&& other) = default; + StructExprFieldWithVal& operator=(StructExprFieldWithVal&& other) = default; + + public: + /*~StructExprFieldWithVal() { + delete value; + }*/ + + ::std::string as_string() const; + }; + + // Identifier and value variant of StructExprField AST node + class StructExprFieldIdentifierValue : public StructExprFieldWithVal { + Identifier field_name; + + // TODO: should this store location data? + + public: + StructExprFieldIdentifierValue( + Identifier field_identifier, ::std::unique_ptr field_value) : + StructExprFieldWithVal(::std::move(field_value)), + field_name(::std::move(field_identifier)) {} + + // copy constructor, destructor, and overloaded assignment operator should carry through + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this rather than base + virtual StructExprFieldIdentifierValue* clone_struct_expr_field_impl() const OVERRIDE { + return new StructExprFieldIdentifierValue(*this); + } + }; + + // Tuple index and value variant of StructExprField AST node + class StructExprFieldIndexValue : public StructExprFieldWithVal { + TupleIndex index; + + // TODO: should this store location data? + + public: + StructExprFieldIndexValue(TupleIndex tuple_index, ::std::unique_ptr field_value) : + StructExprFieldWithVal(::std::move(field_value)), index(tuple_index) {} + + // copy constructor, destructor, and overloaded assignment operator should carry through + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this rather than base + virtual StructExprFieldIndexValue* clone_struct_expr_field_impl() const OVERRIDE { + return new StructExprFieldIndexValue(*this); + } + }; + + // AST node of a struct creator with fields + class StructExprStructFields : public StructExprStruct { + //::std::vector fields; + ::std::vector< ::std::unique_ptr > fields; + + // bool has_struct_base; + StructBase struct_base; + + public: + ::std::string as_string() const; + + inline bool has_struct_base() const { + return !struct_base.is_invalid(); + } + + /*inline ::std::vector< ::std::unique_ptr > get_fields() const { + return fields; + }*/ + + /*inline StructBase get_struct_base() const { + return has_struct_base ? struct_base : StructBase::error(); + }*/ + + // Constructor for StructExprStructFields when no struct base is used + StructExprStructFields(PathInExpression struct_path, + ::std::vector< ::std::unique_ptr > expr_fields, location_t locus, + StructBase base_struct = StructBase::error(), + ::std::vector inner_attribs = ::std::vector(), + ::std::vector outer_attribs = ::std::vector()) : + StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), + ::std::move(outer_attribs), locus), + fields(::std::move(expr_fields)), struct_base(::std::move(base_struct)) {} + + // copy constructor with vector clone + StructExprStructFields(StructExprStructFields const& other) : + StructExprStruct(other), struct_base(other.struct_base) { + // DEBUG + fprintf(stderr, "got past the initialisation list part of copy constructor\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + // DEBUG + fprintf(stderr, "reserved space in fields\n"); + + for (const auto& e : other.fields) { + // DEBUG + fprintf(stderr, "about to clone a field\n"); + + fields.push_back(e->clone_struct_expr_field()); + + // DEBUG + fprintf(stderr, "cloned a field successfully\n"); + } + + // DEBUG + fprintf(stderr, "finished cloning fields\n"); + } + + // overloaded assignment operator with vector clone + StructExprStructFields& operator=(StructExprStructFields const& other) { + StructExprStruct::operator=(other); + struct_base = other.struct_base; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + for (const auto& e : other.fields) { + fields.push_back(e->clone_struct_expr_field()); + } + + return *this; + } + + // move constructors + StructExprStructFields(StructExprStructFields&& other) = default; + StructExprStructFields& operator=(StructExprStructFields&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStructFields* clone_expr_impl() const OVERRIDE { + return new StructExprStructFields(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStructFields* clone_expr_without_block_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "called structexprstructfields clone expr without block impl - about " + "to return new structexprstructfields\n"); + + // DEBUG - test creation of a base from this + fprintf(stderr, "about to try to create and allocate structexprstruct \n"); + StructExprStruct* test_DELETE = new StructExprStruct(*this); + delete test_DELETE; + fprintf(stderr, "managed to create and allocate structexprstruct \n"); + // very weird: can create and allocate structexpstruct but not structexprstructfields + + // DEBUG - test creation of a non-returned class from this + fprintf(stderr, + "about to try to create and allocate structexprstructfields (but not return)\n"); + StructExprStructFields* test_DELETE2 = new StructExprStructFields(*this); + delete test_DELETE2; + fprintf(stderr, + "managed to create and allocate structexprstructfields (if not returned) \n"); + // ok this fails. fair enough. + + return new StructExprStructFields(*this); + } + }; + + // AST node of the functional update struct creator + class StructExprStructBase : public StructExprStruct { + StructBase struct_base; + + public: + ::std::string as_string() const; + + /*inline StructBase get_struct_base() const { + return struct_base; + }*/ + + StructExprStructBase(PathInExpression struct_path, StructBase base_struct, + ::std::vector inner_attribs, ::std::vector outer_attribs, + location_t locus) : + StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), + ::std::move(outer_attribs), locus), + struct_base(::std::move(base_struct)) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStructBase* clone_expr_impl() const OVERRIDE { + return new StructExprStructBase(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprStructBase* clone_expr_without_block_impl() const OVERRIDE { + return new StructExprStructBase(*this); + } + }; + + // AST node of a tuple struct creator + class StructExprTuple : public StructExpr { + ::std::vector inner_attrs; + //::std::vector exprs; + ::std::vector< ::std::unique_ptr > exprs; + + location_t locus; + + public: + ::std::string as_string() const; + + inline const ::std::vector& get_inner_attrs() const { + return inner_attrs; + } + + /*inline ::std::vector< ::std::unique_ptr > get_exprs() const { + return exprs; + }*/ + + StructExprTuple(PathInExpression struct_path, + ::std::vector< ::std::unique_ptr > tuple_exprs, + ::std::vector inner_attribs, ::std::vector outer_attribs, + location_t locus) : + StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), exprs(::std::move(tuple_exprs)), locus(locus) { + } + + // copy constructor with vector clone + StructExprTuple(StructExprTuple const& other) : + StructExpr(other), inner_attrs(other.inner_attrs), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + exprs.reserve(other.exprs.size()); + + for (const auto& e : other.exprs) { + exprs.push_back(e->clone_expr()); + } + } + + // overloaded assignment operator with vector clone + StructExprTuple& operator=(StructExprTuple const& other) { + StructExpr::operator=(other); + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + exprs.reserve(other.exprs.size()); + + for (const auto& e : other.exprs) { + exprs.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + StructExprTuple(StructExprTuple&& other) = default; + StructExprTuple& operator=(StructExprTuple&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprTuple* clone_expr_impl() const OVERRIDE { + return new StructExprTuple(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprTuple* clone_expr_without_block_impl() const OVERRIDE { + return new StructExprTuple(*this); + } + }; + + // AST node of a "unit" struct creator (no fields and no braces) + class StructExprUnit : public StructExpr { + location_t locus; + + public: + ::std::string as_string() const { + return get_struct_name().as_string(); + // return struct_name.as_string(); + } + + StructExprUnit(PathInExpression struct_path, ::std::vector outer_attribs, + location_t locus) : + StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), + locus(locus) {} + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprUnit* clone_expr_impl() const OVERRIDE { + return new StructExprUnit(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual StructExprUnit* clone_expr_without_block_impl() const OVERRIDE { + return new StructExprUnit(*this); + } + }; + + // aka EnumerationVariantExpr + // Base AST node representing creation of an enum variant instance - abstract + class EnumVariantExpr : public ExprWithoutBlock { + PathInExpression enum_variant_path; + + protected: + // Protected constructor for initialising enum_variant_path + EnumVariantExpr( + PathInExpression path_to_enum_variant, ::std::vector outer_attribs) : + ExprWithoutBlock(::std::move(outer_attribs)), + enum_variant_path(::std::move(path_to_enum_variant)) {} + + public: + // TODO: maybe remove and have string version gotten here directly + inline PathInExpression get_enum_variant_path() const { + return enum_variant_path; + } + }; + + // Base AST node for a single enum expression field (in enum instance creation) - abstract + class EnumExprField { + public: + virtual ~EnumExprField() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_enum_expr_field() const { + return ::std::unique_ptr(clone_enum_expr_field_impl()); + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual EnumExprField* clone_enum_expr_field_impl() const = 0; + }; + + // Identifier-only variant of EnumExprField AST node + class EnumExprFieldIdentifier : public EnumExprField { + Identifier field_name; + + // TODO: should this store location data? + + public: + EnumExprFieldIdentifier(Identifier field_identifier) : + field_name(::std::move(field_identifier)) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprFieldIdentifier* clone_enum_expr_field_impl() const OVERRIDE { + return new EnumExprFieldIdentifier(*this); + } + }; + + // Base AST node for a single enum expression field with an assigned value - abstract + class EnumExprFieldWithVal : public EnumExprField { + // Expr* value; + ::std::unique_ptr value; + + // TODO: should this store location data? + + protected: + EnumExprFieldWithVal(::std::unique_ptr field_value) : + value(::std::move(field_value)) {} + + // Copy constructor must clone unique_ptr value + EnumExprFieldWithVal(EnumExprFieldWithVal const& other) : + value(other.value->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + EnumExprFieldWithVal& operator=(EnumExprFieldWithVal const& other) { + value = other.value->clone_expr(); + + return *this; + } + + // move constructors + EnumExprFieldWithVal(EnumExprFieldWithVal&& other) = default; + EnumExprFieldWithVal& operator=(EnumExprFieldWithVal&& other) = default; + }; + + // Identifier and value variant of EnumExprField AST node + class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal { + Identifier field_name; + + // TODO: should this store location data? + + public: + EnumExprFieldIdentifierValue(Identifier field_name, ::std::unique_ptr field_value) : + EnumExprFieldWithVal(::std::move(field_value)), field_name(::std::move(field_name)) {} + + // copy constructor, destructor, and assignment operator should not need defining + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprFieldIdentifierValue* clone_enum_expr_field_impl() const OVERRIDE { + return new EnumExprFieldIdentifierValue(*this); + } + }; + + // Tuple index and value variant of EnumExprField AST node + class EnumExprFieldIndexValue : public EnumExprFieldWithVal { + TupleIndex index; + // TODO: implement "with val" as a template with EnumExprField as type param? + + // TODO: should this store location data? + + public: + EnumExprFieldIndexValue(TupleIndex field_index, ::std::unique_ptr field_value) : + EnumExprFieldWithVal(::std::move(field_value)), index(field_index) {} + + // copy constructor, destructor, and assignment operator should not need defining + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprFieldIndexValue* clone_enum_expr_field_impl() const OVERRIDE { + return new EnumExprFieldIndexValue(*this); + } + }; + + // Struct-like syntax enum variant instance creation AST node + class EnumExprStruct : public EnumVariantExpr { + //::std::vector fields; + ::std::vector< ::std::unique_ptr > fields; + + location_t locus; + + public: + ::std::string as_string() const; + + /*inline ::std::vector< ::std::unique_ptr > get_fields() const { + return fields; + }*/ + + EnumExprStruct(PathInExpression enum_variant_path, + ::std::vector< ::std::unique_ptr > variant_fields, + ::std::vector outer_attribs, location_t locus) : + EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), + fields(::std::move(variant_fields)), locus(locus) {} + + // copy constructor with vector clone + EnumExprStruct(EnumExprStruct const& other) : EnumVariantExpr(other), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + for (const auto& e : other.fields) { + fields.push_back(e->clone_enum_expr_field()); + } + } + + // overloaded assignment operator with vector clone + EnumExprStruct& operator=(EnumExprStruct const& other) { + EnumVariantExpr::operator=(other); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + for (const auto& e : other.fields) { + fields.push_back(e->clone_enum_expr_field()); + } + + return *this; + } + + // move constructors + EnumExprStruct(EnumExprStruct&& other) = default; + EnumExprStruct& operator=(EnumExprStruct&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprStruct* clone_expr_impl() const OVERRIDE { + return new EnumExprStruct(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprStruct* clone_expr_without_block_impl() const OVERRIDE { + return new EnumExprStruct(*this); + } + }; + + // Tuple-like syntax enum variant instance creation AST node + class EnumExprTuple : public EnumVariantExpr { + //::std::vector values; + ::std::vector< ::std::unique_ptr > values; + + location_t locus; + + public: + ::std::string as_string() const; + + /*inline ::std::vector< ::std::unique_ptr > get_values() const { + return values; + }*/ + + EnumExprTuple(PathInExpression enum_variant_path, + ::std::vector< ::std::unique_ptr > variant_values, + ::std::vector outer_attribs, location_t locus) : + EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), + values(::std::move(variant_values)), locus(locus) {} + + // copy constructor with vector clone + EnumExprTuple(EnumExprTuple const& other) : EnumVariantExpr(other), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + values.reserve(other.values.size()); + + for (const auto& e : other.values) { + values.push_back(e->clone_expr()); + } + } + + // overloaded assignment operator with vector clone + EnumExprTuple& operator=(EnumExprTuple const& other) { + EnumVariantExpr::operator=(other); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + values.reserve(other.values.size()); + + for (const auto& e : other.values) { + values.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + EnumExprTuple(EnumExprTuple&& other) = default; + EnumExprTuple& operator=(EnumExprTuple&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprTuple* clone_expr_impl() const OVERRIDE { + return new EnumExprTuple(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprTuple* clone_expr_without_block_impl() const OVERRIDE { + return new EnumExprTuple(*this); + } + }; + + // No-field enum variant instance creation AST node + class EnumExprFieldless : public EnumVariantExpr { + location_t locus; + + public: + ::std::string as_string() const { + // return enum_variant_path.as_string(); + return get_enum_variant_path().as_string(); + } + + EnumExprFieldless(PathInExpression enum_variant_path, + ::std::vector outer_attribs, location_t locus) : + EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), + locus(locus) {} + + // copy constructor, destructor, and assignment operator should not need defining + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprFieldless* clone_expr_impl() const OVERRIDE { + return new EnumExprFieldless(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual EnumExprFieldless* clone_expr_without_block_impl() const OVERRIDE { + return new EnumExprFieldless(*this); + } + }; + + // Function call expression AST node + class CallExpr : public ExprWithoutBlock { + // Expr* function; + ::std::unique_ptr function; + //::std::vector params; // inlined form of CallParams + ::std::vector< ::std::unique_ptr > params; + + location_t locus; + + public: + /*~CallExpr() { + delete function; + }*/ + + ::std::string as_string() const; + + /*inline ::std::vector< ::std::unique_ptr > get_params() const { + return params; + }*/ + + CallExpr(::std::unique_ptr function_expr, + ::std::vector< ::std::unique_ptr > function_params, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + function(::std::move(function_expr)), params(::std::move(function_params)), + locus(locus) {} + + // copy constructor requires clone + CallExpr(CallExpr const& other) : + ExprWithoutBlock(other), function(other.function->clone_expr()), locus(other.locus) + /*, params(other.params),*/ { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + params.reserve(other.params.size()); + + for (const auto& e : other.params) { + params.push_back(e->clone_expr()); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone + CallExpr& operator=(CallExpr const& other) { + ExprWithoutBlock::operator=(other); + function = other.function->clone_expr(); + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + params.reserve(other.params.size()); + + for (const auto& e : other.params) { + params.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + CallExpr(CallExpr&& other) = default; + CallExpr& operator=(CallExpr&& other) = default; + + // Returns whether function call has parameters. + inline bool has_params() const { + return !params.empty(); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual CallExpr* clone_expr_impl() const OVERRIDE { + return new CallExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual CallExpr* clone_expr_without_block_impl() const OVERRIDE { + return new CallExpr(*this); + } + }; + + // Method call expression AST node + class MethodCallExpr : public ExprWithoutBlock { + // Expr* receiver; + ::std::unique_ptr receiver; + PathExprSegment method_name; + //::std::vector params; // inlined form of CallParams + ::std::vector< ::std::unique_ptr > params; + + location_t locus; + + public: + /*~MethodCallExpr() { + delete receiver; + }*/ + + ::std::string as_string() const; + + /*inline ::std::vector< ::std::unique_ptr > get_params() const { + return params; + }*/ + + MethodCallExpr(::std::unique_ptr call_receiver, PathExprSegment method_path, + ::std::vector< ::std::unique_ptr > method_params, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + receiver(::std::move(call_receiver)), method_name(::std::move(method_path)), + params(::std::move(method_params)), locus(locus) {} + + // copy constructor required due to cloning + MethodCallExpr(MethodCallExpr const& other) : + ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), + method_name(other.method_name), locus(other.locus) + /*, params(other.params),*/ { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + params.reserve(other.params.size()); + + for (const auto& e : other.params) { + params.push_back(e->clone_expr()); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone receiver object + MethodCallExpr& operator=(MethodCallExpr const& other) { + ExprWithoutBlock::operator=(other); + receiver = other.receiver->clone_expr(); + method_name = other.method_name; + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + params.reserve(other.params.size()); + + for (const auto& e : other.params) { + params.push_back(e->clone_expr()); + } + + return *this; + } + + // move constructors + MethodCallExpr(MethodCallExpr&& other) = default; + MethodCallExpr& operator=(MethodCallExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MethodCallExpr* clone_expr_impl() const OVERRIDE { + return new MethodCallExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MethodCallExpr* clone_expr_without_block_impl() const OVERRIDE { + return new MethodCallExpr(*this); + } + }; + + // aka FieldExpression + // Struct or union field access expression AST node + class FieldAccessExpr : public ExprWithoutBlock { + // Expr* receiver; + ::std::unique_ptr receiver; + Identifier field; + + location_t locus; + + public: + /*~FieldAccessExpr() { + delete receiver; + }*/ + + ::std::string as_string() const; + + FieldAccessExpr(::std::unique_ptr field_access_receiver, Identifier field_name, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + receiver(::std::move(field_access_receiver)), field(::std::move(field_name)), + locus(locus) {} + + // Copy constructor required due to unique_ptr cloning + FieldAccessExpr(FieldAccessExpr const& other) : + ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), field(other.field), + locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + FieldAccessExpr& operator=(FieldAccessExpr const& other) { + ExprWithoutBlock::operator=(other); + receiver = other.receiver->clone_expr(); + field = other.field; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + FieldAccessExpr(FieldAccessExpr&& other) = default; + FieldAccessExpr& operator=(FieldAccessExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual FieldAccessExpr* clone_expr_impl() const OVERRIDE { + return new FieldAccessExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual FieldAccessExpr* clone_expr_without_block_impl() const OVERRIDE { + return new FieldAccessExpr(*this); + } + }; + + // Closure parameter data structure + struct ClosureParam { + private: + // Pattern pattern; + ::std::unique_ptr pattern; + + // bool has_type_given; + // Type type; + ::std::unique_ptr type; + + // TODO: should this store location data? + + public: + // Returns whether the type of the parameter has been given. + inline bool has_type_given() const { + return type != NULL; + } + + // Constructor for closure parameter + ClosureParam( + ::std::unique_ptr param_pattern, ::std::unique_ptr param_type = NULL) : + pattern(::std::move(param_pattern)), + type(::std::move(param_type)) {} + + // Copy constructor required due to cloning as a result of unique_ptrs + ClosureParam(ClosureParam const& other) : pattern(other.pattern->clone_pattern()) { + // guard to protect from null pointer dereference + if (other.type != NULL) { + type = other.type->clone_type(); + } + } + + ~ClosureParam() = default; + + // Assignment operator must be overloaded to clone as well + ClosureParam& operator=(ClosureParam const& other) { + pattern = other.pattern->clone_pattern(); + type = other.type->clone_type(); + + return *this; + } + + // move constructors + ClosureParam(ClosureParam&& other) = default; + ClosureParam& operator=(ClosureParam&& other) = default; + + // Returns whether closure parameter is in an error state. + inline bool is_error() const { + return pattern == NULL; + } + + // Creates an error state closure parameter. + static ClosureParam create_error() { + return ClosureParam(NULL); + } + + ::std::string as_string() const; + }; + + // Base closure definition expression AST node - abstract + class ClosureExpr : public ExprWithoutBlock { + bool has_move; + ::std::vector params; // may be empty + // also note a double pipe "||" can be used for empty params - does not need a space + + location_t locus; + + protected: + ClosureExpr(::std::vector closure_params, bool has_move, + ::std::vector outer_attribs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attribs)), + has_move(has_move), params(::std::move(closure_params)), locus(locus) {} + + // Copy constructor, destructor, and assignment operator override should not be needed + public: + virtual ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + }; + + // Represents a non-type-specified closure expression AST node + class ClosureExprInner : public ClosureExpr { + // Expr* closure_inner; + ::std::unique_ptr closure_inner; + + public: + /*~ClosureExprInner() { + delete closure_inner; + }*/ + + ::std::string as_string() const; + + // Constructor for a ClosureExprInner + ClosureExprInner(::std::unique_ptr closure_inner_expr, + ::std::vector closure_params, location_t locus, bool is_move = false, + ::std::vector outer_attribs = ::std::vector()) : + ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), + closure_inner(::std::move(closure_inner_expr)) {} + + // Copy constructor must be defined to allow copying via cloning of unique_ptr + ClosureExprInner(ClosureExprInner const& other) : + ClosureExpr(other), closure_inner(other.closure_inner->clone_expr()) {} + // TODO: ensure that this actually constructs properly + + // Destructor - define here if required + + // Overload assignment operator to clone closure_inner + ClosureExprInner& operator=(ClosureExprInner const& other) { + ClosureExpr::operator=(other); + closure_inner = other.closure_inner->clone_expr(); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInner(ClosureExprInner&& other) = default; + ClosureExprInner& operator=(ClosureExprInner&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ClosureExprInner* clone_expr_impl() const OVERRIDE { + return new ClosureExprInner(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ClosureExprInner* clone_expr_without_block_impl() const OVERRIDE { + return new ClosureExprInner(*this); + } + }; + + // Forward decl BlockExpr for ClosureExprInnerTyped + // class BlockExpr; + + // A block AST node + class BlockExpr : public ExprWithBlock { + ::std::vector inner_attrs; + + /*bool has_statements; + Statements statements;*/ + + // bool has_statements; + ::std::vector< ::std::unique_ptr > statements; + // bool has_expr; + ::std::unique_ptr expr; // inlined from Statements + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether the block contains statements. + inline bool has_statements() const { + return !statements.empty(); + } + + // Returns whether the block contains an expression + inline bool has_expr() const { + return expr != NULL; + } + + BlockExpr(::std::vector< ::std::unique_ptr > block_statements, + ::std::unique_ptr block_expr, ::std::vector inner_attribs, + ::std::vector outer_attribs, location_t locus) : + ExprWithBlock(::std::move(outer_attribs)), + inner_attrs(::std::move(inner_attribs)), statements(::std::move(block_statements)), + expr(::std::move(block_expr)), locus(locus) {} + + // Copy constructor with clone + BlockExpr(BlockExpr const& other) : + ExprWithBlock(other), /*statements(other.statements),*/ + inner_attrs(other.inner_attrs), locus(other.locus) { + // guard to protect from null pointer dereference + if (other.expr != NULL) { + expr = other.expr->clone_expr_without_block(); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + statements.reserve(other.statements.size()); + + for (const auto& e : other.statements) { + statements.push_back(e->clone_stmt()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone pointer + BlockExpr& operator=(BlockExpr const& other) { + ExprWithBlock::operator=(other); + // statements = other.statements; + expr = other.expr->clone_expr_without_block(); + inner_attrs = other.inner_attrs; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + statements.reserve(other.statements.size()); + + for (const auto& e : other.statements) { + statements.push_back(e->clone_stmt()); + } + + return *this; + } + + // move constructors + BlockExpr(BlockExpr&& other) = default; + BlockExpr& operator=(BlockExpr&& other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr clone_block_expr() const { + return ::std::unique_ptr(clone_block_expr_impl()); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual BlockExpr* clone_expr_impl() const OVERRIDE { + return new BlockExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual BlockExpr* clone_expr_with_block_impl() const OVERRIDE { + return new BlockExpr(*this); + } + + /* This is the base method as not an abstract class - not virtual but could be in future + * if required. */ + /*virtual*/ BlockExpr* clone_block_expr_impl() const { + return new BlockExpr(*this); + } + }; + + // Represents a type-specified closure expression AST node + class ClosureExprInnerTyped : public ClosureExpr { + // Type return_type; + ::std::unique_ptr return_type; + // BlockExpr* expr; + ::std::unique_ptr expr; // only used because may be polymorphic in future + + public: + /*~ClosureExprInnerTyped() { + delete expr; + }*/ + + ::std::string as_string() const; + + // Constructor potentially with a move + ClosureExprInnerTyped(::std::unique_ptr closure_return_type, + ::std::unique_ptr closure_expr, ::std::vector closure_params, + location_t locus, bool is_move = false, + ::std::vector outer_attribs = ::std::vector()) : + ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), + return_type(::std::move(closure_return_type)), expr(::std::move(closure_expr)) {} + + // Copy constructor requires cloning + ClosureExprInnerTyped(ClosureExprInnerTyped const& other) : + ClosureExpr(other), return_type(other.return_type->clone_type()), + expr(other.expr->clone_block_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptrs + ClosureExprInnerTyped& operator=(ClosureExprInnerTyped const& other) { + ClosureExpr::operator=(other); + return_type = other.return_type->clone_type(); + expr = other.expr->clone_block_expr(); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInnerTyped(ClosureExprInnerTyped&& other) = default; + ClosureExprInnerTyped& operator=(ClosureExprInnerTyped&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ClosureExprInnerTyped* clone_expr_impl() const OVERRIDE { + return new ClosureExprInnerTyped(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ClosureExprInnerTyped* clone_expr_without_block_impl() const OVERRIDE { + return new ClosureExprInnerTyped(*this); + } + }; + + // AST node representing continue expression within loops + class ContinueExpr : public ExprWithoutBlock { + // bool has_label; + Lifetime label; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns true if the continue expr has a label. + inline bool has_label() const { + return !label.is_error(); + } + + // Constructor for a ContinueExpr with a label. + ContinueExpr(location_t locus, Lifetime label = Lifetime::error(), + ::std::vector outer_attribs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attribs)), + label(::std::move(label)), locus(locus) {} + + // copy constructor, destructor, and assignment operator should not need defining + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ContinueExpr* clone_expr_impl() const OVERRIDE { + return new ContinueExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ContinueExpr* clone_expr_without_block_impl() const OVERRIDE { + return new ContinueExpr(*this); + } + }; + // TODO: merge "break" and "continue"? Or even merge in "return"? + + // AST node representing break expression within loops + class BreakExpr : public ExprWithoutBlock { + // bool has_label; + Lifetime label; + + // bool has_break_expr; + // Expr* break_expr; // may be uninitialised + ::std::unique_ptr break_expr; + + location_t locus; + + public: + /*~BreakExpr() { + if (has_break_expr) { + delete break_expr; + } + }*/ + + ::std::string as_string() const; + + // Returns whether the break expression has a label or not. + inline bool has_label() const { + return !label.is_error(); + } + + // Returns whether the break expression has an expression used in the break or not. + inline bool has_break_expr() const { + return break_expr != NULL; + } + + // Constructor for a break expression + BreakExpr(location_t locus, Lifetime break_label = Lifetime::error(), + ::std::unique_ptr expr_in_break = NULL, + ::std::vector outer_attribs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attribs)), + label(::std::move(break_label)), break_expr(::std::move(expr_in_break)), locus(locus) {} + + // Copy constructor defined to use clone for unique pointer + BreakExpr(BreakExpr const& other) : + ExprWithoutBlock(other), label(other.label), locus(other.locus) { + // guard to protect from null pointer dereference + if (other.break_expr != NULL) { + break_expr = other.break_expr->clone_expr(); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone unique pointer + BreakExpr& operator=(BreakExpr const& other) { + ExprWithoutBlock::operator=(other); + label = other.label; + break_expr = other.break_expr->clone_expr(); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BreakExpr(BreakExpr&& other) = default; + BreakExpr& operator=(BreakExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual BreakExpr* clone_expr_impl() const OVERRIDE { + return new BreakExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual BreakExpr* clone_expr_without_block_impl() const OVERRIDE { + return new BreakExpr(*this); + } + }; + + // Base range expression AST node object - abstract + class RangeExpr : public ExprWithoutBlock { + location_t locus; + + protected: + // outer attributes not allowed before range expressions + RangeExpr(location_t locus) : + ExprWithoutBlock(::std::vector()), locus(locus) {} + + public: + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + }; + + // Range from (inclusive) and to (exclusive) expression AST node object + // aka RangeExpr; constructs a std::ops::Range object + class RangeFromToExpr : public RangeExpr { + /*Expr* from; + Expr* to;*/ + ::std::unique_ptr from; + ::std::unique_ptr to; + + public: + /*~RangeFromToExpr() { + delete from; + delete to; + }*/ + + ::std::string as_string() const; + + RangeFromToExpr(::std::unique_ptr range_from, ::std::unique_ptr range_to, + location_t locus) : + RangeExpr(locus), + from(::std::move(range_from)), to(::std::move(range_to)) {} + + // Copy constructor with cloning + RangeFromToExpr(RangeFromToExpr const& other) : + RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique pointers + RangeFromToExpr& operator=(RangeFromToExpr const& other) { + RangeExpr::operator=(other); + from = other.from->clone_expr(); + to = other.to->clone_expr(); + + return *this; + } + + // move constructors + RangeFromToExpr(RangeFromToExpr&& other) = default; + RangeFromToExpr& operator=(RangeFromToExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromToExpr* clone_expr_impl() const OVERRIDE { + return new RangeFromToExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromToExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeFromToExpr(*this); + } + }; + + // Range from (inclusive) expression AST node object + // constructs a std::ops::RangeFrom object + class RangeFromExpr : public RangeExpr { + // Expr* from; + ::std::unique_ptr from; + + public: + /*~RangeFromExpr() { + delete from; + }*/ + + ::std::string as_string() const; + + RangeFromExpr(::std::unique_ptr range_from, location_t locus) : + RangeExpr(locus), from(::std::move(range_from)) {} + + // Copy constructor with clone + RangeFromExpr(RangeFromExpr const& other) : + RangeExpr(other), from(other.from->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + RangeFromExpr& operator=(RangeFromExpr const& other) { + RangeExpr::operator=(other); + from = other.from->clone_expr(); + + return *this; + } + + // move constructors + RangeFromExpr(RangeFromExpr&& other) = default; + RangeFromExpr& operator=(RangeFromExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromExpr* clone_expr_impl() const OVERRIDE { + return new RangeFromExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeFromExpr(*this); + } + }; + + // Range to (exclusive) expression AST node object + // constructs a std::ops::RangeTo object + class RangeToExpr : public RangeExpr { + // Expr* to; + ::std::unique_ptr to; + + public: + /*~RangeToExpr() { + delete to; + }*/ + + ::std::string as_string() const; + + // outer attributes not allowed + RangeToExpr(::std::unique_ptr range_to, location_t locus) : + RangeExpr(locus), to(::std::move(range_to)) {} + + // Copy constructor with clone + RangeToExpr(RangeToExpr const& other) : RangeExpr(other), to(other.to->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + RangeToExpr& operator=(RangeToExpr const& other) { + RangeExpr::operator=(other); + to = other.to->clone_expr(); + + return *this; + } + + // move constructors + RangeToExpr(RangeToExpr&& other) = default; + RangeToExpr& operator=(RangeToExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeToExpr* clone_expr_impl() const OVERRIDE { + return new RangeToExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeToExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeToExpr(*this); + } + }; + + // Full range expression AST node object + // constructs a std::ops::RangeFull object + class RangeFullExpr : public RangeExpr { + public: + ::std::string as_string() const; + + RangeFullExpr(location_t locus) : RangeExpr(locus) {} + // outer attributes not allowed + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFullExpr* clone_expr_impl() const OVERRIDE { + return new RangeFullExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFullExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeFullExpr(*this); + } + }; + + // Range from (inclusive) and to (inclusive) expression AST node object + // aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object + class RangeFromToInclExpr : public RangeExpr { + /*Expr* from; + Expr* to;*/ + ::std::unique_ptr from; + ::std::unique_ptr to; + + public: + /*~RangeFromToInclExpr() { + delete from; + delete to; + }*/ + + ::std::string as_string() const; + + RangeFromToInclExpr(::std::unique_ptr range_from, ::std::unique_ptr range_to, + location_t locus) : + RangeExpr(locus), + from(::std::move(range_from)), to(::std::move(range_to)) {} + // outer attributes not allowed + + // Copy constructor with clone + RangeFromToInclExpr(RangeFromToInclExpr const& other) : + RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} + + // Destructor - define here if required + + // Overload assignment operator to use clone + RangeFromToInclExpr& operator=(RangeFromToInclExpr const& other) { + RangeExpr::operator=(other); + from = other.from->clone_expr(); + to = other.to->clone_expr(); + + return *this; + } + + // move constructors + RangeFromToInclExpr(RangeFromToInclExpr&& other) = default; + RangeFromToInclExpr& operator=(RangeFromToInclExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromToInclExpr* clone_expr_impl() const OVERRIDE { + return new RangeFromToInclExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeFromToInclExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeFromToInclExpr(*this); + } + }; + + // Range to (inclusive) expression AST node object + // aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object + class RangeToInclExpr : public RangeExpr { + // Expr* to; + ::std::unique_ptr to; + + public: + /*~RangeToInclExpr() { + delete to; + }*/ + + ::std::string as_string() const; + + RangeToInclExpr(::std::unique_ptr range_to, location_t locus) : + RangeExpr(locus), to(::std::move(range_to)) {} + // outer attributes not allowed + + // Copy constructor with clone + RangeToInclExpr(RangeToInclExpr const& other) : + RangeExpr(other), to(other.to->clone_expr()) {} + + // Define destructor here if required + + // Overload assignment operator to clone pointer + RangeToInclExpr& operator=(RangeToInclExpr const& other) { + RangeExpr::operator=(other); + to = other.to->clone_expr(); + + return *this; + } + + // move constructors + RangeToInclExpr(RangeToInclExpr&& other) = default; + RangeToInclExpr& operator=(RangeToInclExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangeToInclExpr* clone_expr_impl() const OVERRIDE { + return new RangeToInclExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RangeToInclExpr* clone_expr_without_block_impl() const OVERRIDE { + return new RangeToInclExpr(*this); + } + }; + + // Return expression AST node representation + class ReturnExpr : public ExprWithoutBlock { + // bool has_return_expr; + // Expr* return_expr; + ::std::unique_ptr return_expr; + + location_t locus; + + public: + /*~ReturnExpr() { + if (has_return_expr) { + delete return_expr; + } + }*/ + + ::std::string as_string() const; + + // Returns whether the object has an expression returned (i.e. not void return type). + inline bool has_return_expr() const { + return return_expr != NULL; + } + + // Constructor for ReturnExpr. + ReturnExpr(location_t locus, ::std::unique_ptr returned_expr = NULL, + ::std::vector outer_attribs = ::std::vector()) : + ExprWithoutBlock(::std::move(outer_attribs)), + return_expr(::std::move(returned_expr)), locus(locus) {} + + // Copy constructor with clone + ReturnExpr(ReturnExpr const& other) : ExprWithoutBlock(other), locus(other.locus) { + // guard to protect from null pointer dereference + if (other.return_expr != NULL) { + return_expr = other.return_expr->clone_expr(); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone return_expr pointer + ReturnExpr& operator=(ReturnExpr const& other) { + ExprWithoutBlock::operator=(other); + return_expr = other.return_expr->clone_expr(); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ReturnExpr(ReturnExpr&& other) = default; + ReturnExpr& operator=(ReturnExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ReturnExpr* clone_expr_impl() const OVERRIDE { + return new ReturnExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ReturnExpr* clone_expr_without_block_impl() const OVERRIDE { + return new ReturnExpr(*this); + } + }; + + // Forward decl - defined in rust-macro.h + class MacroInvocation; + /*class MacroInvocation : public ExprWithoutBlock { + public: + ::std::string as_string() const; + };*/ + + // An unsafe block AST node + class UnsafeBlockExpr : public ExprWithBlock { + // Or just have it extend BlockExpr + // BlockExpr* expr; + ::std::unique_ptr expr; + + location_t locus; + + public: + /*~UnsafeBlockExpr() { + delete expr; + }*/ + + ::std::string as_string() const; + + UnsafeBlockExpr(::std::unique_ptr block_expr, + ::std::vector outer_attribs, location_t locus) : + ExprWithBlock(::std::move(outer_attribs)), + expr(::std::move(block_expr)), locus(locus) {} + + // Copy constructor with clone + UnsafeBlockExpr(UnsafeBlockExpr const& other) : + ExprWithBlock(other), expr(other.expr->clone_block_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + UnsafeBlockExpr& operator=(UnsafeBlockExpr const& other) { + ExprWithBlock::operator=(other); + expr = other.expr->clone_block_expr(); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + UnsafeBlockExpr(UnsafeBlockExpr&& other) = default; + UnsafeBlockExpr& operator=(UnsafeBlockExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual UnsafeBlockExpr* clone_expr_impl() const OVERRIDE { + return new UnsafeBlockExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual UnsafeBlockExpr* clone_expr_with_block_impl() const OVERRIDE { + return new UnsafeBlockExpr(*this); + } + }; + + // Loop label expression AST node used with break and continue expressions + // TODO: inline? + class LoopLabel /*: public Node*/ { + Lifetime label; // or type LIFETIME_OR_LABEL + + location_t locus; + + public: + ::std::string as_string() const; + + LoopLabel(Lifetime loop_label, location_t locus = UNKNOWN_LOCATION) : + label(::std::move(loop_label)), locus(locus) {} + + // Returns whether the LoopLabel is in an error state. + inline bool is_error() const { + return label.is_error(); + } + + // Creates an error state LoopLabel. + static LoopLabel error() { + return LoopLabel(Lifetime::error()); + } + + location_t get_locus() const { + return locus; + } + }; + + // Base loop expression AST node - aka LoopExpr + class BaseLoopExpr : public ExprWithBlock { + protected: + // protected to allow subclasses better use of them + // bool has_loop_label; + LoopLabel loop_label; + + // BlockExpr* loop_block; + ::std::unique_ptr loop_block; + + private: + location_t locus; + + protected: + // Constructor for BaseLoopExpr + BaseLoopExpr(::std::unique_ptr loop_block, location_t locus, + LoopLabel loop_label = LoopLabel::error(), + ::std::vector outer_attribs = ::std::vector()) : + ExprWithBlock(::std::move(outer_attribs)), + loop_label(::std::move(loop_label)), loop_block(::std::move(loop_block)), locus(locus) { + } + + // Copy constructor for BaseLoopExpr with clone + BaseLoopExpr(BaseLoopExpr const& other) : + ExprWithBlock(other), loop_label(other.loop_label), + loop_block(other.loop_block->clone_block_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + BaseLoopExpr& operator=(BaseLoopExpr const& other) { + ExprWithBlock::operator=(other); + loop_block = other.loop_block->clone_block_expr(); + loop_label = other.loop_label; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BaseLoopExpr(BaseLoopExpr&& other) = default; + BaseLoopExpr& operator=(BaseLoopExpr&& other) = default; + + public: + /*~BaseLoopExpr() { + delete loop_block; + }*/ + + inline bool has_loop_label() const { + return !loop_label.is_error(); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + }; + + // 'Loop' expression (i.e. the infinite loop) AST node + class LoopExpr : public BaseLoopExpr { + public: + ::std::string as_string() const; + + // Constructor for LoopExpr + LoopExpr(::std::unique_ptr loop_block, location_t locus, + LoopLabel loop_label = LoopLabel::error(), + ::std::vector outer_attribs = ::std::vector()) : + BaseLoopExpr(::std::move(loop_block), locus, ::std::move(loop_label), + ::std::move(outer_attribs)) {} + + // copy constructor, destructor, and assignment operator should not need modification + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LoopExpr* clone_expr_impl() const OVERRIDE { + return new LoopExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual LoopExpr* clone_expr_with_block_impl() const OVERRIDE { + return new LoopExpr(*this); + } + }; + + // While loop expression AST node (predicate loop) + class WhileLoopExpr : public BaseLoopExpr { + // Expr* condition; + ::std::unique_ptr condition; + + public: + /*~WhileLoopExpr() { + delete condition; + }*/ + + ::std::string as_string() const; + + // Constructor for while loop with loop label + WhileLoopExpr(::std::unique_ptr loop_condition, + ::std::unique_ptr loop_block, location_t locus, + LoopLabel loop_label = LoopLabel::error(), + ::std::vector outer_attribs = ::std::vector()) : + BaseLoopExpr( + ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), + condition(::std::move(loop_condition)) {} + + // Copy constructor with clone + WhileLoopExpr(WhileLoopExpr const& other) : + BaseLoopExpr(other), condition(other.condition->clone_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + WhileLoopExpr& operator=(WhileLoopExpr const& other) { + BaseLoopExpr::operator=(other); + condition = other.condition->clone_expr(); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + WhileLoopExpr(WhileLoopExpr&& other) = default; + WhileLoopExpr& operator=(WhileLoopExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual WhileLoopExpr* clone_expr_impl() const OVERRIDE { + return new WhileLoopExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual WhileLoopExpr* clone_expr_with_block_impl() const OVERRIDE { + return new WhileLoopExpr(*this); + } + }; + + // Forward decl MatchArmPatterns + // struct MatchArmPatterns; + + // While let loop expression AST node (predicate pattern loop) + class WhileLetLoopExpr : public BaseLoopExpr { + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined + // Expr* condition; + ::std::unique_ptr condition; + + public: + /*~WhileLetLoopExpr() { + delete condition; + }*/ + + ::std::string as_string() const; + + // Constructor with a loop label + WhileLetLoopExpr(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr condition, ::std::unique_ptr loop_block, + location_t locus, LoopLabel loop_label = LoopLabel::error(), + ::std::vector outer_attribs = ::std::vector()) : + BaseLoopExpr( + ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), + match_arm_patterns(::std::move(match_arm_patterns)), condition(::std::move(condition)) { + } + + // Copy constructor with clone + WhileLetLoopExpr(WhileLetLoopExpr const& other) : + BaseLoopExpr(other), /*match_arm_patterns(other.match_arm_patterns),*/ condition( + other.condition->clone_expr()) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone pointers + WhileLetLoopExpr& operator=(WhileLetLoopExpr const& other) { + BaseLoopExpr::operator=(other); + // match_arm_patterns = other.match_arm_patterns; + condition = other.condition->clone_expr(); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + WhileLetLoopExpr(WhileLetLoopExpr&& other) = default; + WhileLetLoopExpr& operator=(WhileLetLoopExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual WhileLetLoopExpr* clone_expr_impl() const OVERRIDE { + return new WhileLetLoopExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual WhileLetLoopExpr* clone_expr_with_block_impl() const OVERRIDE { + return new WhileLetLoopExpr(*this); + } + }; + + // For loop expression AST node (iterator loop) + class ForLoopExpr : public BaseLoopExpr { + // Pattern pattern; + ::std::unique_ptr pattern; + // Expr* iterator_expr; + ::std::unique_ptr iterator_expr; + + public: + /*~ForLoopExpr() { + delete iterator_expr; + }*/ + + ::std::string as_string() const; + + // Constructor with loop label + ForLoopExpr(::std::unique_ptr loop_pattern, + ::std::unique_ptr iterator_expr, ::std::unique_ptr loop_body, + location_t locus, LoopLabel loop_label = LoopLabel::error(), + ::std::vector outer_attribs = ::std::vector()) : + BaseLoopExpr( + ::std::move(loop_body), locus, ::std::move(loop_label), ::std::move(outer_attribs)), + pattern(::std::move(loop_pattern)), iterator_expr(::std::move(iterator_expr)) {} + + // Copy constructor with clone + ForLoopExpr(ForLoopExpr const& other) : + BaseLoopExpr(other), pattern(other.pattern->clone_pattern()), + iterator_expr(other.iterator_expr->clone_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ForLoopExpr& operator=(ForLoopExpr const& other) { + BaseLoopExpr::operator=(other); + pattern = other.pattern->clone_pattern(); + iterator_expr = other.iterator_expr->clone_expr(); + /*loop_block = other.loop_block->clone_block_expr(); + loop_label = other.loop_label; + outer_attrs = other.outer_attrs;*/ + + return *this; + } + + // move constructors + ForLoopExpr(ForLoopExpr&& other) = default; + ForLoopExpr& operator=(ForLoopExpr&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ForLoopExpr* clone_expr_impl() const OVERRIDE { + return new ForLoopExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ForLoopExpr* clone_expr_with_block_impl() const OVERRIDE { + return new ForLoopExpr(*this); + } + }; + + // forward decl for IfExpr + class IfLetExpr; + + // Base if expression with no "else" or "if let" AST node + class IfExpr : public ExprWithBlock { + /*Expr* condition; + BlockExpr* if_block;*/ + ::std::unique_ptr condition; + ::std::unique_ptr if_block; + /*union { + BlockExpr else_block; + IfExpr* if_expr; + IfLetExpr if_let_expr; + } consequent_block;*/ + + location_t locus; + + public: + /*virtual ~IfExpr() { + delete condition; + delete if_block; + }*/ + + ::std::string as_string() const; + + IfExpr(::std::unique_ptr condition, ::std::unique_ptr if_block, + location_t locus) : + ExprWithBlock(::std::vector()), + condition(::std::move(condition)), if_block(::std::move(if_block)), locus(locus) {} + // outer attributes are never allowed on IfExprs + + // Copy constructor with clone + IfExpr(IfExpr const& other) : + ExprWithBlock(other), condition(other.condition->clone_expr()), + if_block(other.if_block->clone_block_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone expressions + IfExpr& operator=(IfExpr const& other) { + ExprWithBlock::operator=(other); + condition = other.condition->clone_expr(); + if_block = other.if_block->clone_block_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + IfExpr(IfExpr&& other) = default; + IfExpr& operator=(IfExpr&& other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr clone_if_expr() const { + return ::std::unique_ptr(clone_if_expr_impl()); + } + + /* Note that multiple "else if"s are handled via nested ASTs rather than a vector of + * else ifs - i.e. not like a switch statement. TODO - is this a better approach? or + * does it not parse correctly and have downsides? */ + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfExpr* clone_expr_impl() const OVERRIDE { + return new IfExpr(*this); + } + + // Base clone function but still concrete as concrete base class + virtual IfExpr* clone_if_expr_impl() const { + return new IfExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExpr* clone_expr_with_block_impl() const OVERRIDE { + return new IfExpr(*this); + } + }; + + // If expression with an ending "else" expression AST node (trailing) + class IfExprConseqElse : public IfExpr { + // BlockExpr* else_block; + ::std::unique_ptr else_block; + + public: + /*~IfExprConseqElse() { + delete else_block; + }*/ + + ::std::string as_string() const; + + IfExprConseqElse(::std::unique_ptr condition, ::std::unique_ptr if_block, + ::std::unique_ptr else_block, location_t locus) : + IfExpr(::std::move(condition), ::std::move(if_block), locus), + else_block(::std::move(else_block)) {} + // again, outer attributes not allowed + + // Copy constructor with clone + IfExprConseqElse(IfExprConseqElse const& other) : + IfExpr(other), else_block(other.else_block->clone_block_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator with cloning + IfExprConseqElse& operator=(IfExprConseqElse const& other) { + IfExpr::operator=(other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr(); + + return *this; + } + + // move constructors + IfExprConseqElse(IfExprConseqElse&& other) = default; + IfExprConseqElse& operator=(IfExprConseqElse&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqElse* clone_expr_impl() const OVERRIDE { + return new IfExprConseqElse(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { + return new IfExprConseqElse(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqElse* clone_if_expr_impl() const OVERRIDE { + return new IfExprConseqElse(*this); + } + }; + + // If expression with an ending "else if" expression AST node + class IfExprConseqIf : public IfExpr { + // IfExpr* if_expr; + ::std::unique_ptr if_expr; + + public: + /*~IfExprConseqIf() { + delete if_expr; + }*/ + + ::std::string as_string() const; + + IfExprConseqIf(::std::unique_ptr condition, ::std::unique_ptr if_block, + ::std::unique_ptr conseq_if_expr, location_t locus) : + IfExpr(::std::move(condition), ::std::move(if_block), locus), + if_expr(::std::move(conseq_if_expr)) {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIf(IfExprConseqIf const& other) : + IfExpr(other), if_expr(other.if_expr->clone_if_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to use clone + IfExprConseqIf& operator=(IfExprConseqIf const& other) { + IfExpr::operator=(other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_expr = other.if_expr->clone_if_expr(); + + return *this; + } + + // move constructors + IfExprConseqIf(IfExprConseqIf&& other) = default; + IfExprConseqIf& operator=(IfExprConseqIf&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIf* clone_expr_impl() const OVERRIDE { + return new IfExprConseqIf(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { + return new IfExprConseqIf(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIf* clone_if_expr_impl() const OVERRIDE { + return new IfExprConseqIf(*this); + } + }; + + // Basic "if let" expression AST node with no else + class IfLetExpr : public ExprWithBlock { + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined + /*Expr* value; + BlockExpr* if_block;*/ + ::std::unique_ptr value; + ::std::unique_ptr if_block; + /*union { + BlockExpr else_block; + IfExpr if_expr; + IfLetExpr* if_let_expr; + } consequent_block;*/ + + location_t locus; + + public: + ::std::string as_string() const; + + IfLetExpr(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr value, ::std::unique_ptr if_block, + location_t locus) : + ExprWithBlock(::std::vector()), + match_arm_patterns(::std::move(match_arm_patterns)), value(::std::move(value)), + if_block(::std::move(if_block)), locus(locus) {} + // outer attributes not allowed on if let exprs either + + // copy constructor with clone + IfLetExpr(IfLetExpr const& other) : + ExprWithBlock(other), + /*match_arm_patterns(other.match_arm_patterns),*/ value(other.value->clone_expr()), + if_block(other.if_block->clone_block_expr()), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + } + } + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExpr& operator=(IfLetExpr const& other) { + ExprWithBlock::operator=(other); + // match_arm_patterns = other.match_arm_patterns; + value = other.value->clone_expr(); + if_block = other.if_block->clone_block_expr(); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + IfLetExpr(IfLetExpr&& other) = default; + IfLetExpr& operator=(IfLetExpr&& other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr clone_if_let_expr() const { + return ::std::unique_ptr(clone_if_let_expr_impl()); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExpr* clone_expr_impl() const OVERRIDE { + return new IfLetExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExpr* clone_expr_with_block_impl() const OVERRIDE { + return new IfLetExpr(*this); + } + + // Base clone function but still concrete as concrete base class + virtual IfLetExpr* clone_if_let_expr_impl() const { + return new IfLetExpr(*this); + } + }; + + // If expression with an ending "else if let" expression AST node + class IfExprConseqIfLet : public IfExpr { + // IfLetExpr* if_let_expr; + ::std::unique_ptr if_let_expr; + + public: + /*~IfExprIfConseqIfLet() { + delete if_let_expr; + }*/ + + ::std::string as_string() const; + + IfExprConseqIfLet(::std::unique_ptr condition, + ::std::unique_ptr if_block, ::std::unique_ptr conseq_if_let_expr, + location_t locus) : + IfExpr(::std::move(condition), ::std::move(if_block), locus), + if_let_expr(::std::move(conseq_if_let_expr)) {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIfLet(IfExprConseqIfLet const& other) : + IfExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to use clone + IfExprConseqIfLet& operator=(IfExprConseqIfLet const& other) { + IfExpr::operator=(other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr(); + + return *this; + } + + // move constructors + IfExprConseqIfLet(IfExprConseqIfLet&& other) = default; + IfExprConseqIfLet& operator=(IfExprConseqIfLet&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIfLet* clone_expr_impl() const OVERRIDE { + return new IfExprConseqIfLet(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { + return new IfExprConseqIfLet(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfExprConseqIfLet* clone_if_expr_impl() const OVERRIDE { + return new IfExprConseqIfLet(*this); + } + }; + + // AST node representing "if let" expression with an "else" expression at the end + class IfLetExprConseqElse : public IfLetExpr { + // BlockExpr* else_block; + ::std::unique_ptr else_block; + + public: + /*~IfLetExprConseqElse() { + delete else_block; + }*/ + + ::std::string as_string() const; + + IfLetExprConseqElse(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr value, ::std::unique_ptr if_block, + ::std::unique_ptr else_block, location_t locus) : + IfLetExpr( + ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), + else_block(::std::move(else_block)) {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqElse(IfLetExprConseqElse const& other) : + IfLetExpr(other), else_block(other.else_block->clone_block_expr()) {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqElse& operator=(IfLetExprConseqElse const& other) { + IfLetExpr::operator=(other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr(); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + IfLetExprConseqElse(IfLetExprConseqElse&& other) = default; + IfLetExprConseqElse& operator=(IfLetExprConseqElse&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqElse* clone_expr_impl() const OVERRIDE { + return new IfLetExprConseqElse(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { + return new IfLetExprConseqElse(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqElse* clone_if_let_expr_impl() const OVERRIDE { + return new IfLetExprConseqElse(*this); + } + }; + + // AST node representing "if let" expression with an "else if" expression at the end + class IfLetExprConseqIf : public IfLetExpr { + // IfExpr* if_expr; + ::std::unique_ptr if_expr; + + public: + /*~IfLetExprConseqIf() { + delete if_expr; + }*/ + + ::std::string as_string() const; + + IfLetExprConseqIf(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr value, ::std::unique_ptr if_block, + ::std::unique_ptr if_expr, location_t locus) : + IfLetExpr( + ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), + if_expr(::std::move(if_expr)) {} + // again, outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIf(IfLetExprConseqIf const& other) : + IfLetExpr(other), if_expr(other.if_expr->clone_if_expr()) {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqIf& operator=(IfLetExprConseqIf const& other) { + IfLetExpr::operator=(other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_expr = other.if_expr->clone_if_expr(); + + return *this; + } + + // move constructors + IfLetExprConseqIf(IfLetExprConseqIf&& other) = default; + IfLetExprConseqIf& operator=(IfLetExprConseqIf&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIf* clone_expr_impl() const OVERRIDE { + return new IfLetExprConseqIf(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { + return new IfLetExprConseqIf(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIf* clone_if_let_expr_impl() const OVERRIDE { + return new IfLetExprConseqIf(*this); + } + }; + + // AST node representing "if let" expression with an "else if let" expression at the end + class IfLetExprConseqIfLet : public IfLetExpr { + // IfLetExpr* if_let_expr; + ::std::unique_ptr if_let_expr; + + public: + /*~IfLetExprConseqIfLet() { + delete if_let_expr; + }*/ + + ::std::string as_string() const; + + IfLetExprConseqIfLet(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr value, ::std::unique_ptr if_block, + ::std::unique_ptr if_let_expr, location_t locus) : + IfLetExpr( + ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), + if_let_expr(::std::move(if_let_expr)) {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIfLet(IfLetExprConseqIfLet const& other) : + IfLetExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet const& other) { + IfLetExpr::operator=(other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr(); + + return *this; + } + + // move constructors + IfLetExprConseqIfLet(IfLetExprConseqIfLet&& other) = default; + IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIfLet* clone_expr_impl() const OVERRIDE { + return new IfLetExprConseqIfLet(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { + return new IfLetExprConseqIfLet(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual IfLetExprConseqIfLet* clone_if_let_expr_impl() const OVERRIDE { + return new IfLetExprConseqIfLet(*this); + } + }; + + // Match arm expression + struct MatchArm { + private: + ::std::vector outer_attrs; + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined + + // bool has_match_arm_guard; + // Expr* match_arm_guard; // inlined from MatchArmGuard + ::std::unique_ptr guard_expr; + + // TODO: should this store location data? + + public: + /*~MatchArm() { + if (has_match_arm_guard) { + delete match_arm_guard; + } + }*/ + + // Returns whether the MatchArm has a match arm guard expression + inline bool has_match_arm_guard() const { + return guard_expr != NULL; + } + + // Constructor for match arm with a guard expression + MatchArm(::std::vector< ::std::unique_ptr > match_arm_patterns, + ::std::unique_ptr guard_expr = NULL, + ::std::vector outer_attrs = ::std::vector()) : + outer_attrs(::std::move(outer_attrs)), + match_arm_patterns(::std::move(match_arm_patterns)), + guard_expr(::std::move(guard_expr)) {} + + // Copy constructor with clone + MatchArm(MatchArm const& other) : + /*match_arm_patterns(other.match_arm_patterns),*/ outer_attrs(other.outer_attrs) { + // guard to protect from null pointer dereference + if (other.guard_expr != NULL) { + guard_expr = other.guard_expr->clone_expr(); + } + + // DEBUG + fprintf( + stderr, "started copy-constructing match arm (outer attrs, guard expr done)\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + + // DEBUG + fprintf(stderr, "successfully pushed back a match arm pattern\n"); + } + + // DEBUG + fprintf(stderr, "successfully copy-constructed match arm\n"); + } + + ~MatchArm() = default; + + // Overload assignment operator to clone + MatchArm& operator=(MatchArm const& other) { + // match_arm_patterns = other.match_arm_patterns; + outer_attrs = other.outer_attrs; + guard_expr = other.guard_expr->clone_expr(); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arm_patterns.reserve(other.match_arm_patterns.size()); + + for (const auto& e : other.match_arm_patterns) { + match_arm_patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + MatchArm(MatchArm&& other) = default; + MatchArm& operator=(MatchArm&& other) = default; + + // Returns whether match arm is in an error state. + inline bool is_error() const { + return match_arm_patterns.empty(); + } + + // Creates a match arm in an error state. + static MatchArm create_error() { + return MatchArm(::std::vector< ::std::unique_ptr >()); + } + + ::std::string as_string() const; + }; + + // Base "match case" for a match expression - abstract + class MatchCase { + MatchArm arm; + + protected: + MatchCase(MatchArm arm) : arm(::std::move(arm)) {} + + // Should not require copy constructor or assignment operator overloading + + // Clone function implementation as pure virtual method + virtual MatchCase* clone_match_case_impl() const = 0; + + public: + virtual ~MatchCase() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_match_case() const { + // DEBUG + fprintf(stderr, "about to call clone match case impl\n"); + + return ::std::unique_ptr(clone_match_case_impl()); + } + + virtual ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) = 0; + }; + + // Block expression match case + class MatchCaseBlockExpr : public MatchCase { + // BlockExpr* block_expr; + ::std::unique_ptr block_expr; + + // TODO: should this store location data? + + public: + /*~MatchCaseBlockExpr() { + delete block_expr; + }*/ + + MatchCaseBlockExpr(MatchArm arm, ::std::unique_ptr block_expr) : + MatchCase(::std::move(arm)), block_expr(::std::move(block_expr)) {} + + // Copy constructor requires clone + MatchCaseBlockExpr(MatchCaseBlockExpr const& other) : + MatchCase(other), block_expr(other.block_expr->clone_block_expr()) { + // DEBUG + fprintf(stderr, "successfully copy constructed match case expr\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to have clone + MatchCaseBlockExpr& operator=(MatchCaseBlockExpr const& other) { + MatchCase::operator=(other); + block_expr = other.block_expr->clone_block_expr(); + // arm = other.arm; + + return *this; + } + + // move constructors + MatchCaseBlockExpr(MatchCaseBlockExpr&& other) = default; + MatchCaseBlockExpr& operator=(MatchCaseBlockExpr&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MatchCaseBlockExpr* clone_match_case_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "about to copy construct match case block expr\n"); + + return new MatchCaseBlockExpr(*this); + } + }; + + // Expression (except block expression) match case + class MatchCaseExpr : public MatchCase { + // Expr* expr; + ::std::unique_ptr expr; + + // TODO: should this store location data? + + public: + /*~MatchCaseExpr() { + delete expr; + }*/ + + MatchCaseExpr(MatchArm arm, ::std::unique_ptr expr) : + MatchCase(::std::move(arm)), expr(::std::move(expr)) {} + + // Copy constructor requires clone + MatchCaseExpr(MatchCaseExpr const& other) : + MatchCase(other), expr(other.expr->clone_expr()) { + // DEBUG + fprintf(stderr, "successfully copy constructed match case expr\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to have clone + MatchCaseExpr& operator=(MatchCaseExpr const& other) { + MatchCase::operator=(other); + expr = other.expr->clone_expr(); + // arm = other.arm; + + return *this; + } + + // move constructors + MatchCaseExpr(MatchCaseExpr&& other) = default; + MatchCaseExpr& operator=(MatchCaseExpr&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MatchCaseExpr* clone_match_case_impl() const OVERRIDE { + // DEBUG + fprintf(stderr, "about to copy construct match case expr\n"); + if (expr == NULL) { + fprintf( + stderr, "warning: match case expr to be copy constructed has null expr!\n"); + } + + return new MatchCaseExpr(*this); + } + }; + + // Match expression AST node + class MatchExpr : public ExprWithBlock { + // Expr* branch_value; + ::std::unique_ptr branch_value; + ::std::vector inner_attrs; + + // bool has_match_arms; + // MatchArms match_arms; + ::std::vector< ::std::unique_ptr > match_arms; // inlined from MatchArms + + location_t locus; + + public: + /*~MatchExpr() { + delete branch_value; + }*/ + + ::std::string as_string() const; + + // Returns whether the match expression has any match arms. + inline bool has_match_arms() const { + return !match_arms.empty(); + } + + MatchExpr(::std::unique_ptr branch_value, + ::std::vector< ::std::unique_ptr > match_arms, + ::std::vector inner_attrs, ::std::vector outer_attrs, + location_t locus) : + ExprWithBlock(::std::move(outer_attrs)), + branch_value(::std::move(branch_value)), inner_attrs(::std::move(inner_attrs)), + match_arms(::std::move(match_arms)), locus(locus) {} + + // Copy constructor requires clone due to unique_ptr + MatchExpr(MatchExpr const& other) : + ExprWithBlock(other), + branch_value(other.branch_value->clone_expr()), /*match_arms(other.match_arms),*/ + inner_attrs(other.inner_attrs), locus(other.locus) { + fprintf(stderr, "copy constructor for matchexpr called - only match arm vector " + "copying after this\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arms.reserve(other.match_arms.size()); + + fprintf(stderr, "match expr: successfully reserved size\n"); + + for (const auto& e : other.match_arms) { + match_arms.push_back(e->clone_match_case()); + fprintf(stderr, "match expr: successfully pushed back a match case\n"); + } + + fprintf(stderr, "match expr: successfully pushed back all match cases\n"); + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone due to unique_ptr + MatchExpr& operator=(MatchExpr const& other) { + ExprWithBlock::operator=(other); + branch_value = other.branch_value->clone_expr(); + // match_arms = other.match_arms; + inner_attrs = other.inner_attrs; + // outer_attrs = other.outer_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + match_arms.reserve(other.match_arms.size()); + + for (const auto& e : other.match_arms) { + match_arms.push_back(e->clone_match_case()); + } + + return *this; + } + + // move constructors + MatchExpr(MatchExpr&& other) = default; + MatchExpr& operator=(MatchExpr&& other) = default; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MatchExpr* clone_expr_impl() const OVERRIDE { + return new MatchExpr(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MatchExpr* clone_expr_with_block_impl() const OVERRIDE { + return new MatchExpr(*this); + } + }; + + // Await expression AST node (pseudo-member variable access) + class AwaitExpr : public ExprWithoutBlock { + ::std::unique_ptr awaited_expr; + + location_t locus; + + public: + // TODO: ensure outer attributes are actually allowed + AwaitExpr(::std::unique_ptr awaited_expr, ::std::vector outer_attrs, + location_t locus) : + ExprWithoutBlock(::std::move(outer_attrs)), + awaited_expr(::std::move(awaited_expr)), locus(locus) {} + + // copy constructor with clone + AwaitExpr(AwaitExpr const& other) : + ExprWithoutBlock(other), awaited_expr(other.awaited_expr->clone_expr()), + locus(other.locus) {} + + // destructor - define here if required + + // overloaded assignment operator with clone + AwaitExpr& operator=(AwaitExpr const& other) { + ExprWithoutBlock::operator=(other); + awaited_expr = other.awaited_expr->clone_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + AwaitExpr(AwaitExpr&& other) = default; + AwaitExpr& operator=(AwaitExpr&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual AwaitExpr* clone_expr_without_block_impl() const OVERRIDE { + return new AwaitExpr(*this); + } + }; + + // Async block expression AST node (block expr that evaluates to a future) + class AsyncBlockExpr : public ExprWithBlock { + // TODO: should this extend BlockExpr rather than be a composite of it? + bool has_move; + ::std::unique_ptr block_expr; + + location_t locus; + + public: + AsyncBlockExpr(::std::unique_ptr block_expr, bool has_move, + ::std::vector outer_attrs, location_t locus) : + ExprWithBlock(::std::move(outer_attrs)), + has_move(has_move), block_expr(::std::move(block_expr)), locus(locus) {} + + // copy constructor with clone + AsyncBlockExpr(AsyncBlockExpr const& other) : + ExprWithBlock(other), has_move(other.has_move), + block_expr(other.block_expr->clone_block_expr()), locus(other.locus) {} + + // destructor - define if required + + // overloaded assignment operator to clone + AsyncBlockExpr& operator=(AsyncBlockExpr const& other) { + ExprWithBlock::operator=(other); + has_move = other.has_move; + block_expr = other.block_expr->clone_block_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + AsyncBlockExpr(AsyncBlockExpr&& other) = default; + AsyncBlockExpr& operator=(AsyncBlockExpr&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual AsyncBlockExpr* clone_expr_with_block_impl() const OVERRIDE { + return new AsyncBlockExpr(*this); + } + }; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h new file mode 100644 index 0000000..c5154f5 --- /dev/null +++ b/gcc/rust/ast/rust-item.h @@ -0,0 +1,3385 @@ +#ifndef RUST_AST_ITEM_H +#define RUST_AST_ITEM_H + +#include "rust-ast.h" +#include "rust-path.h" + +namespace Rust { + namespace AST { + // forward decls + // struct Lifetime; + // struct LifetimeBounds; + // struct TypeParamBounds; + class BlockExpr; + // class Expr; + // class Type; + class TypePath; + // class Pattern; + class MacroInvocationSemi; + + // TODO: inline? + /*struct AbiName { + ::std::string abi_name; + // Technically is meant to be STRING_LITERAL or RAW_STRING_LITERAL + + public: + // Returns whether abi name is empty, i.e. doesn't exist. + inline bool is_empty() const { + return abi_name.empty(); + } + + AbiName(::std::string name) : abi_name(::std::move(name)) {} + + // Empty AbiName constructor + AbiName() {} + };*/ + + // A type generic parameter (as opposed to a lifetime generic parameter) + class TypeParam : public GenericParam { + // bool has_outer_attribute; + //::std::unique_ptr outer_attr; + Attribute outer_attr; + + Identifier type_representation; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + // bool has_type; + // Type type; + ::std::unique_ptr type; + + location_t locus; + + public: + // Returns whether the type of the type param has been specified. + inline bool has_type() const { + return type != NULL; + } + + // Returns whether the type param has type param bounds. + inline bool has_type_param_bounds() const { + return !type_param_bounds.empty(); + } + + // Returns whether the type param has an outer attribute. + inline bool has_outer_attribute() const { + return !outer_attr.is_empty(); + } + + TypeParam(Identifier type_representation, location_t locus = UNKNOWN_LOCATION, + ::std::vector< ::std::unique_ptr > type_param_bounds + = ::std::vector< ::std::unique_ptr >(), + ::std::unique_ptr type = NULL, Attribute outer_attr = Attribute::create_empty()) : + outer_attr(::std::move(outer_attr)), + type_representation(::std::move(type_representation)), + type_param_bounds(::std::move(type_param_bounds)), type(::std::move(type)), + locus(locus) {} + + // Copy constructor uses clone + TypeParam(TypeParam const& other) : + outer_attr(other.outer_attr), type_representation(other.type_representation), + /*type_param_bounds(other.type_param_bounds),*/ type(other.type->clone_type()), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + TypeParam& operator=(TypeParam const& other) { + type_representation = other.type_representation; + // type_param_bounds = other.type_param_bounds; + type = other.type->clone_type(); + outer_attr = other.outer_attr; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + return *this; + } + + // move constructors + TypeParam(TypeParam&& other) = default; + TypeParam& operator=(TypeParam&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TypeParam* clone_generic_param_impl() const { + return new TypeParam(*this); + } + }; + + // "where" clause item base. Abstract - use LifetimeWhereClauseItem, TypeBoundWhereClauseItem + class WhereClauseItem { + public: + virtual ~WhereClauseItem() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_where_clause_item() const { + return ::std::unique_ptr(clone_where_clause_item_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual WhereClauseItem* clone_where_clause_item_impl() const = 0; + }; + + // A lifetime where clause item + class LifetimeWhereClauseItem : public WhereClauseItem { + Lifetime lifetime; + + // LifetimeBounds lifetime_bounds; + ::std::vector lifetime_bounds; // inlined lifetime bounds + + // should this store location info? + + public: + LifetimeWhereClauseItem(Lifetime lifetime, ::std::vector lifetime_bounds) : + lifetime(::std::move(lifetime)), lifetime_bounds(::std::move(lifetime_bounds)) {} + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual LifetimeWhereClauseItem* clone_where_clause_item_impl() const { + return new LifetimeWhereClauseItem(*this); + } + }; + + // A type bound where clause item + class TypeBoundWhereClauseItem : public WhereClauseItem { + // bool has_for_lifetimes; + // LifetimeParams for_lifetimes; + ::std::vector for_lifetimes; // inlined + + // Type bound_type; + ::std::unique_ptr bound_type; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + // should this store location info? + + public: + // Returns whether the item has ForLifetimes + inline bool has_for_lifetimes() const { + return !for_lifetimes.empty(); + } + + // Returns whether the item has type param bounds + inline bool has_type_param_bounds() const { + return !type_param_bounds.empty(); + } + + TypeBoundWhereClauseItem(::std::vector for_lifetimes, + ::std::unique_ptr bound_type, + ::std::vector< ::std::unique_ptr > type_param_bounds) : + for_lifetimes(::std::move(for_lifetimes)), + bound_type(::std::move(bound_type)), type_param_bounds(::std::move(type_param_bounds)) { + } + + // Copy constructor requires clone + TypeBoundWhereClauseItem(TypeBoundWhereClauseItem const& other) : + for_lifetimes(other.for_lifetimes), bound_type(other.bound_type->clone_type()) /*, + type_param_bounds(other.type_param_bounds)*/ + { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone + TypeBoundWhereClauseItem& operator=(TypeBoundWhereClauseItem const& other) { + for_lifetimes = other.for_lifetimes; + bound_type = other.bound_type->clone_type(); + // type_param_bounds = other.type_param_bounds; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + return *this; + } + + // move constructors + TypeBoundWhereClauseItem(TypeBoundWhereClauseItem&& other) = default; + TypeBoundWhereClauseItem& operator=(TypeBoundWhereClauseItem&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TypeBoundWhereClauseItem* clone_where_clause_item_impl() const { + return new TypeBoundWhereClauseItem(*this); + } + }; + + // A where clause + struct WhereClause { + private: + //::std::vector where_clause_items; + ::std::vector< ::std::unique_ptr > where_clause_items; + + // should this store location info? + + public: + WhereClause(::std::vector< ::std::unique_ptr > where_clause_items) : + where_clause_items(::std::move(where_clause_items)) {} + + // copy constructor with vector clone + WhereClause(WhereClause const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + where_clause_items.reserve(other.where_clause_items.size()); + + for (const auto& e : other.where_clause_items) { + where_clause_items.push_back(e->clone_where_clause_item()); + } + } + + // overloaded assignment operator with vector clone + WhereClause& operator=(WhereClause const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + where_clause_items.reserve(other.where_clause_items.size()); + + for (const auto& e : other.where_clause_items) { + where_clause_items.push_back(e->clone_where_clause_item()); + } + + return *this; + } + + // move constructors + WhereClause(WhereClause&& other) = default; + WhereClause& operator=(WhereClause&& other) = default; + + // Creates a WhereClause with no items. + static WhereClause create_empty() { + return WhereClause(::std::vector< ::std::unique_ptr >()); + } + + // Returns whether the WhereClause has no items. + inline bool is_empty() const { + return where_clause_items.empty(); + } + + ::std::string as_string() const; + }; + + // A self parameter in a method + struct SelfParam { + private: + bool has_ref; + bool is_mut; + // bool has_lifetime; // only possible if also ref + Lifetime lifetime; + + // bool has_type; // only possible if not ref + // Type type; + ::std::unique_ptr type; + + location_t locus; + + // Unrestricted constructor used for error state + SelfParam(Lifetime lifetime, bool has_ref, bool is_mut, Type* type) : + has_ref(has_ref), is_mut(is_mut), lifetime(::std::move(lifetime)), type(type) {} + // this is ok as no outside classes can ever call this + + public: + // Returns whether the self-param has a type field. + inline bool has_type() const { + return type != NULL; + } + + // Returns whether the self-param has a valid lifetime. + inline bool has_lifetime() const { + return !lifetime.is_error(); + } + + // Returns whether the self-param is in an error state. + inline bool is_error() const { + return has_type() && has_lifetime(); + // not having either is not an error + } + + // Creates an error state self-param. + static SelfParam create_error() { + /* HACK: creates a dummy type. Since it's a unique pointer, it should clean it up, but + * it still allocates memory, which is not ideal. */ + return SelfParam(Lifetime(Lifetime::STATIC), false, false, + new QualifiedPathInType(QualifiedPathInType::create_error())); + } + + // Type-based self parameter (not ref, no lifetime) + SelfParam(::std::unique_ptr type, bool is_mut, location_t locus) : + has_ref(false), is_mut(is_mut), lifetime(Lifetime::error()), type(::std::move(type)), + locus(locus) {} + + // Lifetime-based self parameter (is ref, no type) + SelfParam(Lifetime lifetime, bool is_mut, location_t locus) : + /*type(NULL), */ has_ref(true), is_mut(is_mut), lifetime(::std::move(lifetime)), + locus(locus) {} + + // Copy constructor requires clone + SelfParam(SelfParam const& other) : + has_ref(other.has_ref), is_mut(other.is_mut), lifetime(other.lifetime), + type(other.type->clone_type()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to use clone + SelfParam& operator=(SelfParam const& other) { + type = other.type->clone_type(); + is_mut = other.is_mut; + has_ref = other.has_ref; + lifetime = other.lifetime; + locus = other.locus; + + return *this; + } + + // move constructors + SelfParam(SelfParam&& other) = default; + SelfParam& operator=(SelfParam&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + }; + + // Qualifiers for function, i.e. const, unsafe, extern etc. + struct FunctionQualifiers { + public: + // Whether the function is neither const nor async, const only, or async only. + enum AsyncConstStatus { NONE, CONST, ASYNC }; + + private: + AsyncConstStatus const_status; + bool has_unsafe; + bool has_extern; + ::std::string extern_abi; // e.g. extern "C" fn() -> i32 {} + // TODO: maybe ensure that extern_abi only exists if extern exists? + + // should this store location info? + + public: + // Constructor with no extern (and hence no extern abi) + FunctionQualifiers(AsyncConstStatus const_status, bool has_unsafe) : + const_status(const_status), has_unsafe(has_unsafe), has_extern(false), + extern_abi(::std::string("")) {} + + // Constructor with extern abi (and thus extern) + FunctionQualifiers( + AsyncConstStatus const_status, bool has_unsafe, ::std::string extern_abi) : + const_status(const_status), + has_unsafe(has_unsafe), has_extern(true), extern_abi(::std::move(extern_abi)) {} + + // Constructor with all possible options (DON'T HAVE EXTERN_ABI WITHOUT EXTERN!) + FunctionQualifiers(AsyncConstStatus const_status, bool has_unsafe, bool has_extern, + ::std::string extern_abi) : + const_status(const_status), + has_unsafe(has_unsafe), has_extern(has_extern), extern_abi(::std::move(extern_abi)) {} + + ::std::string as_string() const; + }; + + // Forward decl FunctionParams + // struct FunctionParams; + + // A function parameter + struct FunctionParam { + private: + // Pattern* param_name; + ::std::unique_ptr param_name; + // Type type; + ::std::unique_ptr type; + + location_t locus; + + public: + FunctionParam(::std::unique_ptr param_name, ::std::unique_ptr param_type, + location_t locus) : + param_name(::std::move(param_name)), + type(::std::move(param_type)), locus(locus) {} + + // Copy constructor uses clone + FunctionParam(FunctionParam const& other) : + param_name(other.param_name->clone_pattern()), type(other.type->clone_type()), + locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to use clone + FunctionParam& operator=(FunctionParam const& other) { + param_name = other.param_name->clone_pattern(); + type = other.type->clone_type(); + locus = other.locus; + + return *this; + } + + // move constructors + FunctionParam(FunctionParam&& other) = default; + FunctionParam& operator=(FunctionParam&& other) = default; + + // Returns whether FunctionParam is in an invalid state. + inline bool is_error() const { + return param_name == NULL || type == NULL; + } + + // Creates an error FunctionParam. + static FunctionParam create_error() { + return FunctionParam(NULL, NULL, UNKNOWN_LOCATION); + } + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + }; + + // Visibility of item - if the item has it, then it is some form of public + struct Visibility { + public: + enum PublicVisType { NONE, CRATE, SELF, SUPER, IN_PATH }; + + private: + // bool is_pub; + + // if vis is public, one of these + PublicVisType public_vis_type; + + // Only assigned if public_vis_type is IN_PATH + SimplePath in_path; + + // should this store location info? + + public: + // Creates a Visibility - TODO make constructor protected or private? + Visibility(PublicVisType public_vis_type, SimplePath in_path) : + public_vis_type(public_vis_type), in_path(::std::move(in_path)) { + if (public_vis_type != IN_PATH && !in_path.is_empty()) { + // error - invalid state + + // just ignore path if vis type is not that + } + } + + // Returns whether visibility is in an error state. + inline bool is_error() const { + return public_vis_type == IN_PATH && in_path.is_empty(); + } + + // Creates an error visibility. + static Visibility create_error() { + return Visibility(IN_PATH, SimplePath::create_empty()); + } + + // Unique pointer custom clone function + /*::std::unique_ptr clone_visibility() const { + return ::std::unique_ptr(clone_visibility_impl()); + }*/ + + /* TODO: think of a way to only allow valid Visibility states - polymorphism is one + * idea but may be too resource-intensive. */ + + // Creates a public visibility with no further features/arguments. + static Visibility create_public() { + return Visibility(NONE, SimplePath::create_empty()); + } + + // Creates a public visibility with crate-relative paths or whatever. + static Visibility create_crate() { + return Visibility(CRATE, SimplePath::create_empty()); + } + + // Creates a public visibility with self-relative paths or whatever. + static Visibility create_self() { + return Visibility(SELF, SimplePath::create_empty()); + } + + // Creates a public visibility with parent module-relative paths or whatever. + static Visibility create_super() { + return Visibility(SUPER, SimplePath::create_empty()); + } + + // Creates a public visibility with a given path or whatever. + static Visibility create_in_path(SimplePath in_path) { + return Visibility(IN_PATH, ::std::move(in_path)); + } + + ::std::string as_string() const; + + protected: + // Clone function implementation - not currently virtual but may be if polymorphism used + /*virtual*/ Visibility* clone_visibility_impl() const { + return new Visibility(*this); + } + }; + + // A method (function belonging to a type) + class Method + : public InherentImplItem + , public TraitImplItem { + // moved from impl items for consistency + ::std::vector outer_attrs; + Visibility vis; + + FunctionQualifiers qualifiers; + Identifier method_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + ::std::vector function_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + ::std::unique_ptr return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + // BlockExpr* expr; + ::std::unique_ptr expr; + + location_t locus; + + public: + /*~Method() { + delete expr; + }*/ + + // Returns whether the method is in an error state. + inline bool is_error() const { + return expr == NULL || method_name.empty() || self_param.is_error(); + } + + // Creates an error state method. + static Method create_error() { + return Method("", FunctionQualifiers(FunctionQualifiers::NONE, true), + ::std::vector< ::std::unique_ptr >(), SelfParam::create_error(), + ::std::vector(), NULL, WhereClause::create_empty(), NULL, + Visibility::create_error(), ::std::vector()); + } + + // Returns whether the method has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether the method has parameters. + inline bool has_params() const { + return !function_params.empty(); + } + + // Returns whether the method has a return type (void otherwise). + inline bool has_return_type() const { + return return_type != NULL; + } + + // Returns whether the where clause exists (i.e. has items) + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Returns whether method has a non-default visibility. + inline bool has_visibility() const { + return !vis.is_error(); + } + + // Mega-constructor with all possible fields + Method(Identifier method_name, FunctionQualifiers qualifiers, + ::std::vector< ::std::unique_ptr > generic_params, SelfParam self_param, + ::std::vector function_params, ::std::unique_ptr return_type, + WhereClause where_clause, ::std::unique_ptr function_body, Visibility vis, + ::std::vector outer_attrs, location_t locus = UNKNOWN_LOCATION) : + outer_attrs(::std::move(outer_attrs)), + vis(::std::move(vis)), qualifiers(::std::move(qualifiers)), + method_name(::std::move(method_name)), generic_params(::std::move(generic_params)), + self_param(::std::move(self_param)), function_params(::std::move(function_params)), + return_type(::std::move(return_type)), where_clause(::std::move(where_clause)), + expr(::std::move(function_body)), locus(locus) {} + + // TODO: add constructor with less fields + + // Copy constructor with clone + Method(Method const& other) : + outer_attrs(other.outer_attrs), vis(other.vis), qualifiers(other.qualifiers), + method_name(other.method_name), + /*generic_params(other.generic_params),*/ self_param(other.self_param), + function_params(other.function_params), return_type(other.return_type->clone_type()), + where_clause(other.where_clause), expr(other.expr->clone_block_expr()), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + //~Method() = default; + + // Overloaded assignment operator to clone + Method& operator=(Method const& other) { + method_name = other.method_name; + outer_attrs = other.outer_attrs; + vis = other.vis; + qualifiers = other.qualifiers; + // generic_params = other.generic_params; + self_param = other.self_param; + function_params = other.function_params; + return_type = other.return_type->clone_type(); + where_clause = other.where_clause; + expr = other.expr->clone_block_expr(); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + Method(Method&& other) = default; + Method& operator=(Method&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Method* clone_inherent_impl_item_impl() const OVERRIDE { + return new Method(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual Method* clone_trait_impl_item_impl() const OVERRIDE { + return new Method(*this); + } + }; + + // Item that supports visibility - abstract base class + class VisItem : public Item { + Visibility visibility; + + protected: + // Visibility constructor + VisItem(Visibility visibility, + ::std::vector outer_attrs = ::std::vector()) : + Item(::std::move(outer_attrs)), + visibility(::std::move(visibility)) {} + + // Visibility copy constructor + VisItem(VisItem const& other) : Item(other), visibility(other.visibility) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + VisItem& operator=(VisItem const& other) { + Item::operator=(other); + visibility = other.visibility; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + VisItem(VisItem&& other) = default; + VisItem& operator=(VisItem&& other) = default; + + public: + // Does the item have some kind of public visibility (non-default visibility)? + inline bool has_visibility() const { + return !visibility.is_error(); + } + + virtual ::std::string as_string() const; + }; + + // Rust module item - abstract base class + class Module : public VisItem { + Identifier module_name; + + location_t locus; + + protected: + // Protected constructor + Module(Identifier module_name, Visibility visibility, location_t locus, + ::std::vector outer_attrs = ::std::vector()) : + VisItem(::std::move(visibility), ::std::move(outer_attrs)), + module_name(module_name), locus(locus) {} + + public: + virtual ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + }; + + // Module with a body, defined in file + class ModuleBodied : public Module { + // bool has_inner_attrs; + ::std::vector inner_attrs; + // bool has_items; + //::std::vector items; + ::std::vector< ::std::unique_ptr > items; + + public: + virtual ::std::string as_string() const; + + // Returns whether the module has items in its body. + inline bool has_items() const { + return !items.empty(); + } + + // Returns whether the module has any inner attributes. + inline bool has_inner_attrs() const { + return !inner_attrs.empty(); + } + + // Full constructor + ModuleBodied(Identifier name, location_t locus, + ::std::vector< ::std::unique_ptr > items + = ::std::vector< ::std::unique_ptr >(), + Visibility visibility = Visibility::create_error(), + ::std::vector inner_attrs = ::std::vector(), + ::std::vector outer_attrs = ::std::vector()) : + Module(::std::move(name), ::std::move(visibility), locus, ::std::move(outer_attrs)), + inner_attrs(::std::move(inner_attrs)), items(::std::move(items)) {} + + // Copy constructor with vector clone + ModuleBodied(ModuleBodied const& other) : Module(other), inner_attrs(other.inner_attrs) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_item()); + } + } + + // Overloaded assignment operator with vector clone + ModuleBodied& operator=(ModuleBodied const& other) { + Module::operator=(other); + inner_attrs = other.inner_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_item()); + } + + return *this; + } + + // move constructors + ModuleBodied(ModuleBodied&& other) = default; + ModuleBodied& operator=(ModuleBodied&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // Override that runs the function recursively on all items contained within the module. + virtual void add_crate_name(::std::vector< ::std::string>& names) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ModuleBodied* clone_item_impl() const OVERRIDE { + return new ModuleBodied(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual ModuleBodied* clone_statement_impl() const OVERRIDE { + return new ModuleBodied(*this); + }*/ + }; + + // Module without a body, loaded from external file + class ModuleNoBody : public Module { + public: + ::std::string as_string() const; + + // Full constructor + ModuleNoBody(Identifier name, Visibility visibility, ::std::vector outer_attrs, + location_t locus) : + Module(::std::move(name), ::std::move(visibility), locus, ::std::move(outer_attrs)) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ModuleNoBody* clone_item_impl() const OVERRIDE { + return new ModuleNoBody(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual ModuleNoBody* clone_statement_impl() const OVERRIDE { + return new ModuleNoBody(*this); + }*/ + }; + + // Rust extern crate declaration AST node + class ExternCrate : public VisItem { + // this is either an identifier or "self", with self parsed to string + ::std::string referenced_crate; + // bool has_as_clause; + // AsClause as_clause; + // this is either an identifier or "_", with _ parsed to string + ::std::string as_clause_name; + + location_t locus; + + /* e.g. + "extern crate foo as _" + "extern crate foo" + "extern crate std as cool_std" */ + public: + ::std::string as_string() const; + + // Returns whether extern crate declaration has an as clause. + inline bool has_as_clause() const { + return !as_clause_name.empty(); + } + + // Returns whether extern crate declaration references the current crate (i.e. self). + inline bool references_self() const { + return referenced_crate == "self"; + } + + // Constructor + ExternCrate(::std::string referenced_crate, Visibility visibility, + ::std::vector outer_attrs, location_t locus, + ::std::string as_clause_name = ::std::string()) : + VisItem(::std::move(visibility), ::std::move(outer_attrs)), + referenced_crate(::std::move(referenced_crate)), + as_clause_name(::std::move(as_clause_name)), locus(locus) {} + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // Override that adds extern crate name in decl to passed list of names. + virtual void add_crate_name(::std::vector< ::std::string>& names) const OVERRIDE { + names.push_back(referenced_crate); + } + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExternCrate* clone_item_impl() const OVERRIDE { + return new ExternCrate(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual ExternCrate* clone_statement_impl() const OVERRIDE { + return new ExternCrate(*this); + }*/ + }; + + // The path-ish thing referred to in a use declaration - abstract base class + class UseTree { + location_t locus; + + public: + virtual ~UseTree() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_use_tree() const { + return ::std::unique_ptr(clone_use_tree_impl()); + } + + virtual ::std::string as_string() const = 0; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // Clone function implementation as pure virtual method + virtual UseTree* clone_use_tree_impl() const = 0; + + UseTree(location_t locus) : locus(locus) {} + }; + + // Use tree with a glob (wildcard) operator + class UseTreeGlob : public UseTree { + public: + enum PathType { NO_PATH, GLOBAL, PATH_PREFIXED }; + + private: + PathType glob_type; + SimplePath path; + + public: + UseTreeGlob(PathType glob_type, SimplePath path, location_t locus) : + UseTree(locus), glob_type(glob_type), path(::std::move(path)) {} + + // Returns whether has path. Should be made redundant by PathType PATH_PREFIXED. + inline bool has_path() const { + return !path.is_empty(); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory methods? + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual UseTreeGlob* clone_use_tree_impl() const OVERRIDE { + return new UseTreeGlob(*this); + } + }; + + // Use tree with a list of paths with a common prefix + class UseTreeList : public UseTree { + public: + enum PathType { NO_PATH, GLOBAL, PATH_PREFIXED }; + + private: + PathType path_type; + SimplePath path; + + ::std::vector< ::std::unique_ptr > trees; + + public: + UseTreeList(PathType path_type, SimplePath path, + ::std::vector< ::std::unique_ptr > trees, location_t locus) : + UseTree(locus), + path_type(path_type), path(::std::move(path)), trees(::std::move(trees)) {} + + // copy constructor with vector clone + UseTreeList(UseTreeList const& other) : + UseTree(other), path_type(other.path_type), path(other.path) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + trees.reserve(other.trees.size()); + + for (const auto& e : other.trees) { + trees.push_back(e->clone_use_tree()); + } + } + + // overloaded assignment operator with vector clone + UseTreeList& operator=(UseTreeList const& other) { + UseTree::operator=(other); + path_type = other.path_type; + path = other.path; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + trees.reserve(other.trees.size()); + + for (const auto& e : other.trees) { + trees.push_back(e->clone_use_tree()); + } + + return *this; + } + + // move constructors + UseTreeList(UseTreeList&& other) = default; + UseTreeList& operator=(UseTreeList&& other) = default; + + // Returns whether has path. Should be made redundant by path_type. + inline bool has_path() const { + return !path.is_empty(); + } + + // Returns whether has inner tree elements. + inline bool has_trees() const { + return !trees.empty(); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory methods? + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual UseTreeList* clone_use_tree_impl() const OVERRIDE { + return new UseTreeList(*this); + } + }; + + // Use tree where it rebinds the module name as something else + class UseTreeRebind : public UseTree { + public: + enum NewBindType { NONE, IDENTIFIER, WILDCARD }; + + private: + SimplePath path; + + NewBindType bind_type; + Identifier identifier; // only if NewBindType is IDENTIFIER + + public: + UseTreeRebind(NewBindType bind_type, SimplePath path, location_t locus, + Identifier identifier = ::std::string()) : + UseTree(locus), + path(::std::move(path)), bind_type(bind_type), identifier(::std::move(identifier)) {} + + // Returns whether has path (this should always be true). + inline bool has_path() const { + return !path.is_empty(); + } + + // Returns whether has identifier (or, rather, is allowed to). + inline bool has_identifier() const { + return bind_type == IDENTIFIER; + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory methods? + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual UseTreeRebind* clone_use_tree_impl() const OVERRIDE { + return new UseTreeRebind(*this); + } + }; + + // Rust use declaration (i.e. for modules) AST node + class UseDeclaration : public VisItem { + ::std::unique_ptr use_tree; + + location_t locus; + + public: + ::std::string as_string() const; + + UseDeclaration(::std::unique_ptr use_tree, Visibility visibility, + ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(visibility), ::std::move(outer_attrs)), + use_tree(::std::move(use_tree)), locus(locus) {} + + // Copy constructor with clone + UseDeclaration(UseDeclaration const& other) : + VisItem(other), use_tree(other.use_tree->clone_use_tree()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + UseDeclaration& operator=(UseDeclaration const& other) { + VisItem::operator=(other); + use_tree = other.use_tree->clone_use_tree(); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + UseDeclaration(UseDeclaration&& other) = default; + UseDeclaration& operator=(UseDeclaration&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual UseDeclaration* clone_item_impl() const OVERRIDE { + return new UseDeclaration(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual UseDeclaration* clone_statement_impl() const OVERRIDE { + return new UseDeclaration(*this); + }*/ + }; + + // Parameters used in a function - TODO inline? + /*struct FunctionParams { + ::std::vector function_params; + };*/ + + // Rust function declaration AST node + class Function + : public VisItem + , public InherentImplItem + , public TraitImplItem { + FunctionQualifiers qualifiers; + + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_function_params; + // FunctionParams function_params; + ::std::vector function_params; // inlined + + // bool has_function_return_type; + // Type return_type; + ::std::unique_ptr return_type; + + // bool has_where_clause; + WhereClause where_clause; + + // BlockExpr* function_body; + ::std::unique_ptr function_body; + + location_t locus; + + public: + /*~Function() { + delete function_body; + }*/ + ::std::string as_string() const; + + // Returns whether function has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether function has regular parameters. + inline bool has_function_params() const { + return !function_params.empty(); + } + + // Returns whether function has return type - if not, it is void. + inline bool has_function_return_type() const { + return return_type != NULL; + } + + // Returns whether function has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Mega-constructor with all possible fields + Function(Identifier function_name, FunctionQualifiers qualifiers, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::vector function_params, ::std::unique_ptr return_type, + WhereClause where_clause, ::std::unique_ptr function_body, Visibility vis, + ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + qualifiers(::std::move(qualifiers)), function_name(::std::move(function_name)), + generic_params(::std::move(generic_params)), + function_params(::std::move(function_params)), return_type(::std::move(return_type)), + where_clause(::std::move(where_clause)), function_body(::std::move(function_body)), + locus(locus) {} + + // TODO: add constructor with less fields + + // Copy constructor with clone + Function(Function const& other) : + VisItem(other), qualifiers(other.qualifiers), function_name(other.function_name), + /*generic_params(other.generic_params),*/ function_params(other.function_params), + return_type(other.return_type->clone_type()), where_clause(other.where_clause), + function_body(other.function_body->clone_block_expr()), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + Function& operator=(Function const& other) { + VisItem::operator=(other); + function_name = other.function_name; + qualifiers = other.qualifiers; + // generic_params = other.generic_params; + function_params = other.function_params; + return_type = other.return_type->clone_type(); + where_clause = other.where_clause; + function_body = other.function_body->clone_block_expr(); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + Function(Function&& other) = default; + Function& operator=(Function&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Function* clone_item_impl() const OVERRIDE { + return new Function(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual Function* clone_inherent_impl_item_impl() const OVERRIDE { + return new Function(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual Function* clone_trait_impl_item_impl() const OVERRIDE { + return new Function(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual Function* clone_statement_impl() const OVERRIDE { + return new Function(*this); + }*/ + }; + + // Rust type alias (i.e. typedef) AST node + class TypeAlias + : public VisItem + , public TraitImplItem { + Identifier new_type_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + // Type exiting_type; + ::std::unique_ptr existing_type; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether type alias has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether type alias has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Mega-constructor with all possible fields + TypeAlias(Identifier new_type_name, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, ::std::unique_ptr existing_type, Visibility vis, + ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + new_type_name(::std::move(new_type_name)), generic_params(::std::move(generic_params)), + where_clause(::std::move(where_clause)), existing_type(::std::move(existing_type)), + locus(locus) {} + + // Copy constructor + TypeAlias(TypeAlias const& other) : + VisItem(other), + new_type_name(other.new_type_name), /*generic_params(other.generic_params),*/ + where_clause(other.where_clause), existing_type(other.existing_type->clone_type()), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + TypeAlias& operator=(TypeAlias const& other) { + VisItem::operator=(other); + new_type_name = other.new_type_name; + // generic_params = other.generic_params; + where_clause = other.where_clause; + existing_type = other.existing_type->clone_type(); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + TypeAlias(TypeAlias&& other) = default; + TypeAlias& operator=(TypeAlias&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TypeAlias* clone_item_impl() const OVERRIDE { + return new TypeAlias(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TypeAlias* clone_trait_impl_item_impl() const OVERRIDE { + return new TypeAlias(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual TypeAlias* clone_statement_impl() const OVERRIDE { + return new TypeAlias(*this); + }*/ + }; + + // Rust base struct declaration AST node - abstract base class + class Struct : public VisItem { + protected: + // protected to enable access by derived classes - allows better as_string + Identifier struct_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + location_t locus; + + public: + // Returns whether struct has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether struct has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + location_t get_locus() const { + return locus; + } + + protected: + Struct(Identifier struct_name, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, Visibility vis, location_t locus, + ::std::vector outer_attrs = ::std::vector()) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + struct_name(::std::move(struct_name)), generic_params(::std::move(generic_params)), + where_clause(::std::move(where_clause)), locus(locus) {} + + // Copy constructor with vector clone + Struct(Struct const& other) : + VisItem(other), struct_name(other.struct_name), where_clause(other.where_clause), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // Overloaded assignment operator with vector clone + Struct& operator=(Struct const& other) { + VisItem::operator=(other); + struct_name = other.struct_name; + where_clause = other.where_clause; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + Struct(Struct&& other) = default; + Struct& operator=(Struct&& other) = default; + }; + + // A single field in a struct + struct StructField { + private: + // bool has_outer_attributes; + ::std::vector outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier field_name; + // Type field_type; + ::std::unique_ptr field_type; + + // should this store location info? + + public: + // Returns whether struct field has any outer attributes. + inline bool has_outer_attributes() const { + return !outer_attrs.empty(); + } + + // Returns whether struct field has a non-private (non-default) visibility. + inline bool has_visibility() const { + return !visibility.is_error(); + } + + StructField(Identifier field_name, ::std::unique_ptr field_type, Visibility vis, + ::std::vector outer_attrs = ::std::vector()) : + outer_attrs(::std::move(outer_attrs)), + visibility(::std::move(vis)), field_name(::std::move(field_name)), + field_type(::std::move(field_type)) {} + + // Copy constructor + StructField(StructField const& other) : + outer_attrs(other.outer_attrs), visibility(other.visibility), + field_name(other.field_name), field_type(other.field_type->clone_type()) {} + + ~StructField() = default; + + // Overloaded assignment operator to clone + StructField& operator=(StructField const& other) { + field_name = other.field_name; + field_type = other.field_type->clone_type(); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + StructField(StructField&& other) = default; + StructField& operator=(StructField&& other) = default; + + // Returns whether struct field is in an error state. + inline bool is_error() const { + return field_name.empty() && field_type == NULL; + // this should really be an or since neither are allowed + } + + // Creates an error state struct field. + static StructField create_error() { + return StructField(::std::string(""), NULL, Visibility::create_error()); + } + + ::std::string as_string() const; + }; + + // Rust struct declaration with true struct type AST node + class StructStruct : public Struct { + ::std::vector fields; + bool is_unit; + + public: + ::std::string as_string() const; + + // Mega-constructor with all possible fields + StructStruct(::std::vector fields, Identifier struct_name, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, bool is_unit, Visibility vis, + ::std::vector outer_attrs, location_t locus) : + Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), + ::std::move(vis), locus, ::std::move(outer_attrs)), + fields(::std::move(fields)), is_unit(is_unit) {} + + // Unit struct constructor + StructStruct(Identifier struct_name, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, Visibility vis, ::std::vector outer_attrs, + location_t locus) : + Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), + ::std::move(vis), locus, ::std::move(outer_attrs)), + is_unit(true) {} + // TODO: can a unit struct have generic fields? assuming yes for now. + + /* Returns whether the struct is a unit struct - struct defined without fields. This is + * important because it also means an implicit constant of its type is defined. */ + inline bool is_unit_struct() const { + return is_unit; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructStruct* clone_item_impl() const OVERRIDE { + return new StructStruct(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual StructStruct* clone_statement_impl() const OVERRIDE { + return new StructStruct(*this); + }*/ + }; + + // A single field in a tuple + struct TupleField { + private: + // bool has_outer_attributes; + ::std::vector outer_attrs; + + // bool has_visibility; + Visibility visibility; + + // Type field_type; + ::std::unique_ptr field_type; + + // should this store location info? + + public: + // Returns whether tuple field has outer attributes. + inline bool has_outer_attributes() const { + return !outer_attrs.empty(); + } + + // Returns whether tuple field has a non-default visibility (i.e. a public one) + inline bool has_visibility() const { + return !visibility.is_error(); + } + + // Complete constructor + TupleField(::std::unique_ptr field_type, Visibility vis, + ::std::vector outer_attrs = ::std::vector()) : + outer_attrs(::std::move(outer_attrs)), + visibility(::std::move(vis)), field_type(::std::move(field_type)) {} + + // Copy constructor with clone + TupleField(TupleField const& other) : + outer_attrs(other.outer_attrs), visibility(other.visibility), + field_type(other.field_type->clone_type()) {} + + ~TupleField() = default; + + // Overloaded assignment operator to clone + TupleField& operator=(TupleField const& other) { + field_type = other.field_type->clone_type(); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + TupleField(TupleField&& other) = default; + TupleField& operator=(TupleField&& other) = default; + + // Returns whether tuple field is in an error state. + inline bool is_error() const { + return field_type == NULL; + } + + // Creates an error state tuple field. + static TupleField create_error() { + return TupleField(NULL, Visibility::create_error()); + } + + ::std::string as_string() const; + }; + + // Rust tuple declared using struct keyword AST node + class TupleStruct : public Struct { + ::std::vector fields; + + public: + ::std::string as_string() const; + + // Mega-constructor with all possible fields + TupleStruct(::std::vector fields, Identifier struct_name, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, Visibility vis, ::std::vector outer_attrs, + location_t locus) : + Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), + ::std::move(vis), locus, ::std::move(outer_attrs)), + fields(::std::move(fields)) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleStruct* clone_item_impl() const OVERRIDE { + return new TupleStruct(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual TupleStruct* clone_statement_impl() const OVERRIDE { + return new TupleStruct(*this); + }*/ + }; + + // An item used in an "enum" tagged union - not abstract: base represents a name-only enum + class EnumItem { + // bool has_attrs; + ::std::vector outer_attrs; + + Identifier variant_name; + + location_t locus; + + public: + virtual ~EnumItem() {} + + // Returns whether enum item has outer attributes. + inline bool has_outer_attrs() const { + return !outer_attrs.empty(); + } + + EnumItem( + Identifier variant_name, ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + variant_name(::std::move(variant_name)), locus(locus) {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_enum_item() const { + return ::std::unique_ptr(clone_enum_item_impl()); + } + + virtual ::std::string as_string() const; + + // not pure virtual as not abstract + virtual void accept_vis(ASTVisitor& vis); + + protected: + // Clone function implementation as (not pure) virtual method + virtual EnumItem* clone_enum_item_impl() const { + return new EnumItem(*this); + } + }; + + // A tuple item used in an "enum" tagged union + class EnumItemTuple : public EnumItem { + // bool has_tuple_fields; + ::std::vector tuple_fields; + + public: + // Returns whether tuple enum item has tuple fields. + inline bool has_tuple_fields() const { + return !tuple_fields.empty(); + } + + EnumItemTuple(Identifier variant_name, ::std::vector tuple_fields, + ::std::vector outer_attrs, location_t locus) : + EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), + tuple_fields(::std::move(tuple_fields)) {} + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual EnumItemTuple* clone_enum_item_impl() const { + return new EnumItemTuple(*this); + } + }; + + // A struct item used in an "enum" tagged union + class EnumItemStruct : public EnumItem { + // bool has_struct_fields; + ::std::vector struct_fields; + + public: + // Returns whether struct enum item has struct fields. + inline bool has_struct_fields() const { + return !struct_fields.empty(); + } + + EnumItemStruct(Identifier variant_name, ::std::vector struct_fields, + ::std::vector outer_attrs, location_t locus) : + EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), + struct_fields(::std::move(struct_fields)) {} + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual EnumItemStruct* clone_enum_item_impl() const { + return new EnumItemStruct(*this); + } + }; + + // A discriminant (numbered enum) item used in an "enum" tagged union + class EnumItemDiscriminant : public EnumItem { + // Expr* expression; + ::std::unique_ptr expression; + + public: + /*~EnumItemDiscriminant() { + delete expression; + }*/ + + EnumItemDiscriminant(Identifier variant_name, ::std::unique_ptr expr, + ::std::vector outer_attrs, location_t locus) : + EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), + expression(::std::move(expr)) {} + + // Copy constructor with clone + EnumItemDiscriminant(EnumItemDiscriminant const& other) : + EnumItem(other), expression(other.expression->clone_expr()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + EnumItemDiscriminant& operator=(EnumItemDiscriminant const& other) { + EnumItem::operator=(other); + expression = other.expression->clone_expr(); + // variant_name = other.variant_name; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + EnumItemDiscriminant(EnumItemDiscriminant&& other) = default; + EnumItemDiscriminant& operator=(EnumItemDiscriminant&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual EnumItemDiscriminant* clone_enum_item_impl() const { + return new EnumItemDiscriminant(*this); + } + }; + + // AST node for Rust "enum" - tagged union + class Enum : public VisItem { + Identifier enum_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + ::std::vector< ::std::unique_ptr > items; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether "enum" has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether "enum" has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + /* Returns whether enum is a "zero-variant" (no possible variant) enum, which cannot be + * instantiated.*/ + inline bool is_zero_variant() const { + return items.empty(); + } + + // Mega-constructor + Enum(Identifier enum_name, Visibility vis, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, ::std::vector< ::std::unique_ptr > items, + ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + enum_name(::std::move(enum_name)), generic_params(::std::move(generic_params)), + where_clause(::std::move(where_clause)), items(::std::move(items)), locus(locus) {} + + // TODO: constructor with less arguments + + // Copy constructor with vector clone + Enum(Enum const& other) : + VisItem(other), enum_name(other.enum_name), where_clause(other.where_clause), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_enum_item()); + } + } + + // Overloaded assignment operator with vector clone + Enum& operator=(Enum const& other) { + VisItem::operator=(other); + enum_name = other.enum_name; + where_clause = other.where_clause; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_enum_item()); + } + + return *this; + } + + // Move constructors + Enum(Enum&& other) = default; + Enum& operator=(Enum&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Enum* clone_item_impl() const OVERRIDE { + return new Enum(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual Enum* clone_statement_impl() const OVERRIDE { + return new Enum(*this); + }*/ + }; + + // Rust untagged union used for C compat AST node + class Union : public VisItem { + Identifier union_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + ::std::vector variants; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether union has generic params. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether union has where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + Union(Identifier union_name, Visibility vis, + ::std::vector< ::std::unique_ptr > generic_params, + WhereClause where_clause, ::std::vector variants, + ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + union_name(::std::move(union_name)), generic_params(::std::move(generic_params)), + where_clause(::std::move(where_clause)), variants(::std::move(variants)), locus(locus) { + } + + // copy constructor with vector clone + Union(Union const& other) : + VisItem(other), union_name(other.union_name), where_clause(other.where_clause), + variants(other.variants), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // overloaded assignment operator with vector clone + Union& operator=(Union const& other) { + VisItem::operator=(other); + union_name = other.union_name; + where_clause = other.where_clause; + variants = other.variants; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + Union(Union&& other) = default; + Union& operator=(Union&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Union* clone_item_impl() const OVERRIDE { + return new Union(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual Union* clone_statement_impl() const OVERRIDE { + return new Union(*this); + }*/ + }; + + // "Constant item" AST node - used for constant, compile-time expressions within module scope + class ConstantItem + : public VisItem + , public InherentImplItem + , public TraitImplItem { + // either has an identifier or "_" - maybe handle in identifier? + // bool identifier_is_underscore; + // if no identifier declared, identifier will be "_" + Identifier identifier; + + // Type type; + ::std::unique_ptr type; + + // Expr* const_expr; + ::std::unique_ptr const_expr; + + location_t locus; + + public: + /*~ConstantItem() { + delete const_expr; + }*/ + + ::std::string as_string() const; + + ConstantItem(Identifier ident, Visibility vis, ::std::unique_ptr type, + ::std::unique_ptr const_expr, ::std::vector outer_attrs, + location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + identifier(::std::move(ident)), type(::std::move(type)), + const_expr(::std::move(const_expr)), locus(locus) {} + + ConstantItem(ConstantItem const& other) : + VisItem(other), identifier(other.identifier), type(other.type->clone_type()), + const_expr(other.const_expr->clone_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + ConstantItem& operator=(ConstantItem const& other) { + VisItem::operator=(other); + identifier = other.identifier; + type = other.type->clone_type(); + const_expr = other.const_expr->clone_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + ConstantItem(ConstantItem&& other) = default; + ConstantItem& operator=(ConstantItem&& other) = default; + + /* Returns whether constant item is an "unnamed" (wildcard underscore used as identifier) + * constant. */ + inline bool is_unnamed() const { + return identifier == ::std::string("_"); + } + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ConstantItem* clone_item_impl() const OVERRIDE { + return new ConstantItem(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ConstantItem* clone_inherent_impl_item_impl() const OVERRIDE { + return new ConstantItem(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ConstantItem* clone_trait_impl_item_impl() const OVERRIDE { + return new ConstantItem(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual ConstantItem* clone_statement_impl() const OVERRIDE { + return new ConstantItem(*this); + }*/ + }; + + // Static item AST node - items within module scope with fixed storage duration? + class StaticItem : public VisItem { + bool has_mut; + + Identifier name; + + // Type type; + ::std::unique_ptr type; + + // Expr* expr; + ::std::unique_ptr expr; + + location_t locus; + + public: + /*~StaticItem() { + delete expr; + }*/ + + ::std::string as_string() const; + + StaticItem(Identifier name, bool is_mut, ::std::unique_ptr type, + ::std::unique_ptr expr, Visibility vis, ::std::vector outer_attrs, + location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + has_mut(is_mut), name(::std::move(name)), type(::std::move(type)), + expr(::std::move(expr)), locus(locus) {} + + // Copy constructor with clone + StaticItem(StaticItem const& other) : + VisItem(other), has_mut(other.has_mut), name(other.name), + type(other.type->clone_type()), expr(other.expr->clone_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + StaticItem& operator=(StaticItem const& other) { + VisItem::operator=(other); + name = other.name; + has_mut = other.has_mut; + type = other.type->clone_type(); + expr = other.expr->clone_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + StaticItem(StaticItem&& other) = default; + StaticItem& operator=(StaticItem&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StaticItem* clone_item_impl() const OVERRIDE { + return new StaticItem(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual StaticItem* clone_statement_impl() const OVERRIDE { + return new StaticItem(*this); + }*/ + }; + + // Function declaration in traits + struct TraitFunctionDecl { + private: + // TODO: delete and replace with Function decl item? no as no body in this. + FunctionQualifiers qualifiers; + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_params; + // FunctionParams function_params; + ::std::vector function_params; // inlined + + // bool has_return_type; + // Type return_type; + ::std::unique_ptr return_type; + + // bool has_where_clause; + WhereClause where_clause; + + // should this store location info? + + public: + // Returns whether function decl has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether function decl has regular parameters. + inline bool has_params() const { + return !function_params.empty(); + } + + // Returns whether function has return type (otherwise is void). + inline bool has_return_type() const { + return return_type != NULL; + } + + // Returns whether function has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Mega-constructor + TraitFunctionDecl(Identifier function_name, FunctionQualifiers qualifiers, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::vector function_params, ::std::unique_ptr return_type, + WhereClause where_clause) : + qualifiers(::std::move(qualifiers)), + function_name(::std::move(function_name)), generic_params(::std::move(generic_params)), + function_params(::std::move(function_params)), return_type(::std::move(return_type)), + where_clause(::std::move(where_clause)) {} + + // Copy constructor with clone + TraitFunctionDecl(TraitFunctionDecl const& other) : + qualifiers(other.qualifiers), function_name(other.function_name), + /*generic_params(other.generic_params),*/ function_params(other.function_params), + return_type(other.return_type->clone_type()), where_clause(other.where_clause) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + ~TraitFunctionDecl() = default; + + // Overloaded assignment operator with clone + TraitFunctionDecl& operator=(TraitFunctionDecl const& other) { + function_name = other.function_name; + qualifiers = other.qualifiers; + // generic_params = other.generic_params; + function_params = other.function_params; + return_type = other.return_type->clone_type(); + where_clause = other.where_clause; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + TraitFunctionDecl(TraitFunctionDecl&& other) = default; + TraitFunctionDecl& operator=(TraitFunctionDecl&& other) = default; + + ::std::string as_string() const; + }; + + // Actual trait item function declaration within traits + class TraitItemFunc : public TraitItem { + ::std::vector outer_attrs; + TraitFunctionDecl decl; + // BlockExpr* block_expr; + ::std::unique_ptr block_expr; + + location_t locus; + + public: + /*~TraitItemFunc() { + delete block_expr; + }*/ + + // Returns whether function has a definition or is just a declaration. + inline bool has_definition() const { + return block_expr != NULL; + } + + TraitItemFunc(TraitFunctionDecl decl, ::std::unique_ptr block_expr, + ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + decl(::std::move(decl)), block_expr(::std::move(block_expr)), locus(locus) {} + + // Copy constructor with clone + TraitItemFunc(TraitItemFunc const& other) : + outer_attrs(other.outer_attrs), + decl(other.decl) /*, block_expr(other.block_expr->clone_block_expr())*/, + locus(other.locus) { + if (other.block_expr != NULL) { + block_expr = other.block_expr->clone_block_expr(); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + TraitItemFunc& operator=(TraitItemFunc const& other) { + TraitItem::operator=(other); + outer_attrs = other.outer_attrs; + decl = other.decl; + locus = other.locus; + if (other.block_expr != NULL) { + block_expr = other.block_expr->clone_block_expr(); + } + + return *this; + } + + // move constructors + TraitItemFunc(TraitItemFunc&& other) = default; + TraitItemFunc& operator=(TraitItemFunc&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TraitItemFunc* clone_trait_item_impl() const { + return new TraitItemFunc(*this); + } + }; + + // Method declaration within traits + struct TraitMethodDecl { + private: + // TODO: delete and replace with Function decl item? no as no body. + FunctionQualifiers qualifiers; + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + ::std::vector function_params; // inlined + + // bool has_return_type; + // Type return_type; + ::std::unique_ptr return_type; + + // bool has_where_clause; + WhereClause where_clause; + + // should this store location info? + + public: + // Returns whether method decl has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether method decl has regular parameters. + inline bool has_params() const { + return !function_params.empty(); + } + + // Returns whether method has return type (otherwise is void). + inline bool has_return_type() const { + return return_type != NULL; + } + + // Returns whether method has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Mega-constructor + TraitMethodDecl(Identifier function_name, FunctionQualifiers qualifiers, + ::std::vector< ::std::unique_ptr > generic_params, SelfParam self_param, + ::std::vector function_params, ::std::unique_ptr return_type, + WhereClause where_clause) : + qualifiers(::std::move(qualifiers)), + function_name(::std::move(function_name)), generic_params(::std::move(generic_params)), + self_param(::std::move(self_param)), function_params(::std::move(function_params)), + return_type(::std::move(return_type)), where_clause(::std::move(where_clause)) {} + + // Copy constructor with clone + TraitMethodDecl(TraitMethodDecl const& other) : + qualifiers(other.qualifiers), function_name(other.function_name), + /*generic_params(other.generic_params),*/ self_param(other.self_param), + function_params(other.function_params), return_type(other.return_type->clone_type()), + where_clause(other.where_clause) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + ~TraitMethodDecl() = default; + + // Overloaded assignment operator with clone + TraitMethodDecl& operator=(TraitMethodDecl const& other) { + function_name = other.function_name; + qualifiers = other.qualifiers; + // generic_params = other.generic_params; + self_param = other.self_param; + function_params = other.function_params; + return_type = other.return_type->clone_type(); + where_clause = other.where_clause; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + TraitMethodDecl(TraitMethodDecl&& other) = default; + TraitMethodDecl& operator=(TraitMethodDecl&& other) = default; + + ::std::string as_string() const; + }; + + // Actual trait item method declaration within traits + class TraitItemMethod : public TraitItem { + ::std::vector outer_attrs; + TraitMethodDecl decl; + // BlockExpr* block_expr; + ::std::unique_ptr block_expr; + + location_t locus; + + public: + /*~TraitItemMethod() { + delete block_expr; + }*/ + + // Returns whether method has a definition or is just a declaration. + inline bool has_definition() const { + return block_expr != NULL; + } + + TraitItemMethod(TraitMethodDecl decl, ::std::unique_ptr block_expr, + ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + decl(::std::move(decl)), block_expr(::std::move(block_expr)), locus(locus) {} + + // Copy constructor with clone + TraitItemMethod(TraitItemMethod const& other) : + outer_attrs(other.outer_attrs), decl(other.decl), + block_expr(other.block_expr->clone_block_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + TraitItemMethod& operator=(TraitItemMethod const& other) { + TraitItem::operator=(other); + outer_attrs = other.outer_attrs; + decl = other.decl; + block_expr = other.block_expr->clone_block_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + TraitItemMethod(TraitItemMethod&& other) = default; + TraitItemMethod& operator=(TraitItemMethod&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TraitItemMethod* clone_trait_item_impl() const { + return new TraitItemMethod(*this); + } + }; + + // Constant item within traits + class TraitItemConst : public TraitItem { + ::std::vector outer_attrs; + Identifier name; + // Type type; + ::std::unique_ptr type; + + // bool has_expression; + // Expr* expr; + ::std::unique_ptr expr; + + location_t locus; + + public: + /*~TraitItemConst() { + delete expr; + }*/ + + // Whether the constant item has an associated expression. + inline bool has_expression() const { + return expr != NULL; + } + + TraitItemConst(Identifier name, ::std::unique_ptr type, + ::std::unique_ptr expr, ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + name(::std::move(name)), type(::std::move(type)), expr(::std::move(expr)), + locus(locus) {} + + // Copy constructor with clones + TraitItemConst(TraitItemConst const& other) : + outer_attrs(other.outer_attrs), name(other.name), type(other.type->clone_type()), + expr(other.expr->clone_expr()), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + TraitItemConst& operator=(TraitItemConst const& other) { + TraitItem::operator=(other); + outer_attrs = other.outer_attrs; + name = other.name; + type = other.type->clone_type(); + expr = other.expr->clone_expr(); + locus = other.locus; + + return *this; + } + + // move constructors + TraitItemConst(TraitItemConst&& other) = default; + TraitItemConst& operator=(TraitItemConst&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TraitItemConst* clone_trait_item_impl() const { + return new TraitItemConst(*this); + } + }; + + // Type items within traits + class TraitItemType : public TraitItem { + ::std::vector outer_attrs; + + Identifier name; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + location_t locus; + + public: + // Returns whether trait item type has type param bounds. + inline bool has_type_param_bounds() const { + return !type_param_bounds.empty(); + } + + TraitItemType(Identifier name, + ::std::vector< ::std::unique_ptr > type_param_bounds, + ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + name(::std::move(name)), type_param_bounds(::std::move(type_param_bounds)), + locus(locus) {} + + // Copy constructor with vector clone + TraitItemType(TraitItemType const& other) : + outer_attrs(other.outer_attrs), name(other.name), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + } + + // Overloaded assignment operator with vector clone + TraitItemType& operator=(TraitItemType const& other) { + TraitItem::operator=(other); + outer_attrs = other.outer_attrs; + name = other.name; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + return *this; + } + + // default move constructors + TraitItemType(TraitItemType&& other) = default; + TraitItemType& operator=(TraitItemType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TraitItemType* clone_trait_item_impl() const { + return new TraitItemType(*this); + } + }; + + // Macro invocation items within traits - TODO is this approach better or is making + // MacroInvocationSemi itself implement TraitItem better? Leaning toward latter. + /*class TraitItemMacroInvoc : public TraitItem { + MacroInvocationSemi macro_invoc; + + public: + TraitItemMacroInvoc( + MacroInvocationSemi macro_invoc, ::std::vector outer_attrs) : + macro_invoc(macro_invoc), + TraitItem(outer_attrs) {} + };*/ + // replaced with MacroInvocationSemi implementing TraitItem + + // Rust trait item declaration AST node + class Trait : public VisItem { + bool has_unsafe; + + Identifier name; + + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_trait_items; + ::std::vector< ::std::unique_ptr > trait_items; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether trait has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether trait has type parameter bounds. + inline bool has_type_param_bounds() const { + return !type_param_bounds.empty(); + } + + // Returns whether trait has where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Returns whether trait has trait items. + inline bool has_trait_items() const { + return !trait_items.empty(); + } + + // Mega-constructor + Trait(Identifier name, bool is_unsafe, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::vector< ::std::unique_ptr > type_param_bounds, + WhereClause where_clause, ::std::vector< ::std::unique_ptr > trait_items, + Visibility vis, ::std::vector outer_attrs, location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + has_unsafe(is_unsafe), name(::std::move(name)), + generic_params(::std::move(generic_params)), + type_param_bounds(::std::move(type_param_bounds)), + where_clause(::std::move(where_clause)), trait_items(::std::move(trait_items)), + locus(locus) {} + + // Copy constructor with vector clone + Trait(Trait const& other) : + VisItem(other), has_unsafe(other.has_unsafe), name(other.name), + where_clause(other.where_clause), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + // again for type param bounds + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + // again for trait items + trait_items.reserve(other.trait_items.size()); + + for (const auto& e : other.trait_items) { + trait_items.push_back(e->clone_trait_item()); + } + } + + // Overloaded assignment operator with vector clone + Trait& operator=(Trait const& other) { + VisItem::operator=(other); + name = other.name; + has_unsafe = other.has_unsafe; + where_clause = other.where_clause; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + // again for type param bounds + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + // again for trait items + trait_items.reserve(other.trait_items.size()); + + for (const auto& e : other.trait_items) { + trait_items.push_back(e->clone_trait_item()); + } + + return *this; + } + + // default move constructors + Trait(Trait&& other) = default; + Trait& operator=(Trait&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual Trait* clone_item_impl() const OVERRIDE { + return new Trait(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual Trait* clone_statement_impl() const OVERRIDE { + return new Trait(*this); + }*/ + }; + + // Implementation item declaration AST node - abstract base class + class Impl : public VisItem { + // must be protected to allow subclasses to access them properly + protected: + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // Type trait_type; + ::std::unique_ptr trait_type; + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_inner_attrs; + ::std::vector inner_attrs; + + private: + // doesn't really need to be protected as write access probably not needed + location_t locus; + + public: + // Returns whether impl has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether impl has where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + // Returns whether impl has inner attributes. + inline bool has_inner_attrs() const { + return !inner_attrs.empty(); + } + + location_t get_locus() const { + return locus; + } + + protected: + // Mega-constructor + Impl(::std::vector< ::std::unique_ptr > generic_params, + ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, + ::std::vector inner_attrs, ::std::vector outer_attrs, + location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + generic_params(::std::move(generic_params)), trait_type(::std::move(trait_type)), + where_clause(::std::move(where_clause)), inner_attrs(::std::move(inner_attrs)), + locus(locus) {} + + // Copy constructor + Impl(Impl const& other) : + VisItem(other), + /*generic_params(other.generic_params),*/ trait_type(other.trait_type->clone_type()), + where_clause(other.where_clause), inner_attrs(other.inner_attrs), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // Destructor - define here if required + + // Assignment operator overload with cloning + Impl& operator=(Impl const& other) { + VisItem::operator=(other); + // generic_params = other.generic_params; + trait_type = other.trait_type->clone_type(); + where_clause = other.where_clause; + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + Impl(Impl&& other) = default; + Impl& operator=(Impl&& other) = default; + }; + + // Regular "impl foo" impl block declaration AST node + class InherentImpl : public Impl { + // bool has_impl_items; + ::std::vector< ::std::unique_ptr > impl_items; + + public: + ::std::string as_string() const; + + // Returns whether inherent impl block has inherent impl items. + inline bool has_impl_items() const { + return !impl_items.empty(); + } + + // Mega-constructor + InherentImpl(::std::vector< ::std::unique_ptr > impl_items, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, + ::std::vector inner_attrs, ::std::vector outer_attrs, + location_t locus) : + Impl(::std::move(generic_params), ::std::move(trait_type), ::std::move(where_clause), + ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus), + impl_items(::std::move(impl_items)) {} + + // Copy constructor with vector clone + InherentImpl(InherentImpl const& other) : Impl(other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + impl_items.reserve(other.impl_items.size()); + + for (const auto& e : other.impl_items) { + impl_items.push_back(e->clone_inherent_impl_item()); + } + } + + // Overloaded assignment operator with vector clone + InherentImpl& operator=(InherentImpl const& other) { + Impl::operator=(other); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + impl_items.reserve(other.impl_items.size()); + + for (const auto& e : other.impl_items) { + impl_items.push_back(e->clone_inherent_impl_item()); + } + + return *this; + } + + // default move constructors + InherentImpl(InherentImpl&& other) = default; + InherentImpl& operator=(InherentImpl&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual InherentImpl* clone_item_impl() const OVERRIDE { + return new InherentImpl(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual InherentImpl* clone_statement_impl() const OVERRIDE { + return new InherentImpl(*this); + }*/ + }; + + // The "impl footrait for foo" impl block declaration AST node + class TraitImpl : public Impl { + bool has_unsafe; + + bool has_exclam; + + TypePath trait_path; + + // bool has_impl_items; + ::std::vector< ::std::unique_ptr > impl_items; + + public: + ::std::string as_string() const; + + // Returns whether trait impl has impl items. + inline bool has_impl_items() const { + return !impl_items.empty(); + } + + // Mega-constructor + TraitImpl(TypePath trait_path, bool is_unsafe, bool has_exclam, + ::std::vector< ::std::unique_ptr > impl_items, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, + ::std::vector inner_attrs, ::std::vector outer_attrs, + location_t locus) : + Impl(::std::move(generic_params), ::std::move(trait_type), ::std::move(where_clause), + ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus), + has_unsafe(is_unsafe), has_exclam(has_exclam), trait_path(::std::move(trait_path)), + impl_items(::std::move(impl_items)) {} + + // TODO: constructors with less params + + // Copy constructor with vector clone + TraitImpl(TraitImpl const& other) : + Impl(other), has_unsafe(other.has_unsafe), has_exclam(other.has_exclam), + trait_path(other.trait_path) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + impl_items.reserve(other.impl_items.size()); + + for (const auto& e : other.impl_items) { + impl_items.push_back(e->clone_trait_impl_item()); + } + } + + // Overloaded assignment operator with vector clone + TraitImpl& operator=(TraitImpl const& other) { + Impl::operator=(other); + trait_path = other.trait_path; + has_unsafe = other.has_unsafe; + has_exclam = other.has_exclam; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + impl_items.reserve(other.impl_items.size()); + + for (const auto& e : other.impl_items) { + impl_items.push_back(e->clone_trait_impl_item()); + } + + return *this; + } + + // move constructors + TraitImpl(TraitImpl&& other) = default; + TraitImpl& operator=(TraitImpl&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TraitImpl* clone_item_impl() const OVERRIDE { + return new TraitImpl(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual TraitImpl* clone_statement_impl() const OVERRIDE { + return new TraitImpl(*this); + }*/ + }; + + // Abstract base class for an item used inside an extern block + class ExternalItem { + // bool has_outer_attrs; + ::std::vector outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + + location_t locus; + + public: + virtual ~ExternalItem() {} + + // Returns whether item has outer attributes. + inline bool has_outer_attrs() const { + return !outer_attrs.empty(); + } + + // Returns whether item has non-default visibility. + inline bool has_visibility() const { + return !visibility.is_error(); + } + + // Unique pointer custom clone function + ::std::unique_ptr clone_external_item() const { + return ::std::unique_ptr(clone_external_item_impl()); + } + + virtual ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + ExternalItem(Identifier item_name, Visibility vis, ::std::vector outer_attrs, + location_t locus) : + outer_attrs(::std::move(outer_attrs)), + visibility(::std::move(vis)), item_name(::std::move(item_name)), locus(locus) {} + + // Copy constructor + ExternalItem(ExternalItem const& other) : + outer_attrs(other.outer_attrs), visibility(other.visibility), + item_name(other.item_name), locus(other.locus) {} + + // Overloaded assignment operator to clone + ExternalItem& operator=(ExternalItem const& other) { + item_name = other.item_name; + visibility = other.visibility; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ExternalItem(ExternalItem&& other) = default; + ExternalItem& operator=(ExternalItem&& other) = default; + + // Clone function implementation as pure virtual method + virtual ExternalItem* clone_external_item_impl() const = 0; + + // possibly make this public if required + ::std::string get_item_name() const { + return item_name; + } + }; + + // A static item used in an extern block + class ExternalStaticItem : public ExternalItem { + bool has_mut; + + // Type item_type; + ::std::unique_ptr item_type; + + public: + ExternalStaticItem(Identifier item_name, ::std::unique_ptr item_type, bool is_mut, + Visibility vis, ::std::vector outer_attrs, location_t locus) : + ExternalItem(::std::move(item_name), ::std::move(vis), ::std::move(outer_attrs), locus), + has_mut(is_mut), item_type(::std::move(item_type)) {} + + // Copy constructor + ExternalStaticItem(ExternalStaticItem const& other) : + ExternalItem(other), has_mut(other.has_mut), item_type(other.item_type->clone_type()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ExternalStaticItem& operator=(ExternalStaticItem const& other) { + ExternalItem::operator=(other); + item_type = other.item_type->clone_type(); + has_mut = other.has_mut; + + return *this; + } + + // move constructors + ExternalStaticItem(ExternalStaticItem&& other) = default; + ExternalStaticItem& operator=(ExternalStaticItem&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExternalStaticItem* clone_external_item_impl() const OVERRIDE { + return new ExternalStaticItem(*this); + } + }; + + // A named function parameter used in external functions + struct NamedFunctionParam { + private: + // bool has_name; // otherwise is _ + Identifier name; // TODO: handle wildcard in identifier? + + // Type param_type; + ::std::unique_ptr param_type; + + // TODO: should this store location data? + + public: + // Returns whether the named function parameter has a name (i.e. name is not '_'). + inline bool has_name() const { + return name != "_"; + } + + // Returns whether the named function parameter is in an error state. + inline bool is_error() const { + // also if identifier is "" but that is probably more costly to compute + return param_type == NULL; + } + + // Creates an error state named function parameter. + static NamedFunctionParam create_error() { + return NamedFunctionParam("", NULL); + } + + NamedFunctionParam(Identifier name, ::std::unique_ptr param_type) : + name(::std::move(name)), param_type(::std::move(param_type)) {} + + // Copy constructor + NamedFunctionParam(NamedFunctionParam const& other) : + name(other.name), param_type(other.param_type->clone_type()) {} + + ~NamedFunctionParam() = default; + + // Overloaded assignment operator to clone + NamedFunctionParam& operator=(NamedFunctionParam const& other) { + name = other.name; + param_type = other.param_type->clone_type(); + // has_name = other.has_name; + + return *this; + } + + // move constructors + NamedFunctionParam(NamedFunctionParam&& other) = default; + NamedFunctionParam& operator=(NamedFunctionParam&& other) = default; + + ::std::string as_string() const; + }; + + // A function item used in an extern block + class ExternalFunctionItem : public ExternalItem { + // bool has_generics; + // Generics generic_params; + ::std::vector< ::std::unique_ptr > generic_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + ::std::unique_ptr return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + ::std::vector function_params; + + bool has_variadics; + + public: + // Returns whether item has generic parameters. + inline bool has_generics() const { + return !generic_params.empty(); + } + + // Returns whether item has a return type (otherwise void). + inline bool has_return_type() const { + return return_type != NULL; + } + + // Returns whether item has a where clause. + inline bool has_where_clause() const { + return !where_clause.is_empty(); + } + + ExternalFunctionItem(Identifier item_name, + ::std::vector< ::std::unique_ptr > generic_params, + ::std::unique_ptr return_type, WhereClause where_clause, + ::std::vector function_params, bool has_variadics, Visibility vis, + ::std::vector outer_attrs, location_t locus) : + ExternalItem(::std::move(item_name), ::std::move(vis), ::std::move(outer_attrs), locus), + generic_params(::std::move(generic_params)), return_type(::std::move(return_type)), + where_clause(::std::move(where_clause)), function_params(::std::move(function_params)), + has_variadics(has_variadics) {} + + // Copy constructor with clone + ExternalFunctionItem(ExternalFunctionItem const& other) : + ExternalItem(other), + /*generic_params(other.generic_params),*/ return_type(other.return_type->clone_type()), + where_clause(other.where_clause), function_params(other.function_params), + has_variadics(other.has_variadics) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator with clone + ExternalFunctionItem& operator=(ExternalFunctionItem const& other) { + ExternalItem::operator=(other); + // generic_params = other.generic_params; + return_type = other.return_type->clone_type(); + where_clause = other.where_clause; + function_params = other.function_params; + has_variadics = other.has_variadics; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + generic_params.reserve(other.generic_params.size()); + + for (const auto& e : other.generic_params) { + generic_params.push_back(e->clone_generic_param()); + } + + return *this; + } + + // move constructors + ExternalFunctionItem(ExternalFunctionItem&& other) = default; + ExternalFunctionItem& operator=(ExternalFunctionItem&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExternalFunctionItem* clone_external_item_impl() const OVERRIDE { + return new ExternalFunctionItem(*this); + } + }; + + // An extern block AST node + class ExternBlock : public VisItem { + // bool has_abi; + ::std::string abi; + + // bool has_inner_attrs; + ::std::vector inner_attrs; + + // bool has_extern_items; + ::std::vector< ::std::unique_ptr > extern_items; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns whether extern block has inner attributes. + inline bool has_inner_attrs() const { + return !inner_attrs.empty(); + } + + // Returns whether extern block has extern items. + inline bool has_extern_items() const { + return !extern_items.empty(); + } + + // Returns whether extern block has ABI name. + inline bool has_abi() const { + return !abi.empty(); + } + + ExternBlock(::std::string abi, + ::std::vector< ::std::unique_ptr > extern_items, Visibility vis, + ::std::vector inner_attrs, ::std::vector outer_attrs, + location_t locus) : + VisItem(::std::move(vis), ::std::move(outer_attrs)), + abi(::std::move(abi)), inner_attrs(::std::move(inner_attrs)), + extern_items(::std::move(extern_items)), locus(locus) {} + + // Copy constructor with vector clone + ExternBlock(ExternBlock const& other) : + VisItem(other), abi(other.abi), inner_attrs(other.inner_attrs), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + extern_items.reserve(other.extern_items.size()); + + for (const auto& e : other.extern_items) { + extern_items.push_back(e->clone_external_item()); + } + } + + // Overloaded assignment operator with vector clone + ExternBlock& operator=(ExternBlock const& other) { + VisItem::operator=(other); + abi = other.abi; + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + extern_items.reserve(other.extern_items.size()); + + for (const auto& e : other.extern_items) { + extern_items.push_back(e->clone_external_item()); + } + + return *this; + } + + // move constructors + ExternBlock(ExternBlock&& other) = default; + ExternBlock& operator=(ExternBlock&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExternBlock* clone_item_impl() const OVERRIDE { + return new ExternBlock(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + /*virtual ExternBlock* clone_statement_impl() const OVERRIDE { + return new ExternBlock(*this); + }*/ + }; + + // Replaced with forward decls - defined in "rust-macro.h" + class MacroItem; + class MacroInvocationSemi; + class MacroRulesDefinition; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h new file mode 100644 index 0000000..4c8237e --- /dev/null +++ b/gcc/rust/ast/rust-macro.h @@ -0,0 +1,588 @@ +#ifndef RUST_AST_MACRO_H +#define RUST_AST_MACRO_H + +#include "rust-ast.h" + +namespace Rust { + namespace AST { + // Decls as definitions moved to rust-ast.h + class MacroItem; + class MacroInvocationSemi; + + enum MacroFragSpec { + BLOCK, + EXPR, + IDENT, + ITEM, + LIFETIME, + LITERAL, + META, + PAT, + PATH, + STMT, + TT, + TY, + VIS, + INVALID // not really a specifier, but used to mark invalid one passed in + }; + + inline MacroFragSpec get_frag_spec_from_str(::std::string str) { + if (str == "block") + return BLOCK; + else if (str == "expr") + return EXPR; + else if (str == "ident") + return IDENT; + else if (str == "item") + return ITEM; + else if (str == "lifetime") + return LIFETIME; + else if (str == "literal") + return LITERAL; + else if (str == "meta") + return META; + else if (str == "pat") + return PAT; + else if (str == "path") + return PATH; + else if (str == "stmt") + return STMT; + else if (str == "tt") + return TT; + else if (str == "ty") + return TY; + else if (str == "vis") + return VIS; + else { + // error_at("invalid string '%s' used as fragment specifier", str->c_str()); + return INVALID; + } + } + + // A macro match that has an identifier and fragment spec + class MacroMatchFragment : public MacroMatch { + Identifier ident; + MacroFragSpec frag_spec; + + // TODO: should store location information? + + public: + MacroMatchFragment(Identifier ident, MacroFragSpec frag_spec) : + ident(::std::move(ident)), frag_spec(frag_spec) {} + + // Returns whether macro match fragment is in an error state. + inline bool is_error() const { + return frag_spec == INVALID; + } + + // Creates an error state macro match fragment. + static MacroMatchFragment create_error() { + return MacroMatchFragment(::std::string(""), INVALID); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroMatchFragment* clone_macro_match_impl() const OVERRIDE { + return new MacroMatchFragment(*this); + } + }; + + // A repetition macro match + class MacroMatchRepetition : public MacroMatch { + public: + enum MacroRepOp { NONE, ASTERISK, PLUS, QUESTION_MARK }; + + private: + //::std::vector matches; + ::std::vector< ::std::unique_ptr > matches; + MacroRepOp op; + + // bool has_sep; + typedef Token MacroRepSep; + // any token except delimiters and repetition operators + ::std::unique_ptr sep; + + // TODO: should store location information? + + public: + // Returns whether macro match repetition has separator token. + inline bool has_sep() const { + return sep != NULL; + } + + MacroMatchRepetition(::std::vector< ::std::unique_ptr > matches, + MacroRepOp op, ::std::unique_ptr sep) : + matches(::std::move(matches)), + op(op), sep(::std::move(sep)) {} + + // Copy constructor with clone + MacroMatchRepetition(MacroMatchRepetition const& other) : + /*matches(other.matches),*/ op(other.op), sep(other.sep->clone_token()) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + matches.reserve(other.matches.size()); + + for (const auto& e : other.matches) { + matches.push_back(e->clone_macro_match()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + MacroMatchRepetition& operator=(MacroMatchRepetition const& other) { + // matches = other.matches; // TODO: this needs to clone somehow? + op = other.op; + sep = other.sep->clone_token(); + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + matches.reserve(other.matches.size()); + + for (const auto& e : other.matches) { + matches.push_back(e->clone_macro_match()); + } + + return *this; + } + + // move constructors + MacroMatchRepetition(MacroMatchRepetition&& other) = default; + MacroMatchRepetition& operator=(MacroMatchRepetition&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroMatchRepetition* clone_macro_match_impl() const OVERRIDE { + return new MacroMatchRepetition(*this); + } + }; + + // can't inline due to polymorphism + class MacroMatcher : public MacroMatch { + DelimType delim_type; + //::std::vector matches; + ::std::vector< ::std::unique_ptr > matches; + + // TODO: think of way to mark invalid that doesn't take up more space + bool is_invalid; + + // TODO: should store location information? + + public: + MacroMatcher( + DelimType delim_type, ::std::vector< ::std::unique_ptr > matches) : + delim_type(delim_type), + matches(::std::move(matches)), is_invalid(false) {} + + // copy constructor with vector clone + MacroMatcher(MacroMatcher const& other) : delim_type(other.delim_type) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + matches.reserve(other.matches.size()); + + for (const auto& e : other.matches) { + matches.push_back(e->clone_macro_match()); + } + } + + // overloaded assignment operator with vector clone + MacroMatcher& operator=(MacroMatcher const& other) { + delim_type = other.delim_type; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + matches.reserve(other.matches.size()); + + for (const auto& e : other.matches) { + matches.push_back(e->clone_macro_match()); + } + + return *this; + } + + // move constructors + MacroMatcher(MacroMatcher&& other) = default; + MacroMatcher& operator=(MacroMatcher&& other) = default; + + // Creates an error state macro matcher. + static MacroMatcher create_error() { + return MacroMatcher(true); + } + + // Returns whether MacroMatcher is in an error state. + inline bool is_error() const { + return is_invalid; + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroMatcher* clone_macro_match_impl() const OVERRIDE { + return new MacroMatcher(*this); + } + + // constructor only used to create error matcher + MacroMatcher(bool is_invalid) : delim_type(PARENS), is_invalid(is_invalid) {} + }; + + // TODO: inline? + struct MacroTranscriber { + private: + DelimTokenTree token_tree; + + // TODO: should store location information? + + public: + MacroTranscriber(DelimTokenTree token_tree) : token_tree(::std::move(token_tree)) {} + + ::std::string as_string() const { + return token_tree.as_string(); + } + }; + + // A macro rule? Matcher and transcriber pair? + struct MacroRule { + private: + MacroMatcher matcher; + MacroTranscriber transcriber; + + // TODO: should store location information? + + public: + MacroRule(MacroMatcher matcher, MacroTranscriber transcriber) : + matcher(::std::move(matcher)), transcriber(::std::move(transcriber)) {} + + // Returns whether macro rule is in error state. + inline bool is_error() const { + return matcher.is_error(); + } + + // Creates an error state macro rule. + static MacroRule create_error() { + return MacroRule( + MacroMatcher::create_error(), MacroTranscriber(DelimTokenTree::create_empty())); + } + + ::std::string as_string() const; + }; + + // A macro rules definition item AST node + class MacroRulesDefinition : public MacroItem { + Identifier rule_name; + // MacroRulesDef rules_def; // TODO: inline + // only curly without required semicolon at end + DelimType delim_type; + // MacroRules rules; + ::std::vector rules; // inlined form + + location_t locus; + + public: + ::std::string as_string() const; + + MacroRulesDefinition(Identifier rule_name, DelimType delim_type, + ::std::vector rules, ::std::vector outer_attrs, + location_t locus) : + MacroItem(::std::move(outer_attrs)), + rule_name(::std::move(rule_name)), delim_type(delim_type), rules(::std::move(rules)), + locus(locus) {} + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroRulesDefinition* clone_item_impl() const OVERRIDE { + return new MacroRulesDefinition(*this); + } + }; + + // AST node of a macro invocation, which is replaced by the macro result at compile time + class MacroInvocation + : public TypeNoBounds + , public Pattern + , public ExprWithoutBlock { + SimplePath path; + DelimTokenTree token_tree; + + location_t locus; + + public: + ::std::string as_string() const; + + MacroInvocation(SimplePath path, DelimTokenTree token_tree, + ::std::vector outer_attrs, location_t locus) : + ExprWithoutBlock(::std::move(outer_attrs)), + path(::std::move(path)), token_tree(::std::move(token_tree)), locus(locus) {} + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocation* clone_pattern_impl() const OVERRIDE { + return new MacroInvocation(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocation* clone_expr_impl() const OVERRIDE { + return new MacroInvocation(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocation* clone_expr_without_block_impl() const OVERRIDE { + return new MacroInvocation(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocation* clone_type_impl() const OVERRIDE { + return new MacroInvocation(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual MacroInvocation* clone_type_no_bounds_impl() const OVERRIDE { + return new MacroInvocation(*this); + } + }; + + // more generic meta item path-only form + class MetaItemPath : public MetaItem { + SimplePath path; + + public: + MetaItemPath(SimplePath path) : path(::std::move(path)) {} + + ::std::string as_string() const OVERRIDE { + return path.as_string(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // HACK: used to simplify parsing - returns non-empty only in this case + virtual SimplePath to_path_item() const OVERRIDE { + // this should copy construct - TODO ensure it does + return path; + } + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemPath* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaItemPath(*this); + } + }; + + // more generic meta item sequence form + class MetaItemSeq : public MetaItem { + SimplePath path; + ::std::vector< ::std::unique_ptr > seq; + + public: + MetaItemSeq(SimplePath path, ::std::vector< ::std::unique_ptr > seq) : + path(::std::move(path)), seq(::std::move(seq)) {} + + // copy constructor with vector clone + MetaItemSeq(const MetaItemSeq& other) : path(other.path) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + seq.reserve(other.seq.size()); + + for (const auto& e : other.seq) { + seq.push_back(e->clone_meta_item_inner()); + } + } + + // destructor definition not required + + // overloaded assignment operator with vector clone + MetaItemSeq& operator=(const MetaItemSeq& other) { + MetaItem::operator=(other); + path = other.path; + // crappy vector unique pointer clone - TODO is there a better way of doing this? + seq.reserve(other.seq.size()); + + for (const auto& e : other.seq) { + seq.push_back(e->clone_meta_item_inner()); + } + + return *this; + } + + // default move constructors + MetaItemSeq(MetaItemSeq&& other) = default; + MetaItemSeq& operator=(MetaItemSeq&& other) = default; + + ::std::string as_string() const OVERRIDE; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemSeq* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaItemSeq(*this); + } + }; + + // Preferred specialisation for single-identifier meta items. + class MetaWord : public MetaItem { + Identifier ident; + + public: + MetaWord(Identifier ident) : ident(::std::move(ident)) {} + + ::std::string as_string() const OVERRIDE { + return ident; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaWord* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaWord(*this); + } + }; + + // Preferred specialisation for "identifier '=' string literal" meta items. + class MetaNameValueStr : public MetaItem { + Identifier ident; + ::std::string str; + + public: + MetaNameValueStr(Identifier ident, ::std::string str) : + ident(::std::move(ident)), str(::std::move(str)) {} + + ::std::string as_string() const OVERRIDE { + return ident + " = " + str; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + // HACK: used to simplify parsing - creates a copy of this + virtual MetaNameValueStr* to_meta_name_value_str() const OVERRIDE { + return clone_meta_item_inner_impl(); + } + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaNameValueStr(*this); + } + }; + + // doubles up as MetaListIdents - determine via iterating through each path? + // Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'" + class MetaListPaths : public MetaItem { + Identifier ident; + ::std::vector paths; + + public: + MetaListPaths(Identifier ident, ::std::vector paths) : + ident(::std::move(ident)), paths(::std::move(paths)) {} + + ::std::string as_string() const OVERRIDE; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + private: + bool check_path_exists_in_cfg(const Session& session, const SimplePath& path) const; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaListPaths* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaListPaths(*this); + } + }; + + // Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'" + class MetaListNameValueStr : public MetaItem { + Identifier ident; + ::std::vector strs; + + public: + MetaListNameValueStr(Identifier ident, ::std::vector strs) : + ident(::std::move(ident)), strs(::std::move(strs)) {} + + ::std::string as_string() const OVERRIDE; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this type + virtual MetaListNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { + return new MetaListNameValueStr(*this); + } + }; + + // Object that parses macros from a token stream. + struct MacroParser { + private: + ::std::vector< ::std::unique_ptr > token_stream; + // probably have to make this mutable (mutable int stream_pos) otherwise const has to be + // removed up to DelimTokenTree or further ok since this changing would have an effect on + // the results of the methods run (i.e. not logically const), the parsing methods + // shouldn't be const + int stream_pos; + + public: + MacroParser( + ::std::vector< ::std::unique_ptr > token_stream, int stream_start_pos = 0) : + token_stream(::std::move(token_stream)), + stream_pos(stream_start_pos) {} + + ~MacroParser() = default; + + ::std::vector< ::std::unique_ptr > parse_meta_item_seq(); + + private: + // Parses a MetaItemInner. + ::std::unique_ptr parse_meta_item_inner(); + // Returns whether token can end a meta item. + bool is_end_meta_item_tok(TokenId id) const; + // Parses a simple path. + SimplePath parse_simple_path(); + // Parses a segment of a simple path (but not scope resolution operator). + SimplePathSegment parse_simple_path_segment(); + // Parses a MetaItemLitExpr. + ::std::unique_ptr parse_meta_item_lit(); + // Parses a literal. + Literal parse_literal(); + // Parses a meta item that begins with a simple path. + ::std::unique_ptr parse_path_meta_item(); + + // TODO: should this be const? + ::std::unique_ptr& peek_token(int i = 0) { + return token_stream[stream_pos + i]; + } + + void skip_token(int i = 0) { + stream_pos += 1 + i; + } + }; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h new file mode 100644 index 0000000..cddd062 --- /dev/null +++ b/gcc/rust/ast/rust-path.h @@ -0,0 +1,803 @@ +#ifndef RUST_AST_PATH_H +#define RUST_AST_PATH_H +/* "Path" (identifier within namespaces, essentially) handling. Required include for virtually all + * AST-related functionality. */ + +#include "rust-ast.h" + +#include +#include + +namespace Rust { + namespace AST { + // make intellisense calm + /*typedef ::std::string Symbol; + typedef int Lifetime; + typedef int Type; + typedef int Binding;*/ + + // The "identifier" (not generic args) aspect of each path expression segment + class PathIdentSegment { + ::std::string segment_name; + + // TODO: should this have location info stored? + + // only allow identifiers, "super", "self", "Self", "crate", or "$crate" + public: + PathIdentSegment(::std::string segment_name) : segment_name(::std::move(segment_name)) {} + + /* TODO: insert check in constructor for this? Or is this a semantic error best handled + * then? */ + + // TODO: does this require visitor. pretty sure this isn't polymorphic, but not entirely sure + + // Creates an error PathIdentSegment. + static PathIdentSegment create_error() { + return PathIdentSegment(""); + } + + // Returns whether PathIdentSegment is in an error state. + inline bool is_error() const { + return segment_name.empty(); + } + + ::std::string as_string() const { + return segment_name; + } + }; + + // A binding of an identifier to a type used in generic arguments in paths + struct GenericArgsBinding { + private: + Identifier identifier; + // Type type; + ::std::unique_ptr type; + + location_t locus; + + public: + // Returns whether binding is in an error state. + inline bool is_error() const { + return type == NULL; // and also identifier is empty, but cheaper computation + } + + // Creates an error state generic args binding. + static GenericArgsBinding create_error() { + return GenericArgsBinding("", NULL); + } + + // Pointer type for type in constructor to enable polymorphism + GenericArgsBinding(Identifier ident, ::std::unique_ptr type_ptr, + location_t locus = UNKNOWN_LOCATION) : + identifier(::std::move(ident)), + type(::std::move(type_ptr)), locus(locus) {} + + // Copy constructor has to deep copy the type as it is a unique pointer + GenericArgsBinding(GenericArgsBinding const& other) : + identifier(other.identifier), type(other.type->clone_type()), locus(other.locus) {} + + // default destructor + ~GenericArgsBinding() = default; + + // Overload assignment operator to deep copy the pointed-to type + GenericArgsBinding& operator=(GenericArgsBinding const& other) { + identifier = other.identifier; + type = other.type->clone_type(); + locus = other.locus; + return *this; + } + + // move constructors + GenericArgsBinding(GenericArgsBinding&& other) = default; + GenericArgsBinding& operator=(GenericArgsBinding&& other) = default; + + ::std::string as_string() const; + }; + + // Generic arguments allowed in each path expression segment - inline? + struct GenericArgs { + ::std::vector lifetime_args; + //::std::vector type_args; + ::std::vector< ::std::unique_ptr > type_args; + ::std::vector binding_args; + + location_t locus; + + public: + // Returns true if there are any generic arguments + inline bool has_generic_args() const { + return !(lifetime_args.empty() && type_args.empty() && binding_args.empty()); + } + + GenericArgs(::std::vector lifetime_args, + ::std::vector< ::std::unique_ptr > type_args, + ::std::vector binding_args, location_t locus = UNKNOWN_LOCATION) : + lifetime_args(::std::move(lifetime_args)), + type_args(::std::move(type_args)), binding_args(::std::move(binding_args)), + locus(locus) {} + + // copy constructor with vector clone + GenericArgs(GenericArgs const& other) : + lifetime_args(other.lifetime_args), binding_args(other.binding_args), + locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_args.reserve(other.type_args.size()); + + for (const auto& e : other.type_args) { + type_args.push_back(e->clone_type()); + } + } + + ~GenericArgs() = default; + + // overloaded assignment operator to vector clone + GenericArgs& operator=(GenericArgs const& other) { + lifetime_args = other.lifetime_args; + binding_args = other.binding_args; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_args.reserve(other.type_args.size()); + + for (const auto& e : other.type_args) { + type_args.push_back(e->clone_type()); + } + + return *this; + } + + // move constructors + GenericArgs(GenericArgs&& other) = default; + GenericArgs& operator=(GenericArgs&& other) = default; + + // Creates an empty GenericArgs (no arguments) + static GenericArgs create_empty() { + return GenericArgs(::std::vector(), + ::std::vector< ::std::unique_ptr >(), ::std::vector()); + } + + ::std::string as_string() const; + }; + + // A segment of a path in expression, including an identifier aspect and maybe generic args + class PathExprSegment { // or should this extend PathIdentSegment? + private: + PathIdentSegment segment_name; + + // bool has_generic_args; + GenericArgs generic_args; + + location_t locus; + + // TODO: does this require visitor? pretty sure not polymorphic + + public: + // Returns true if there are any generic arguments + inline bool has_generic_args() const { + return generic_args.has_generic_args(); + } + + // Constructor for segment (from IdentSegment and GenericArgs) + PathExprSegment(PathIdentSegment segment_name, location_t locus = UNKNOWN_LOCATION, + GenericArgs generic_args = GenericArgs::create_empty()) : + segment_name(::std::move(segment_name)), + generic_args(::std::move(generic_args)), locus(locus) {} + + // Constructor for segment with generic arguments (from segment name and all args) + PathExprSegment(::std::string segment_name, location_t locus, + ::std::vector lifetime_args = ::std::vector(), + ::std::vector< ::std::unique_ptr > type_args + = ::std::vector< ::std::unique_ptr >(), + ::std::vector binding_args = ::std::vector()) : + segment_name(PathIdentSegment(::std::move(segment_name))), + generic_args(GenericArgs( + ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))), + locus(locus) {} + + // Returns whether path expression segment is in an error state. + inline bool is_error() const { + return segment_name.is_error(); + } + + // Creates an error-state path expression segment. + static PathExprSegment create_error() { + return PathExprSegment(PathIdentSegment::create_error()); + } + + ::std::string as_string() const; + + inline location_t get_locus() const { + return locus; + } + }; + + // AST node representing a pattern that involves a "path" - abstract base class + class PathPattern : public Pattern { + ::std::vector segments; + + protected: + PathPattern(::std::vector segments) : segments(::std::move(segments)) {} + + // Returns whether path has segments. + inline bool has_segments() const { + return !segments.empty(); + } + + /* Converts path segments to their equivalent SimplePath segments if possible, and creates + * a SimplePath from them. */ + SimplePath convert_to_simple_path(bool with_opening_scope_resolution) const; + + public: + /* Returns whether the path is a single segment (excluding qualified path initial as + * segment). */ + inline bool is_single_segment() const { + return segments.size() == 1; + } + + virtual ::std::string as_string() const; + }; + + // AST node representing a path-in-expression pattern (path that allows generic arguments) + class PathInExpression + : public PathPattern + , public PathExpr { + bool has_opening_scope_resolution; + + location_t locus; + + public: + ::std::string as_string() const; + + // Constructor + PathInExpression(::std::vector path_segments, + location_t locus = UNKNOWN_LOCATION, bool has_opening_scope_resolution = false, + ::std::vector outer_attrs = ::std::vector()) : + PathPattern(::std::move(path_segments)), + PathExpr(::std::move(outer_attrs)), + has_opening_scope_resolution(has_opening_scope_resolution), locus(locus) {} + + // Creates an error state path in expression. + static PathInExpression create_error() { + return PathInExpression(::std::vector()); + } + + // Returns whether path in expression is in an error state. + inline bool is_error() const { + return !has_segments(); + } + + /* Converts PathInExpression to SimplePath if possible (i.e. no generic arguments). + * Otherwise returns an empty SimplePath. */ + inline SimplePath as_simple_path() const { + /* delegate to parent class as can't access segments. however, + * QualifiedPathInExpression conversion to simple path wouldn't make sense, so the + * method in the parent class should be protected, not public. + * Have to pass in opening scope resolution as parent class has no access to it. */ + return convert_to_simple_path(has_opening_scope_resolution); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual PathInExpression* clone_pattern_impl() const OVERRIDE { + return new PathInExpression(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual PathInExpression* clone_expr_without_block_impl() const OVERRIDE { + return new PathInExpression(*this); + } + }; + + // Base class for segments used in type paths - not abstract (represents an ident-only + // segment) + class TypePathSegment { + /* TODO: may have to unify TypePathSegment and PathExprSegment (which are mostly the + * same anyway) in order to resolve goddamn syntax ambiguities. + * One difference is that function on TypePathSegment is not allowed if GenericArgs are, + * so could disallow that in constructor, which won't give that much size overhead. */ + PathIdentSegment ident_segment; + + location_t locus; + + protected: + // This is protected because it is only really used by derived classes, not the base. + bool has_separating_scope_resolution; + + // Clone function implementation - not pure virtual as overrided by subclasses + virtual TypePathSegment* clone_type_path_segment_impl() const { + return new TypePathSegment(*this); + } + + public: + virtual ~TypePathSegment() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_type_path_segment() const { + return ::std::unique_ptr(clone_type_path_segment_impl()); + } + + TypePathSegment(PathIdentSegment ident_segment, bool has_separating_scope_resolution, + location_t locus) : + ident_segment(::std::move(ident_segment)), + locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} + + TypePathSegment( + ::std::string segment_name, bool has_separating_scope_resolution, location_t locus) : + ident_segment(PathIdentSegment(::std::move(segment_name))), + locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} + + virtual ::std::string as_string() const { + return ident_segment.as_string(); + } + + // Returns whether the type path segment is in an error state. May be virtual in future. + inline bool is_error() const { + return ident_segment.is_error(); + } + + /* Returns whether segment is identifier only (as opposed to generic args or function). + Overriden in derived classes with other segments. */ + virtual bool is_ident_only() const { + return true; + } + + inline bool get_locus() const { + return locus; + } + + // not pure virtual as class not abstract + virtual void accept_vis(ASTVisitor& vis); + }; + + // Segment used in type path with generic args + class TypePathSegmentGeneric : public TypePathSegment { + GenericArgs generic_args; + + public: + inline bool has_generic_args() const { + return generic_args.has_generic_args(); + } + + bool is_ident_only() const { + return false; + } + + // Constructor with PathIdentSegment and GenericArgs + TypePathSegmentGeneric(PathIdentSegment ident_segment, + bool has_separating_scope_resolution, GenericArgs generic_args, location_t locus) : + TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), + generic_args(::std::move(generic_args)) {} + + // Constructor from segment name and all args + TypePathSegmentGeneric(::std::string segment_name, bool has_separating_scope_resolution, + ::std::vector lifetime_args, + ::std::vector< ::std::unique_ptr > type_args, + ::std::vector binding_args, location_t locus) : + TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), + generic_args(GenericArgs( + ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))) {} + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to override base class method + virtual TypePathSegmentGeneric* clone_type_path_segment_impl() const OVERRIDE { + return new TypePathSegmentGeneric(*this); + } + }; + + // A function as represented in a type path + struct TypePathFunction { + private: + // TODO: remove + /*bool has_inputs; + TypePathFnInputs inputs;*/ + //::std::vector inputs; // inlined from TypePathFnInputs + ::std::vector< ::std::unique_ptr > inputs; + + // bool has_type; + // Type type; + ::std::unique_ptr return_type; + + // FIXME: think of better way to mark as invalid than taking up storage + bool is_invalid; + + // TODO: should this have location info? + + protected: + // Constructor only used to create invalid type path functions. + TypePathFunction(bool is_invalid) : is_invalid(is_invalid) {} + + public: + // Returns whether the return type of the function has been specified. + inline bool has_return_type() const { + return return_type != NULL; + } + + // Returns whether the function has inputs. + inline bool has_inputs() const { + return !inputs.empty(); + } + + // Returns whether function is in an error state. + inline bool is_error() const { + return is_invalid; + } + + // Creates an error state function. + static TypePathFunction create_error() { + return TypePathFunction(true); + } + + // Constructor + TypePathFunction(::std::vector< ::std::unique_ptr > inputs, Type* type = NULL) : + inputs(::std::move(inputs)), return_type(type), is_invalid(false) {} + // FIXME: deprecated + + // Constructor + TypePathFunction( + ::std::vector< ::std::unique_ptr > inputs, ::std::unique_ptr type = NULL) : + inputs(::std::move(inputs)), + return_type(::std::move(type)), is_invalid(false) {} + + // Copy constructor with clone + TypePathFunction(TypePathFunction const& other) : + /*inputs(other.inputs),*/ return_type(other.return_type->clone_type()), + is_invalid(other.is_invalid) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + inputs.reserve(other.inputs.size()); + + for (const auto& e : other.inputs) { + inputs.push_back(e->clone_type()); + } + } + + ~TypePathFunction() = default; + + // Overloaded assignment operator to clone type + TypePathFunction& operator=(TypePathFunction const& other) { + // inputs = other.inputs; + return_type = other.return_type->clone_type(); + is_invalid = other.is_invalid; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + inputs.reserve(other.inputs.size()); + + for (const auto& e : other.inputs) { + inputs.push_back(e->clone_type()); + } + + return *this; + } + + // move constructors + TypePathFunction(TypePathFunction&& other) = default; + TypePathFunction& operator=(TypePathFunction&& other) = default; + + ::std::string as_string() const; + }; + + // Segment used in type path with a function argument + class TypePathSegmentFunction : public TypePathSegment { + TypePathFunction function_path; + + public: + // Constructor with PathIdentSegment and TypePathFn + TypePathSegmentFunction(PathIdentSegment ident_segment, + bool has_separating_scope_resolution, TypePathFunction function_path, + location_t locus) : + TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), + function_path(::std::move(function_path)) {} + + // Constructor with segment name and TypePathFn + TypePathSegmentFunction(::std::string segment_name, bool has_separating_scope_resolution, + TypePathFunction function_path, location_t locus) : + TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), + function_path(::std::move(function_path)) {} + + ::std::string as_string() const; + + bool is_ident_only() const { + return false; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to override base class method + virtual TypePathSegmentFunction* clone_type_path_segment_impl() const OVERRIDE { + return new TypePathSegmentFunction(*this); + } + }; + + // Path used inside types + class TypePath : public TypeNoBounds { + bool has_opening_scope_resolution; + ::std::vector< ::std::unique_ptr > segments; + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TypePath* clone_type_impl() const OVERRIDE { + return new TypePath(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TypePath* clone_type_no_bounds_impl() const OVERRIDE { + return new TypePath(*this); + } + + public: + /* Returns whether the TypePath has an opening scope resolution operator (i.e. is global + * path or crate-relative path, not module-relative) */ + inline bool has_opening_scope_resolution_op() const { + return has_opening_scope_resolution; + } + + // Returns whether the TypePath is in an invalid state. + inline bool is_error() const { + return segments.empty(); + } + + // Creates an error state TypePath. + static TypePath create_error() { + return TypePath(::std::vector< ::std::unique_ptr >()); + } + + // Constructor + TypePath(::std::vector< ::std::unique_ptr > segments, + location_t locus = UNKNOWN_LOCATION, bool has_opening_scope_resolution = false) : + has_opening_scope_resolution(has_opening_scope_resolution), + segments(::std::move(segments)), locus(locus) {} + + // Copy constructor with vector clone + TypePath(TypePath const& other) : + has_opening_scope_resolution(other.has_opening_scope_resolution), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + segments.reserve(other.segments.size()); + + for (const auto& e : other.segments) { + segments.push_back(e->clone_type_path_segment()); + } + } + + // Overloaded assignment operator with clone + TypePath& operator=(TypePath const& other) { + has_opening_scope_resolution = other.has_opening_scope_resolution; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + segments.reserve(other.segments.size()); + + for (const auto& e : other.segments) { + segments.push_back(e->clone_type_path_segment()); + } + + return *this; + } + + // move constructors + TypePath(TypePath&& other) = default; + TypePath& operator=(TypePath&& other) = default; + + ::std::string as_string() const; + + /* Converts TypePath to SimplePath if possible (i.e. no generic or function arguments). + * Otherwise returns an empty SimplePath. */ + SimplePath as_simple_path() const; + + // Creates a trait bound with a clone of this type path as its only element. + virtual TraitBound* to_trait_bound(bool in_parens) const OVERRIDE; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + struct QualifiedPathType { + private: + // Type type_to_invoke_on; + ::std::unique_ptr type_to_invoke_on; + + // bool has_as_clause; + TypePath trait_path; + + location_t locus; + + public: + // Constructor + QualifiedPathType(::std::unique_ptr invoke_on_type, + location_t locus = UNKNOWN_LOCATION, TypePath trait_path = TypePath::create_error()) : + type_to_invoke_on(::std::move(invoke_on_type)), + trait_path(::std::move(trait_path)), locus(locus) {} + + // Copy constructor uses custom deep copy for Type to preserve polymorphism + QualifiedPathType(QualifiedPathType const& other) : + type_to_invoke_on(other.type_to_invoke_on->clone_type()), trait_path(other.trait_path), + locus(other.locus) {} + + // default destructor + ~QualifiedPathType() = default; + + // overload assignment operator to use custom clone method + QualifiedPathType& operator=(QualifiedPathType const& other) { + type_to_invoke_on = other.type_to_invoke_on->clone_type(); + trait_path = other.trait_path; + locus = other.locus; + return *this; + } + + // move constructor + QualifiedPathType(QualifiedPathType&& other) = default; + QualifiedPathType& operator=(QualifiedPathType&& other) = default; + + // Returns whether the qualified path type has a rebind as clause. + inline bool has_as_clause() const { + return !trait_path.is_error(); + } + + // Returns whether the qualified path type is in an error state. + inline bool is_error() const { + return type_to_invoke_on == NULL; + } + + // Creates an error state qualified path type. + static QualifiedPathType create_error() { + return QualifiedPathType(NULL); + } + + ::std::string as_string() const; + + inline location_t get_locus() const { + return locus; + } + }; + + /* AST node representing a qualified path-in-expression pattern (path that allows specifying + * trait functions) */ + class QualifiedPathInExpression + : public PathPattern + , public PathExpr { + QualifiedPathType path_type; + + location_t locus; + + public: + ::std::string as_string() const; + + QualifiedPathInExpression(QualifiedPathType qual_path_type, + ::std::vector path_segments, location_t locus = UNKNOWN_LOCATION, + ::std::vector outer_attrs = ::std::vector()) : + PathPattern(::std::move(path_segments)), + PathExpr(::std::move(outer_attrs)), path_type(::std::move(qual_path_type)), + locus(locus) {} + + // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params + + // Copy constructor, destructor, and assignment operator overload shouldn't be required + + // Returns whether qualified path in expression is in an error state. + inline bool is_error() const { + return path_type.is_error(); + } + + // Creates an error qualified path in expression. + static QualifiedPathInExpression create_error() { + return QualifiedPathInExpression( + QualifiedPathType::create_error(), ::std::vector()); + } + + location_t get_locus() const { + return locus; + } + + location_t get_locus_slow() const OVERRIDE { + return get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual QualifiedPathInExpression* clone_pattern_impl() const OVERRIDE { + return new QualifiedPathInExpression(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual QualifiedPathInExpression* clone_expr_without_block_impl() const OVERRIDE { + return new QualifiedPathInExpression(*this); + } + }; + + // Represents a qualified path in a type; used for disambiguating trait function calls + class QualifiedPathInType : public TypeNoBounds { + QualifiedPathType path_type; + // ::std::vector segments; + ::std::vector< ::std::unique_ptr > segments; + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual QualifiedPathInType* clone_type_impl() const OVERRIDE { + return new QualifiedPathInType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual QualifiedPathInType* clone_type_no_bounds_impl() const OVERRIDE { + return new QualifiedPathInType(*this); + } + + public: + QualifiedPathInType(QualifiedPathType qual_path_type, + ::std::vector< ::std::unique_ptr > path_segments, + location_t locus = UNKNOWN_LOCATION) : + path_type(::std::move(qual_path_type)), + segments(::std::move(path_segments)), locus(locus) {} + + // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params + + // Copy constructor with vector clone + QualifiedPathInType(QualifiedPathInType const& other) : + path_type(other.path_type), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + segments.reserve(other.segments.size()); + + for (const auto& e : other.segments) { + segments.push_back(e->clone_type_path_segment()); + } + } + + // Overloaded assignment operator with vector clone + QualifiedPathInType& operator=(QualifiedPathInType const& other) { + path_type = other.path_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + segments.reserve(other.segments.size()); + + for (const auto& e : other.segments) { + segments.push_back(e->clone_type_path_segment()); + } + + return *this; + } + + // move constructors + QualifiedPathInType(QualifiedPathInType&& other) = default; + QualifiedPathInType& operator=(QualifiedPathInType&& other) = default; + + // Returns whether qualified path in type is in an error state. + inline bool is_error() const { + return path_type.is_error(); + } + + // Creates an error state qualified path in type. + static QualifiedPathInType create_error() { + return QualifiedPathInType(QualifiedPathType::create_error(), + ::std::vector< ::std::unique_ptr >()); + } + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h new file mode 100644 index 0000000..f0cabee --- /dev/null +++ b/gcc/rust/ast/rust-pattern.h @@ -0,0 +1,1163 @@ +#ifndef RUST_AST_PATTERN_H +#define RUST_AST_PATTERN_H + +#include "rust-ast.h" + +namespace Rust { + namespace AST { + // Literal pattern AST node (comparing to a literal) + class LiteralPattern : public Pattern { + Literal lit; // make literal have a type given by enum, etc. rustc uses an extended form + // of its literal token implementation + // FIXME: literal representation - use LiteralExpr? or another thing? + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + // Actually, this might be a good place to use a template. + + location_t locus; + + public: + ::std::string as_string() const; + + // Constructor for a literal pattern + LiteralPattern(Literal lit, location_t locus, bool has_minus = false) : + lit(::std::move(lit)), has_minus(has_minus), locus(locus) {} + + LiteralPattern( + ::std::string val, Literal::LitType type, location_t locus, bool has_minus = false) : + lit(Literal(::std::move(val), type)), + has_minus(has_minus), locus(locus) {} + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LiteralPattern* clone_pattern_impl() const OVERRIDE { + return new LiteralPattern(*this); + } + }; + + // Identifier pattern AST node (bind value matched to a variable) + class IdentifierPattern : public Pattern { + Identifier variable_ident; + bool is_ref; + bool is_mut; + + // bool has_pattern; + // Pattern* to_bind; + ::std::unique_ptr to_bind; + + location_t locus; + + public: + /*~IdentifierPattern() { + delete to_bind; + }*/ + + ::std::string as_string() const; + + // Returns whether the IdentifierPattern has a pattern to bind. + inline bool has_pattern_to_bind() const { + return to_bind != NULL; + } + + // Constructor + IdentifierPattern(Identifier ident, location_t locus, bool is_ref = false, + bool is_mut = false, ::std::unique_ptr to_bind = NULL) : + variable_ident(::std::move(ident)), + is_ref(is_ref), is_mut(is_mut), to_bind(::std::move(to_bind)), locus(locus) {} + + // Copy constructor with clone + IdentifierPattern(IdentifierPattern const& other) : + variable_ident(other.variable_ident), is_ref(other.is_ref), is_mut(other.is_mut), + locus(other.locus) { + // fix to get prevent null pointer dereference + if (other.to_bind != NULL) { + to_bind = other.to_bind->clone_pattern(); + } + } + + // Destructor - define here if required + + // Overload assignment operator to use clone + IdentifierPattern& operator=(IdentifierPattern const& other) { + variable_ident = other.variable_ident; + is_ref = other.is_ref; + is_mut = other.is_mut; + locus = other.locus; + // fix to get prevent null pointer dereference + if (other.to_bind != NULL) { + to_bind = other.to_bind->clone_pattern(); + } + + return *this; + } + + // default move semantics + IdentifierPattern(IdentifierPattern&& other) = default; + IdentifierPattern& operator=(IdentifierPattern&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual IdentifierPattern* clone_pattern_impl() const OVERRIDE { + return new IdentifierPattern(*this); + } + }; + + // AST node for using the '_' wildcard "match any value" pattern + class WildcardPattern : public Pattern { + location_t locus; + + public: + ::std::string as_string() const { + return ::std::string(1, '_'); + } + + WildcardPattern(location_t locus) : locus(locus) {} + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual WildcardPattern* clone_pattern_impl() const OVERRIDE { + return new WildcardPattern(*this); + } + }; + + // Base range pattern bound (lower or upper limit) - abstract + class RangePatternBound { + /*union { + CharLiteral char_lit; + ByteLiteral byte_lit; + IntLiteral int_lit; + FloatLiteral float_lit; + PathInExpression path; + QualifiedPathInExpression qual_path; + } pattern;*/ + public: + virtual ~RangePatternBound() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_range_pattern_bound() const { + return ::std::unique_ptr(clone_range_pattern_bound_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual as RangePatternBound is abstract + virtual RangePatternBound* clone_range_pattern_bound_impl() const = 0; + }; + + // Literal-based pattern bound + class RangePatternBoundLiteral : public RangePatternBound { + Literal literal; + // Can only be a char, byte, int, or float literal - same impl here as previously + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + + location_t locus; + + public: + // Constructor + RangePatternBoundLiteral(Literal literal, location_t locus, bool has_minus = false) : + literal(literal), has_minus(has_minus), locus(locus) {} + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangePatternBoundLiteral* clone_range_pattern_bound_impl() const OVERRIDE { + return new RangePatternBoundLiteral(*this); + } + }; + + // Path-based pattern bound + class RangePatternBoundPath : public RangePatternBound { + PathInExpression path; + + // TODO: should this be refactored so that PathInExpression is a subclass of + // RangePatternBound? + + public: + RangePatternBoundPath(PathInExpression path) : path(::std::move(path)) {} + + ::std::string as_string() const { + return path.as_string(); + } + + location_t get_locus() const { + return path.get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangePatternBoundPath* clone_range_pattern_bound_impl() const OVERRIDE { + return new RangePatternBoundPath(*this); + } + }; + + // Qualified path-based pattern bound + class RangePatternBoundQualPath : public RangePatternBound { + QualifiedPathInExpression path; + + /* TODO: should this be refactored so that QualifiedPathInExpression is a subclass of + * RangePatternBound? */ + + public: + RangePatternBoundQualPath(QualifiedPathInExpression path) : path(::std::move(path)) {} + + ::std::string as_string() const { + return path.as_string(); + } + + location_t get_locus() const { + return path.get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangePatternBoundQualPath* clone_range_pattern_bound_impl() const OVERRIDE { + return new RangePatternBoundQualPath(*this); + } + }; + + // AST node for matching within a certain range (range pattern) + class RangePattern : public Pattern { + /*RangePatternBound lower; + RangePatternBound upper;*/ + ::std::unique_ptr lower; + ::std::unique_ptr upper; + + bool has_ellipsis_syntax; + + // location only stored to avoid a dereference - lower pattern should give correct + // location so maybe change in future + location_t locus; + + public: + ::std::string as_string() const; + + // Constructor + RangePattern(::std::unique_ptr lower, + ::std::unique_ptr upper, location_t locus, + bool has_ellipsis_syntax = false) : + lower(::std::move(lower)), + upper(::std::move(upper)), has_ellipsis_syntax(has_ellipsis_syntax), locus(locus) {} + + // Copy constructor with clone + RangePattern(RangePattern const& other) : + lower(other.lower->clone_range_pattern_bound()), + upper(other.upper->clone_range_pattern_bound()), + has_ellipsis_syntax(other.has_ellipsis_syntax), locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + RangePattern& operator=(RangePattern const& other) { + lower = other.lower->clone_range_pattern_bound(); + upper = other.upper->clone_range_pattern_bound(); + has_ellipsis_syntax = other.has_ellipsis_syntax; + locus = other.locus; + + return *this; + } + + // default move semantics + RangePattern(RangePattern&& other) = default; + RangePattern& operator=(RangePattern&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RangePattern* clone_pattern_impl() const OVERRIDE { + return new RangePattern(*this); + } + }; + + // AST node for pattern based on dereferencing the pointers given + class ReferencePattern : public Pattern { + bool has_two_amps; + bool is_mut; + // Pattern* pattern; + ::std::unique_ptr pattern; + + location_t locus; + + public: + /*~ReferencePattern() { + delete pattern; + }*/ + + ::std::string as_string() const; + + ReferencePattern(::std::unique_ptr pattern, bool is_mut_reference, + bool ref_has_two_amps, location_t locus) : + has_two_amps(ref_has_two_amps), + is_mut(is_mut_reference), pattern(::std::move(pattern)), locus(locus) {} + + // Copy constructor requires clone + ReferencePattern(ReferencePattern const& other) : + has_two_amps(other.has_two_amps), is_mut(other.is_mut), + pattern(other.pattern->clone_pattern()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + ReferencePattern& operator=(ReferencePattern const& other) { + pattern = other.pattern->clone_pattern(); + is_mut = other.is_mut; + has_two_amps = other.has_two_amps; + locus = other.locus; + + return *this; + } + + // default move semantics + ReferencePattern(ReferencePattern&& other) = default; + ReferencePattern& operator=(ReferencePattern&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ReferencePattern* clone_pattern_impl() const OVERRIDE { + return new ReferencePattern(*this); + } + }; + + // aka StructPatternEtCetera; potential element in struct pattern + struct StructPatternEtc { + private: + ::std::vector outer_attrs; + + // should this store location data? + + public: + StructPatternEtc(::std::vector outer_attribs) : + outer_attrs(::std::move(outer_attribs)) {} + + // Creates an empty StructPatternEtc + static StructPatternEtc create_empty() { + return StructPatternEtc(::std::vector()); + } + }; + + // Base class for a single field in a struct pattern - abstract + class StructPatternField { + ::std::vector outer_attrs; + /*union { + struct { + //TupleIndex index; + Pattern tuple_pattern; + } tuple_pattern; + struct { + //Identifier ident; + Pattern ident_pattern; + } ident_pattern; + struct { + bool has_ref; + bool has_mut; + //Identifier ident; + } ident; + } pattern;*/ + + location_t locus; + + public: + virtual ~StructPatternField() {} + + // Unique pointer custom clone function + ::std::unique_ptr clone_struct_pattern_field() const { + return ::std::unique_ptr(clone_struct_pattern_field_impl()); + } + + virtual ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + StructPatternField(::std::vector outer_attribs, location_t locus) : + outer_attrs(::std::move(outer_attribs)), locus(locus) {} + + // Clone function implementation as pure virtual method + virtual StructPatternField* clone_struct_pattern_field_impl() const = 0; + }; + + // Tuple pattern single field in a struct pattern + class StructPatternFieldTuplePat : public StructPatternField { + TupleIndex index; + // Pattern* tuple_pattern; + ::std::unique_ptr tuple_pattern; + + public: + /*~StructPatternFieldTuplePat() { + delete tuple_pattern; + }*/ + + StructPatternFieldTuplePat(TupleIndex index, ::std::unique_ptr tuple_pattern, + ::std::vector outer_attribs, location_t locus) : + StructPatternField(::std::move(outer_attribs), locus), + index(index), tuple_pattern(::std::move(tuple_pattern)) {} + + // Copy constructor requires clone + StructPatternFieldTuplePat(StructPatternFieldTuplePat const& other) : + StructPatternField(other), index(other.index), + tuple_pattern(other.tuple_pattern->clone_pattern()) {} + + // Destructor - define here if required + + // Overload assignment operator to perform clone + StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat const& other) { + StructPatternField::operator=(other); + tuple_pattern = other.tuple_pattern->clone_pattern(); + index = other.index; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldTuplePat(StructPatternFieldTuplePat&& other) = default; + StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructPatternFieldTuplePat* clone_struct_pattern_field_impl() const OVERRIDE { + return new StructPatternFieldTuplePat(*this); + } + }; + + // Identifier pattern single field in a struct pattern + class StructPatternFieldIdentPat : public StructPatternField { + Identifier ident; + // Pattern* ident_pattern; + ::std::unique_ptr ident_pattern; + + public: + /*~StructPatternFieldIdentPat() { + delete ident_pattern; + }*/ + + StructPatternFieldIdentPat(Identifier ident, ::std::unique_ptr ident_pattern, + ::std::vector outer_attrs, location_t locus) : + StructPatternField(::std::move(outer_attrs), locus), + ident(::std::move(ident)), ident_pattern(::std::move(ident_pattern)) {} + + // Copy constructor requires clone + StructPatternFieldIdentPat(StructPatternFieldIdentPat const& other) : + StructPatternField(other), ident(other.ident), + ident_pattern(other.ident_pattern->clone_pattern()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat const& other) { + StructPatternField::operator=(other); + ident = other.ident; + ident_pattern = other.ident_pattern->clone_pattern(); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldIdentPat(StructPatternFieldIdentPat&& other) = default; + StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructPatternFieldIdentPat* clone_struct_pattern_field_impl() const OVERRIDE { + return new StructPatternFieldIdentPat(*this); + } + }; + + // Identifier only (with no pattern) single field in a struct pattern + class StructPatternFieldIdent : public StructPatternField { + bool has_ref; + bool has_mut; + + Identifier ident; + + public: + StructPatternFieldIdent(Identifier ident, bool is_ref, bool is_mut, + ::std::vector outer_attrs, location_t locus) : + StructPatternField(::std::move(outer_attrs), locus), + has_ref(is_ref), has_mut(is_mut), ident(::std::move(ident)) {} + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructPatternFieldIdent* clone_struct_pattern_field_impl() const OVERRIDE { + return new StructPatternFieldIdent(*this); + } + }; + + // Elements of a struct pattern + struct StructPatternElements { + private: + // bool has_struct_pattern_fields; + //::std::vector fields; + ::std::vector< ::std::unique_ptr > fields; + + bool has_struct_pattern_etc; + StructPatternEtc etc; + + // must have at least one of the two and maybe both + + // should this store location data? + + public: + // Returns whether there are any struct pattern fields + inline bool has_struct_pattern_fields() const { + return !fields.empty(); + } + + // Returns whether the struct pattern elements is entirely empty (no fields, no etc). + inline bool is_empty() const { + return !has_struct_pattern_fields() && !has_struct_pattern_etc; + } + + // Constructor for StructPatternElements with both (potentially) + StructPatternElements( + ::std::vector< ::std::unique_ptr > fields, StructPatternEtc etc) : + fields(::std::move(fields)), + has_struct_pattern_etc(true), etc(::std::move(etc)) {} + + // Constructor for StructPatternElements with no StructPatternEtc + StructPatternElements(::std::vector< ::std::unique_ptr > fields) : + fields(::std::move(fields)), has_struct_pattern_etc(false), + etc(StructPatternEtc::create_empty()) {} + + // Copy constructor with vector clone + StructPatternElements(StructPatternElements const& other) : + has_struct_pattern_etc(other.has_struct_pattern_etc), etc(other.etc) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + for (const auto& e : other.fields) { + fields.push_back(e->clone_struct_pattern_field()); + } + } + + // Overloaded assignment operator with vector clone + StructPatternElements& operator=(StructPatternElements const& other) { + etc = other.etc; + has_struct_pattern_etc = other.has_struct_pattern_etc; + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + fields.reserve(other.fields.size()); + + for (const auto& e : other.fields) { + fields.push_back(e->clone_struct_pattern_field()); + } + + return *this; + } + + // move constructors + StructPatternElements(StructPatternElements&& other) = default; + StructPatternElements& operator=(StructPatternElements&& other) = default; + + // Creates an empty StructPatternElements + static StructPatternElements create_empty() { + return StructPatternElements( + ::std::vector< ::std::unique_ptr >()); + } + + ::std::string as_string() const; + }; + + // Struct pattern AST node representation + class StructPattern : public Pattern { + PathInExpression path; + + // bool has_struct_pattern_elements; + StructPatternElements elems; + + // TODO: should this store location data? Accessor uses path location data. + + public: + ::std::string as_string() const; + + // Constructs a struct pattern from specified StructPatternElements + StructPattern(PathInExpression struct_path, + StructPatternElements elems = StructPatternElements::create_empty()) : + path(::std::move(struct_path)), + elems(::std::move(elems)) {} + + // TODO: constructor to construct via elements included in StructPatternElements + + // Returns whether struct pattern has any struct pattern elements (if not, it is empty). + inline bool has_struct_pattern_elems() const { + return !elems.is_empty(); + } + + location_t get_locus() const { + return path.get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual StructPattern* clone_pattern_impl() const OVERRIDE { + return new StructPattern(*this); + } + }; + + // Base abstract class for patterns used in TupleStructPattern + class TupleStructItems { + public: + virtual ~TupleStructItems() {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + ::std::unique_ptr clone_tuple_struct_items() const { + return ::std::unique_ptr(clone_tuple_struct_items_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual clone implementation + virtual TupleStructItems* clone_tuple_struct_items_impl() const = 0; + }; + + // Class for non-ranged tuple struct pattern patterns + class TupleStructItemsNoRange : public TupleStructItems { + //::std::vector patterns; + ::std::vector< ::std::unique_ptr > patterns; + + public: + TupleStructItemsNoRange(::std::vector< ::std::unique_ptr > patterns) : + patterns(::std::move(patterns)) {} + + // Copy constructor with vector clone + TupleStructItemsNoRange(TupleStructItemsNoRange const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + patterns.reserve(other.patterns.size()); + + for (const auto& e : other.patterns) { + patterns.push_back(e->clone_pattern()); + } + } + + // Overloaded assignment operator with vector clone + TupleStructItemsNoRange& operator=(TupleStructItemsNoRange const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + patterns.reserve(other.patterns.size()); + + for (const auto& e : other.patterns) { + patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + TupleStructItemsNoRange(TupleStructItemsNoRange&& other) = default; + TupleStructItemsNoRange& operator=(TupleStructItemsNoRange&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleStructItemsNoRange* clone_tuple_struct_items_impl() const OVERRIDE { + return new TupleStructItemsNoRange(*this); + } + }; + + // Class for ranged tuple struct pattern patterns + class TupleStructItemsRange : public TupleStructItems { + /*::std::vector lower_patterns; + ::std::vector upper_patterns;*/ + ::std::vector< ::std::unique_ptr > lower_patterns; + ::std::vector< ::std::unique_ptr > upper_patterns; + + public: + TupleStructItemsRange(::std::vector< ::std::unique_ptr > lower_patterns, + ::std::vector< ::std::unique_ptr > upper_patterns) : + lower_patterns(::std::move(lower_patterns)), + upper_patterns(::std::move(upper_patterns)) {} + + // Copy constructor with vector clone + TupleStructItemsRange(TupleStructItemsRange const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + lower_patterns.reserve(other.lower_patterns.size()); + + for (const auto& e : other.lower_patterns) { + lower_patterns.push_back(e->clone_pattern()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + upper_patterns.reserve(other.upper_patterns.size()); + + for (const auto& e : other.upper_patterns) { + upper_patterns.push_back(e->clone_pattern()); + } + } + + // Overloaded assignment operator to clone + TupleStructItemsRange& operator=(TupleStructItemsRange const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + lower_patterns.reserve(other.lower_patterns.size()); + + for (const auto& e : other.lower_patterns) { + lower_patterns.push_back(e->clone_pattern()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + upper_patterns.reserve(other.upper_patterns.size()); + + for (const auto& e : other.upper_patterns) { + upper_patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + TupleStructItemsRange(TupleStructItemsRange&& other) = default; + TupleStructItemsRange& operator=(TupleStructItemsRange&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleStructItemsRange* clone_tuple_struct_items_impl() const OVERRIDE { + return new TupleStructItemsRange(*this); + } + }; + + // AST node representing a tuple struct pattern + class TupleStructPattern : public Pattern { + PathInExpression path; + // TupleStructItems items; + ::std::unique_ptr items; + + // TOOD: should this store location data? current accessor uses path location data + + public: + ::std::string as_string() const; + + TupleStructPattern( + PathInExpression tuple_struct_path, ::std::unique_ptr items) : + path(::std::move(tuple_struct_path)), + items(::std::move(items)) {} + + // Copy constructor required to clone + TupleStructPattern(TupleStructPattern const& other) : + path(other.path), items(other.items->clone_tuple_struct_items()) {} + + // Destructor - define here if required + + // Operator overload assignment operator to clone + TupleStructPattern& operator=(TupleStructPattern const& other) { + path = other.path; + items = other.items->clone_tuple_struct_items(); + + return *this; + } + + // move constructors + TupleStructPattern(TupleStructPattern&& other) = default; + TupleStructPattern& operator=(TupleStructPattern&& other) = default; + + location_t get_locus() const { + return path.get_locus(); + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleStructPattern* clone_pattern_impl() const OVERRIDE { + return new TupleStructPattern(*this); + } + }; + + // Base abstract class representing TuplePattern patterns + class TuplePatternItems { + public: + virtual ~TuplePatternItems() {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + ::std::unique_ptr clone_tuple_pattern_items() const { + return ::std::unique_ptr(clone_tuple_pattern_items_impl()); + } + + virtual ::std::string as_string() const = 0; + + virtual void accept_vis(ASTVisitor& vis) = 0; + + protected: + // pure virtual clone implementation + virtual TuplePatternItems* clone_tuple_pattern_items_impl() const = 0; + }; + + // Class representing TuplePattern patterns where there is only a single pattern + /*class TuplePatternItemsSingle : public TuplePatternItems { + // Pattern pattern; + ::std::unique_ptr pattern; + + public: + TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} + + // Copy constructor uses clone + TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : + pattern(other.pattern->clone_pattern()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { + pattern = other.pattern->clone_pattern(); + + return *this; + } + + // move constructors + TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = default; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TuplePatternItemsSingle* clone_tuple_pattern_items_impl() const OVERRIDE { + return new TuplePatternItemsSingle(*this); + } + };*/ + // removed in favour of single-element TuplePatternItemsMultiple + + // Class representing TuplePattern patterns where there are multiple patterns + class TuplePatternItemsMultiple : public TuplePatternItems { + //::std::vector patterns; + ::std::vector< ::std::unique_ptr > patterns; + + public: + TuplePatternItemsMultiple(::std::vector< ::std::unique_ptr > patterns) : + patterns(::std::move(patterns)) {} + + // Copy constructor with vector clone + TuplePatternItemsMultiple(TuplePatternItemsMultiple const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + patterns.reserve(other.patterns.size()); + + for (const auto& e : other.patterns) { + patterns.push_back(e->clone_pattern()); + } + } + + // Overloaded assignment operator to vector clone + TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + patterns.reserve(other.patterns.size()); + + for (const auto& e : other.patterns) { + patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + TuplePatternItemsMultiple(TuplePatternItemsMultiple&& other) = default; + TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TuplePatternItemsMultiple* clone_tuple_pattern_items_impl() const OVERRIDE { + return new TuplePatternItemsMultiple(*this); + } + }; + + // Class representing TuplePattern patterns where there are a range of patterns + class TuplePatternItemsRanged : public TuplePatternItems { + /*::std::vector lower_patterns; + ::std::vector upper_patterns;*/ + ::std::vector< ::std::unique_ptr > lower_patterns; + ::std::vector< ::std::unique_ptr > upper_patterns; + + public: + TuplePatternItemsRanged(::std::vector< ::std::unique_ptr > lower_patterns, + ::std::vector< ::std::unique_ptr > upper_patterns) : + lower_patterns(::std::move(lower_patterns)), + upper_patterns(::std::move(upper_patterns)) {} + + // Copy constructor with vector clone + TuplePatternItemsRanged(TuplePatternItemsRanged const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + lower_patterns.reserve(other.lower_patterns.size()); + + for (const auto& e : other.lower_patterns) { + lower_patterns.push_back(e->clone_pattern()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + upper_patterns.reserve(other.upper_patterns.size()); + + for (const auto& e : other.upper_patterns) { + upper_patterns.push_back(e->clone_pattern()); + } + } + + // Overloaded assignment operator to clone + TuplePatternItemsRanged& operator=(TuplePatternItemsRanged const& other) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + lower_patterns.reserve(other.lower_patterns.size()); + + for (const auto& e : other.lower_patterns) { + lower_patterns.push_back(e->clone_pattern()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing this? + upper_patterns.reserve(other.upper_patterns.size()); + + for (const auto& e : other.upper_patterns) { + upper_patterns.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + TuplePatternItemsRanged(TuplePatternItemsRanged&& other) = default; + TuplePatternItemsRanged& operator=(TuplePatternItemsRanged&& other) = default; + + ::std::string as_string() const; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TuplePatternItemsRanged* clone_tuple_pattern_items_impl() const OVERRIDE { + return new TuplePatternItemsRanged(*this); + } + }; + + // AST node representing a tuple pattern + class TuplePattern : public Pattern { + // bool has_tuple_pattern_items; + // TuplePatternItems items; + ::std::unique_ptr items; + + location_t locus; + + public: + ::std::string as_string() const; + + // Returns true if the tuple pattern has items + inline bool has_tuple_pattern_items() const { + return items != NULL; + } + + TuplePattern(::std::unique_ptr items, location_t locus) : + items(::std::move(items)), locus(locus) {} + + // Copy constructor requires clone + TuplePattern(TuplePattern const& other) : + items(other.items->clone_tuple_pattern_items()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + TuplePattern& operator=(TuplePattern const& other) { + items = other.items->clone_tuple_pattern_items(); + locus = other.locus; + + return *this; + } + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TuplePattern* clone_pattern_impl() const OVERRIDE { + return new TuplePattern(*this); + } + }; + + // AST node representing a pattern in parentheses, used to control precedence + class GroupedPattern : public Pattern { + // Pattern pattern_in_parens; + ::std::unique_ptr pattern_in_parens; + + location_t locus; + + public: + ::std::string as_string() const { + return "(" + pattern_in_parens->as_string() + ")"; + } + + GroupedPattern(::std::unique_ptr pattern_in_parens, location_t locus) : + pattern_in_parens(::std::move(pattern_in_parens)), locus(locus) {} + + // Copy constructor uses clone + GroupedPattern(GroupedPattern const& other) : + pattern_in_parens(other.pattern_in_parens->clone_pattern()), locus(other.locus) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + GroupedPattern& operator=(GroupedPattern const& other) { + pattern_in_parens = other.pattern_in_parens->clone_pattern(); + locus = other.locus; + + return *this; + } + + // default move semantics + GroupedPattern(GroupedPattern&& other) = default; + GroupedPattern& operator=(GroupedPattern&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual GroupedPattern* clone_pattern_impl() const OVERRIDE { + return new GroupedPattern(*this); + } + }; + + // AST node representing patterns that can match slices and arrays + class SlicePattern : public Pattern { + //::std::vector items; + ::std::vector< ::std::unique_ptr > items; + + location_t locus; + + public: + ::std::string as_string() const; + + SlicePattern(::std::vector< ::std::unique_ptr > items, location_t locus) : + items(::std::move(items)), locus(locus) {} + + // Copy constructor with vector clone + SlicePattern(SlicePattern const& other) : locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_pattern()); + } + } + + // Overloaded assignment operator to vector clone + SlicePattern& operator=(SlicePattern const& other) { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing this? + items.reserve(other.items.size()); + + for (const auto& e : other.items) { + items.push_back(e->clone_pattern()); + } + + return *this; + } + + // move constructors + SlicePattern(SlicePattern&& other) = default; + SlicePattern& operator=(SlicePattern&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual SlicePattern* clone_pattern_impl() const OVERRIDE { + return new SlicePattern(*this); + } + }; + + // forward decl PathExprSegment + // class PathExprSegment; + + // Moved definition to rust-path.h + class PathPattern; + + // Forward decls for paths (defined in rust-path.h) + class PathInExpression; + class QualifiedPathInExpression; + + // Replaced with forward decl - defined in rust-macro.h + class MacroInvocation; + /*class MacroInvocation : public Pattern { + public: + ::std::string as_string() const; + };*/ + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h new file mode 100644 index 0000000..ece0801 --- /dev/null +++ b/gcc/rust/ast/rust-stmt.h @@ -0,0 +1,245 @@ +#ifndef RUST_AST_STATEMENT_H +#define RUST_AST_STATEMENT_H + +#include "rust-ast.h" +#include "rust-path.h" +#include "rust-expr.h" + +namespace Rust { + namespace AST { + // Just a semi-colon, which apparently is a statement. + class EmptyStmt : public Stmt { + location_t locus; + + public: + ::std::string as_string() const { + return ::std::string(1, ';'); + } + + EmptyStmt(location_t locus) : locus(locus) {} + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual EmptyStmt* clone_stmt_impl() const OVERRIDE { + return new EmptyStmt(*this); + } + }; + + /* This is syntactically identical to declaring an item inside a module BUT it has block + * scope. Type of "declaration statement" as it introduces new name into scope */ + /*class ItemStatement : public Statement { + // TODO: put in same params as regular item + // maybe even merge data structure with module item? + + public: + ::std::string as_string() const; + };*/ + // removed - just made item inherit from statement + + /* Variable assignment let statement - type of "declaration statement" as it introduces new + * name into scope */ + class LetStmt : public Stmt { + // bool has_outer_attrs; + ::std::vector outer_attrs; + + // Pattern variables_pattern; + ::std::unique_ptr variables_pattern; + + // bool has_type; + // Type type; + ::std::unique_ptr type; + + // bool has_init_expr; + // Expr* init_expr; + ::std::unique_ptr init_expr; + + location_t locus; + + public: + // Returns whether let statement has outer attributes. + inline bool has_outer_attrs() const { + return !outer_attrs.empty(); + } + + // Returns whether let statement has a given return type. + inline bool has_type() const { + return type != NULL; + } + + // Returns whether let statement has an initialisation expression. + inline bool has_init_expr() const { + return init_expr != NULL; + } + + /*~LetStatement() { + if (has_init_expr) { + delete init_expr; + } + }*/ + + ::std::string as_string() const; + + LetStmt(::std::unique_ptr variables_pattern, ::std::unique_ptr init_expr, + ::std::unique_ptr type, ::std::vector outer_attrs, location_t locus) : + outer_attrs(::std::move(outer_attrs)), + variables_pattern(::std::move(variables_pattern)), type(::std::move(type)), + init_expr(::std::move(init_expr)), locus(locus) {} + + // Copy constructor with clone + LetStmt(LetStmt const& other) : + outer_attrs(other.outer_attrs), + variables_pattern(other.variables_pattern->clone_pattern()), + type(other.type->clone_type()), init_expr(other.init_expr->clone_expr()), + locus(other.locus) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + LetStmt& operator=(LetStmt const& other) { + variables_pattern = other.variables_pattern->clone_pattern(); + init_expr = other.init_expr->clone_expr(); + type = other.type->clone_type(); + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + LetStmt(LetStmt&& other) = default; + LetStmt& operator=(LetStmt&& other) = default; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual LetStmt* clone_stmt_impl() const OVERRIDE { + return new LetStmt(*this); + } + }; + + // Abstract base class for expression statements (statements containing an expression) + class ExprStmt : public Stmt { + // TODO: add any useful virtual functions + + location_t locus; + + public: + location_t get_locus() const { + return locus; + } + + protected: + ExprStmt(location_t locus) : locus(locus) {} + }; + + /* Statement containing an expression without a block (or, due to technical difficulties, can + * only be guaranteed to hold an expression). */ + class ExprStmtWithoutBlock : public ExprStmt { + // ExprWithoutBlock* expr; + /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, so have to + * store more general type of Expr. FIXME: fix this issue somehow or redesign AST. */ + //::std::unique_ptr expr; + ::std::unique_ptr expr; + + public: + /*~ExpressionStatementWithoutBlock() { + delete expr; + }*/ + + ::std::string as_string() const; + + // ExprStmtWithoutBlock(::std::unique_ptr expr) : + // expr(::std::move(expr)) {} + ExprStmtWithoutBlock(::std::unique_ptr expr, location_t locus) : + ExprStmt(locus), expr(::std::move(expr)) {} + + // Copy constructor with clone + ExprStmtWithoutBlock(ExprStmtWithoutBlock const& other) : + ExprStmt(other), expr(other.expr->clone_expr /*_without_block*/ ()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock const& other) { + ExprStmt::operator=(other); + expr = other.expr->clone_expr /*_without_block*/ (); + + return *this; + } + + // move constructors + ExprStmtWithoutBlock(ExprStmtWithoutBlock&& other) = default; + ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExprStmtWithoutBlock* clone_stmt_impl() const OVERRIDE { + return new ExprStmtWithoutBlock(*this); + } + }; + + // Statement containing an expression with a block + class ExprStmtWithBlock : public ExprStmt { + // ExprWithBlock* expr; + ::std::unique_ptr expr; + + public: + /*~ExpressionStatementWithBlock() { + delete expr; + }*/ + + ::std::string as_string() const; + + ExprStmtWithBlock(::std::unique_ptr expr, location_t locus) : + ExprStmt(locus), expr(::std::move(expr)) {} + + // Copy constructor with clone + ExprStmtWithBlock(ExprStmtWithBlock const& other) : + ExprStmt(other), expr(other.expr->clone_expr_with_block()) {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ExprStmtWithBlock& operator=(ExprStmtWithBlock const& other) { + ExprStmt::operator=(other); + expr = other.expr->clone_expr_with_block(); + + return *this; + } + + // move constructors + ExprStmtWithBlock(ExprStmtWithBlock&& other) = default; + ExprStmtWithBlock& operator=(ExprStmtWithBlock&& other) = default; + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ExprStmtWithBlock* clone_stmt_impl() const OVERRIDE { + return new ExprStmtWithBlock(*this); + } + }; + + // Replaced definition of MacroInvocationSemi with forward decl - defined in rust-macro.h + class MacroInvocationSemi; + /*class MacroInvocationSemi : public Statement { + public: + ::std::string as_string() const; + };*/ + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h new file mode 100644 index 0000000..4ca408d --- /dev/null +++ b/gcc/rust/ast/rust-type.h @@ -0,0 +1,828 @@ +#ifndef RUST_AST_TYPE_H +#define RUST_AST_TYPE_H + +#include "rust-ast.h" +#include "rust-path.h" + +namespace Rust { + namespace AST { + // definitions moved to rust-ast.h + class TypeParamBound; + class Lifetime; + + // A trait bound + class TraitBound : public TypeParamBound { + bool in_parens; + bool opening_question_mark; + + // bool has_for_lifetimes; + // LifetimeParams for_lifetimes; + ::std::vector for_lifetimes; // inlined LifetimeParams + + TypePath type_path; + + location_t locus; + + public: + // Returns whether trait bound has "for" lifetimes + inline bool has_for_lifetimes() const { + return !for_lifetimes.empty(); + } + + TraitBound(TypePath type_path, location_t locus, bool in_parens = false, + bool opening_question_mark = false, + ::std::vector for_lifetimes = ::std::vector()) : + in_parens(in_parens), + opening_question_mark(opening_question_mark), for_lifetimes(::std::move(for_lifetimes)), + type_path(::std::move(type_path)), locus(locus) {} + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Clone function implementation as (not pure) virtual method + virtual TraitBound* clone_type_param_bound_impl() const { + return new TraitBound(*this); + } + }; + + // definition moved to rust-ast.h + class TypeNoBounds; + + // An impl trait? Poor reference material here. + class ImplTraitType : public Type { + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ImplTraitType* clone_type_impl() const OVERRIDE { + return new ImplTraitType(*this); + } + + public: + ImplTraitType(::std::vector< ::std::unique_ptr > type_param_bounds, + location_t locus) : + type_param_bounds(::std::move(type_param_bounds)), + locus(locus) {} + + // copy constructor with vector clone + ImplTraitType(ImplTraitType const& other) : locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + } + + // overloaded assignment operator to clone + ImplTraitType& operator=(ImplTraitType const& other) { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + return *this; + } + + // move constructors + ImplTraitType(ImplTraitType&& other) = default; + ImplTraitType& operator=(ImplTraitType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + // An opaque value of another type that implements a set of traits + class TraitObjectType : public Type { + bool has_dyn; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TraitObjectType* clone_type_impl() const OVERRIDE { + return new TraitObjectType(*this); + } + + public: + TraitObjectType(::std::vector< ::std::unique_ptr > type_param_bounds, + location_t locus, bool is_dyn_dispatch = false) : + has_dyn(is_dyn_dispatch), + type_param_bounds(::std::move(type_param_bounds)), locus(locus) {} + + // copy constructor with vector clone + TraitObjectType(TraitObjectType const& other) : + has_dyn(other.has_dyn), locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + } + + // overloaded assignment operator to clone + TraitObjectType& operator=(TraitObjectType const& other) { + has_dyn = other.has_dyn; + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing this? + type_param_bounds.reserve(other.type_param_bounds.size()); + + for (const auto& e : other.type_param_bounds) { + type_param_bounds.push_back(e->clone_type_param_bound()); + } + + return *this; + } + + // move constructors + TraitObjectType(TraitObjectType&& other) = default; + TraitObjectType& operator=(TraitObjectType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + // A type with parentheses around it, used to avoid ambiguity. + class ParenthesisedType : public TypeNoBounds { + // Type type_in_parens; + ::std::unique_ptr type_in_parens; + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ParenthesisedType* clone_type_impl() const OVERRIDE { + return new ParenthesisedType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ParenthesisedType* clone_type_no_bounds_impl() const OVERRIDE { + return new ParenthesisedType(*this); + } + + public: + // Constructor uses Type pointer for polymorphism + ParenthesisedType(::std::unique_ptr type_inside_parens, location_t locus) : + type_in_parens(::std::move(type_inside_parens)), locus(locus) {} + + // Copy constructor uses custom deep copy method for type to preserve polymorphism + ParenthesisedType(ParenthesisedType const& other) : + type_in_parens(other.type_in_parens->clone_type()), locus(other.locus) {} + + // define destructor here if required + + // overload assignment operator to use custom clone method + ParenthesisedType& operator=(ParenthesisedType const& other) { + type_in_parens = other.type_in_parens->clone_type(); + locus = other.locus; + return *this; + } + + // default move semantics + ParenthesisedType(ParenthesisedType&& other) = default; + ParenthesisedType& operator=(ParenthesisedType&& other) = default; + + ::std::string as_string() const { + return "(" + type_in_parens->as_string() + ")"; + } + + // Creates a trait bound (clone of this one's trait bound) - HACK + virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { + /* NOTE: obviously it is unknown whether the internal type is a trait bound due to + * polymorphism, so just let the internal type handle it. As parenthesised type, it + * must be in parentheses. */ + return type_in_parens->to_trait_bound(true); + } + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + // Impl trait with a single bound? Poor reference material here. + class ImplTraitTypeOneBound : public TypeNoBounds { + TraitBound trait_bound; + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ImplTraitTypeOneBound* clone_type_impl() const OVERRIDE { + return new ImplTraitTypeOneBound(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ImplTraitTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { + return new ImplTraitTypeOneBound(*this); + } + + public: + ImplTraitTypeOneBound(TraitBound trait_bound, location_t locus) : + trait_bound(::std::move(trait_bound)), locus(locus) {} + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + /* A trait object with a single trait bound. The "trait bound" is really just the trait. + * Basically like using an interface as a type in an OOP language. */ + class TraitObjectTypeOneBound : public TypeNoBounds { + bool has_dyn; + TraitBound trait_bound; + + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TraitObjectTypeOneBound* clone_type_impl() const OVERRIDE { + return new TraitObjectTypeOneBound(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TraitObjectTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { + return new TraitObjectTypeOneBound(*this); + } + + public: + TraitObjectTypeOneBound( + TraitBound trait_bound, location_t locus, bool is_dyn_dispatch = false) : + has_dyn(is_dyn_dispatch), + trait_bound(::std::move(trait_bound)), locus(locus) {} + + ::std::string as_string() const; + + // Creates a trait bound (clone of this one's trait bound) - HACK + virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { + /* NOTE: this assumes there is no dynamic dispatch specified- if there was, this + * cloning would not be required as parsing is unambiguous. */ + return new AST::TraitBound(trait_bound); + } + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + class TypePath; // definition moved to "rust-path.h" + + // A type consisting of the "product" of others (the tuple's elements) in a specific order + class TupleType : public TypeNoBounds { + //::std::vector elems; + ::std::vector< ::std::unique_ptr > elems; + + location_t locus; + + public: + // Returns whether the tuple type is the unit type, i.e. has no elements. + inline bool is_unit_type() const { + return elems.empty(); + } + + TupleType(::std::vector< ::std::unique_ptr > elems, location_t locus) : + elems(::std::move(elems)), locus(locus) {} + + // copy constructor with vector clone + TupleType(TupleType const& other) : locus(other.locus) { + // crappy vector unique pointer clone - TODO is there a better way of doing this? + elems.reserve(other.elems.size()); + + for (const auto& e : other.elems) { + elems.push_back(e->clone_type()); + } + } + + // overloaded assignment operator to clone + TupleType& operator=(TupleType const& other) { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing this? + elems.reserve(other.elems.size()); + + for (const auto& e : other.elems) { + elems.push_back(e->clone_type()); + } + + return *this; + } + + // move constructors + TupleType(TupleType&& other) = default; + TupleType& operator=(TupleType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual TupleType* clone_type_impl() const OVERRIDE { + return new TupleType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual TupleType* clone_type_no_bounds_impl() const OVERRIDE { + return new TupleType(*this); + } + }; + + /* A type with no values, representing the result of computations that never complete. + * Expressions of NeverType can be coerced into any other types. Represented as "!". */ + class NeverType : public TypeNoBounds { + location_t locus; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual NeverType* clone_type_impl() const OVERRIDE { + return new NeverType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual NeverType* clone_type_no_bounds_impl() const OVERRIDE { + return new NeverType(*this); + } + + public: + NeverType(location_t locus) : locus(locus) {} + + ::std::string as_string() const { + return "! (never type)"; + } + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + // A type consisting of a pointer without safety or liveness guarantees + class RawPointerType : public TypeNoBounds { + public: + enum PointerType { MUT, CONST }; + + private: + PointerType pointer_type; + + // TypeNoBounds type; + ::std::unique_ptr type; + + location_t locus; + + public: + // Returns whether the pointer is mutable or constant. + inline PointerType get_pointer_type() const { + return pointer_type; + } + + // Constructor requires pointer for polymorphism reasons + RawPointerType(PointerType pointer_type, ::std::unique_ptr type_no_bounds, + location_t locus) : + pointer_type(pointer_type), + type(::std::move(type_no_bounds)), locus(locus) {} + + // Copy constructor calls custom polymorphic clone function + RawPointerType(RawPointerType const& other) : + pointer_type(other.pointer_type), type(other.type->clone_type_no_bounds()), + locus(other.locus) {} + + // no destructor required? + + // overload assignment operator to use custom clone method + RawPointerType& operator=(RawPointerType const& other) { + pointer_type = other.pointer_type; + type = other.type->clone_type_no_bounds(); + locus = other.locus; + return *this; + } + + // default move semantics + RawPointerType(RawPointerType&& other) = default; + RawPointerType& operator=(RawPointerType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual RawPointerType* clone_type_impl() const OVERRIDE { + return new RawPointerType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual RawPointerType* clone_type_no_bounds_impl() const OVERRIDE { + return new RawPointerType(*this); + } + }; + + // A type pointing to memory owned by another value + class ReferenceType : public TypeNoBounds { + // bool has_lifetime; // TODO: handle in lifetime or something? + Lifetime lifetime; + + bool has_mut; + + // TypeNoBounds type; + ::std::unique_ptr type; + + location_t locus; + + public: + // Returns whether the reference is mutable or immutable. + inline bool is_mut() const { + return has_mut; + } + + // Returns whether the reference has a lifetime. + inline bool has_lifetime() const { + return !lifetime.is_error(); + } + + // Constructor + ReferenceType(bool is_mut, ::std::unique_ptr type_no_bounds, + location_t locus, Lifetime lifetime = Lifetime::error()) : + lifetime(::std::move(lifetime)), + has_mut(is_mut), type(::std::move(type_no_bounds)), locus(locus) {} + + // Copy constructor with custom clone method + ReferenceType(ReferenceType const& other) : + lifetime(other.lifetime), has_mut(other.has_mut), + type(other.type->clone_type_no_bounds()), locus(other.locus) {} + + // Destructor not required? + + // Operator overload assignment operator to custom clone the unique pointer + ReferenceType& operator=(ReferenceType const& other) { + lifetime = other.lifetime; + has_mut = other.has_mut; + type = other.type->clone_type_no_bounds(); + locus = other.locus; + + return *this; + } + + // move constructors + ReferenceType(ReferenceType&& other) = default; + ReferenceType& operator=(ReferenceType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ReferenceType* clone_type_impl() const OVERRIDE { + return new ReferenceType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ReferenceType* clone_type_no_bounds_impl() const OVERRIDE { + return new ReferenceType(*this); + } + }; + + // A fixed-size sequence of elements of a specified type + class ArrayType : public TypeNoBounds { + // Type elem_type; + ::std::unique_ptr elem_type; + // Expr* size; + ::std::unique_ptr size; + + location_t locus; + + public: + // Constructor requires pointers for polymorphism + ArrayType( + ::std::unique_ptr type, ::std::unique_ptr array_size, location_t locus) : + elem_type(::std::move(type)), + size(::std::move(array_size)), locus(locus) {} + + // Copy constructor requires deep copies of both unique pointers + ArrayType(ArrayType const& other) : + elem_type(other.elem_type->clone_type()), size(other.size->clone_expr()), + locus(other.locus) {} + + // destructor not required? + + // Overload assignment operator to deep copy pointers + ArrayType& operator=(ArrayType const& other) { + elem_type = other.elem_type->clone_type(); + size = other.size->clone_expr(); + locus = other.locus; + return *this; + } + + // move constructors + ArrayType(ArrayType&& other) = default; + ArrayType& operator=(ArrayType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + /*~ArrayType() { + delete size; + }*/ + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayType* clone_type_impl() const OVERRIDE { + return new ArrayType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual ArrayType* clone_type_no_bounds_impl() const OVERRIDE { + return new ArrayType(*this); + } + }; + + // A dynamically-sized type representing a "view" into a sequence of elements of a type + class SliceType : public TypeNoBounds { + // Type elem_type; + ::std::unique_ptr elem_type; + + location_t locus; + + public: + // Constructor requires pointer for polymorphism + SliceType(::std::unique_ptr type, location_t locus) : + elem_type(::std::move(type)), locus(locus) {} + + // Copy constructor requires deep copy of Type smart pointer + SliceType(SliceType const& other) : + elem_type(other.elem_type->clone_type()), locus(other.locus) {} + + // destructor not required? + + // Overload assignment operator to deep copy + SliceType& operator=(SliceType const& other) { + elem_type = other.elem_type->clone_type(); + locus = other.locus; + + return *this; + } + + // move constructors + SliceType(SliceType&& other) = default; + SliceType& operator=(SliceType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual SliceType* clone_type_impl() const OVERRIDE { + return new SliceType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual SliceType* clone_type_no_bounds_impl() const OVERRIDE { + return new SliceType(*this); + } + }; + + // Type used in generic arguments to explicitly request type inference (wildcard pattern) + class InferredType : public TypeNoBounds { + location_t locus; + + // e.g. Vec<_> = whatever + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual InferredType* clone_type_impl() const OVERRIDE { + return new InferredType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual InferredType* clone_type_no_bounds_impl() const OVERRIDE { + return new InferredType(*this); + } + + public: + InferredType(location_t locus) : locus(locus) {} + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + }; + + class QualifiedPathInType; // definition moved to "rust-path.h" + + // A possibly named param used in a BaseFunctionType + struct MaybeNamedParam { + public: + enum ParamKind { UNNAMED, IDENTIFIER, WILDCARD }; + + private: + // Type param_type; + ::std::unique_ptr param_type; + + ParamKind param_kind; + Identifier name; // technically, can be an identifier or '_' + + location_t locus; + + public: + MaybeNamedParam(Identifier name, ParamKind param_kind, ::std::unique_ptr param_type, + location_t locus) : + param_type(::std::move(param_type)), + param_kind(param_kind), name(::std::move(name)), locus(locus) {} + + // Copy constructor with clone + MaybeNamedParam(MaybeNamedParam const& other) : + param_type(other.param_type->clone_type()), param_kind(other.param_kind), + name(other.name), locus(other.locus) {} + + ~MaybeNamedParam() = default; + + // Overloaded assignment operator with clone + MaybeNamedParam& operator=(MaybeNamedParam const& other) { + name = other.name; + param_kind = other.param_kind; + param_type = other.param_type->clone_type(); + locus = other.locus; + + return *this; + } + + // move constructors + MaybeNamedParam(MaybeNamedParam&& other) = default; + MaybeNamedParam& operator=(MaybeNamedParam&& other) = default; + + ::std::string as_string() const; + + // Returns whether the param is in an error state. + inline bool is_error() const { + return param_type == NULL; + } + + // Creates an error state param. + static MaybeNamedParam create_error() { + return MaybeNamedParam("", UNNAMED, NULL, UNKNOWN_LOCATION); + } + + location_t get_locus() const { + return locus; + } + }; + + /* A function pointer type - can be created via coercion from function items and non- + * capturing closures. */ + class BareFunctionType : public TypeNoBounds { + // bool has_for_lifetimes; + // ForLifetimes for_lifetimes; + ::std::vector for_lifetimes; // inlined version + + FunctionQualifiers function_qualifiers; + ::std::vector params; + bool is_variadic; + + // bool has_return_type; + // BareFunctionReturnType return_type; + ::std::unique_ptr return_type; // inlined version + + location_t locus; + + public: + // Whether a return type is defined with the function. + inline bool has_return_type() const { + return return_type != NULL; + } + + // Whether the function has ForLifetimes. + inline bool has_for_lifetimes() const { + return !for_lifetimes.empty(); + } + + BareFunctionType(::std::vector lifetime_params, + FunctionQualifiers qualifiers, ::std::vector named_params, + bool is_variadic, ::std::unique_ptr type, location_t locus) : + for_lifetimes(::std::move(lifetime_params)), + function_qualifiers(::std::move(qualifiers)), params(::std::move(named_params)), + is_variadic(is_variadic), return_type(::std::move(type)), locus(locus) {} + + // Copy constructor with clone + BareFunctionType(BareFunctionType const& other) : + for_lifetimes(other.for_lifetimes), function_qualifiers(other.function_qualifiers), + params(other.params), is_variadic(other.is_variadic), + return_type(other.return_type->clone_type_no_bounds()), locus(other.locus) {} + + // destructor - define here if required + + // Overload assignment operator to deep copy + BareFunctionType& operator=(BareFunctionType const& other) { + for_lifetimes = other.for_lifetimes; + function_qualifiers = other.function_qualifiers; + params = other.params; + is_variadic = other.is_variadic; + return_type = other.return_type->clone_type_no_bounds(); + locus = other.locus; + + return *this; + } + + // move constructors + BareFunctionType(BareFunctionType&& other) = default; + BareFunctionType& operator=(BareFunctionType&& other) = default; + + ::std::string as_string() const; + + location_t get_locus() const { + return locus; + } + + virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + + protected: + // Use covariance to implement clone function as returning this object rather than base + virtual BareFunctionType* clone_type_impl() const OVERRIDE { + return new BareFunctionType(*this); + } + + // Use covariance to implement clone function as returning this object rather than base + virtual BareFunctionType* clone_type_no_bounds_impl() const OVERRIDE { + return new BareFunctionType(*this); + } + }; + + // Forward decl - defined in rust-macro.h + class MacroInvocation; + + /*// AST node of a macro invocation, which is replaced by the macro result at compile time + class MacroInvocation : public TypeNoBounds, public Pattern, public ExprWithoutBlock { + SimplePath path; + DelimTokenTree token_tree; + };*/ + + /* TODO: possible types + * struct type? + * "enum" (tagged union) type? + * C-like union type? + * function item type? + * closure expression types? + * primitive types (bool, int, float, char, str (the slice)) + * Although supposedly TypePaths are used to reference these types (including primitives) */ + + /* FIXME: Incomplete spec references: + * anonymous type parameters, aka "impl Trait in argument position" - impl then trait bounds + * abstract return types, aka "impl Trait in return position" - impl then trait bounds */ + } +} + +#endif \ No newline at end of file diff --git a/gcc/rust/backend.h b/gcc/rust/backend.h new file mode 100644 index 0000000..e7c360f --- /dev/null +++ b/gcc/rust/backend.h @@ -0,0 +1,764 @@ +// backend.h -- Rust frontend interface to backend -*- C++ -*- + +// Copyright 2011 The Rust Authors. All rights reserved. +// Use of this source code is rustverned by a BSD-style +// license that can be found in the LICENSE file. + +#ifndef RUST_BACKEND_H +#define RUST_BACKEND_H + +#include +#include +#include + +#include "operator.h" + +// Pointers to these types are created by the backend, passed to the +// frontend, and passed back to the backend. The types must be +// defined by the backend using these names. + +// The backend representation of a type. +class Btype; + +// The backend represention of an expression. +class Bexpression; + +// The backend representation of a statement. +class Bstatement; + +// The backend representation of a function definition or declaration. +class Bfunction; + +// The backend representation of a block. +class Bblock; + +// The backend representation of a variable. +class Bvariable; + +// The backend representation of a label. +class Blabel; + +// The backend interface. This is a pure abstract class that a +// specific backend will implement. + +class Backend +{ +public: + virtual ~Backend () {} + + // Name/type/location. Used for function parameters, struct fields, + // interface methods. + struct Btyped_identifier + { + std::string name; + Btype *btype; + Location location; + + Btyped_identifier () + : name (), btype (NULL), location (Linemap::unknown_location ()) + {} + + Btyped_identifier (const std::string &a_name, Btype *a_btype, + Location a_location) + : name (a_name), btype (a_btype), location (a_location) + {} + }; + + // Types. + + // Produce an error type. Actually the backend could probably just + // crash if this is called. + virtual Btype *error_type () = 0; + + // Get a void type. This is used in (at least) two ways: 1) as the + // return type of a function with no result parameters; 2) + // unsafe.Pointer is represented as *void. + virtual Btype *void_type () = 0; + + // Get the unnamed boolean type. + virtual Btype *bool_type () = 0; + + // Get an unnamed integer type with the given signedness and number + // of bits. + virtual Btype *integer_type (bool is_unsigned, int bits) = 0; + + // Get an unnamed floating point type with the given number of bits + // (32 or 64). + virtual Btype *float_type (int bits) = 0; + + // Get an unnamed complex type with the given number of bits (64 or 128). + virtual Btype *complex_type (int bits) = 0; + + // Get a pointer type. + virtual Btype *pointer_type (Btype *to_type) = 0; + + // Get a function type. The receiver, parameter, and results are + // generated from the types in the Function_type. The Function_type + // is provided so that the names are available. This should return + // not the type of a Rust function (which is a pointer to a struct) + // but the type of a C function pointer (which will be used as the + // type of the first field of the struct). If there is more than + // one result, RESULT_STRUCT is a struct type to hold the results, + // and RESULTS may be ignored; if there are zero or one results, + // RESULT_STRUCT is NULL. + virtual Btype * + function_type (const Btyped_identifier &receiver, + const std::vector ¶meters, + const std::vector &results, + Btype *result_struct, Location location) + = 0; + + // Get a struct type. + virtual Btype *struct_type (const std::vector &fields) = 0; + + // Get an array type. + virtual Btype *array_type (Btype *element_type, Bexpression *length) = 0; + + // Create a placeholder pointer type. This is used for a named + // pointer type, since in Rust a pointer type may refer to itself. + // NAME is the name of the type, and the location is where the named + // type is defined. This function is also used for unnamed function + // types with multiple results, in which case the type has no name + // and NAME will be empty. FOR_FUNCTION is true if this is for a C + // pointer to function type. A Rust func type is represented as a + // pointer to a struct, and the first field of the struct is a C + // pointer to function. The return value will later be passed as + // the first parameter to set_placeholder_pointer_type or + // set_placeholder_function_type. + virtual Btype *placeholder_pointer_type (const std::string &name, Location, + bool for_function) + = 0; + + // Fill in a placeholder pointer type as a pointer. This takes a + // type returned by placeholder_pointer_type and arranges for it to + // point to the type that TO_TYPE points to (that is, PLACEHOLDER + // becomes the same type as TO_TYPE). Returns true on success, + // false on failure. + virtual bool set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) + = 0; + + // Fill in a placeholder pointer type as a function. This takes a + // type returned by placeholder_pointer_type and arranges for it to + // become a real Rust function type (which corresponds to a C/C++ + // pointer to function type). FT will be something returned by the + // function_type method. Returns true on success, false on failure. + virtual bool set_placeholder_function_type (Btype *placeholder, Btype *ft) + = 0; + + // Create a placeholder struct type. This is used for a named + // struct type, as with placeholder_pointer_type. It is also used + // for interface types, in which case NAME will be the empty string. + virtual Btype *placeholder_struct_type (const std::string &name, Location) + = 0; + + // Fill in a placeholder struct type. This takes a type returned by + // placeholder_struct_type and arranges for it to become a real + // struct type. The parameter is as for struct_type. Returns true + // on success, false on failure. + virtual bool + set_placeholder_struct_type (Btype *placeholder, + const std::vector &fields) + = 0; + + // Create a placeholder array type. This is used for a named array + // type, as with placeholder_pointer_type, to handle cases like + // type A []*A. + virtual Btype *placeholder_array_type (const std::string &name, Location) = 0; + + // Fill in a placeholder array type. This takes a type returned by + // placeholder_array_type and arranges for it to become a real array + // type. The parameters are as for array_type. Returns true on + // success, false on failure. + virtual bool set_placeholder_array_type (Btype *placeholder, + Btype *element_type, + Bexpression *length) + = 0; + + // Return a named version of a type. The location is the location + // of the type definition. This will not be called for a type + // created via placeholder_pointer_type, placeholder_struct_type, or + // placeholder_array_type.. (It may be called for a pointer, + // struct, or array type in a case like "type P *byte; type Q P".) + virtual Btype *named_type (const std::string &name, Btype *, Location) = 0; + + // Create a marker for a circular pointer type. Rust pointer and + // function types can refer to themselves in ways that are not + // permitted in C/C++. When a circular type is found, this function + // is called for the circular reference. This permits the backend + // to decide how to handle such a type. PLACEHOLDER is the + // placeholder type which has already been created; if the backend + // is prepared to handle a circular pointer type, it may simply + // return PLACEHOLDER. FOR_FUNCTION is true if this is for a + // function type. + // + // For "type P *P" the sequence of calls will be + // bt1 = placeholder_pointer_type(); + // bt2 = circular_pointer_type(bt1, false); + // set_placeholder_pointer_type(bt1, bt2); + virtual Btype *circular_pointer_type (Btype *placeholder, bool for_function) + = 0; + + // Return whether the argument could be a special type created by + // circular_pointer_type. This is used to introduce explicit type + // conversions where needed. If circular_pointer_type returns its + // PLACEHOLDER parameter, this may safely always return false. + virtual bool is_circular_pointer_type (Btype *) = 0; + + // Return the size of a type. + virtual int64_t type_size (Btype *) = 0; + + // Return the alignment of a type. + virtual int64_t type_alignment (Btype *) = 0; + + // Return the alignment of a struct field of this type. This is + // normally the same as type_alignment, but not always. + virtual int64_t type_field_alignment (Btype *) = 0; + + // Return the offset of field INDEX in a struct type. INDEX is the + // entry in the FIELDS std::vector parameter of struct_type or + // set_placeholder_struct_type. + virtual int64_t type_field_offset (Btype *, size_t index) = 0; + + // Expressions. + + // Return an expression for a zero value of the given type. This is + // used for cases such as local variable initialization and + // converting nil to other types. + virtual Bexpression *zero_expression (Btype *) = 0; + + // Create an error expression. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // rusting without crashing. + virtual Bexpression *error_expression () = 0; + + // Create a nil pointer expression. + virtual Bexpression *nil_pointer_expression () = 0; + + // Create a reference to a variable. + virtual Bexpression *var_expression (Bvariable *var, Location) = 0; + + // Create an expression that indirects through the pointer expression EXPR + // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer + // is known to point to a valid memory location. BTYPE is the expected type + // of the indirected EXPR. + virtual Bexpression *indirect_expression (Btype *btype, Bexpression *expr, + bool known_valid, Location) + = 0; + + // Return an expression that declares a constant named NAME with the + // constant value VAL in BTYPE. + virtual Bexpression *named_constant_expression (Btype *btype, + const std::string &name, + Bexpression *val, Location) + = 0; + + // Return an expression for the multi-precision integer VAL in BTYPE. + virtual Bexpression *integer_constant_expression (Btype *btype, mpz_t val) + = 0; + + // Return an expression for the floating point value VAL in BTYPE. + virtual Bexpression *float_constant_expression (Btype *btype, mpfr_t val) = 0; + + // Return an expression for the complex value VAL in BTYPE. + virtual Bexpression *complex_constant_expression (Btype *btype, mpc_t val) + = 0; + + // Return an expression for the string value VAL. + virtual Bexpression *string_constant_expression (const std::string &val) = 0; + + // Return an expression for the boolean value VAL. + virtual Bexpression *boolean_constant_expression (bool val) = 0; + + // Return an expression for the real part of BCOMPLEX. + virtual Bexpression *real_part_expression (Bexpression *bcomplex, Location) + = 0; + + // Return an expression for the imaginary part of BCOMPLEX. + virtual Bexpression *imag_part_expression (Bexpression *bcomplex, Location) + = 0; + + // Return an expression for the complex number (BREAL, BIMAG). + virtual Bexpression *complex_expression (Bexpression *breal, + Bexpression *bimag, Location) + = 0; + + // Return an expression that converts EXPR to TYPE. + virtual Bexpression *convert_expression (Btype *type, Bexpression *expr, + Location) + = 0; + + // Create an expression for the address of a function. This is used to + // get the address of the code for a function. + virtual Bexpression *function_code_expression (Bfunction *, Location) = 0; + + // Create an expression that takes the address of an expression. + virtual Bexpression *address_expression (Bexpression *, Location) = 0; + + // Return an expression for the field at INDEX in BSTRUCT. + virtual Bexpression *struct_field_expression (Bexpression *bstruct, + size_t index, Location) + = 0; + + // Create an expression that executes BSTAT before BEXPR. + virtual Bexpression *compound_expression (Bstatement *bstat, + Bexpression *bexpr, Location) + = 0; + + // Return an expression that executes THEN_EXPR if CONDITION is true, or + // ELSE_EXPR otherwise and returns the result as type BTYPE, within the + // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. + virtual Bexpression * + conditional_expression (Bfunction *function, Btype *btype, + Bexpression *condition, Bexpression *then_expr, + Bexpression *else_expr, Location) + = 0; + + // Return an expression for the unary operation OP EXPR. + // Supported values of OP are (from operators.h): + // MINUS, NOT, XOR. + virtual Bexpression *unary_expression (Operator op, Bexpression *expr, + Location) + = 0; + + // Return an expression for the binary operation LEFT OP RIGHT. + // Supported values of OP are (from operators.h): + // EQEQ, NOTEQ, LT, LE, GT, GE, PLUS, MINUS, OR, XOR, MULT, DIV, MOD, + // LSHIFT, RSHIFT, AND, NOT. + virtual Bexpression *binary_expression (Operator op, Bexpression *left, + Bexpression *right, Location) + = 0; + + // Return an expression that constructs BTYPE with VALS. BTYPE must be the + // backend representation a of struct. VALS must be in the same order as the + // corresponding fields in BTYPE. + virtual Bexpression * + constructor_expression (Btype *btype, const std::vector &vals, + Location) + = 0; + + // Return an expression that constructs an array of BTYPE with INDEXES and + // VALS. INDEXES and VALS must have the same amount of elements. Each index + // in INDEXES must be in the same order as the corresponding value in VALS. + virtual Bexpression *array_constructor_expression ( + Btype *btype, const std::vector &indexes, + const std::vector &vals, Location) + = 0; + + // Return an expression for the address of BASE[INDEX]. + // BASE has a pointer type. This is used for slice indexing. + virtual Bexpression *pointer_offset_expression (Bexpression *base, + Bexpression *index, Location) + = 0; + + // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid + // fixed-length array, not a slice. + virtual Bexpression *array_index_expression (Bexpression *array, + Bexpression *index, Location) + = 0; + + // Create an expression for a call to FN with ARGS, taking place within + // caller CALLER. + virtual Bexpression *call_expression (Bfunction *caller, Bexpression *fn, + const std::vector &args, + Bexpression *static_chain, Location) + = 0; + + // Statements. + + // Create an error statement. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // rusting without crashing. + virtual Bstatement *error_statement () = 0; + + // Create an expression statement within the specified function. + virtual Bstatement *expression_statement (Bfunction *, Bexpression *) = 0; + + // Create a variable initialization statement in the specified + // function. This initializes a local variable at the point in the + // program flow where it is declared. + virtual Bstatement *init_statement (Bfunction *, Bvariable *var, + Bexpression *init) + = 0; + + // Create an assignment statement within the specified function. + virtual Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, + Bexpression *rhs, Location) + = 0; + + // Create a return statement, passing the representation of the + // function and the list of values to return. + virtual Bstatement * + return_statement (Bfunction *, const std::vector &, Location) + = 0; + + // Create an if statement within a function. ELSE_BLOCK may be NULL. + virtual Bstatement *if_statement (Bfunction *, Bexpression *condition, + Bblock *then_block, Bblock *else_block, + Location) + = 0; + + // Create a switch statement where the case values are constants. + // CASES and STATEMENTS must have the same number of entries. If + // VALUE matches any of the list in CASES[i], which will all be + // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will + // either end with a goto statement or will fall through into + // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, + // which need not be last. FUNCTION is the current function. + virtual Bstatement * + switch_statement (Bfunction *function, Bexpression *value, + const std::vector > &cases, + const std::vector &statements, Location) + = 0; + + // Create a single statement from two statements. + virtual Bstatement *compound_statement (Bstatement *, Bstatement *) = 0; + + // Create a single statement from a list of statements. + virtual Bstatement *statement_list (const std::vector &) = 0; + + // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if + // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and + // if not NULL, it will always be executed. This is used for handling defers + // in Rust functions. In C++, the resulting code is of this form: + // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } + virtual Bstatement * + exception_handler_statement (Bstatement *bstat, Bstatement *except_stmt, + Bstatement *finally_stmt, Location) + = 0; + + // Blocks. + + // Create a block. The frontend will call this function when it + // starts converting a block within a function. FUNCTION is the + // current function. ENCLOSING is the enclosing block; it will be + // NULL for the top-level block in a function. VARS is the list of + // local variables defined within this block; each entry will be + // created by the local_variable function. START_LOCATION is the + // location of the start of the block, more or less the location of + // the initial curly brace. END_LOCATION is the location of the end + // of the block, more or less the location of the final curly brace. + // The statements will be added after the block is created. + virtual Bblock *block (Bfunction *function, Bblock *enclosing, + const std::vector &vars, + Location start_location, Location end_location) + = 0; + + // Add the statements to a block. The block is created first. Then + // the statements are created. Then the statements are added to the + // block. This will called exactly once per block. The vector may + // be empty if there are no statements. + virtual void block_add_statements (Bblock *, + const std::vector &) + = 0; + + // Return the block as a statement. This is used to include a block + // in a list of statements. + virtual Bstatement *block_statement (Bblock *) = 0; + + // Variables. + + // Create an error variable. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // rusting without crashing. + virtual Bvariable *error_variable () = 0; + + // Create a global variable. NAME is the package-qualified name of + // the variable. ASM_NAME is the encoded identifier for the + // variable, incorporating the package, and made safe for the + // assembler. BTYPE is the type of the variable. IS_EXTERNAL is + // true if the variable is defined in some other package. IS_HIDDEN + // is true if the variable is not exported (name begins with a lower + // case letter). IN_UNIQUE_SECTION is true if the variable should + // be put into a unique section if possible; this is intended to + // permit the linker to garbage collect the variable if it is not + // referenced. LOCATION is where the variable was defined. + virtual Bvariable *global_variable (const std::string &name, + const std::string &asm_name, Btype *btype, + bool is_external, bool is_hidden, + bool in_unique_section, Location location) + = 0; + + // A global variable will 1) be initialized to zero, or 2) be + // initialized to a constant value, or 3) be initialized in the init + // function. In case 2, the frontend will call + // global_variable_set_init to set the initial value. If this is + // not called, the backend should initialize a global variable to 0. + // The init function may then assign a value to it. + virtual void global_variable_set_init (Bvariable *, Bexpression *) = 0; + + // Create a local variable. The frontend will create the local + // variables first, and then create the block which contains them. + // FUNCTION is the function in which the variable is defined. NAME + // is the name of the variable. TYPE is the type. DECL_VAR, if not + // null, gives the location at which the value of this variable may + // be found, typically used to create an inner-scope reference to an + // outer-scope variable, to extend the lifetime of the variable beyond + // the inner scope. IS_ADDRESS_TAKEN is true if the address of this + // variable is taken (this implies that the address does not escape + // the function, as otherwise the variable would be on the heap). + // LOCATION is where the variable is defined. For each local variable + // the frontend will call init_statement to set the initial value. + virtual Bvariable * + local_variable (Bfunction *function, const std::string &name, Btype *type, + Bvariable *decl_var, bool is_address_taken, Location location) + = 0; + + // Create a function parameter. This is an incoming parameter, not + // a result parameter (result parameters are treated as local + // variables). The arguments are as for local_variable. + virtual Bvariable * + parameter_variable (Bfunction *function, const std::string &name, Btype *type, + bool is_address_taken, Location location) + = 0; + + // Create a static chain parameter. This is the closure parameter. + virtual Bvariable *static_chain_variable (Bfunction *function, + const std::string &name, + Btype *type, Location location) + = 0; + + // Create a temporary variable. A temporary variable has no name, + // just a type. We pass in FUNCTION and BLOCK in case they are + // needed. If INIT is not NULL, the variable should be initialized + // to that value. Otherwise the initial value is irrelevant--the + // backend does not have to explicitly initialize it to zero. + // ADDRESS_IS_TAKEN is true if the programs needs to take the + // address of this temporary variable. LOCATION is the location of + // the statement or expression which requires creating the temporary + // variable, and may not be very useful. This function should + // return a variable which can be referenced later and should set + // *PSTATEMENT to a statement which initializes the variable. + virtual Bvariable * + temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *init, + bool address_is_taken, Location location, + Bstatement **pstatement) + = 0; + + // Create an implicit variable that is compiler-defined. This is + // used when generating GC data and roots, when storing the values + // of a slice constructor, and for the zero value of types. This returns a + // Bvariable because it corresponds to an initialized variable in C. + // + // NAME is the name to use for the initialized variable this will create. + // + // ASM_NAME is encoded assembler-friendly version of the name, or the + // empty string if no encoding is needed. + // + // TYPE is the type of the implicit variable. + // + // IS_HIDDEN will be true if the descriptor should only be visible + // within the current object. + // + // IS_CONSTANT is true if the implicit variable should be treated like it is + // immutable. For slice initializers, if the values must be copied to the + // heap, the variable IS_CONSTANT. + // + // IS_COMMON is true if the implicit variable should + // be treated as a common variable (multiple definitions with + // different sizes permitted in different object files, all merged + // into the largest definition at link time); this will be true for + // the zero value. IS_HIDDEN and IS_COMMON will never both be true. + // + // If ALIGNMENT is not zero, it is the desired alignment of the variable. + virtual Bvariable * + implicit_variable (const std::string &name, const std::string &asm_name, + Btype *type, bool is_hidden, bool is_constant, + bool is_common, int64_t alignment) + = 0; + + // Set the initial value of a variable created by implicit_variable. + // This must be called even if there is no initializer, i.e., INIT is NULL. + // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are + // the same ones passed to implicit_variable. INIT will be a composite + // literal of type TYPE. It will not contain any function calls or anything + // else that can not be put into a read-only data section. + // It may contain the address of variables created by implicit_variable. + // + // If IS_COMMON is true, INIT will be NULL, and the + // variable should be initialized to all zeros. + virtual void implicit_variable_set_init (Bvariable *, const std::string &name, + Btype *type, bool is_hidden, + bool is_constant, bool is_common, + Bexpression *init) + = 0; + + // Create a reference to a named implicit variable defined in some + // other package. This will be a variable created by a call to + // implicit_variable with the same NAME, ASM_NAME and TYPE and with + // IS_COMMON passed as false. This corresponds to an extern global + // variable in C. + virtual Bvariable *implicit_variable_reference (const std::string &name, + const std::string &asm_name, + Btype *type) + = 0; + + // Create a named immutable initialized data structure. This is + // used for type descriptors, map descriptors, and function + // descriptors. This returns a Bvariable because it corresponds to + // an initialized const variable in C. + // + // NAME is the name to use for the initialized global variable which + // this call will create. + // + // ASM_NAME is the encoded, assembler-friendly version of NAME, or + // the empty string if no encoding is needed. + // + // IS_HIDDEN will be true if the descriptor should only be visible + // within the current object. + // + // IS_COMMON is true if NAME may be defined by several packages, and + // the linker should merge all such definitions. If IS_COMMON is + // false, NAME should be defined in only one file. In general + // IS_COMMON will be true for the type descriptor of an unnamed type + // or a builtin type. IS_HIDDEN and IS_COMMON will never both be + // true. + // + // TYPE will be a struct type; the type of the returned expression + // must be a pointer to this struct type. + // + // We must create the named structure before we know its + // initializer, because the initializer may refer to its own + // address. After calling this the frontend will call + // immutable_struct_set_init. + virtual Bvariable * + immutable_struct (const std::string &name, const std::string &asm_name, + bool is_hidden, bool is_common, Btype *type, Location) + = 0; + + // Set the initial value of a variable created by immutable_struct. + // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are + // the same ones passed to immutable_struct. INITIALIZER will be a + // composite literal of type TYPE. It will not contain any function + // calls or anything else that can not be put into a read-only data + // section. It may contain the address of variables created by + // immutable_struct. + virtual void immutable_struct_set_init (Bvariable *, const std::string &name, + bool is_hidden, bool is_common, + Btype *type, Location, + Bexpression *initializer) + = 0; + + // Create a reference to a named immutable initialized data + // structure defined in some other package. This will be a + // structure created by a call to immutable_struct with the same + // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This + // corresponds to an extern const global variable in C. + virtual Bvariable *immutable_struct_reference (const std::string &name, + const std::string &asm_name, + Btype *type, Location) + = 0; + + // Labels. + + // Create a new label. NAME will be empty if this is a label + // created by the frontend for a loop construct. The location is + // where the label is defined. + virtual Blabel *label (Bfunction *, const std::string &name, Location) = 0; + + // Create a statement which defines a label. This statement will be + // put into the codestream at the point where the label should be + // defined. + virtual Bstatement *label_definition_statement (Blabel *) = 0; + + // Create a goto statement to a label. + virtual Bstatement *goto_statement (Blabel *, Location) = 0; + + // Create an expression for the address of a label. This is used to + // get the return address of a deferred function which may call + // recover. + virtual Bexpression *label_address (Blabel *, Location) = 0; + + // Functions. + + // Create an error function. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // rusting without crashing. + virtual Bfunction *error_function () = 0; + + // Bit flags to pass to the function method. + + // Set if the function should be visible outside of the current + // compilation unit. + static const unsigned int function_is_visible = 1 << 0; + + // Set if this is a function declaration rather than a definition; + // the definition will be in another compilation unit. + static const unsigned int function_is_declaration = 1 << 1; + + // Set if the function can be inlined. This is normally set, but is + // false for functions that may not be inlined because they call + // recover and must be visible for correct panic recovery. + static const unsigned int function_is_inlinable = 1 << 2; + + // Set if the function may not split the stack. This is set for the + // implementation of recover itself, among other things. + static const unsigned int function_no_split_stack = 1 << 3; + + // Set if the function does not return. This is set for the + // implementation of panic. + static const unsigned int function_does_not_return = 1 << 4; + + // Set if the function should be put in a unique section if + // possible. This is used for field tracking. + static const unsigned int function_in_unique_section = 1 << 5; + + // Set if the function should be available for inlining in the + // backend, but should not be emitted as a standalone function. Any + // call to the function that is not inlined should be treated as a + // call to a function defined in a different compilation unit. This + // is like a C99 function marked inline but not extern. + static const unsigned int function_only_inline = 1 << 6; + + // Declare or define a function of FNTYPE. + // NAME is the Rust name of the function. ASM_NAME, if not the empty + // string, is the name that should be used in the symbol table; this + // will be non-empty if a magic extern comment is used. FLAGS is + // bit flags described above. + virtual Bfunction *function (Btype *fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, + Location) + = 0; + + // Create a statement that runs all deferred calls for FUNCTION. This should + // be a statement that looks like this in C++: + // finish: + // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } + virtual Bstatement * + function_defer_statement (Bfunction *function, Bexpression *undefer, + Bexpression *check_defer, Location) + = 0; + + // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. + // This will only be called for a function definition. Returns true on + // success, false on failure. + virtual bool + function_set_parameters (Bfunction *function, + const std::vector ¶m_vars) + = 0; + + // Set the function body for FUNCTION using the code in CODE_STMT. Returns + // true on success, false on failure. + virtual bool function_set_body (Bfunction *function, Bstatement *code_stmt) + = 0; + + // Look up a named built-in function in the current backend implementation. + // Returns NULL if no built-in function by that name exists. + virtual Bfunction *lookup_builtin (const std::string &) = 0; + + // Utility. + + // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, + // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. + virtual void + write_global_definitions (const std::vector &type_decls, + const std::vector &constant_decls, + const std::vector &function_decls, + const std::vector &variable_decls) + = 0; + + // Write SIZE bytes of export data from BYTES to the proper + // section in the output object file. + virtual void write_export_data (const char *bytes, unsigned int size) = 0; +}; + +#endif // !defined(RUST_BACKEND_H) diff --git a/gcc/rust/config-lang.in b/gcc/rust/config-lang.in index 0fd7109..c50b721 100644 --- a/gcc/rust/config-lang.in +++ b/gcc/rust/config-lang.in @@ -31,4 +31,4 @@ build_by_default="no" target_libs="target-libffi target-libbacktrace" -gtfiles="\$(srcdir)/rust/rust-lang.c \$(srcdir)/rust/rust-c.h" +gtfiles="\$(srcdir)/rust/rust-lang.cc" diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc new file mode 100644 index 0000000..613d94f --- /dev/null +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -0,0 +1,69 @@ +#include "rust-macro-expand.h" +#include "rust-ast-full.h" +// is full really required? + +namespace Rust { + void MacroExpander::expand_invoc(::std::unique_ptr& invoc) { + // if current expansion depth > recursion limit, create an error (maybe fatal error) and return + + /* switch on type of macro: + - '!' syntax macro (inner switch) + - procedural macro - "A token-based function-like macro" + - 'macro_rules' (by example/pattern-match) macro? or not? "an AST-based function-like macro" + - else is unreachable + - attribute syntax macro (inner switch) + - procedural macro attribute syntax - "A token-based attribute macro" + - legacy macro attribute syntax? - "an AST-based attribute macro" + - non-macro attribute: mark known + - else is unreachable + - derive macro (inner switch) + - derive or legacy derive - "token-based" vs "AST-based" + - else is unreachable + - derive container macro - unreachable*/ + + } + + // Determines whether cfg predicate is true and item with attribute should not be stripped. + bool check_cfg_predicate() {} + + // Determines whether cfg predicate is true and item with attribute should not be stripped. + bool check_cfg(AST::Attribute& attr) { + + } + + // Expands cfg_attr attributes. + void expand_attrs_cfgattr(::std::vector& attrs) { + for (auto it = attrs.begin(); it != attrs.end(); ) { + auto& attr = *it; + if (attr.get_path() == "cfg_attr") { + if (check_cfg(attr)) {} + + /* do something - if feature (first token in tree) is in fact enabled, make tokens listed + * afterwards into attributes. + * i.e.: for [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add attributes + * [wow1] and [wow2] to attribute list. + * This can also be recursive, so check for expanded attributes being recursive and + * possibly recursively call the expand_attrs? */ + } else { + ++it; + } + } + } + + void MacroExpander::expand_crate(AST::Crate& crate) { + // fill macro/decorator map from init list? not sure where init list comes from? + + // expand crate attributes + expand_attrs_cfgattr(crate.inner_attrs); + + // expand module attributes? + + // expand module tree recursively + + // post-process + + // extract exported macros? + + + } +} \ No newline at end of file diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h new file mode 100644 index 0000000..a252a41 --- /dev/null +++ b/gcc/rust/expand/rust-macro-expand.h @@ -0,0 +1,47 @@ +#ifndef RUST_MACRO_EXPAND_H +#define RUST_MACRO_EXPAND_H + +#include "rust-ast.h" + +// Provides objects and method prototypes for macro expansion + +namespace Rust { + // forward decls for AST + namespace AST { + class MacroInvocation; + } + + // Object used to store configuration data for macro expansion. + struct ExpansionCfg { + // features? + unsigned int recursion_limit; // TODO: determine default recursion limit + // trace macros? + // should test? + // more default stuff? + }; + + // Object used to store shared data (between functions) for macro expansion. + struct MacroExpander { + ExpansionCfg cfg; + unsigned int expansion_depth = 0; + + MacroExpander(AST::Crate& crate, ExpansionCfg cfg) : cfg(cfg), crate(crate) {} + + ~MacroExpander() = default; + + // Expands all macros in the crate passed in. + void expand_crate(AST::Crate& crate); + + /* Expands a macro invocation (not macro invocation semi) - possibly make both have similar + * duck-typed interface and use templates?*/ + // should this be public or private? + void expand_invoc(::std::unique_ptr& invoc); + + // TODO: make it extend ASTVisitor so that individual items can be accessed properly? + + private: + AST::Crate& crate; + }; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index 42c6093..4757dfb 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -22,6 +22,8 @@ ; Please try to keep this file in ASCII collating order. +; Describes command-line options used by this frontend + Language Rust @@ -33,6 +35,10 @@ L Rust Joined Separate ; Not documented +frust-dump- +Rust Joined RejectNegative +-frust-dump- Dump Rust frontend internal information. + o Rust Joined Separate ; Documented in common.opt diff --git a/gcc/rust/lex/rust-codepoint.h b/gcc/rust/lex/rust-codepoint.h new file mode 100644 index 0000000..a00edb3 --- /dev/null +++ b/gcc/rust/lex/rust-codepoint.h @@ -0,0 +1,26 @@ +#ifndef RUST_CODEPOINT_H +#define RUST_CODEPOINT_H + +#include "config.h" +#include "system.h" +#include "coretypes.h" +// config, system, coretypes - TODO: ensure all are needed + +#include + +namespace Rust { + struct Codepoint { + uint32_t value; + + // Creates a zero codepoint. + Codepoint() : value(0) {} + + // Creates a codepoint from UTF-8 value. + Codepoint(uint32_t value_) : value(value_) {} + + // Returns a C++ string containing value of codepoint. + ::std::string as_string(); + }; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc new file mode 100644 index 0000000..5a7b0cb --- /dev/null +++ b/gcc/rust/lex/rust-lex.cc @@ -0,0 +1,2349 @@ +#include "rust-lex.h" + +#include "diagnostic.h" // for error_at +#include "safe-ctype.h" + +#include // for ostringstream + +namespace Rust { + // TODO: move to separate compilation unit? + // overload += for uint32_t to allow 32-bit encoded utf-8 to be added + ::std::string& operator+=(::std::string& str, Codepoint char32) { + if (char32.value < 0x80) { + str += static_cast(char32.value); + } else if (char32.value < (0x1F + 1) << (1 * 6)) { + str += static_cast(0xC0 | ((char32.value >> 6) & 0x1F)); + str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); + } else if (char32.value < (0x0F + 1) << (2 * 6)) { + str += static_cast(0xE0 | ((char32.value >> 12) & 0x0F)); + str += static_cast(0x80 | ((char32.value >> 6) & 0x3F)); + str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); + } else if (char32.value < (0x07 + 1) << (3 * 6)) { + str += static_cast(0xF0 | ((char32.value >> 18) & 0x07)); + str += static_cast(0x80 | ((char32.value >> 12) & 0x3F)); + str += static_cast(0x80 | ((char32.value >> 6) & 0x3F)); + str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); + } else { + fprintf(stderr, "Invalid unicode codepoint found: '%u' \n", char32.value); + // error_at(get_current_location(), "Invalid unicode codepoint found: '%u'", + // char32.value); + } + return str; + } + + ::std::string Codepoint::as_string() { + std::string str; + + // do i need to do this? or can i just do str += value due to op overloading? + + // ok can't figure out how to just convert to codepoint or use "this" so create new one + str += Codepoint(value); + + /*if (value < 0x80) { + str += static_cast(value); + } else if (value < (0x1F + 1) << (1 * 6)) { + str += static_cast(0xC0 | ((value >> 6) & 0x1F)); + str += static_cast(0x80 | ((value >> 0) & 0x3F)); + } else if (value < (0x0F + 1) << (2 * 6)) { + str += static_cast(0xE0 | ((value >> 12) & 0x0F)); + str += static_cast(0x80 | ((value >> 6) & 0x3F)); + str += static_cast(0x80 | ((value >> 0) & 0x3F)); + } else if (value < (0x07 + 1) << (3 * 6)) { + str += static_cast(0xF0 | ((value >> 18) & 0x07)); + str += static_cast(0x80 | ((value >> 12) & 0x3F)); + str += static_cast(0x80 | ((value >> 6) & 0x3F)); + str += static_cast(0x80 | ((value >> 0) & 0x3F)); + } else { + error_at(get_current_location(), "Invalid unicode codepoint found: '%u'", value); + }*/ + return str; + } + + // Includes all allowable float digits EXCEPT _ and . as that needs lookahead for handling. + inline bool is_float_digit(char number) { + return ISDIGIT(number) || number == 'E' || number == 'e'; + } + + // Basically ISXDIGIT from safe-ctype but may change if Rust's encoding or whatever is different + inline bool is_x_digit(char number) { + return ISXDIGIT(number); + } + + inline bool is_octal_digit(char number) { + return number >= '0' && number <= '7'; + } + + inline bool is_bin_digit(char number) { + return number == '0' || number == '1'; + } + + inline bool check_valid_float_dot_end(char character) { + return character != '.' && character != '_' && !ISALPHA(character); + } + + // ISSPACE from safe-ctype but may change in future + inline bool is_whitespace(char character) { + return ISSPACE(character); + } + + Lexer::Lexer(const char* filename, FILE* input) : + input(input), current_line(1), current_column(1), line_map(0), input_source(input), + input_queue(input_source), token_source(this), token_queue(token_source) { + // inform line_table that file is being entered and is in line 1 + line_map + = ::linemap_add(::line_table, ::LC_ENTER, /* sysp */ 0, filename, /* current_line */ 1); + } + + Lexer::~Lexer() { + ::linemap_add(::line_table, ::LC_LEAVE, /* sysp */ 0, /* filename */ NULL, /* to_line */ 0); + } + + location_t Lexer::get_current_location() { + return ::linemap_position_for_column(::line_table, current_column); + } + + int Lexer::peek_input(int n) { + return input_queue.peek(n); + } + + int Lexer::peek_input() { + return peek_input(0); + } + + void Lexer::skip_input(int n) { + input_queue.skip(n); + } + + void Lexer::skip_input() { + skip_input(0); + } + + const_TokenPtr Lexer::peek_token(int n) { + return token_queue.peek(n); + } + + const_TokenPtr Lexer::peek_token() { + return peek_token(0); + } + + void Lexer::skip_token(int n) { + token_queue.skip(n); + } + + void Lexer::skip_token() { + skip_token(0); + } + + void Lexer::replace_current_token(TokenPtr replacement) { + token_queue.replace_current_value(replacement); + } + + /* shitty anonymous namespace that can only be accessed inside the compilation unit - used for + * classify_keyword + * Binary search in sorted array of keywords created with x-macros. */ + namespace { + const std::string keyword_index[] = { +#define RS_TOKEN(x, y) +#define RS_TOKEN_KEYWORD(name, keyword) keyword, + RS_TOKEN_LIST +#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN + }; + + TokenId keyword_keys[] = { +#define RS_TOKEN(x, y) +#define RS_TOKEN_KEYWORD(name, keyword) name, + RS_TOKEN_LIST +#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN + }; + + const int num_keywords = sizeof(keyword_index) / sizeof(*keyword_index); + } + + /* Determines whether the string passed in is a keyword or not. If it is, it returns the keyword + * name. */ + TokenId Lexer::classify_keyword(const std::string& str) { + const std::string* last = keyword_index + num_keywords; + const std::string* idx = std::lower_bound(keyword_index, last, str); + + if (idx == last || str != *idx) { + return IDENTIFIER; + } else { + return keyword_keys[idx - keyword_index]; + } + } + + TokenPtr Lexer::build_token() { + // loop to go through multiple characters to build a single token + while (true) { + location_t loc = get_current_location(); + /*int */ current_char = peek_input(); + skip_input(); + + // return end of file token if end of file + if (current_char == EOF) { + return Token::make(END_OF_FILE, loc); + } + + // detect shebang + if (loc == 1 && current_line == 1 && current_char == '#') { + current_char = peek_input(); + + if (current_char == '!') { + skip_input(); + current_char = peek_input(); + + switch (current_char) { + case '/': + // shebang + + skip_input(); + + // ignore rest of line + while (current_char != '\n') { + current_char = peek_input(); + skip_input(); + } + + // newline + current_line++; + current_column = 1; + // tell line_table that new line starts + linemap_line_start(::line_table, current_line, max_column_hint); + continue; + } + } + } + + // if not end of file, start tokenising + switch (current_char) { + // ignore whitespace characters for tokens but continue updating location + case '\n': // newline + current_line++; + current_column = 1; + // tell line_table that new line starts + linemap_line_start(::line_table, current_line, max_column_hint); + continue; + case ' ': // space + current_column++; + continue; + case '\t': // tab + // width of a tab is not well-defined, assume 8 spaces + current_column += 8; + continue; + + // punctuation - actual tokens + case '=': + if (peek_input() == '>') { + // match arm arrow + skip_input(); + current_column += 2; + + return Token::make(MATCH_ARROW, loc); + } else if (peek_input() == '=') { + // equality operator + skip_input(); + current_column += 2; + + return Token::make(EQUAL_EQUAL, loc); + } else { + // assignment operator + current_column++; + return Token::make(EQUAL, loc); + } + case '(': + current_column++; + return Token::make(LEFT_PAREN, loc); + case '-': + if (peek_input() == '>') { + // return type specifier + skip_input(); + current_column += 2; + + return Token::make(RETURN_TYPE, loc); + } else if (peek_input() == '=') { + // minus-assign + skip_input(); + current_column += 2; + + return Token::make(MINUS_EQ, loc); + } else { + // minus + current_column++; + return Token::make(MINUS, loc); + } + case '+': + if (peek_input() == '=') { + // add-assign + skip_input(); + current_column += 2; + + return Token::make(PLUS_EQ, loc); + } else { + // add + current_column++; + return Token::make(PLUS, loc); + } + case ')': + current_column++; + return Token::make(RIGHT_PAREN, loc); + case ';': + current_column++; + return Token::make(SEMICOLON, loc); + case '*': + if (peek_input() == '=') { + // multiplication-assign + skip_input(); + current_column += 2; + + return Token::make(ASTERISK_EQ, loc); + } else { + // multiplication + current_column++; + return Token::make(ASTERISK, loc); + } + case ',': + current_column++; + return Token::make(COMMA, loc); + case '/': + if (peek_input() == '=') { + // division-assign + skip_input(); + current_column += 2; + + return Token::make(DIV_EQ, loc); + } else if (peek_input() == '/') { + // TODO: single-line doc comments + + // single line comment + skip_input(); + current_column += 2; + + // basically ignore until line finishes + while (current_char != '\n' && current_char != EOF) { + skip_input(); + current_column++; // not used + current_char = peek_input(); + } + continue; + break; + } else if (peek_input() == '*') { + // block comment + skip_input(); + current_column += 2; + + // TODO: block doc comments + + current_char = peek_input(); + + int level = 1; + while (level > 0) { + skip_input(); + current_column++; // for error-handling + current_char = peek_input(); + + // if /* found + if (current_char == '/') { + if (peek_input(1) == '*') { + // skip /* characters + skip_input(1); + + current_column += 2; + + level += 1; + } + } + + // ignore until */ is found + if (current_char == '*') { + if (peek_input(1) == '/') { + // skip */ characters + skip_input(1); + + current_column += 2; + // should only break inner loop here - seems to do so + // break; + + level -= 1; + } + } + } + + // refresh new token + continue; + break; + } else { + // division + current_column++; + return Token::make(DIV, loc); + } + case '%': + if (peek_input() == '=') { + // modulo-assign + current_column += 2; + return Token::make(PERCENT_EQ, loc); + } else { + // modulo + current_column++; + return Token::make(PERCENT, loc); + } + case '^': + if (peek_input() == '=') { + // xor-assign? + current_column += 2; + return Token::make(CARET_EQ, loc); + } else { + // xor? + current_column++; + return Token::make(CARET, loc); + } + case '<': + if (peek_input() == '<') { + if (peek_input(1) == '=') { + // left-shift assign + skip_input(1); + current_column += 3; + + return Token::make(LEFT_SHIFT_EQ, loc); + } else { + // left-shift + skip_input(); + current_column += 2; + + return Token::make(LEFT_SHIFT, loc); + } + } else if (peek_input() == '=') { + // smaller than or equal to + skip_input(); + current_column += 2; + + return Token::make(LESS_OR_EQUAL, loc); + } else { + // smaller than + current_column++; + return Token::make(LEFT_ANGLE, loc); + } + break; + case '>': + if (peek_input() == '>') { + if (peek_input(1) == '=') { + // right-shift-assign + skip_input(1); + current_column += 3; + + return Token::make(RIGHT_SHIFT_EQ, loc); + } else { + // right-shift + skip_input(); + current_column += 2; + + return Token::make(RIGHT_SHIFT, loc); + } + } else if (peek_input() == '=') { + // larger than or equal to + skip_input(); + current_column += 2; + + return Token::make(GREATER_OR_EQUAL, loc); + } else { + // larger than + current_column++; + return Token::make(RIGHT_ANGLE, loc); + } + case ':': + if (peek_input() == ':') { + // scope resolution :: + skip_input(); + current_column += 2; + + return Token::make(SCOPE_RESOLUTION, loc); + } else { + // single colon : + current_column++; + return Token::make(COLON, loc); + } + case '!': + // no special handling for macros in lexer? + if (peek_input() == '=') { + // not equal boolean operator + skip_input(); + current_column += 2; + + return Token::make(NOT_EQUAL, loc); + } else { + // not equal unary operator + current_column++; + + return Token::make(EXCLAM, loc); + } + case '?': + current_column++; + return Token::make(QUESTION_MARK, loc); + case '#': + current_column++; + return Token::make(HASH, loc); + case '[': + current_column++; + return Token::make(LEFT_SQUARE, loc); + case ']': + current_column++; + return Token::make(RIGHT_SQUARE, loc); + case '{': + current_column++; + return Token::make(LEFT_CURLY, loc); + case '}': + current_column++; + return Token::make(RIGHT_CURLY, loc); + case '@': + // TODO: i don't know what this does, does it need special handling? + current_column++; + return Token::make(PATTERN_BIND, loc); + case '$': + // TODO: i don't know what this does, does it need special handling? + current_column++; + return Token::make(DOLLAR_SIGN, loc); + case '~': + // TODO: i don't know what this does, does it need special handling? + current_column++; + return Token::make(TILDE, loc); + case '\\': + // TODO: i don't know what this does, does it need special handling? + current_column++; + return Token::make(BACKSLASH, loc); + case '`': + // TODO: i don't know what this does, does it need special handling? + current_column++; + return Token::make(BACKTICK, loc); + case '|': + if (peek_input() == '=') { + // bitwise or-assign? + skip_input(); + current_column += 2; + + return Token::make(PIPE_EQ, loc); + } else if (peek_input() == '|') { + // logical or + skip_input(); + current_column += 2; + + return Token::make(OR, loc); + } else { + // bitwise or + current_column++; + + return Token::make(PIPE, loc); + } + case '&': + if (peek_input() == '=') { + // bitwise and-assign? + skip_input(); + current_column += 2; + + return Token::make(AMP_EQ, loc); + } else if (peek_input() == '&') { + // logical and + skip_input(); + current_column += 2; + + return Token::make(LOGICAL_AND, loc); + } else { + // bitwise and/reference + current_column++; + + return Token::make(AMP, loc); + } + case '.': + if (peek_input() == '.') { + if (peek_input(1) == '.') { + // ellipsis + skip_input(1); + current_column += 3; + + return Token::make(ELLIPSIS, loc); + } else if (peek_input(1) == '=') { + // ..= + skip_input(1); + current_column += 3; + + return Token::make(DOT_DOT_EQ, loc); + } else { + // .. + skip_input(); + current_column += 2; + + return Token::make(DOT_DOT, loc); + } + } else if (!ISDIGIT(peek_input())) { + // single dot . + // Only if followed by a non-number + current_column++; + return Token::make(DOT, loc); + } + } + // TODO: special handling of _ in the lexer? instead of being identifier + + // byte and byte string test + if (current_char == 'b') { + if (peek_input() == '\'') { + // byte - allows any ascii or escapes + // would also have to take into account escapes: \x hex_digit hex_digit, + // \n, \r, \t, \\, \0 + + int length = 1; + + // char to save + char byte_char; + + skip_input(); + // make current char the next character + current_char = peek_input(); + + // detect escapes + if (current_char == '\\') { + /*skip_input(); + + // make current_char next character (letter) + current_char = peek_input();*/ + + parse_escape(length, byte_char, '\''); + + if (byte_char > 127) { + error_at( + get_current_location(), "byte char '%c' out of range", byte_char); + byte_char = 0; + } + + // skip_input(); + current_char = peek_input(); + length++; + + if (current_char != '\'') { + error_at(get_current_location(), "unclosed byte char"); + } + + // TODO: ensure skipping is needed here + skip_input(); + current_char = peek_input(); + length++; // go to next char + } else if (current_char != '\'') { + // otherwise, get character from direct input character + byte_char = current_char; + + skip_input(); + current_char = peek_input(); + + if (current_char != '\'') { + error_at(get_current_location(), "unclosed byte char"); + } + + // TODO: ensure skipping is needed here + skip_input(); + current_char = peek_input(); + length++; // go to next char + } else { + error_at(get_current_location(), "no character inside '' for byte char"); + } + + current_column += length; + + return Token::make_byte_char(loc, byte_char); + } else if (peek_input() == '"') { + // byte string + + // skip quote character + skip_input(); + + std::string str; + str.reserve(16); // some sensible default + + int length = 1; + current_char = peek_input(); + // TODO: handle escapes properly + + while (current_char != '"' && current_char != '\n') { + if (current_char == '\\') { + char output_char = 0; + parse_escape(length, output_char, '"'); + + if (output_char > 127) { + error_at(get_current_location(), + "char '%c' in byte string out of range", output_char); + output_char = 0; + } + + str += output_char; + + continue; + } + + length++; + + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + if (current_char == '\n') { + error_at(get_current_location(), "unended byte string literal"); + } else if (current_char == '"') { + skip_input(); + current_char = peek_input(); + } else { + gcc_unreachable(); + } + + return Token::make_byte_string(loc, str); + // TODO: ensure escapes and string continue work properly + } else if (peek_input() == 'r' && (peek_input(1) == '#' || peek_input(1) == '"')) { + // raw byte string literals + std::string str; + str.reserve(16); // some sensible default + + int length = 1; + int hash_count = 0; + + // get hash count at beginnning + skip_input(); + current_char = peek_input(); + while (current_char == '#') { + hash_count++; + length++; + + skip_input(); + current_char = peek_input(); + } + + if (current_char != '"') { + error_at(get_current_location(), "raw byte string has no opening '\"'"); + } + + skip_input(); + current_char = peek_input(); + + while (true) { + if (current_char == '"') { + bool enough_hashes = true; + + for (int i = 0; i < hash_count; i++) { + if (peek_input(i + 1) != '#') { + enough_hashes + = false; // could continue here - improve performance + } + } + + if (enough_hashes) { + // skip enough input and peek enough input + skip_input(hash_count); // is this enough? + current_char = peek_input(); + length += hash_count + 1; + break; + } + } + + length++; + + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + return Token::make_byte_string(loc, str); // TODO: does this work properly + } + } + + // raw stuff + if (current_char == 'r') { + int peek = peek_input(); + int peek1 = peek_input(1); + + if (peek == '#' && (ISALPHA(peek1) || peek1 == '_')) { + // raw identifier + std::string str; + str.reserve(16); // default + + skip_input(); + current_char = peek_input(); + + current_column += 2; + + str += current_char; + + bool first_is_underscore = current_char == '_'; + + int length = 1; + current_char = peek_input(); + // loop through entire name + while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { + length++; + + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + // if just a single underscore, not an identifier + if (first_is_underscore && length == 1) { + error_at(get_current_location(), "'_' is not a valid raw identifier"); + } + + if (str == "crate" || str == "extern" || str == "self" || str == "super" + || str == "Self") { + error_at( + get_current_location(), "'%s' is a forbidden raw identifier", str.c_str()); + } else { + return Token::make_identifier(loc, str); + } + } else if (peek == '"' || (peek == '#' && (ISALPHA(peek1) || peek1 == '_'))) { + // raw string literals + std::string str; + str.reserve(16); // some sensible default + + int length = 1; + int hash_count = 0; + + // get hash count at beginnning + current_char = peek; + while (current_char == '#') { + hash_count++; + length++; + + skip_input(); + current_char = peek_input(); + } + + if (current_char != '"') { + error_at(get_current_location(), "raw string has no opening '\"'"); + } + + skip_input(); + Codepoint current_char32 = test_peek_codepoint_input(); + + while (true) { + if (current_char32.value == '"') { + bool enough_hashes = true; + + for (int i = 0; i < hash_count; i++) { + // if (test_peek_codepoint_input(i + 1) != '#') { + // TODO: ensure this is a good enough replacement + if (peek_input(i + 1) != '#') { + enough_hashes + = false; // could continue here - improve performance + } + } + + if (enough_hashes) { + // skip enough input and peek enough input + skip_input(hash_count); // is this enough? + current_char = peek_input(); + length += hash_count + 1; + break; + } + } + + length++; + + str += current_char32; + test_skip_codepoint_input(); + current_char32 = test_peek_codepoint_input(); + } + + current_column += length; + + return Token::make_string(loc, str); // TODO: does this work properly + } + } + + // find identifiers and keywords + if (ISALPHA(current_char) || current_char == '_') { + std::string str; + str.reserve(16); // default + str += current_char; + + bool first_is_underscore = current_char == '_'; + + int length = 1; + current_char = peek_input(); + // loop through entire name + while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { + length++; + + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + // if just a single underscore, not an identifier + if (first_is_underscore && length == 1) { + return Token::make(UNDERSCORE, loc); + } + + TokenId keyword = classify_keyword(str); + if (keyword == IDENTIFIER) { + return Token::make_identifier(loc, str); + } else { + return Token::make(keyword, loc); + } + } + + // identify literals + // int or float literals - not processed properly + if (ISDIGIT(current_char) || current_char == '.') { // _ not allowed as first char + std::string str; + str.reserve(16); // some sensible default + str += current_char; + + PrimitiveCoreType type_hint = CORETYPE_UNKNOWN; + + bool is_real = (current_char == '.'); + + int length = 1; + + // handle binary, octal, hex literals + if (current_char == '0' && !ISDIGIT(peek_input())) { + current_char = peek_input(); + + if (current_char == 'x') { + // hex (integer only) + + skip_input(); + current_char = peek_input(); + + length++; + + // add 'x' to string after 0 so it is 0xFFAA or whatever + str += 'x'; + + // loop through to add entire hex number to string + while (is_x_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw hex numbers + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + // convert hex value to decimal representation + long hex_num = ::std::strtol(str.c_str(), NULL, 16); + + // create output string stream for hex value to be converted to string + // again + // TODO: if too slow, use sprintf + ::std::ostringstream ostr; + ostr << hex_num; + + // reassign string representation to converted value + str = ostr.str(); + + // parse in type suffix if it exists + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { + error_at(get_current_location(), + "invalid type suffix '%s' for integer (hex) literal", + get_type_hint_string(type_hint)); + } + } else if (current_char == 'o') { + // octal (integer only) + + skip_input(); + current_char = peek_input(); + + length++; + + // don't add any characters as C octals are just 0124 or whatever + + // loop through to add entire octal number to string + while (is_octal_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw octal numbers + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + // convert octal value to decimal representation + long octal_num = ::std::strtol(str.c_str(), NULL, 8); + + // create output string stream for octal value to be converted to + // string again + // TODO: if too slow, use sprintf + ::std::ostringstream ostr; + ostr << octal_num; + + // reassign string representation to converted value + str = ostr.str(); + + // parse in type suffix if it exists + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { + error_at(get_current_location(), + "invalid type suffix '%s' for integer (octal) literal", + get_type_hint_string(type_hint)); + } + } else if (current_char == 'b') { + // binary (integer only) + + skip_input(); + current_char = peek_input(); + + length++; + + // don't add any characters as C binary numbers are not really + // supported + + // loop through to add entire binary number to string + while (is_bin_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw binary numbers + str += current_char; + skip_input(); + current_char = peek_input(); + } + + current_column += length; + + // convert binary value to decimal representation + long bin_num = ::std::strtol(str.c_str(), NULL, 2); + + // create output string stream for binary value to be converted to + // string again + // TODO: if too slow, use sprintf + ::std::ostringstream ostr; + ostr << bin_num; + + // reassign string representation to converted value + str = ostr.str(); + + // parse in type suffix if it exists + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { + error_at(get_current_location(), + "invalid type suffix '%s' for integer (binary) literal", + get_type_hint_string(type_hint)); + } + } + } else { + // handle decimals (integer or float) + + current_char = peek_input(); + + // parse initial decimal literal - assuming integer + // TODO: test if works + parse_in_decimal(/*current_char, */ str, length); + + // detect float literal - TODO: fix: "242." is not recognised as a float literal + if (current_char == '.' && is_float_digit(peek_input(1))) { + // float with a '.', parse another decimal into it + + is_real = true; + + // add . to str + str += current_char; + skip_input(); + current_char = peek_input(); + + length++; + + // parse another decimal number for float + // TODO: test if works + parse_in_decimal(/*current_char, */ str, length); + + // parse in exponent part if it exists + // test to see if this works: + parse_in_exponent_part(/*current_char, */ str, length); + + // parse in type suffix if it exists + // TODO: see if works: + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 + && type_hint != CORETYPE_UNKNOWN) { + error_at(get_current_location(), + "invalid type suffix '%s' for float literal", + get_type_hint_string(type_hint)); + } + + } else if (current_char == '.' && check_valid_float_dot_end(peek_input(1))) { + is_real = true; + + // add . to str + str += current_char; + skip_input(); + current_char = peek_input(); + length++; + + // add a '0' after the . to stop ambiguity + str += '0'; + + // don't parse another decimal number for float + + // parse in exponent part if it exists - shouldn't exist? + // parse_in_exponent_part(/*current_char, */ str, length); + + // parse in type suffix if it exists - shouldn't exist? + // TODO: see if works: + // parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 + && type_hint != CORETYPE_UNKNOWN) { + error_at(get_current_location(), + "invalid type suffix '%s' for float literal", + get_type_hint_string(type_hint)); + } + } else if (current_char == 'E' || current_char == 'e') { + is_real = true; + + // parse exponent part + parse_in_exponent_part(/*current_char, */ str, length); + + // parse in type suffix if it exists + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 + && type_hint != CORETYPE_UNKNOWN) { + error_at(get_current_location(), + "invalid type suffix '%s' for float literal", + get_type_hint_string(type_hint)); + } + } else { + // is an integer + + // parse in type suffix if it exists + parse_in_type_suffix(/*current_char, */ type_hint, length); + + if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { + error_at(get_current_location(), + "invalid type suffix '%s' for integer (decimal) literal", + get_type_hint_string(type_hint)); + } + } + + current_column += length; + } + + // actually make the tokens + if (is_real) { + return Token::make_float(loc, str, type_hint); + } else { + return Token::make_int(loc, str, type_hint); + } + } + + // string literals - not processed properly + if (current_char == '"') { + Codepoint current_char32; + + std::string str; + str.reserve(16); // some sensible default + + int length = 1; + current_char32 = test_peek_codepoint_input(); + + // ok initial peek_codepoint seems to work without "too long" + + while (current_char32.value != '\n' && current_char32.value != '"') { + // TODO: handle escapes and string continue + if (current_char32.value == '\\') { + // parse escape + parse_utf8_escape(length, current_char32, '\''); + + // TODO: find a way to parse additional characters after the escape? + // return after parsing escape? + + str += current_char32; + + // required as parsing utf8 escape only changes current_char or something + current_char32 = test_peek_codepoint_input(); + + continue; + } + + length += test_get_input_codepoint_length(); + + // does this work? not technically a char. maybe have to convert to char series + str += current_char32; + test_skip_codepoint_input(); + current_char32 = test_peek_codepoint_input(); + } + + current_column += length; + + if (current_char32.value == '\n') { + error_at(get_current_location(), "unended string literal"); + } else if (current_char32.value == '"') { + skip_input(); + + current_char = peek_input(); + } else { + gcc_unreachable(); + } + + return Token::make_string(loc, str); + // TODO: account for escapes and string continue + // also, in rust a string is a series of unicode characters (4 bytes) + } + + // char literal attempt + if (current_char == '\'') { + // rust chars are 4 bytes and have some weird unicode representation thing + Codepoint current_char32; + + int length = 1; + + current_char32 = test_peek_codepoint_input(); + + // parse escaped char literal + if (current_char32.value == '\\') { + // parse escape + parse_utf8_escape(length, current_char32, '\''); + + // TODO - this skip may not be needed? + // test_skip_codepoint_input(); + + if (test_peek_codepoint_input().value != '\'') { + error_at(get_current_location(), "unended char literal"); + } else { + test_skip_codepoint_input(); + current_char = peek_input(); + length++; + } + + current_column += length; + + // TODO: FIX - char is actually 4 bytes in Rust (uint32) due to unicode + return Token::make_char(loc, current_char32); + } else { + // current_char32 = test_peek_codepoint_input(); + test_skip_codepoint_input(); + + if (test_peek_codepoint_input().value == '\'') { + // parse normal char literal + // TODO: FIX - char is actually 4 bytes in Rust (uint32) due to unicode + + // skip the ' character + skip_input(); + current_char = peek_input(); + + // TODO fix due to different widths of utf-8 chars + current_column += 3; + + return Token::make_char(loc, current_char32); + } else if (ISDIGIT(current_char32.value) || ISALPHA(current_char32.value) + || current_char32.value == '_') { + // parse lifetime name + ::std::string str; + // TODO: does this work properly? + str += current_char32; + + // TODO: fix lifetime name thing - actually, why am I even using utf-8 here? + + int length = 1; + + current_char32 = test_peek_codepoint_input(); + + while (ISDIGIT(current_char32.value) || ISALPHA(current_char32.value) + || current_char32.value == '_') { + length += test_get_input_codepoint_length(); + + str += current_char32; + test_skip_codepoint_input(); + current_char32 = test_peek_codepoint_input(); + } + + current_column += length; + + return Token::make_lifetime(loc, str); + } else { + error_at(get_current_location(), "expected ' after character constant"); + } + } + } + + // didn't match anything so error + error_at(loc, "unexpected character '%x'", current_char); + current_column++; + } + } + + // Shitty pass-by-reference way of parsing in type suffix. + bool Lexer::parse_in_type_suffix( + /*char& current_char, */ PrimitiveCoreType& type_hint, int& length) { + ::std::string suffix; + suffix.reserve(5); + + // get suffix + while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to suffix + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + suffix += current_char; + skip_input(); + current_char = peek_input(); + } + + if (suffix.empty()) { + // no type suffix: do nothing but also no error + return false; + } else if (suffix == "f32") { + type_hint = CORETYPE_F32; + } else if (suffix == "f64") { + type_hint = CORETYPE_F64; + } else if (suffix == "i8") { + type_hint = CORETYPE_I8; + } else if (suffix == "i16") { + type_hint = CORETYPE_I16; + } else if (suffix == "i32") { + type_hint = CORETYPE_I32; + } else if (suffix == "i64") { + type_hint = CORETYPE_I64; + } else if (suffix == "i128") { + type_hint = CORETYPE_I128; + } else if (suffix == "isize") { + type_hint = CORETYPE_ISIZE; + } else if (suffix == "u8") { + type_hint = CORETYPE_U8; + } else if (suffix == "u16") { + type_hint = CORETYPE_U16; + } else if (suffix == "u32") { + type_hint = CORETYPE_U32; + } else if (suffix == "u64") { + type_hint = CORETYPE_U64; + } else if (suffix == "u128") { + type_hint = CORETYPE_U128; + } else if (suffix == "usize") { + type_hint = CORETYPE_USIZE; + } else { + error_at(get_current_location(), "unknown number suffix '%s'", suffix.c_str()); + + return false; + } + + return true; + } + + void Lexer::parse_in_exponent_part(/*char& current_char, */ std::string& str, int& length) { + if (current_char == 'E' || current_char == 'e') { + // add exponent to string as strtod works with it + str += current_char; + skip_input(); + current_char = peek_input(); + + length++; + + // special - and + handling + if (current_char == '-') { + str += '-'; + + skip_input(); + current_char = peek_input(); + + length++; + } else if (current_char == '+') { + // don't add + but still skip input + skip_input(); + current_char = peek_input(); + + length++; + } + + // parse another decimal number for exponent + parse_in_decimal(/*current_char, */ str, length); + } + } + + void Lexer::parse_in_decimal(/*char& current_char, */ std::string& str, int& length) { + while (ISDIGIT(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + str += current_char; + skip_input(); + current_char = peek_input(); + } + } + + // Replace all assorted parse_x_escape with this? Avoids the backwards/peek issue. + bool Lexer::parse_escape(int& length, char& output_char, char opening_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + switch (current_char) { + case 'x': { + // hex char string (null-terminated) + char hexNum[3] = { 0, 0, 0 }; + + // first hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[0] = current_char; + + // second hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[1] = current_char; + + long hexLong = ::std::strtol(hexNum, NULL, 16); + + if (hexLong > 127) + error_at(get_current_location(), + "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); + // gcc_assert(hexLong < 128); // as ascii + char hexChar = static_cast(hexLong); + + // TODO: fix - does this actually give the right character? + output_char = hexChar; + } break; + case 'n': + output_char = '\n'; + break; + case 'r': + output_char = '\r'; + break; + case 't': + output_char = '\t'; + break; + case '\\': + output_char = '\\'; + break; + case '0': + output_char = '\0'; + break; + case '\'': + output_char = '\''; + break; + case '"': + output_char = '"'; + break; + case 'u': { + // TODO: shouldn't be used with this - use parse_utf8_escape + + skip_input(); + current_char = peek_input(); + length++; + + bool need_close_brace = false; + + // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at + // spec? + if (current_char == '{') { + need_close_brace = true; + + skip_input(); + current_char = peek_input(); + length++; + } + + // parse unicode escape + // 1-6 hex digits? + ::std::string num_str; + num_str.reserve(6); + + // test adding number directly + uint32_t test_val; + + // loop through to add entire hex number to string + while (is_x_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw hex numbers + num_str += current_char; + + // test adding number directly + char tmp[2] = { current_char, 0 }; + test_val *= 16; + test_val += ::std::strtol(tmp, NULL, 16); + + skip_input(); + current_char = peek_input(); + } + + // ensure closing brace + if (need_close_brace && current_char != '}') { + // actually an error + error_at(get_current_location(), "expected terminating '}' in unicode escape"); + return false; + } + + // ensure 1-6 hex characters + if (num_str.length() > 6 || num_str.length() < 1) { + error_at(get_current_location(), + "unicode escape should be between 1 and 6 hex characters; it is %lu", + num_str.length()); + return false; + } + + long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); + + // as debug, check hex_num = test_val + if (hex_num > 255) { + error_at( + get_current_location(), "non-ascii chars not implemented yet, defaulting to 0"); + hex_num = 0; + } + + // make output_char the value - UTF-8? + // TODO: actually make this work - output char must be 4 bytes, do I need a string for + // this? + output_char = static_cast(hex_num); + + return true; + } break; + case '\r': + case '\n': + // string continue + while (is_whitespace(current_char)) { + if (current_char == '\n') { + current_line++; + current_column = 1; + // tell line_table that new line starts + linemap_line_start(::line_table, current_line, max_column_hint); + + // reset "length" + length = 1; + + // get next char + skip_input(); + current_char = peek_input(); + + continue; + } + + skip_input(); + current_char = peek_input(); + length++; + } + + if (current_char == '\\') { + parse_escape(length, output_char, opening_char); + return true; + } else if (current_char == opening_char) { + // TODO: does this skip the ' or " character? It shouldn't. + output_char = 0; + return true; + } else { + output_char = current_char; + + // TODO: test has right result + /*skip_input(); + current_char = peek_input();*/ + + return true; + } + default: + error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); + // returns false if no parsing could be done + return false; + break; + } + // all non-special cases (unicode, string continue) should skip their used char + skip_input(); + current_char = peek_input(); + length++; + + // returns true if parsing was successful + return true; + } + + bool Lexer::parse_utf8_escape(int& length, Codepoint& output_char, char opening_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + switch (current_char) { + case 'x': { + // hex char string (null-terminated) + char hexNum[3] = { 0, 0, 0 }; + + // first hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[0] = current_char; + + // second hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[1] = current_char; + + long hexLong = ::std::strtol(hexNum, NULL, 16); + + if (hexLong > 127) + error_at(get_current_location(), + "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); + // gcc_assert(hexLong < 128); // as ascii + char hexChar = static_cast(hexLong); + + // TODO: fix - does this actually give the right character? + output_char = hexChar; + } break; + case 'n': + output_char = '\n'; + break; + case 'r': + output_char = '\r'; + break; + case 't': + output_char = '\t'; + break; + case '\\': + output_char = '\\'; + break; + case '0': + output_char = '\0'; + break; + case '\'': + output_char = '\''; + break; + case '"': + output_char = '"'; + break; + case 'u': { + skip_input(); + current_char = peek_input(); + length++; + + bool need_close_brace = false; + + // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at + // spec? + if (current_char == '{') { + need_close_brace = true; + + skip_input(); + current_char = peek_input(); + length++; + } + + // parse unicode escape + // 1-6 hex digits? + ::std::string num_str; + num_str.reserve(6); + + // test adding number directly + uint32_t test_val; + + // loop through to add entire hex number to string + while (is_x_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw hex numbers + num_str += current_char; + + // test adding number directly + char tmp[2] = { current_char, 0 }; + test_val *= 16; + test_val += ::std::strtol(tmp, NULL, 16); + + skip_input(); + current_char = peek_input(); + } + + // ensure closing brace if required + if (need_close_brace) { + if (current_char == '}') { + skip_input(); + current_char = peek_input(); + length++; + } else { + // actually an error + error_at( + get_current_location(), "expected terminating '}' in unicode escape"); + return false; + } + } + + // ensure 1-6 hex characters + if (num_str.length() > 6 || num_str.length() < 1) { + error_at(get_current_location(), + "unicode escape should be between 1 and 6 hex characters; it is %lu", + num_str.length()); + return false; + } + + long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); + + // assert fits a uint32_t + gcc_assert(hex_num < 4294967296); + + // ok can't figure out how to just convert to codepoint or use "this" so create new + // one + output_char = Codepoint(static_cast(hex_num)); + + // TODO: what is being outputted? the escape code for the unicode char (unicode + // number) or the character number? + + return true; + } break; + case '\r': + case '\n': + // string continue + while (is_whitespace(current_char)) { + if (current_char == '\n') { + current_line++; + current_column = 1; + // tell line_table that new line starts + linemap_line_start(::line_table, current_line, max_column_hint); + + // reset "length" + length = 1; + + // get next char + skip_input(); + current_char = peek_input(); + + continue; + } + + skip_input(); + current_char = peek_input(); + length++; + } + + if (current_char == '\\') { + parse_utf8_escape(length, output_char, opening_char); + return true; + } else if (current_char == opening_char) { + // TODO: does this skip the ' or " character? It shouldn't. + output_char = 0; + return true; + } else { + output_char = current_char; + + // TODO: test has right result + /*skip_input(); + current_char = peek_input();*/ + + return true; + } + default: + error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); + // returns false if no parsing could be done + return false; + break; + } + // all non-special cases (unicode, string continue) should skip their used char + skip_input(); + current_char = peek_input(); + length++; + + // returns true if parsing was successful + return true; + } + +#if 0 + bool Lexer::parse_ascii_escape(/*char& current_char, */ int& length, char& output_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + switch (current_char) { + case 'x': { + // hex char string (null-terminated) + char hexNum[3] = { 0, 0, 0 }; + + // first hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[0] = current_char; + + // second hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[1] = current_char; + + long hexLong = ::std::strtol(hexNum, NULL, 16); + + if (hexLong > 127) + error_at(get_current_location(), + "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); + // gcc_assert(hexLong < 128); // as ascii + char hexChar = static_cast(hexLong); + + // TODO: fix - does this actually give the right character? + output_char = hexChar; + } break; + case 'n': + output_char = '\n'; + break; + case 'r': + output_char = '\r'; + break; + case 't': + output_char = '\t'; + break; + case '\\': + output_char = '\\'; + break; + case '0': + output_char = '\0'; + break; + default: + // error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); + // returns false if no parsing could be done + return false; + break; + } + // returns true if parsing was successful + return true; + } + + bool Lexer::parse_quote_escape(/*char& current_char, */ int& length, char& output_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + switch (current_char) { + case '\'': + output_char = '\''; + break; + case '"': + output_char = '"'; + break; + default: + return false; + break; + } + return true; + } + + bool Lexer::parse_unicode_escape( + /*char& current_char, */ int& length, /*char*/ uint32_t& output_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + if (current_char != 'u') { + // not a unicode escape, but not necessarily an error + return false; + } + + skip_input(); + current_char = peek_input(); + length++; + + bool need_close_brace = false; + + // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at spec? + if (current_char == '{') { + need_close_brace = true; + + skip_input(); + current_char = peek_input(); + length++; + } + + // parse unicode escape + // 1-6 hex digits? + ::std::string num_str; + num_str.reserve(6); + + // test adding number directly + uint32_t test_val; + + // loop through to add entire hex number to string + while (is_x_digit(current_char) || current_char == '_') { + if (current_char == '_') { + // don't add _ to number + skip_input(); + current_char = peek_input(); + + length++; + + continue; + } + + length++; + + // add raw hex numbers + num_str += current_char; + + // test adding number directly + char tmp[2] = { current_char, 0 }; + test_val *= 16; + test_val += ::std::strtol(tmp, NULL, 16); + + skip_input(); + current_char = peek_input(); + } + + // ensure closing brace + if (need_close_brace && current_char != '}') { + // actually an error + error_at(get_current_location(), "expected terminating '}' in unicode escape"); + return false; + } + + // ensure 1-6 hex characters + if (num_str.length() > 6 || num_str.length() < 1) { + error_at(get_current_location(), + "unicode escape should be between 1 and 6 hex characters; it is %lu", num_str.length()); + return false; + } + + long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); + + // as debug, check hex_num = test_val + + // make output_char the value - UTF-8? + // TODO: actually make this work - output char must be 4 bytes, do I need a string for this? + output_char = static_cast(hex_num); + + return true; + } + + bool Lexer::parse_byte_escape(/*char& current_char, */ int& length, char& output_char) { + // skip to actual letter + skip_input(); + current_char = peek_input(); + length++; + + switch (current_char) { + case 'x': { + // hex char string (null-terminated) + char hexNum[3] = { 0, 0, 0 }; + + // first hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[0] = current_char; + + // second hex char + skip_input(); + current_char = peek_input(); + length++; + + if (!ISXDIGIT(current_char)) { + error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", + current_char); + } + hexNum[1] = current_char; + + long hexLong = ::std::strtol(hexNum, NULL, 16); + + if (hexLong > 255) + error_at(get_current_location(), + "ascii \\x escape '\\x%s' out of range - allows up to '\\xFF'", hexNum); + // gcc_assert(hexLong < 128); // as ascii + char hexChar = static_cast(hexLong); + + // TODO: fix - does this actually give the right character? + output_char = hexChar; + } break; + case 'n': + output_char = '\n'; + break; + case 'r': + output_char = '\r'; + break; + case 't': + output_char = '\t'; + break; + case '\\': + output_char = '\\'; + break; + case '0': + output_char = '\0'; + break; + default: + // error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); + // returns false if no parsing could be done + return false; + break; + } + // returns true if parsing was successful + return true; + } +#endif + + int Lexer::test_get_input_codepoint_length() { + uint8_t input = peek_input(); + + if (input < 128) { + // ascii -- 1 byte + // return input; + + return 1; + } else if ((input & 0xC0) == 0x80) { + // invalid (continuation; can't be first char) + // return 0xFFFE; + + return 0; + } else if ((input & 0xE0) == 0xC0) { + // 2 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + // uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); + // return output; + return 2; + } else if ((input & 0xF0) == 0xE0) { + // 3 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + /*uint32_t output + = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); + return output;*/ + return 3; + } else if ((input & 0xF8) == 0xF0) { + // 4 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + uint8_t input4 = peek_input(3); + if ((input4 & 0xC0) != 0x80) + return 0; + // return 0xFFFE; + + /*uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) + | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); + return output;*/ + return 4; + } else { + error_at(get_current_location(), "invalid UTF-8 (too long)"); + return 0; + } + } + + // TODO: rewrite lexing system to use utf-8 "codepoints" rather than bytes? + Codepoint Lexer::test_peek_codepoint_input() { + uint8_t input = peek_input(); + + if (input < 128) { + // ascii -- 1 byte + return { input }; + } else if ((input & 0xC0) == 0x80) { + // invalid (continuation; can't be first char) + return { 0xFFFE }; + } else if ((input & 0xE0) == 0xC0) { + // 2 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); + return { output }; + } else if ((input & 0xF0) == 0xE0) { + // 3 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint32_t output + = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); + return { output }; + } else if ((input & 0xF8) == 0xF0) { + // 4 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint8_t input4 = peek_input(3); + if ((input4 & 0xC0) != 0x80) + return { 0xFFFE }; + + uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) + | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); + return { output }; + } else { + error_at(get_current_location(), "invalid UTF-8 (too long)"); + return { 0xFFFE }; + } + } + + void Lexer::test_skip_codepoint_input() { + int toSkip = test_get_input_codepoint_length(); + gcc_assert(toSkip >= 1); + + skip_input(toSkip - 1); + } + + int Lexer::test_get_input_codepoint_n_length(int n_start_offset) { + uint8_t input = peek_input(n_start_offset); + + if (input < 128) { + // ascii -- 1 byte + // return input; + return 1; + } else if ((input & 0xC0) == 0x80) { + // invalid (continuation; can't be first char) + // return 0xFFFE; + return 0; + } else if ((input & 0xE0) == 0xC0) { + // 2 bytes + uint8_t input2 = peek_input(n_start_offset + 1); + if ((input2 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + // uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); + // return output; + return 2; + } else if ((input & 0xF0) == 0xE0) { + // 3 bytes + uint8_t input2 = peek_input(n_start_offset + 1); + if ((input2 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + uint8_t input3 = peek_input(n_start_offset + 2); + if ((input3 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + /*uint32_t output + = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); + return output;*/ + return 3; + } else if ((input & 0xF8) == 0xF0) { + // 4 bytes + uint8_t input2 = peek_input(n_start_offset + 1); + if ((input2 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + uint8_t input3 = peek_input(n_start_offset + 2); + if ((input3 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + uint8_t input4 = peek_input(n_start_offset + 3); + if ((input4 & 0xC0) != 0x80) + // return 0xFFFE; + return 0; + + /*uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) + | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); + return output;*/ + return 4; + } else { + error_at(get_current_location(), "invalid UTF-8 (too long)"); + return 0; + } + } + + // peeks the codepoint input at n codepoints ahead of current codepoint - try not to use + Codepoint Lexer::test_peek_codepoint_input(int n) { + int totalOffset = 0; + + // add up all offsets into total offset? does this do what I want? + for (int i = 0; i < n; i++) { + totalOffset += test_get_input_codepoint_n_length(totalOffset); + } + // issues: this would have (at least) O(n) lookup time, not O(1) like the rest? + + // TODO: implement if still needed + + // error out of function as it is not implemented + gcc_assert(1 == 0); + return { 0 }; + /* + uint8_t input = peek_input(); + + if (input < 128) { + // ascii -- 1 byte + return input; + } else if ((input & 0xC0) == 0x80) { + // invalid (continuation; can't be first char) + return 0xFFFE; + } else if ((input & 0xE0) == 0xC0) { + // 2 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0xFFFE; + + uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); + return output; + } else if ((input & 0xF0) == 0xE0) { + // 3 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0xFFFE; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return 0xFFFE; + + uint32_t output + = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); + return output; + } else if ((input & 0xF8) == 0xF0) { + // 4 bytes + uint8_t input2 = peek_input(1); + if ((input2 & 0xC0) != 0x80) + return 0xFFFE; + + uint8_t input3 = peek_input(2); + if ((input3 & 0xC0) != 0x80) + return 0xFFFE; + + uint8_t input4 = peek_input(3); + if ((input4 & 0xC0) != 0x80) + return 0xFFFE; + + uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) + | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); + return output; + } else { + error_at(get_current_location(), "invalid UTF-8 (too long)"); + return 0xFFFE; + }*/ + } +} \ No newline at end of file diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h new file mode 100644 index 0000000..b16cfeb --- /dev/null +++ b/gcc/rust/lex/rust-lex.h @@ -0,0 +1,125 @@ +#ifndef RUST_LEX_H +#define RUST_LEX_H + +#include "rust-buffered-queue.h" +#include "rust-token.h" + +namespace Rust { + class Lexer { + private: + // Request new location_t for current column in line_table + location_t get_current_location(); + + // Skips the current input char. + void skip_input(); + // Advances current input char to n + 1 chars ahead of current position. + void skip_input(int n); + + // Returns char n chars ahead of current position. + int peek_input(); + // Peeks the current char. + int peek_input(int n); + + // Classifies keyword (i.e. gets id for keyword). + TokenId classify_keyword(const std::string& str); + + // Builds a token from the input queue. + TokenPtr build_token(); + + // ok maybe all these may mean the lexer structure needs to be rethought + /* separated into functions because main method was too long, but they rely on and change + * state in the lexer, so variables must be passed by reference. */ + inline void parse_in_decimal(/*char& current_char, */std::string& str, int& length); + inline void parse_in_exponent_part(/*char& current_char, */std::string& str, int& length); + inline bool parse_in_type_suffix( + /*char& current_char, */PrimitiveCoreType& type_hint, int& length); + inline bool parse_ascii_escape(/*char& current_char, */int& length, char& output_char); + inline bool parse_quote_escape(/*char& current_char, */int& length, char& output_char); + inline bool parse_unicode_escape(/*char& current_char, */int& length, Codepoint& output_char); + inline bool parse_byte_escape(/*char& current_char, */int& length, char& output_char); + inline bool parse_escape(int& length, char& output_char, char opening_char); + inline bool parse_utf8_escape(int& length, Codepoint& output_char, char opening_char); + inline int test_get_input_codepoint_length(); + inline int test_get_input_codepoint_n_length(int n_start_offset); + inline Codepoint test_peek_codepoint_input(); + inline Codepoint test_peek_codepoint_input(int n); // maybe can use get_input_codepoint_length to get starting index + inline void test_skip_codepoint_input(); + + public: + // Construct lexer with input file and filename provided + Lexer(const char* filename, FILE* input); + ~Lexer(); + + // Returns token n tokens ahead of current position. + const_TokenPtr peek_token(int n); + // Peeks the current token. + const_TokenPtr peek_token(); + + // Advances current token to n + 1 tokens ahead of current position. + void skip_token(int n); + // Skips the current token. + void skip_token(); + + // Replaces the current token with a specified token. + void replace_current_token(TokenPtr replacement); + + private: + // File for use as input. + FILE* input; + + // Current line number. + int current_line; + // Current column number. + int current_column; + // Line map. + const struct line_map* line_map; + + // Max column number that can be quickly allocated - higher may require allocating new linemap + static const int max_column_hint = 80; + + // Input source wrapper thing. + struct InputSource { + // Input source file. + FILE* input; + + // Create new input source from file. + InputSource(FILE* input) : input(input) {} + + // Overload operator () to return next char from input stream. + int operator()() { + return fgetc(input); + } + }; + + // The input source for the lexer. + InputSource input_source; + // Input file queue. + buffered_queue input_queue; + + // Token source wrapper thing. + struct TokenSource { + // The lexer object that will use this TokenSource. + Lexer* lexer; + + // Create a new TokenSource with given lexer. + TokenSource(Lexer* parLexer) : lexer(parLexer) {} + + // Overload operator () to build token in lexer. + TokenPtr operator()() { + return lexer->build_token(); + } + }; + + // The token source for the lexer. + TokenSource token_source; + // Token stream queue. + buffered_queue, TokenSource> token_queue; + + // START CRAPPY CHANGES + int current_char; + + // END CRAPPY CHANGES + }; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc new file mode 100644 index 0000000..47bf750 --- /dev/null +++ b/gcc/rust/lex/rust-token.cc @@ -0,0 +1,100 @@ +#include "rust-token.h" + +#include "diagnostic.h" // for error_at + +namespace Rust { + // Hackily defined way to get token description for enum value using x-macros + const char* get_token_description(TokenId id) { + switch (id) { +#define RS_TOKEN(name, descr) \ + case name: \ + return descr; +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) + RS_TOKEN_LIST +#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN + default: + gcc_unreachable(); + } + } + + // Hackily defined way to get token description as a string for enum value using x-macros + const char* token_id_to_str(TokenId id) { + switch (id) { +#define RS_TOKEN(name, _) \ + case name: \ + return #name; +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) + RS_TOKEN_LIST +#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN + default: + gcc_unreachable(); + } + } + + const char* get_type_hint_string(PrimitiveCoreType type) { + switch (type) { + case CORETYPE_BOOL: + return "bool"; + case CORETYPE_CHAR: + return "char"; + case CORETYPE_STR: + return "str"; + // case CORETYPE_INT: + case CORETYPE_ISIZE: + return "isize"; + // case CORETYPE_UINT: + case CORETYPE_USIZE: + return "usize"; + case CORETYPE_F32: + return "f32"; + case CORETYPE_F64: + return "f64"; + case CORETYPE_I8: + return "i8"; + case CORETYPE_I16: + return "i16"; + case CORETYPE_I32: + return "i32"; + case CORETYPE_I64: + return "i64"; + case CORETYPE_I128: + return "i128"; + case CORETYPE_U8: + return "u8"; + case CORETYPE_U16: + return "u16"; + case CORETYPE_U32: + return "u32"; + case CORETYPE_U64: + return "u64"; + case CORETYPE_U128: + return "u128"; + case CORETYPE_UNKNOWN: + default: + return "unknown"; + } + } + + const char* Token::get_type_hint_str() const { + return get_type_hint_string(type_hint); + } + + const ::std::string& Token::get_str() const { + // FIXME: attempt to return null again + // gcc_assert(str != NULL); + + // HACK: allow referencing an empty string + static const ::std::string empty = ""; + + if (str == NULL) { + error_at(get_locus(), + "attempted to get string for '%s', which has no string. returning empty string " + "instead.", + get_token_description()); + return empty; + } + return *str; + } +} \ No newline at end of file diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h new file mode 100644 index 0000000..bf65ed3 --- /dev/null +++ b/gcc/rust/lex/rust-token.h @@ -0,0 +1,385 @@ +#ifndef RUST_TOKEN_H +#define RUST_TOKEN_H + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "input.h" +// order: config, system, coretypes, input + +#include +//#include // as shared_ptr is not available in std memory in c++03 +// replace with proper std::memory in c++11 +#include + +#include "rust-codepoint.h" + +namespace Rust { + // "Primitive core types" in Rust - the different int and float types, as well as some others + enum PrimitiveCoreType { + CORETYPE_UNKNOWN, + // named primitives + CORETYPE_BOOL, + CORETYPE_CHAR, + CORETYPE_STR, + // okay technically int and uint are arch-dependent (pointer size) + CORETYPE_INT, + CORETYPE_UINT, + // numbered number primitives + CORETYPE_F32, + CORETYPE_F64, + CORETYPE_I8, + CORETYPE_I16, + CORETYPE_I32, + CORETYPE_I64, + CORETYPE_I128, + CORETYPE_U8, + CORETYPE_U16, + CORETYPE_U32, + CORETYPE_U64, + CORETYPE_U128, + // arch-dependent pointer sizes + CORETYPE_ISIZE = CORETYPE_INT, + CORETYPE_USIZE = CORETYPE_UINT + }; + +// RS_TOKEN(name, description) +// RS_TOKEN_KEYWORD(name, identifier) +// +// Keep RS_TOKEN_KEYWORD sorted + +// note that abstract, async, become, box, do, final, macro, override, priv, try, typeof, unsized, +// virtual, and yield are unused +// TODO finish converting to rust keywords +#define RS_TOKEN_LIST \ + RS_TOKEN(FIRST_TOKEN, "") \ + RS_TOKEN(END_OF_FILE, "end of file") \ + RS_TOKEN(EXCLAM, "!") \ + RS_TOKEN(NOT_EQUAL, "!=") \ + RS_TOKEN(PERCENT, "%") \ + RS_TOKEN(PERCENT_EQ, "%=") \ + RS_TOKEN(AMP, "&") \ + RS_TOKEN(AMP_EQ, "&=") \ + RS_TOKEN(LOGICAL_AND, "&&") \ + RS_TOKEN(ASTERISK, "*") \ + RS_TOKEN(ASTERISK_EQ, "*=") \ + RS_TOKEN(PLUS, "+") \ + RS_TOKEN(PLUS_EQ, "+=") \ + RS_TOKEN(COMMA, ",") \ + RS_TOKEN(MINUS, "-") \ + RS_TOKEN(MINUS_EQ, "-=") \ + RS_TOKEN(RETURN_TYPE, "->") \ + RS_TOKEN(DOT, ".") \ + RS_TOKEN(DOT_DOT, "..") \ + RS_TOKEN(DOT_DOT_EQ, "..=") \ + RS_TOKEN(ELLIPSIS, "...") \ + RS_TOKEN(DIV, "/") \ + RS_TOKEN(DIV_EQ, "/=") \ + RS_TOKEN(COLON, ":") \ + RS_TOKEN(SEMICOLON, ";") \ + RS_TOKEN(LEFT_SHIFT, "<<") \ + RS_TOKEN(LEFT_SHIFT_EQ, "<<=") \ + RS_TOKEN(LEFT_ANGLE, "<") \ + RS_TOKEN(LESS_OR_EQUAL, "<=") \ + RS_TOKEN(EQUAL, "=") \ + RS_TOKEN(EQUAL_EQUAL, "==") \ + RS_TOKEN(MATCH_ARROW, "=>") \ + RS_TOKEN(RIGHT_ANGLE, ">") \ + RS_TOKEN(GREATER_OR_EQUAL, ">=") \ + RS_TOKEN(RIGHT_SHIFT, ">>") \ + RS_TOKEN(RIGHT_SHIFT_EQ, ">>=") \ + RS_TOKEN(PATTERN_BIND, "@") \ + RS_TOKEN(TILDE, "~") \ + RS_TOKEN(BACKSLASH, "\\") \ + RS_TOKEN(BACKTICK, "`") \ + RS_TOKEN(CARET, "^") \ + RS_TOKEN(CARET_EQ, "^=") \ + RS_TOKEN(PIPE, "|") \ + RS_TOKEN(PIPE_EQ, "|=") \ + RS_TOKEN(OR, "||") \ + RS_TOKEN(QUESTION_MARK, "?") \ + RS_TOKEN(HASH, "#") \ + /* from here on, dodgy and may not be correct. not operators and may be symbols */ \ + /* RS_TOKEN(SPACE, " ") probably too dodgy */ \ + /* RS_TOKEN(NEWLINE, "\n")*/ \ + RS_TOKEN(SCOPE_RESOLUTION, "::") /* dodgy */ \ + RS_TOKEN(SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ \ + RS_TOKEN(DOUBLE_QUOTE, "\"") \ + RS_TOKEN(UNDERSCORE, "_") /* TODO: treat as reserved word like mrustc instead? */ \ + RS_TOKEN(IDENTIFIER, "identifier") \ + RS_TOKEN(INT_LITERAL, \ + "integer literal") /* do different int and float types need different literal types? */ \ + RS_TOKEN(FLOAT_LITERAL, "float literal") \ + RS_TOKEN(STRING_LITERAL, "string literal") \ + RS_TOKEN(CHAR_LITERAL, "character literal") \ + RS_TOKEN(BYTE_STRING_LITERAL, "byte string literal") \ + RS_TOKEN(BYTE_CHAR_LITERAL, "byte character literal") \ + RS_TOKEN(LIFETIME, "lifetime") /* TODO: improve token type */ \ + /* Have "interpolated" tokens (whatever that means)? identifer, path, type, pattern, */ \ + /* expression, statement, block, meta, item in mrustc (but not directly in lexer). */ \ + RS_TOKEN(LEFT_PAREN, "(") \ + RS_TOKEN(RIGHT_PAREN, ")") \ + RS_TOKEN(LEFT_CURLY, "{") \ + RS_TOKEN(RIGHT_CURLY, "}") \ + RS_TOKEN(LEFT_SQUARE, "[") \ + RS_TOKEN(RIGHT_SQUARE, "]") \ + /* Macros */ \ + RS_TOKEN(DOLLAR_SIGN, "$") \ + /* Comments */ \ + RS_TOKEN(LINE_COMMENT, "//") \ + RS_TOKEN(INNER_LINE_DOC, "//!") \ + RS_TOKEN(OUTER_LINE_DOC, "///") \ + RS_TOKEN(BLOCK_COMMENT_START, "/*") \ + RS_TOKEN(BLOCK_COMMENT_END, "*/") \ + RS_TOKEN(INNER_BLOCK_DOC_START, "/*!") \ + RS_TOKEN(OUTER_BLOCK_DOC_START, "/**") /* have "weak" union and 'static keywords? */ \ + \ + RS_TOKEN_KEYWORD(ABSTRACT, "abstract") /* unused */ \ + RS_TOKEN_KEYWORD(AS, "as") \ + RS_TOKEN_KEYWORD(ASYNC, "async") /* unused */ \ + RS_TOKEN_KEYWORD(BECOME, "become") /* unused */ \ + RS_TOKEN_KEYWORD(BOX, "box") /* unused */ \ + RS_TOKEN_KEYWORD(BREAK, "break") \ + RS_TOKEN_KEYWORD(CONST, "const") \ + RS_TOKEN_KEYWORD(CONTINUE, "continue") \ + RS_TOKEN_KEYWORD(CRATE, "crate") \ + RS_TOKEN_KEYWORD(DO, "do") /* unused */ \ + RS_TOKEN_KEYWORD(DYN, "dyn") \ + RS_TOKEN_KEYWORD(ELSE, "else") \ + RS_TOKEN_KEYWORD(ENUM_TOK, "enum") \ + RS_TOKEN_KEYWORD(EXTERN_TOK, "extern") \ + RS_TOKEN_KEYWORD(FALSE_LITERAL, "false") \ + RS_TOKEN_KEYWORD(FINAL_TOK, "final") /* unused */ \ + RS_TOKEN_KEYWORD(FN_TOK, "fn") \ + RS_TOKEN_KEYWORD(FOR, "for") \ + RS_TOKEN_KEYWORD(IF, "if") \ + RS_TOKEN_KEYWORD(IMPL, "impl") \ + RS_TOKEN_KEYWORD(IN, "in") \ + RS_TOKEN_KEYWORD(LET, "let") \ + RS_TOKEN_KEYWORD(LOOP, "loop") \ + RS_TOKEN_KEYWORD(MACRO, "macro") /* unused */ \ + RS_TOKEN_KEYWORD(MATCH_TOK, "match") \ + RS_TOKEN_KEYWORD(MOD, "mod") \ + RS_TOKEN_KEYWORD(MOVE, "move") \ + RS_TOKEN_KEYWORD(MUT, "mut") \ + RS_TOKEN_KEYWORD(OVERRIDE_TOK, "override") /* unused */ \ + RS_TOKEN_KEYWORD(PRIV, "priv") /* unused */ \ + RS_TOKEN_KEYWORD(PUB, "pub") \ + RS_TOKEN_KEYWORD(REF, "ref") \ + RS_TOKEN_KEYWORD(RETURN_TOK, "return") \ + RS_TOKEN_KEYWORD(SELF_ALIAS, "Self") /* mrustc does not treat this as a reserved word*/ \ + RS_TOKEN_KEYWORD(SELF, "self") \ + RS_TOKEN_KEYWORD(STATIC_TOK, "static") \ + RS_TOKEN_KEYWORD(STRUCT_TOK, "struct") \ + RS_TOKEN_KEYWORD(SUPER, "super") \ + RS_TOKEN_KEYWORD(TRAIT, "trait") \ + RS_TOKEN_KEYWORD(TRUE_LITERAL, "true") \ + RS_TOKEN_KEYWORD(TRY, "try") /* unused */ \ + RS_TOKEN_KEYWORD(TYPE, "type") \ + RS_TOKEN_KEYWORD(TYPEOF, "typeof") /* unused */ \ + RS_TOKEN_KEYWORD(UNSAFE, "unsafe") \ + RS_TOKEN_KEYWORD(UNSIZED, "unsized") /* unused */ \ + RS_TOKEN_KEYWORD(USE, "use") \ + RS_TOKEN_KEYWORD(VIRTUAL, "virtual") /* unused */ \ + RS_TOKEN_KEYWORD(WHERE, "where") \ + RS_TOKEN_KEYWORD(WHILE, "while") \ + RS_TOKEN_KEYWORD(YIELD, "yield") /* unused */ \ + \ + RS_TOKEN(LAST_TOKEN, "") + + // Contains all token types. Crappy implementation via x-macros. + enum TokenId { +#define RS_TOKEN(name, _) name, +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) + RS_TOKEN_LIST +#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN + }; + + // dodgy "TokenPtr" declaration with Token forward declaration + class Token; + // A smart pointer (shared_ptr) to Token. + typedef ::std::shared_ptr TokenPtr; + // A smart pointer (shared_ptr) to a constant Token. + typedef ::std::shared_ptr const_TokenPtr; + + // Hackily defined way to get token description for enum value using x-macros + const char* get_token_description(TokenId id); + // Hackily defined way to get token description as a string for enum value using x-macros + const char* token_id_to_str(TokenId id); + // Get type hint description as a string. + const char* get_type_hint_string(PrimitiveCoreType type); + + // Represents a single token. Create using factory static methods. + class Token { + private: + // Token kind. + TokenId token_id; + // Token location. + location_t locus; + // Associated text (if any) of token. + ::std::string* str; + // Type hint for token based on lexer data (e.g. type suffix). Does not exist for most tokens. + PrimitiveCoreType type_hint; + + // Token constructor from token id and location. Has a null string. + Token(TokenId token_id, location_t location) : + token_id(token_id), locus(location), str(NULL), type_hint(CORETYPE_UNKNOWN) {} + + // Token constructor from token id, location, and a string. + Token(TokenId token_id, location_t location, const ::std::string& paramStr) : + token_id(token_id), locus(location), str(new ::std::string(paramStr)), + type_hint(CORETYPE_UNKNOWN) {} + + // Token constructor from token id, location, and a char. + Token(TokenId token_id, location_t location, char paramChar) : + token_id(token_id), locus(location), str(new ::std::string(1, paramChar)), + type_hint(CORETYPE_UNKNOWN) {} + + // Token constructor from token id, location, and a "codepoint". + Token(TokenId token_id, location_t location, Codepoint paramCodepoint) : + token_id(token_id), locus(location), str(new ::std::string(paramCodepoint.as_string())), + type_hint(CORETYPE_UNKNOWN) {} + + // Token constructor from token id, location, a string, and type hint. + Token(TokenId token_id, location_t location, const ::std::string& paramStr, + PrimitiveCoreType parType) : + token_id(token_id), + locus(location), str(new ::std::string(paramStr)), type_hint(parType) {} + + // No default initialiser. + Token(); + // Do not copy/assign tokens. + Token(const Token&); + Token& operator=(const Token&); + + public: + ~Token() { + delete str; + } + + // Makes and returns a new TokenPtr (with null string). + static TokenPtr make(TokenId token_id, location_t locus) { + return TokenPtr(new Token(token_id, locus)); + } + + // Makes and returns a new TokenPtr of type IDENTIFIER. + static TokenPtr make_identifier(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(IDENTIFIER, locus, str)); + } + + // Makes and returns a new TokenPtr of type INT_LITERAL. + static TokenPtr make_int(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(INT_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type INT_LITERAL. + static TokenPtr make_int( + location_t locus, const ::std::string& str, PrimitiveCoreType type_hint) { + return TokenPtr(new Token(INT_LITERAL, locus, str, type_hint)); + } + + // Makes and returns a new TokenPtr of type FLOAT_LITERAL. + static TokenPtr make_float(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(FLOAT_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type FLOAT_LITERAL. + static TokenPtr make_float( + location_t locus, const ::std::string& str, PrimitiveCoreType type_hint) { + return TokenPtr(new Token(FLOAT_LITERAL, locus, str, type_hint)); + } + + // Makes and returns a new TokenPtr of type STRING_LITERAL. + static TokenPtr make_string(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(STRING_LITERAL, locus, str, CORETYPE_STR)); + } + + // Makes and returns a new TokenPtr of type CHAR_LITERAL (fix). + static TokenPtr make_char(location_t locus, Codepoint char_lit) { + return TokenPtr(new Token(CHAR_LITERAL, locus, char_lit)); + } + + // Makes and returns a new TokenPtr of type BYTE_CHAR_LITERAL (fix). + static TokenPtr make_byte_char(location_t locus, char byte_char) { + return TokenPtr(new Token(BYTE_CHAR_LITERAL, locus, byte_char)); + } + + // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). + static TokenPtr make_byte_string(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(BYTE_STRING_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type LIFETIME. + static TokenPtr make_lifetime(location_t locus, const ::std::string& str) { + return TokenPtr(new Token(LIFETIME, locus, str)); + } + + // Gets id of the token. + TokenId get_id() const { + return token_id; + } + + // Gets location of the token. + location_t get_locus() const { + return locus; + } + + // Gets string description of the token. + const ::std::string& get_str() const; /*{ + // FIXME: put in header again when fix null problem + //gcc_assert(str != NULL); + if (str == NULL) { + error_at(get_locus(), "attempted to get string for '%s', which has no string. returning empty string instead.", get_token_description()); + return ""; + } + return *str; + }*/ + + // Gets token's type hint info. + PrimitiveCoreType get_type_hint() const { + return type_hint; + } + + // diagnostics (error reporting) + const char* get_token_description() const { + return Rust::get_token_description(token_id); + } + + // debugging + const char* token_id_to_str() const { + return Rust::token_id_to_str(token_id); + } + + // debugging + const char* get_type_hint_str() const; + + /* Returns whether the token is a literal of any type (int, float, char, string, byte char, + * byte string). */ + inline bool is_literal() const { + switch (token_id) { + case INT_LITERAL: + case FLOAT_LITERAL: + case CHAR_LITERAL: + case STRING_LITERAL: + case BYTE_CHAR_LITERAL: + case BYTE_STRING_LITERAL: + return true; + default: + return false; + } + } + + // Returns whether the token actually has a string (regardless of whether it should or not). + inline bool has_str() const { + return str != NULL; + } + + // Returns whether the token should have a string. + inline bool should_have_str() const { + return is_literal() || token_id == IDENTIFIER || token_id == LIFETIME; + } + }; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/mrustc_parser/ast/ast.cpp b/gcc/rust/mrustc_parser/ast/ast.cpp deleted file mode 100644 index e4fe49d..0000000 --- a/gcc/rust/mrustc_parser/ast/ast.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/ast.cpp - * - Implementation of the various AST classes - */ -#include "ast.hpp" -#include "crate.hpp" -#include "types.hpp" -#include "expr.hpp" -#include "../common.hpp" -#include -#include "../parse/parseerror.hpp" -#include - -namespace AST { - - -namespace { - ::std::vector clone_mivec(const ::std::vector& v) { - ::std::vector ri; - ri.reserve(v.size()); - for(const auto& i : v) - ri.push_back( i.clone() ); - return ri; - } -} - -AttributeList AttributeList::clone() const -{ - return AttributeList( clone_mivec(m_items) ); -} - -void AttributeList::push_back(Attribute i) -{ - m_items.push_back( ::std::move(i) ); -} -const Attribute* AttributeList::get(const char *name) const -{ - for( auto& i : m_items ) { - if(i.name() == name) { - //i.mark_used(); - return &i; - } - } - return 0; -} - -Attribute Attribute::clone() const -{ - TU_MATCHA( (m_data), (e), - (None, - return Attribute(m_span, m_name); - ), - (String, - return Attribute(m_span, m_name, e.val); - ), - (List, - return Attribute(m_span, m_name, clone_mivec(e.sub_items)); - ) - ) - throw ::std::runtime_error("Attribute::clone - Fell off end"); -} - -StructItem StructItem::clone() const -{ - return StructItem(m_attrs.clone(), m_is_public, m_name, m_type.clone()); -} -TupleItem TupleItem::clone() const -{ - return TupleItem(m_attrs.clone(), m_is_public, m_type.clone()); -} - - -TypeAlias TypeAlias::clone() const -{ - return TypeAlias( m_params.clone(), m_type.clone() ); -} -Static Static::clone() const -{ - return Static( m_class, m_type.clone(), m_value.is_valid() ? AST::Expr( m_value.node().clone() ) : AST::Expr() ); -} - -Function::Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args): - m_span(sp), - m_params( move(params) ), - m_rettype( move(ret_type) ), - m_args( move(args) ), - m_abi( mv$(abi) ), - m_is_const(is_const), - m_is_unsafe(is_unsafe), - m_is_variadic(is_variadic) -{ -} -Function Function::clone() const -{ - decltype(m_args) new_args; - for(const auto& arg : m_args) - new_args.push_back( ::std::make_pair( arg.first.clone(), arg.second.clone() ) ); - - auto rv = Function( m_span, m_params.clone(), m_abi, m_is_unsafe, m_is_const, m_is_variadic, m_rettype.clone(), mv$(new_args) ); - if( m_code.is_valid() ) - { - rv.m_code = AST::Expr( m_code.node().clone() ); - } - return rv; -} - -void Trait::add_type(::std::string name, AttributeList attrs, TypeRef type) { - m_items.push_back( Named(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) ); - m_items.back().data.attrs = mv$(attrs); -} -void Trait::add_function(::std::string name, AttributeList attrs, Function fcn) { - DEBUG("trait fn " << name); - m_items.push_back( Named(mv$(name), Item::make_Function({mv$(fcn)}), true) ); - m_items.back().data.attrs = mv$(attrs); -} -void Trait::add_static(::std::string name, AttributeList attrs, Static v) { - m_items.push_back( Named(mv$(name), Item::make_Static({mv$(v)}), true) ); - m_items.back().data.attrs = mv$(attrs); -} -void Trait::set_is_marker() { - m_is_marker = true; -} -bool Trait::is_marker() const { - return m_is_marker; -} -bool Trait::has_named_item(const ::std::string& name, bool& out_is_fcn) const -{ - for( const auto& i : m_items ) - { - if( i.name == name ) { - out_is_fcn = i.data.is_Function(); - return true; - } - } - return false; -} - -Trait Trait::clone() const -{ - auto rv = Trait(m_params.clone(), m_supertraits); - for(const auto& item : m_items) - { - rv.m_items.push_back( Named { item.name, item.data.clone(), item.is_pub } ); - } - return rv; -} - -Enum Enum::clone() const -{ - decltype(m_variants) new_variants; - for(const auto& var : m_variants) - { - TU_MATCHA( (var.m_data), (e), - (Value, - new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, e.m_value.clone()) ); - ), - (Tuple, - decltype(e.m_sub_types) new_st; - for(const auto& f : e.m_sub_types) - new_st.push_back( f.clone() ); - new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_st)) ); - ), - (Struct, - decltype(e.m_fields) new_fields; - for(const auto& f : e.m_fields) - new_fields.push_back( f.clone() ); - new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_fields)) ); - ) - ) - } - return Enum(m_params.clone(), mv$(new_variants)); -} -Struct Struct::clone() const -{ - TU_MATCHA( (m_data), (e), - (Unit, - return Struct(m_params.clone()); - ), - (Tuple, - decltype(e.ents) new_fields; - for(const auto& f : e.ents) - new_fields.push_back( f.clone() ); - return Struct(m_params.clone(), mv$(new_fields)); - ), - (Struct, - decltype(e.ents) new_fields; - for(const auto& f : e.ents) - new_fields.push_back( f.clone() ); - return Struct(m_params.clone(), mv$(new_fields)); - ) - ) - throw ""; -} - -Union Union::clone() const -{ - decltype(m_variants) new_vars; - for(const auto& f : m_variants) - new_vars.push_back( f.clone() ); - return Union(m_params.clone(), mv$(new_vars)); -} - -::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl) -{ - return os << "impl<" << impl.m_params << "> " << impl.m_trait.ent << " for " << impl.m_type << ""; -} - -void Impl::add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn) -{ - DEBUG("impl fn " << name); - m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Function(mv$(fcn)) ) } ); -} -void Impl::add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type) -{ - m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Type(TypeAlias(GenericParams(), mv$(type))) ) } ); -} -void Impl::add_static(bool is_public, bool is_specialisable, ::std::string name, Static v) -{ - m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Static(mv$(v)) ) } ); -} -void Impl::add_macro_invocation(MacroInvocation item) { - m_items.push_back( ImplItem { false, false, "", box$( Item::make_MacroInv(mv$(item)) ) } ); -} - -bool Impl::has_named_item(const ::std::string& name) const -{ - for( const auto& it : this->items() ) - { - if( it.name == name ) { - return true; - } - } - return false; -} - -::std::ostream& operator<<(::std::ostream& os, const Impl& impl) -{ - return os << impl.m_def; -} - -::std::ostream& operator<<(::std::ostream& os, const UseStmt& x) -{ - os << "Use(" << x.path << ")"; - return os; -} - - - -MacroInvocation MacroInvocation::clone() const -{ - return MacroInvocation(m_span, m_macro_name, m_ident, m_input.clone()); -} - - -UseStmt UseStmt::clone() const -{ - return UseStmt(sp, path); -} - -void ExternBlock::add_item(Named named_item) -{ - ASSERT_BUG(named_item.data.span, named_item.data.is_Function() || named_item.data.is_Static(), "Incorrect item type for ExternBlock"); - m_items.push_back( mv$(named_item) ); -} -ExternBlock ExternBlock::clone() const -{ - TODO(Span(), "Clone an extern block"); -} - -::std::shared_ptr Module::add_anon() { - auto rv = ::std::shared_ptr( new Module(m_my_path + FMT("#" << m_anon_modules.size())) ); - DEBUG("New anon " << rv->m_my_path); - rv->m_file_info = m_file_info; - - m_anon_modules.push_back( rv ); - - return rv; -} - -void Module::add_item( Named named_item ) { - m_items.push_back( mv$(named_item) ); - const auto& i = m_items.back(); - if( i.name == "" ) { - } - else { - DEBUG(m_my_path << "::" << i.name << " = " << i.data.tag_str() << ", attrs = " << i.data.attrs); - } -} -void Module::add_item(bool is_pub, ::std::string name, Item it, AttributeList attrs) { - it.attrs = mv$(attrs); - add_item( Named( mv$(name), mv$(it), is_pub ) ); -} -void Module::add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs) { - this->add_item( is_public, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) ); -} -void Module::add_alias(bool is_public, UseStmt us, ::std::string name, AttributeList attrs) { - this->add_item( is_public, mv$(name), Item(mv$(us)), mv$(attrs) ); -} -void Module::add_macro_invocation(MacroInvocation item) { - this->add_item( false, "", Item( mv$(item) ), ::AST::AttributeList {} ); -} -void Module::add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro) { - m_macros.push_back( Named( mv$(name), mv$(macro), is_exported ) ); -} -void Module::add_macro_import(::std::string name, const MacroRules& mr) { - m_macro_import_res.push_back( Named( mv$(name), &mr, false ) ); -} - -Item Item::clone() const -{ - TU_MATCHA( (*this), (e), - (None, - return AST::Item(e); - ), - (MacroInv, - TODO(this->span, "Clone on Item::MacroInv"); - ), - (Use, - return AST::Item(e.clone()); - ), - (ExternBlock, - TODO(this->span, "Clone on Item::" << this->tag_str()); - ), - (Impl, - TODO(this->span, "Clone on Item::Impl"); - ), - (NegImpl, - TODO(this->span, "Clone on Item::NegImpl"); - ), - (Module, - TODO(this->span, "Clone on Item::Module"); - ), - (Crate, - return AST::Item(e); - ), - (Type, - return AST::Item(e.clone()); - ), - (Struct, - return AST::Item(e.clone()); - ), - (Enum, - return AST::Item(e.clone()); - ), - (Union, - return AST::Item(e.clone()); - ), - (Trait, - return AST::Item(e.clone()); - ), - - (Function, - return AST::Item(e.clone()); - ), - (Static, - return AST::Item(e.clone()); - ) - ) - throw ""; -} - - - -::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp) -{ - //os << "TypeParam("; - os << tp.m_name; - os << " = "; - os << tp.m_default; - //os << ")"; - return os; -} -::std::ostream& operator<<(::std::ostream& os, const LifetimeParam& p) -{ - os << "'" << p.m_name; - return os; -} - -::std::ostream& operator<<(::std::ostream& os, const HigherRankedBounds& x) -{ - if( x.m_lifetimes.empty() ) { - return os; - } - os << "for<"; - for(const auto& l : x.m_lifetimes) - os << "'" << l << ","; - os << "> "; - return os; -} - - -::std::ostream& operator<<(::std::ostream& os, const GenericBound& x) -{ - TU_MATCH(GenericBound, (x), (ent), - (None, - os << "/*-*/"; - ), - (Lifetime, - os << "'" << ent.test << ": '" << ent.bound; - ), - (TypeLifetime, - os << ent.type << ": '" << ent.bound; - ), - (IsTrait, - os << ent.outer_hrbs << ent.type << ": " << ent.inner_hrbs << ent.trait; - ), - (MaybeTrait, - os << ent.type << ": ?" << ent.trait; - ), - (NotTrait, - os << ent.type << ": !" << ent.trait; - ), - (Equality, - os << ent.type << " = " << ent.replacement; - ) - ) - return os; -} - - -int GenericParams::find_name(const char* name) const -{ - for( unsigned int i = 0; i < m_type_params.size(); i ++ ) - { - if( m_type_params[i].name() == name ) - return i; - } - DEBUG("Type param '" << name << "' not in list"); - return -1; -} - -::std::ostream& operator<<(::std::ostream& os, const GenericParams& tps) -{ - return os << "<" << tps.m_lifetime_params << "," << tps.m_type_params << "> where {" << tps.m_bounds << "}"; -} - -} // namespace AST diff --git a/gcc/rust/mrustc_parser/ast/ast.hpp b/gcc/rust/mrustc_parser/ast/ast.hpp deleted file mode 100644 index 0a43cc7..0000000 --- a/gcc/rust/mrustc_parser/ast/ast.hpp +++ /dev/null @@ -1,638 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/ast.hpp - * - Core AST header - */ -#ifndef AST_HPP_INCLUDED -#define AST_HPP_INCLUDED - -#include -#include -#include -#include "../coretypes.hpp" -#include -#include -#include -#include - -#include "../parse/tokentree.hpp" -#include "types.hpp" - -#include -#include -#include -#include -#include // MacroInvocation - -#include "generics.hpp" - -#include - -namespace AST { - -class Crate; - -class Module; -class Item; - -using ::std::unique_ptr; -using ::std::move; - -enum eItemType -{ - ITEM_TRAIT, - ITEM_STRUCT, - ITEM_FN, - ITEM_STATIC, -}; - -struct StructItem -{ - ::AST::AttributeList m_attrs; - bool m_is_public; - ::std::string m_name; - TypeRef m_type; - - //StructItem() {} - - StructItem(::AST::AttributeList attrs, bool is_pub, ::std::string name, TypeRef ty): - m_attrs( mv$(attrs) ), - m_is_public(is_pub), - m_name( mv$(name) ), - m_type( mv$(ty) ) - { - } - - friend ::std::ostream& operator<<(::std::ostream& os, const StructItem& x) { - return os << (x.m_is_public ? "pub " : "") << x.m_name << ": " << x.m_type; - } - - StructItem clone() const; -}; - -struct TupleItem -{ - ::AST::AttributeList m_attrs; - bool m_is_public; - TypeRef m_type; - - //TupleItem() {} - - TupleItem(::AST::AttributeList attrs, bool is_pub, TypeRef ty): - m_attrs( mv$(attrs) ), - m_is_public(is_pub), - m_type( mv$(ty) ) - { - } - - friend ::std::ostream& operator<<(::std::ostream& os, const TupleItem& x) { - return os << (x.m_is_public ? "pub " : "") << x.m_type; - } - - TupleItem clone() const; -}; - -class TypeAlias -{ - GenericParams m_params; - TypeRef m_type; -public: - //TypeAlias() {} - TypeAlias(GenericParams params, TypeRef type): - m_params( move(params) ), - m_type( move(type) ) - {} - - const GenericParams& params() const { return m_params; } - const TypeRef& type() const { return m_type; } - - GenericParams& params() { return m_params; } - TypeRef& type() { return m_type; } - - TypeAlias clone() const; -}; - -class Static -{ -public: - enum Class - { - CONST, - STATIC, - MUT, - }; -private: - Class m_class; - TypeRef m_type; - Expr m_value; -public: - Static(Class s_class, TypeRef type, Expr value): - m_class(s_class), - m_type( move(type) ), - m_value( move(value) ) - {} - - const Class& s_class() const { return m_class; } - const TypeRef& type() const { return m_type; } - const Expr& value() const { return m_value; } - - TypeRef& type() { return m_type; } - Expr& value() { return m_value; } - - Static clone() const; -}; - -class Function -{ -public: - typedef ::std::vector< ::std::pair > Arglist; - -private: - Span m_span; - GenericParams m_params; - Expr m_code; - TypeRef m_rettype; - Arglist m_args; - - ::std::string m_abi; - bool m_is_const; - bool m_is_unsafe; - bool m_is_variadic; // extern only -public: - Function(const Function&) = delete; - Function& operator=(const Function&) = delete; - Function(Function&&) = default; - Function& operator=(Function&&) = default; - - Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args); - - void set_code(Expr code) { m_code = ::std::move(code); } - - const ::std::string& abi() const { return m_abi; }; - bool is_const() const { return m_is_const; } - bool is_unsafe() const { return m_is_unsafe; } - bool is_variadic() const { return m_is_variadic; } - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - const Expr& code() const { return m_code; } - Expr& code() { return m_code; } - const TypeRef& rettype() const { return m_rettype; } - TypeRef& rettype() { return m_rettype; } - const Arglist& args() const { return m_args; } - Arglist& args() { return m_args; } - - Function clone() const; -}; - -class Trait -{ - GenericParams m_params; - ::std::vector< Spanned > m_supertraits; - - bool m_is_marker; - bool m_is_unsafe; - NamedList m_items; -public: - Trait(): - m_is_marker(false), - m_is_unsafe(false) - {} - Trait(GenericParams params, ::std::vector< Spanned > supertraits): - m_params( mv$(params) ), - m_supertraits( mv$(supertraits) ), - m_is_marker(false), - m_is_unsafe(false) - { - } - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - const ::std::vector >& supertraits() const { return m_supertraits; } - ::std::vector >& supertraits() { return m_supertraits; } - - const NamedList& items() const { return m_items; } - NamedList& items() { return m_items; } - - void add_type(::std::string name, AttributeList attrs, TypeRef type); - void add_function(::std::string name, AttributeList attrs, Function fcn); - void add_static(::std::string name, AttributeList attrs, Static v); - - void set_is_marker(); - bool is_marker() const; - void set_is_unsafe() { m_is_unsafe = true; } - bool is_unsafe() const { return m_is_unsafe; } - - bool has_named_item(const ::std::string& name, bool& out_is_fcn) const; - - Trait clone() const; -}; - -TAGGED_UNION_EX(EnumVariantData, (), Value, - ( - (Value, struct { - ::AST::Expr m_value; - }), - (Tuple, struct { - ::std::vector m_sub_types; - }), - (Struct, struct { - ::std::vector m_fields; - }) - ), - (), (), - ( - public: - ) - ); - -struct EnumVariant -{ - AttributeList m_attrs; - ::std::string m_name; - EnumVariantData m_data; - - EnumVariant() - { - } - - EnumVariant(AttributeList attrs, ::std::string name, Expr&& value): - m_attrs( mv$(attrs) ), - m_name( mv$(name) ), - m_data( EnumVariantData::make_Value({mv$(value)}) ) - { - } - - EnumVariant(AttributeList attrs, ::std::string name, ::std::vector sub_types): - m_attrs( mv$(attrs) ), - m_name( ::std::move(name) ), - m_data( EnumVariantData::make_Tuple( {mv$(sub_types)} ) ) - { - } - - EnumVariant(AttributeList attrs, ::std::string name, ::std::vector fields): - m_attrs( mv$(attrs) ), - m_name( ::std::move(name) ), - m_data( EnumVariantData::make_Struct( {mv$(fields)} ) ) - { - } - - friend ::std::ostream& operator<<(::std::ostream& os, const EnumVariant& x) - { - os << "EnumVariant(" << x.m_name; - TU_MATCH(EnumVariantData, (x.m_data), (e), - (Value, - os << " = " << e.m_value; - ), - (Tuple, - os << "(" << e.m_sub_types << ")"; - ), - (Struct, - os << " { " << e.m_fields << " }"; - ) - ) - return os << ")"; - } -}; - -class Enum -{ - GenericParams m_params; - ::std::vector m_variants; -public: - Enum() {} - Enum( GenericParams params, ::std::vector variants ): - m_params( move(params) ), - m_variants( move(variants) ) - {} - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - const ::std::vector& variants() const { return m_variants; } - ::std::vector& variants() { return m_variants; } - - Enum clone() const; -}; - -TAGGED_UNION_EX(StructData, (), Struct, - ( - (Unit, struct {}), - (Tuple, struct { - ::std::vector ents; - }), - (Struct, struct { - ::std::vector ents; - }) - ), - (),(), - ( - public: - ) - ); - -class Struct -{ - GenericParams m_params; -public: - StructData m_data; - - Struct() {} - Struct(GenericParams params): - m_params( mv$(params) ), - m_data( StructData::make_Unit({}) ) - { - } - Struct( GenericParams params, ::std::vector fields ): - m_params( move(params) ), - m_data( StructData::make_Struct({mv$(fields)}) ) - {} - Struct( GenericParams params, ::std::vector fields ): - m_params( move(params) ), - m_data( StructData::make_Tuple({mv$(fields)}) ) - {} - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - - Struct clone() const; -}; - -class Union -{ -public: - GenericParams m_params; - ::std::vector m_variants; - - Union( GenericParams params, ::std::vector fields ): - m_params( move(params) ), - m_variants( mv$(fields) ) - {} - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - - Union clone() const; -}; - -class ImplDef -{ - AttributeList m_attrs; - bool m_is_unsafe; - GenericParams m_params; - Spanned m_trait; - TypeRef m_type; -public: - ImplDef(AttributeList attrs, GenericParams params, Spanned trait_type, TypeRef impl_type): - m_attrs( mv$(attrs) ), - m_is_unsafe( false ), - m_params( mv$(params) ), - m_trait( mv$(trait_type) ), - m_type( mv$(impl_type) ) - {} - - ImplDef(ImplDef&&) /*noexcept*/ = default; - ImplDef& operator=(ImplDef&&) = default; - - void set_is_unsafe() { m_is_unsafe = true; } - bool is_unsafe() const { return m_is_unsafe; } - - // Accessors - const AttributeList& attrs() const { return m_attrs; } - AttributeList& attrs() { return m_attrs; } - - const GenericParams& params() const { return m_params; } - GenericParams& params() { return m_params; } - const Spanned& trait() const { return m_trait; } - Spanned& trait() { return m_trait; } - const TypeRef& type() const { return m_type; } - TypeRef& type() { return m_type; } - - - friend ::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl); -}; - -class Impl -{ -public: - struct ImplItem { - bool is_pub; // Ignored for trait impls - bool is_specialisable; - ::std::string name; - - ::std::unique_ptr data; - }; - -private: - ImplDef m_def; - - ::std::vector< ImplItem > m_items; - //NamedList m_types; - //NamedList m_functions; - //NamedList m_statics; - -public: - Impl(Impl&&) /*noexcept*/ = default; - Impl(ImplDef def): - m_def( mv$(def) ) - {} - Impl& operator=(Impl&&) = default; - - void add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn); - void add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type); - void add_static(bool is_public, bool is_specialisable, ::std::string name, Static v); - void add_macro_invocation( MacroInvocation inv ); - - const ImplDef& def() const { return m_def; } - ImplDef& def() { return m_def; } - const ::std::vector& items() const { return m_items; } - ::std::vector& items() { return m_items; } - - bool has_named_item(const ::std::string& name) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl); - -private: -}; - -struct UseStmt -{ - Span sp; - ::AST::Path path; - ::AST::PathBinding alt_binding; - - UseStmt(Span sp, Path p): - sp(sp), - path(p) - { - } - - UseStmt clone() const; - - friend ::std::ostream& operator<<(::std::ostream& os, const UseStmt& x); -}; - -class ExternBlock -{ - ::std::string m_abi; - ::std::vector< Named> m_items; -public: - ExternBlock(::std::string abi): - m_abi( mv$(abi) ) - {} - - const ::std::string& abi() const { return m_abi; } - - void add_item(Named named_item); - - // NOTE: Only Function and Static are valid. - ::std::vector>& items() { return m_items; } - const ::std::vector>& items() const { return m_items; } - - ExternBlock clone() const; -}; - -/// Representation of a parsed (and being converted) function -class Module -{ - ::AST::Path m_my_path; - - // Module-level items - /// General items - ::std::vector> m_items; - - // --- Runtime caches and state --- - ::std::vector< ::std::shared_ptr > m_anon_modules; - - ::std::vector< Named > m_macro_import_res; - ::std::vector< Named > m_macros; - -public: - struct FileInfo - { - bool controls_dir = false; - ::std::string path = "!"; - }; - - FileInfo m_file_info; - - bool m_insert_prelude = true; // Set to false by `#[no_prelude]` handler - char m_index_populated = 0; // 0 = no, 1 = partial, 2 = complete - struct IndexEnt { - bool is_pub; // Used as part of glob import checking - bool is_import; // Set if this item has a path that isn't `mod->path() + name` - ::AST::Path path; - }; - - // TODO: Document difference between namespace and Type - ::std::unordered_map< ::std::string, IndexEnt > m_namespace_items; - ::std::unordered_map< ::std::string, IndexEnt > m_type_items; - ::std::unordered_map< ::std::string, IndexEnt > m_value_items; - - // List of macros imported from other modules (via #[macro_use], includes proc macros) - // - First value is an absolute path to the macro (including crate name) - ::std::vector<::std::pair< ::std::vector<::std::string>, const MacroRules* >> m_macro_imports; - -public: - Module() {} - Module(::AST::Path path): - m_my_path( mv$(path) ) - { - } - - bool is_anon() const { - return m_my_path.nodes().size() > 0 && m_my_path.nodes().back().name()[0] == '#'; - } - - /// Create an anon module (for use inside expressions) - ::std::shared_ptr add_anon(); - - void add_item(Named item); - void add_item(bool is_pub, ::std::string name, Item it, AttributeList attrs); - void add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs); - void add_alias(bool is_public, UseStmt path, ::std::string name, AttributeList attrs); - void add_macro_invocation(MacroInvocation item); - - void add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro); - void add_macro_import(::std::string name, const MacroRules& mr); - - - - const ::AST::Path& path() const { return m_my_path; } - - ::std::vector>& items() { return m_items; } - const ::std::vector>& items() const { return m_items; } - - ::std::vector< ::std::shared_ptr >& anon_mods() { return m_anon_modules; } - const ::std::vector< ::std::shared_ptr >& anon_mods() const { return m_anon_modules; } - - - NamedList& macros() { return m_macros; } - const NamedList& macros() const { return m_macros; } - const ::std::vector > macro_imports_res() const { return m_macro_import_res; } - -private: - void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name); -}; - -TAGGED_UNION_EX(Item, (), None, - ( - (None, struct {} ), - (MacroInv, MacroInvocation), - (Use, UseStmt), - - // Nameless items - (ExternBlock, ExternBlock), - (Impl, Impl), - (NegImpl, ImplDef), - - (Module, Module), - (Crate, struct { - ::std::string name; - }), - - (Type, TypeAlias), - (Struct, Struct), - (Enum, Enum), - (Union, Union), - (Trait, Trait), - - (Function, Function), - (Static, Static) - ), - - (, attrs(mv$(x.attrs))), (attrs = mv$(x.attrs);), - ( - public: - AttributeList attrs; - Span span; - - Item clone() const; - ) - ); - -} // namespace AST - -class GenericResolveClosure -{ - const ::AST::GenericParams& m_params; - const ::std::vector& m_args; -public: - GenericResolveClosure(const AST::GenericParams& params, const ::std::vector& args): - m_params(params), - m_args(args) - {} - const TypeRef& operator()(const char *argname) { - for(unsigned int i = 0; i < m_params.ty_params().size(); i ++) - { - if( m_params.ty_params()[i].name() == argname ) { - return m_args.at(i); - } - } - throw ::std::runtime_error("BUGCHECK - Unknown arg in field type"); - } -}; - - -#endif // AST_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/ast/attrs.hpp b/gcc/rust/mrustc_parser/ast/attrs.hpp deleted file mode 100644 index 0e1c814..0000000 --- a/gcc/rust/mrustc_parser/ast/attrs.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/attrs.hpp - * - AST Attributes (#[foo] and #![foo]) - */ -#ifndef _AST_ATTRS_HPP_ -#define _AST_ATTRS_HPP_ - - -namespace AST { - -// -class Attribute; -::std::ostream& operator<<(::std::ostream& os, const Attribute& x); - -/// A list of attributes on an item (searchable by the attribute name) -class AttributeList -{ -public: - ::std::vector m_items; - - AttributeList() {} - AttributeList(::std::vector items): - m_items( mv$(items) ) - { - } - - // Move present - AttributeList(AttributeList&&) = default; - AttributeList& operator=(AttributeList&&) = default; - // No copy assign, but explicit copy - explicit AttributeList(const AttributeList&) = default; - AttributeList& operator=(const AttributeList&) = delete; - // Explicit clone - AttributeList clone() const; - - void push_back(Attribute i); - - const Attribute* get(const char *name) const; - Attribute* get(const char *name) { - return const_cast( const_cast(this)->get(name)); - } - bool has(const char *name) const { - return get(name) != 0; - } - - friend ::std::ostream& operator<<(::std::ostream& os, const AttributeList& x) { - for(const auto& i : x.m_items) { - os << "#[" << i << "]"; - } - return os; - } -}; - - -TAGGED_UNION(AttributeData, None, - (None, struct {}), - (String, struct { - ::std::string val; - }), - (List, struct { - ::std::vector sub_items; - }) - ); - -// An attribute can has a name, and optional data: -// Data can be: -// - A parenthesised token tree -// > In 1.19 this was actually just sub-attributes -// - an associated (string) literal - -class Attribute -{ - Span m_span; - ::std::string m_name; - AttributeData m_data; - mutable bool m_is_used; -public: - Attribute(Span sp, ::std::string name): - m_span(::std::move(sp)), - m_name(name), - m_data( AttributeData::make_None({}) ) - { - } - Attribute(Span sp, ::std::string name, ::std::string str_val): - m_span(::std::move(sp)), - m_name(name), - m_data( AttributeData::make_String({mv$(str_val)}) ) - { - } - Attribute(Span sp, ::std::string name, ::std::vector items): - m_span(::std::move(sp)), - m_name(name), - m_data( AttributeData::make_List({mv$(items)}) ) - { - } - - explicit Attribute(const Attribute& x): - m_span(x.m_span), - m_name(x.m_name), - m_is_used(x.m_is_used) - { - TU_MATCHA( (x.m_data), (e), - (None, - ), - (String, - m_data = AttributeData::make_String({ e.val }); - ), - (List, - m_data = AttributeData::make_List({ ::std::vector(e.sub_items) }); - ) - ) - } - Attribute& operator=(const Attribute& ) = delete; - Attribute(Attribute&& ) = default; - Attribute& operator=(Attribute&& ) = default; - Attribute clone() const; - - void mark_used() const { m_is_used = true; } - bool is_used() const { return m_is_used; } - - const Span& span() const { return m_span; } - const ::std::string& name() const { return m_name; } - const AttributeData& data() const { return m_data; } - - // Legacy accessors/checkers - bool has_noarg() const { return m_data.is_None(); } - - bool has_string() const { return m_data.is_String(); } - const ::std::string& string() const { return m_data.as_String().val; } - - bool has_sub_items() const { return m_data.is_List(); } - const ::std::vector& items() const { return m_data.as_List().sub_items; } - ::std::vector& items() { return m_data.as_List().sub_items; } - - friend ::std::ostream& operator<<(::std::ostream& os, const Attribute& x) { - os << x.m_name; - TU_MATCHA( (x.m_data), (e), - (None, - ), - (String, - os << "=\"" << e.val << "\""; - ), - (List, - os << "(" << e.sub_items << ")"; - ) - ) - return os; - } -}; - -} // namespace AST - -#endif - diff --git a/gcc/rust/mrustc_parser/ast/crate.cpp b/gcc/rust/mrustc_parser/ast/crate.cpp deleted file mode 100644 index 3db09f1..0000000 --- a/gcc/rust/mrustc_parser/ast/crate.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/crate.cpp - * - Helper functions for the AST::Crate type (includes loading `extern crate`s) - */ -#include "crate.hpp" -#include "ast.hpp" -#include "../parse/parseerror.hpp" -#include "../expand/cfg.hpp" -#include // HIR::Crate -#include // HIR_Deserialise -#include - -::std::vector<::std::string> AST::g_crate_load_dirs = { }; -::std::map<::std::string, ::std::string> AST::g_crate_overrides; - -namespace { - bool check_item_cfg(const ::AST::AttributeList& attrs) - { - for(const auto& at : attrs.m_items) { - if( at.name() == "cfg" && !check_cfg(at.span(), at) ) { - return false; - } - } - return true; - } - void iterate_module(::AST::Module& mod, ::std::function fcn) - { - fcn(mod); - for( auto& sm : mod.items() ) - { - TU_IFLET(::AST::Item, sm.data, Module, e, - if( check_item_cfg(sm.data.attrs) ) - { - iterate_module(e, fcn); - } - ) - } - // TODO: What about if an anon mod has been #[cfg]-d out? - // - For now, disable - //for(const auto& anon : mod.anon_mods() ) { - // iterate_module(*anon, fcn); - //} - } -} - - -namespace AST { - -Crate::Crate(): - m_root_module(::AST::Path("",{})), - m_load_std(LOAD_STD) -{ -} - -void Crate::load_externs() -{ - auto cb = [this](Module& mod) { - for( /*const*/ auto& it : mod.items() ) - { - TU_IFLET(AST::Item, it.data, Crate, c, - if( check_item_cfg(it.data.attrs) ) - { - c.name = load_extern_crate( it.data.span, c.name ); - } - ) - } - }; - iterate_module(m_root_module, cb); - - // Check for no_std or no_core, and load libstd/libcore - // - Duplicates some of the logic in "Expand", but also helps keep crate loading separate to most of expand - // NOTE: Not all crates are loaded here, any crates loaded by macro invocations will be done during expand. - bool no_std = false; - bool no_core = false; - - for( const auto& a : this->m_attrs.m_items ) - { - if( a.name() == "no_std" ) - no_std = true; - if( a.name() == "no_core" ) - no_core = true; - if( a.name() == "cfg_attr" && a.items().size() == 2 ) { - if( check_cfg(a.span(), a.items().at(0)) ) - { - const auto& a2 = a.items().at(1); - if( a2.name() == "no_std" ) - no_std = true; - if( a2.name() == "no_core" ) - no_core = true; - } - } - } - - if( no_core ) { - // Don't load anything - } - else if( no_std ) { - auto n = this->load_extern_crate(Span(), "core"); - ASSERT_BUG(Span(), n == "core", "libcore wasn't loaded as `core`, instead `" << n << "`"); - } - else { - auto n = this->load_extern_crate(Span(), "std"); - ASSERT_BUG(Span(), n == "std", "libstd wasn't loaded as `std`, instead `" << n << "`"); - } -} -// TODO: Handle disambiguating crates with the same name (e.g. libc in std and crates.io libc) -// - Crates recorded in rlibs should specify a hash/tag that's passed in to this function. -::std::string Crate::load_extern_crate(Span sp, const ::std::string& name, const ::std::string& basename/*=""*/) -{ - DEBUG("Loading crate '" << name << "'"); - - ::std::string path; - auto it = g_crate_overrides.find(name); - if(basename == "" && it != g_crate_overrides.end()) - { - path = it->second; - if( !::std::ifstream(path).good() ) { - ERROR(sp, E0000, "Unable to open crate '" << name << "' at path " << path); - } - } - else - { - // Search a list of load paths for the crate - for(const auto& p : g_crate_load_dirs) - { - if( basename == "" ) - { - path = p + "/lib" + name + ".hir"; - // TODO: Search for `p+"/lib"+name+"-*.hir" (which would match e.g. libnum-0.11.hir) - } - else - { - path = p + "/" + basename; - } - - if( ::std::ifstream(path).good() ) { - break ; - } - } - if( !::std::ifstream(path).good() ) { - if( basename.empty() ) - ERROR(sp, E0000, "Unable to locate crate '" << name << "' in search directories"); - else - ERROR(sp, E0000, "Unable to locate crate '" << name << "' with filename " << basename << " in search directories"); - } - } - - // NOTE: Creating `ExternCrate` loads the crate from the specified path - auto ec = ExternCrate { name, path }; - auto real_name = ec.m_hir->m_crate_name; - assert(!real_name.empty()); - auto res = m_extern_crates.insert(::std::make_pair( real_name, mv$(ec) )); - if( !res.second ) { - // Crate already loaded? - } - auto& ext_crate = res.first->second; - // Move the external list out (doesn't need to be kept in the nested crate) - auto crate_ext_list = mv$( ext_crate.m_hir->m_ext_crates ); - - // Load referenced crates - for( const auto& ext : crate_ext_list ) - { - if( m_extern_crates.count(ext.first) == 0 ) - { - const auto load_name = this->load_extern_crate(sp, ext.first, ext.second.m_basename); - if( load_name != ext.first ) - { - // ERROR - The crate loaded wasn't the one that was used when compiling this crate. - ERROR(sp, E0000, "The crate file `" << ext.second.m_basename << "` didn't load the expected crate - have " << load_name << " != exp " << ext.first); - } - } - } - - DEBUG("Loaded '" << name << "' from '" << basename << "' (actual name is '" << real_name << "')"); - return real_name; -} - -ExternCrate::ExternCrate(const ::std::string& name, const ::std::string& path): - m_name(name), - m_filename(path) -{ - TRACE_FUNCTION_F("name=" << name << ", path='" << path << "'"); - m_hir = HIR_Deserialise(path, name); - - m_hir->post_load_update(name); - m_name = m_hir->m_crate_name; -} - -void ExternCrate::with_all_macros(::std::function cb) const -{ - for(const auto& m : m_hir->m_exported_macros) - { - cb(m.first, *m.second); - } -} -const MacroRules* ExternCrate::find_macro_rules(const ::std::string& name) const -{ - auto i = m_hir->m_exported_macros.find(name); - if(i != m_hir->m_exported_macros.end()) - return &*i->second; - return nullptr; -} - - -} // namespace AST - diff --git a/gcc/rust/mrustc_parser/ast/crate.hpp b/gcc/rust/mrustc_parser/ast/crate.hpp deleted file mode 100644 index 87a9f86..0000000 --- a/gcc/rust/mrustc_parser/ast/crate.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/crate.hpp - * - AST::Crate type, and other top-level AST definitions - */ -#pragma once - -#include "ast.hpp" -#include "types.hpp" -#include - -namespace AST { - - -class ExternCrate; - -class TestDesc -{ -public: - ::AST::Path path; - ::std::string name; - bool ignore = false; - bool is_benchmark = false; - - enum class ShouldPanic { - No, - Yes, - YesWithMessage, - } panic_type = ShouldPanic::No; - - ::std::string expected_panic_message; -}; - -class ProcMacroDef -{ -public: - ::std::string name; - ::AST::Path path; - ::std::vector<::std::string> attributes; -}; - -class Crate -{ -public: - ::AST::AttributeList m_attrs; - - ::std::map< ::std::string, ::AST::Path> m_lang_items; -public: - Module m_root_module; - ::std::map< ::std::string, ExternCrate> m_extern_crates; - // Mapping filled by searching for (?visible) macros with is_pub=true - ::std::map< ::std::string, const MacroRules*> m_exported_macros; - - // List of tests (populated in expand if --test is passed) - bool m_test_harness = false; - ::std::vector m_tests; - - //::std::vector<::std::string> m_extra_files; - - // Procedural macros! - ::std::vector m_proc_macros; - - enum class Type { - Unknown, - RustLib, - RustDylib, - CDylib, - Executable, - ProcMacro, // Procedural macro - } m_crate_type = Type::Unknown; - enum LoadStd { - LOAD_STD, - LOAD_CORE, - LOAD_NONE, - } m_load_std = LOAD_STD; - ::std::string m_crate_name_suffix; - ::std::string m_crate_name; - AST::Path m_prelude_path; - - - Crate(); - - const Module& root_module() const { return m_root_module; } - Module& root_module() { return m_root_module; } - - /// Load referenced crates - void load_externs(); - - /// Load the named crate and returns the crate's unique name - /// If the parameter `file` is non-empty, only that particular filename will be loaded (from any of the search paths) - ::std::string load_extern_crate(Span sp, const ::std::string& name, const ::std::string& file=""); -}; - -/// Representation of an imported crate -class ExternCrate -{ -public: - ::std::string m_name; - ::std::string m_filename; - ::HIR::CratePtr m_hir; - - ExternCrate(const ::std::string& name, const ::std::string& path); - - ExternCrate(ExternCrate&&) = default; - ExternCrate& operator=(ExternCrate&&) = default; - ExternCrate(const ExternCrate&) = delete; - ExternCrate& operator=(const ExternCrate& ) = delete; - - void with_all_macros(::std::function cb) const; - const MacroRules* find_macro_rules(const ::std::string& name) const; -}; - -extern ::std::vector<::std::string> g_crate_load_dirs; -extern ::std::map<::std::string, ::std::string> g_crate_overrides; - -} // namespace AST diff --git a/gcc/rust/mrustc_parser/ast/dump.cpp b/gcc/rust/mrustc_parser/ast/dump.cpp deleted file mode 100644 index f1481ab..0000000 --- a/gcc/rust/mrustc_parser/ast/dump.cpp +++ /dev/null @@ -1,1179 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/dump.cpp - * - Dumps the AST of a crate as rust code (annotated) - */ -#include -#include -#include -#include -#include // ABI_RUST - TODO: Move elsewhere? -#include - -#include - -#define IS(v, c) (dynamic_cast(&v) != 0) -#define WRAPIF_CMD(v, t) || IS(v, t) -#define WRAPIF(uniq_ptr, class1, ...) do { auto& _v = *(uniq_ptr); if( IS(_v, class1) CC_ITERATE(WRAPIF_CMD, (_v), __VA_ARGS__) ) { paren_wrap(uniq_ptr); } else { AST::NodeVisitor::visit(uniq_ptr); } } while(0) - -class RustPrinter: - public AST::NodeVisitor -{ - ::std::ostream& m_os; - int m_indent_level; - bool m_expr_root; //!< used to allow 'if' and 'match' to behave differently as standalone exprs -public: - RustPrinter(::std::ostream& os): - m_os(os), - m_indent_level(0), - m_expr_root(false) - {} - - void handle_module(const AST::Module& mod); - void handle_struct(const AST::Struct& s); - void handle_enum(const AST::Enum& s); - void handle_trait(const AST::Trait& s); - - void handle_function(bool is_pub, const ::std::string& name, const AST::Function& f); - - virtual bool is_const() const override { return true; } - virtual void visit(AST::ExprNode_Block& n) override { - if( n.m_is_unsafe ) { - m_os << "unsafe "; - } - m_os << "{"; - inc_indent(); - if( n.m_local_mod ) - { - handle_module(*n.m_local_mod); - } - bool is_first = true; - for( auto& child : n.m_nodes ) - { - if(is_first) { - is_first = false; - } else { - m_os << ";"; - } - m_os << "\n"; - m_os << indent(); - m_expr_root = true; - if( !child.get() ) - m_os << "/* nil */"; - else - AST::NodeVisitor::visit(child); - } - if( !n.m_yields_final_value ) - m_os << ";"; - m_os << "\n"; - dec_indent(); - m_os << indent() << "}"; - } - virtual void visit(AST::ExprNode_Macro& n) override { - m_expr_root = false; - m_os << n.m_name << "!( /* TODO: Macro TT */ )"; - } - virtual void visit(AST::ExprNode_Asm& n) override { - m_os << "asm!( \"" << n.m_text << "\""; - m_os << " :"; - for(const auto& v : n.m_output) - { - m_os << " \"" << v.name << "\" ("; - AST::NodeVisitor::visit(v.value); - m_os << "),"; - } - m_os << " :"; - for(const auto& v : n.m_input) - { - m_os << " \"" << v.name << "\" ("; - AST::NodeVisitor::visit(v.value); - m_os << "),"; - } - m_os << " :"; - for(const auto& v : n.m_clobbers) - m_os << " \"" << v << "\","; - m_os << " :"; - for(const auto& v : n.m_flags) - m_os << " \"" << v << "\","; - m_os << " )"; - } - virtual void visit(AST::ExprNode_Flow& n) override { - m_expr_root = false; - switch(n.m_type) - { - case AST::ExprNode_Flow::RETURN: m_os << "return "; break; - case AST::ExprNode_Flow::BREAK: m_os << "break "; break; - case AST::ExprNode_Flow::CONTINUE: m_os << "continue "; break; - } - AST::NodeVisitor::visit(n.m_value); - } - virtual void visit(AST::ExprNode_LetBinding& n) override { - m_expr_root = false; - m_os << "let "; - print_pattern(n.m_pat, false); - m_os << ": "; - print_type(n.m_type); - m_os << " = "; - AST::NodeVisitor::visit(n.m_value); - } - virtual void visit(AST::ExprNode_Assign& n) override { - m_expr_root = false; - AST::NodeVisitor::visit(n.m_slot); - switch(n.m_op) - { - case AST::ExprNode_Assign::NONE: m_os << " = "; break; - case AST::ExprNode_Assign::ADD: m_os << " += "; break; - case AST::ExprNode_Assign::SUB: m_os << " -= "; break; - case AST::ExprNode_Assign::MUL: m_os << " *= "; break; - case AST::ExprNode_Assign::DIV: m_os << " /= "; break; - case AST::ExprNode_Assign::MOD: m_os << " %= "; break; - case AST::ExprNode_Assign::AND: m_os << " &= "; break; - case AST::ExprNode_Assign::OR: m_os << " |= "; break; - case AST::ExprNode_Assign::XOR: m_os << " ^= "; break; - case AST::ExprNode_Assign::SHR: m_os << " >>= "; break; - case AST::ExprNode_Assign::SHL: m_os << " <<= "; break; - } - AST::NodeVisitor::visit(n.m_value); - } - virtual void visit(AST::ExprNode_CallPath& n) override { - m_expr_root = false; - m_os << n.m_path; - m_os << "("; - bool is_first = true; - for( auto& arg : n.m_args ) - { - if(is_first) { - is_first = false; - } else { - m_os << ", "; - } - AST::NodeVisitor::visit(arg); - } - m_os << ")"; - } - virtual void visit(AST::ExprNode_CallMethod& n) override { - m_expr_root = false; - WRAPIF( n.m_val - , AST::ExprNode_Deref, AST::ExprNode_UniOp - , AST::ExprNode_Cast, AST::ExprNode_BinOp, AST::ExprNode_Assign - , AST::ExprNode_Match, AST::ExprNode_If, AST::ExprNode_IfLet, AST::ExprNode_Match - ); - m_os << "." << n.m_method; - m_os << "("; - bool is_first = true; - for( auto& arg : n.m_args ) - { - if(is_first) { - is_first = false; - } else { - m_os << ", "; - } - AST::NodeVisitor::visit(arg); - } - m_os << ")"; - } - virtual void visit(AST::ExprNode_CallObject& n) override { - m_expr_root = false; - m_os << "("; - AST::NodeVisitor::visit(n.m_val); - m_os << ")("; - bool is_first = true; - for( auto& arg : n.m_args ) - { - if(is_first) { - is_first = false; - } else { - m_os << ", "; - } - AST::NodeVisitor::visit(arg); - } - m_os << ")"; - } - virtual void visit(AST::ExprNode_Loop& n) override { - bool expr_root = m_expr_root; - m_expr_root = false; - - switch(n.m_type) - { - case AST::ExprNode_Loop::LOOP: - m_os << "loop"; - break; - case AST::ExprNode_Loop::WHILE: - m_os << "while "; - AST::NodeVisitor::visit(n.m_cond); - break; - case AST::ExprNode_Loop::WHILELET: - m_os << "while let "; - print_pattern(n.m_pattern, true); - m_os << " = "; - AST::NodeVisitor::visit(n.m_cond); - break; - case AST::ExprNode_Loop::FOR: - m_os << "while for "; - print_pattern(n.m_pattern, true); - m_os << " in "; - AST::NodeVisitor::visit(n.m_cond); - break; - } - - if( expr_root ) - { - m_os << "\n"; - m_os << indent(); - } - else - { - m_os << " "; - } - - AST::NodeVisitor::visit(n.m_code); - } - virtual void visit(AST::ExprNode_Match& n) override { - bool expr_root = m_expr_root; - m_expr_root = false; - m_os << "match "; - AST::NodeVisitor::visit(n.m_val); - - if(expr_root) - { - m_os << "\n"; - m_os << indent() << "{\n"; - } - else - { - m_os << " {\n"; - inc_indent(); - } - - for( auto& arm : n.m_arms ) - { - m_os << indent(); - bool is_first = true; - for( const auto& pat : arm.m_patterns ) { - if(!is_first) - m_os << "|"; - is_first = false; - print_pattern(pat, true); - } - if( arm.m_cond ) - { - m_os << " if "; - AST::NodeVisitor::visit(arm.m_cond); - } - m_os << " => "; - // Increase indent, but don't print. Causes nested blocks to be indented above the match - inc_indent(); - AST::NodeVisitor::visit(arm.m_code); - dec_indent(); - m_os << ",\n"; - } - - if(expr_root) - { - m_os << indent() << "}"; - } - else - { - m_os << indent() << "}"; - dec_indent(); - } - } - virtual void visit(AST::ExprNode_If& n) override { - bool expr_root = m_expr_root; - m_expr_root = false; - m_os << "if "; - AST::NodeVisitor::visit(n.m_cond); - - visit_if_common(expr_root, n.m_true, n.m_false); - } - virtual void visit(AST::ExprNode_IfLet& n) override { - bool expr_root = m_expr_root; - m_expr_root = false; - m_os << "if let "; - print_pattern(n.m_pattern, true); - m_os << " = "; - AST::NodeVisitor::visit(n.m_value); - - visit_if_common(expr_root, n.m_true, n.m_false); - } - void visit_if_common(bool expr_root, const ::std::unique_ptr& tv, const ::std::unique_ptr& fv) - { - if( expr_root ) - { - m_os << "\n"; - m_os << indent(); - } - else - { - m_os << " "; - } - - bool is_block = (dynamic_cast(&*tv) != nullptr); - if( !is_block ) m_os << "{ "; - AST::NodeVisitor::visit(tv); - if( !is_block ) m_os << " }"; - if(fv.get()) - { - if( expr_root ) - { - m_os << "\n"; - m_os << indent() << "else"; - // handle chained if statements nicely - if( IS(*fv, AST::ExprNode_If) || IS(*fv, AST::ExprNode_IfLet) ) { - m_expr_root = true; - m_os << " "; - } - else - m_os << "\n" << indent(); - } - else - { - m_os << " else "; - } - AST::NodeVisitor::visit(fv); - } - } - virtual void visit(AST::ExprNode_Closure& n) override { - m_expr_root = false; - m_os << "|"; - bool is_first = true; - for( const auto& arg : n.m_args ) - { - if(!is_first) m_os << ", "; - is_first = false; - print_pattern(arg.first, false); - m_os << ": "; - print_type(arg.second); - } - m_os << "| ->"; - print_type(n.m_return); - m_os << " "; - AST::NodeVisitor::visit(n.m_code); - } - virtual void visit(AST::ExprNode_Integer& n) override { - m_expr_root = false; - switch(n.m_datatype) - { - case CORETYPE_INVAL: - m_os << "0x" << ::std::hex << n.m_value << ::std::dec << "_/*INVAL*/"; - break; - case CORETYPE_BOOL: - case CORETYPE_STR: - m_os << "0x" << ::std::hex << n.m_value << ::std::dec << "_/*bool/str*/"; - break; - case CORETYPE_CHAR: - m_os << "'\\u{" << ::std::hex << n.m_value << ::std::dec << "}'"; - break; - case CORETYPE_F32: - case CORETYPE_F64: - break; - case CORETYPE_U8: - case CORETYPE_U16: - case CORETYPE_U32: - case CORETYPE_U64: - case CORETYPE_U128: - case CORETYPE_UINT: - case CORETYPE_ANY: - m_os << "0x" << ::std::hex << n.m_value << ::std::dec; - break; - case CORETYPE_I8: - case CORETYPE_I16: - case CORETYPE_I32: - case CORETYPE_I64: - case CORETYPE_I128: - case CORETYPE_INT: - m_os << (int64_t)n.m_value; - break; - } - } - virtual void visit(AST::ExprNode_Float& n) override { - m_expr_root = false; - switch(n.m_datatype) - { - case CORETYPE_ANY: - case CORETYPE_F32: - case CORETYPE_F64: - m_os.precision(10); - m_os << n.m_value; - break; - default: - break; - } - } - virtual void visit(AST::ExprNode_Bool& n) override { - m_expr_root = false; - if( n.m_value ) - m_os << "true"; - else - m_os << "false"; - } - virtual void visit(AST::ExprNode_String& n) override { - m_expr_root = false; - m_os << "\"" << n.m_value << "\""; - } - virtual void visit(AST::ExprNode_ByteString& n) override { - m_expr_root = false; - m_os << "b\"" << n.m_value << "\""; - } - - virtual void visit(AST::ExprNode_StructLiteral& n) override { - m_expr_root = false; - m_os << n.m_path << " {\n"; - inc_indent(); - for( const auto& i : n.m_values ) - { - // TODO: Attributes - m_os << indent() << i.name << ": "; - AST::NodeVisitor::visit(i.value); - m_os << ",\n"; - } - if( n.m_base_value.get() ) - { - m_os << indent() << ".. "; - AST::NodeVisitor::visit(n.m_base_value); - m_os << "\n"; - } - m_os << indent() << "}"; - dec_indent(); - } - virtual void visit(AST::ExprNode_Array& n) override { - m_expr_root = false; - m_os << "["; - if( n.m_size.get() ) - { - AST::NodeVisitor::visit(n.m_values[0]); - m_os << "; "; - AST::NodeVisitor::visit(n.m_size); - } - else { - for( auto& item : n.m_values ) - { - AST::NodeVisitor::visit(item); - m_os << ", "; - } - } - m_os << "]"; - } - virtual void visit(AST::ExprNode_Tuple& n) override { - m_expr_root = false; - m_os << "("; - for( auto& item : n.m_values ) - { - AST::NodeVisitor::visit(item); - m_os << ", "; - } - m_os << ")"; - } - virtual void visit(AST::ExprNode_NamedValue& n) override { - m_expr_root = false; - m_os << n.m_path; - } - virtual void visit(AST::ExprNode_Field& n) override { - m_expr_root = false; - WRAPIF( n.m_obj - , AST::ExprNode_Deref, AST::ExprNode_UniOp - , AST::ExprNode_Cast, AST::ExprNode_BinOp, AST::ExprNode_Assign - , AST::ExprNode_Match, AST::ExprNode_If, AST::ExprNode_IfLet, AST::ExprNode_Match - ); - m_os << "." << n.m_name; - } - virtual void visit(AST::ExprNode_Index& n) override { - m_expr_root = false; - WRAPIF( n.m_obj - , AST::ExprNode_Deref, AST::ExprNode_UniOp - , AST::ExprNode_Cast, AST::ExprNode_BinOp, AST::ExprNode_Assign - , AST::ExprNode_Match, AST::ExprNode_If, AST::ExprNode_IfLet, AST::ExprNode_Match - ); - m_os << "["; - AST::NodeVisitor::visit(n.m_idx); - m_os << "]"; - } - virtual void visit(AST::ExprNode_Deref& n) override { - m_expr_root = false; - m_os << "*("; - AST::NodeVisitor::visit(n.m_value); - m_os << ")"; - } - virtual void visit(AST::ExprNode_Cast& n) override { - m_expr_root = false; - AST::NodeVisitor::visit(n.m_value); - m_os << " as " << n.m_type; - } - virtual void visit(AST::ExprNode_TypeAnnotation& n) override { - m_expr_root = false; - AST::NodeVisitor::visit(n.m_value); - m_os << ": " << n.m_type; - } - virtual void visit(AST::ExprNode_BinOp& n) override { - m_expr_root = false; - if( IS(*n.m_left, AST::ExprNode_BinOp) && dynamic_cast(*n.m_left).m_type == n.m_type ) { - AST::NodeVisitor::visit(n.m_left); - } - else { - WRAPIF(n.m_left - , AST::ExprNode_Cast, AST::ExprNode_BinOp - ); - } - m_os << " "; - switch(n.m_type) - { - case AST::ExprNode_BinOp::CMPEQU: m_os << "=="; break; - case AST::ExprNode_BinOp::CMPNEQU:m_os << "!="; break; - case AST::ExprNode_BinOp::CMPLT: m_os << "<"; break; - case AST::ExprNode_BinOp::CMPLTE: m_os << "<="; break; - case AST::ExprNode_BinOp::CMPGT: m_os << ">"; break; - case AST::ExprNode_BinOp::CMPGTE: m_os << ">="; break; - case AST::ExprNode_BinOp::BOOLAND:m_os << "&&"; break; - case AST::ExprNode_BinOp::BOOLOR: m_os << "||"; break; - case AST::ExprNode_BinOp::BITAND: m_os << "&"; break; - case AST::ExprNode_BinOp::BITOR: m_os << "|"; break; - case AST::ExprNode_BinOp::BITXOR: m_os << "^"; break; - case AST::ExprNode_BinOp::SHL: m_os << "<<"; break; - case AST::ExprNode_BinOp::SHR: m_os << ">>"; break; - case AST::ExprNode_BinOp::MULTIPLY: m_os << "*"; break; - case AST::ExprNode_BinOp::DIVIDE: m_os << "/"; break; - case AST::ExprNode_BinOp::MODULO: m_os << "%"; break; - case AST::ExprNode_BinOp::ADD: m_os << "+"; break; - case AST::ExprNode_BinOp::SUB: m_os << "-"; break; - case AST::ExprNode_BinOp::RANGE: m_os << ".."; break; - case AST::ExprNode_BinOp::RANGE_INC: m_os << "..."; break; - case AST::ExprNode_BinOp::PLACE_IN: m_os << "<-"; break; - } - m_os << " "; - if( IS(*n.m_right, AST::ExprNode_BinOp) && dynamic_cast(*n.m_right).m_type != n.m_type ) { - paren_wrap(n.m_right); - } - else - AST::NodeVisitor::visit(n.m_right); - } - virtual void visit(AST::ExprNode_UniOp& n) override { - m_expr_root = false; - switch(n.m_type) - { - case AST::ExprNode_UniOp::NEGATE: m_os << "-"; break; - case AST::ExprNode_UniOp::INVERT: m_os << "!"; break; - case AST::ExprNode_UniOp::BOX: m_os << "box "; break; - case AST::ExprNode_UniOp::REF: m_os << "&"; break; - case AST::ExprNode_UniOp::REFMUT: m_os << "&mut "; break; - case AST::ExprNode_UniOp::QMARK: break; - } - - if( IS(*n.m_value, AST::ExprNode_BinOp) ) - m_os << "("; - AST::NodeVisitor::visit(n.m_value); - if( IS(*n.m_value, AST::ExprNode_BinOp) ) - m_os << ")"; - switch(n.m_type) - { - case AST::ExprNode_UniOp::QMARK: m_os << "?"; break; - default: break; - } - } - - -private: - void paren_wrap(::std::unique_ptr& node) { - m_os << "("; - AST::NodeVisitor::visit(node); - m_os << ")"; - } - - void print_attrs(const AST::AttributeList& attrs); - void print_params(const AST::GenericParams& params); - void print_bounds(const AST::GenericParams& params); - void print_pattern_tuple(const AST::Pattern::TuplePat& v, bool is_refutable); - void print_pattern(const AST::Pattern& p, bool is_refutable); - void print_type(const TypeRef& t); - - void inc_indent(); - RepeatLitStr indent(); - void dec_indent(); -}; - -void Dump_Rust(const char *filename, const AST::Crate& crate) -{ - ::std::ofstream os(filename); - RustPrinter printer(os); - printer.handle_module(crate.root_module()); -} - -void RustPrinter::print_attrs(const AST::AttributeList& attrs) -{ - for(const auto& a : attrs.m_items) - { - m_os << indent() << "#[" << a << "]\n"; - } -} - -void RustPrinter::handle_module(const AST::Module& mod) -{ - bool need_nl = true; - - for( const auto& i : mod.items() ) - { - if( !i.data.is_Use() ) continue ; - const auto& i_data = i.data.as_Use(); - //if(need_nl) { - // m_os << "\n"; - // need_nl = false; - //} - if( i_data.path == AST::Path() ) { - continue ; - } - m_os << indent() << (i.is_pub ? "pub " : "") << "use " << i_data; - if( i.name == "" ) - { - m_os << "::*"; - } - else if( i_data.path.nodes().back().name() != i.name ) - { - m_os << " as " << i.name; - } - m_os << ";\n"; - } - need_nl = true; - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Crate() ) continue ; - const auto& e = item.data.as_Crate(); - - print_attrs(item.data.attrs); - m_os << indent() << "extern crate \"" << e.name << "\" as " << item.name << ";\n"; - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_ExternBlock() ) continue ; - const auto& e = item.data.as_ExternBlock(); - - print_attrs(item.data.attrs); - m_os << indent() << "extern \"" << e.abi() << "\" {}\n"; - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Module() ) continue ; - const auto& e = item.data.as_Module(); - - m_os << "\n"; - m_os << indent() << (item.is_pub ? "pub " : "") << "mod " << item.name << "\n"; - m_os << indent() << "{\n"; - inc_indent(); - handle_module(e); - dec_indent(); - m_os << indent() << "}\n"; - m_os << "\n"; - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Type() ) continue ; - const auto& e = item.data.as_Type(); - - if(need_nl) { - m_os << "\n"; - need_nl = false; - } - print_attrs(item.data.attrs); - m_os << indent() << (item.is_pub ? "pub " : "") << "type " << item.name; - print_params(e.params()); - m_os << " = " << e.type(); - print_bounds(e.params()); - m_os << ";\n"; - } - need_nl = true; - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Struct() ) continue ; - const auto& e = item.data.as_Struct(); - - m_os << "\n"; - print_attrs(item.data.attrs); - m_os << indent() << (item.is_pub ? "pub " : "") << "struct " << item.name; - handle_struct(e); - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Enum() ) continue ; - const auto& e = item.data.as_Enum(); - - m_os << "\n"; - print_attrs(item.data.attrs); - m_os << indent() << (item.is_pub ? "pub " : "") << "enum " << item.name; - handle_enum(e); - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Trait() ) continue ; - const auto& e = item.data.as_Trait(); - - m_os << "\n"; - print_attrs(item.data.attrs); - m_os << indent() << (item.is_pub ? "pub " : "") << "trait " << item.name; - handle_trait(e); - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Static() ) continue ; - const auto& e = item.data.as_Static(); - - if(need_nl) { - m_os << "\n"; - need_nl = false; - } - print_attrs(item.data.attrs); - m_os << indent() << (item.is_pub ? "pub " : ""); - switch( e.s_class() ) - { - case AST::Static::CONST: m_os << "const "; break; - case AST::Static::STATIC: m_os << "static "; break; - case AST::Static::MUT: m_os << "static mut "; break; - } - m_os << item.name << ": " << e.type() << " = "; - e.value().visit_nodes(*this); - m_os << ";\n"; - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Function() ) continue ; - const auto& e = item.data.as_Function(); - - m_os << "\n"; - print_attrs(item.data.attrs); - handle_function(item.is_pub, item.name, e); - } - - for( const auto& item : mod.items() ) - { - if( !item.data.is_Impl() ) continue ; - const auto& i = item.data.as_Impl(); - - m_os << "\n"; - m_os << indent() << "impl"; - print_params(i.def().params()); - if( i.def().trait().ent != AST::Path() ) - { - m_os << " " << i.def().trait().ent << " for"; - } - m_os << " " << i.def().type() << "\n"; - - print_bounds(i.def().params()); - m_os << indent() << "{\n"; - inc_indent(); - for( const auto& it : i.items() ) - { - TU_MATCH_DEF(AST::Item, (*it.data), (e), - ( - throw ::std::runtime_error(FMT("Unexpected item type in impl block - " << it.data->tag_str())); - ), - (None, - // Ignore, it's been deleted by #[cfg] - ), - (MacroInv, - // TODO: Dump macro invocations - ), - (Static, - m_os << indent(); - switch(e.s_class()) - { - case ::AST::Static::CONST: m_os << "const "; break; - case ::AST::Static::STATIC: m_os << "static "; break; - case ::AST::Static::MUT: m_os << "static mut "; break; - } - m_os << it.name << ": " << e.type() << " = "; - e.value().visit_nodes(*this); - m_os << ";\n"; - ), - (Type, - m_os << indent() << "type " << it.name << " = " << e.type() << ";\n"; - ), - (Function, - handle_function(it.is_pub, it.name, e); - ) - ) - } - dec_indent(); - m_os << indent() << "}\n"; - } -} - -void RustPrinter::print_params(const AST::GenericParams& params) -{ - if( params.ty_params().size() > 0 || params.lft_params().size() > 0 ) - { - bool is_first = true; - m_os << "<"; - // Lifetimes - for( const auto& p : params.lft_params() ) - { - if( !is_first ) - m_os << ", "; - m_os << "'" << p; - is_first = false; - } - // Types - for( const auto& p : params.ty_params() ) - { - if( !is_first ) - m_os << ", "; - m_os << p.name(); - if( !p.get_default().is_wildcard() ) - m_os << " = " << p.get_default(); - is_first = false; - } - m_os << ">"; - } -} - -void RustPrinter::print_bounds(const AST::GenericParams& params) -{ - if( params.bounds().size() ) - { - m_os << indent() << "where\n"; - inc_indent(); - bool is_first = true; - - for( const auto& b : params.bounds() ) - { - if( !is_first ) - m_os << ",\n"; - is_first = false; - - m_os << indent(); - TU_MATCH(AST::GenericBound, (b), (ent), - (None, - m_os << "/*-*/"; - ), - (Lifetime, - m_os << "'" << ent.test << ": '" << ent.bound; - ), - (TypeLifetime, - m_os << ent.type << ": '" << ent.bound; - ), - (IsTrait, - m_os << ent.outer_hrbs << ent.type << ": " << ent.inner_hrbs << ent.trait; - ), - (MaybeTrait, - m_os << ent.type << ": ?" << ent.trait; - ), - (NotTrait, - m_os << ent.type << ": !" << ent.trait; - ), - (Equality, - m_os << ent.type << ": =" << ent.replacement; - ) - ) - } - m_os << "\n"; - - dec_indent(); - } -} - -void RustPrinter::print_pattern_tuple(const AST::Pattern::TuplePat& v, bool is_refutable) -{ - for(const auto& sp : v.start) { - print_pattern(sp, is_refutable); - m_os << ", "; - } - if( v.has_wildcard ) - { - m_os << ".., "; - for(const auto& sp : v.end) { - print_pattern(sp, is_refutable); - m_os << ", "; - } - } -} -void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) -{ - if( p.binding().is_valid() ) { - if( p.binding().m_mutable ) - m_os << "mut "; - switch(p.binding().m_type) - { - case ::AST::PatternBinding::Type::MOVE: - break; - case ::AST::PatternBinding::Type::REF: - m_os << "ref "; - break; - case ::AST::PatternBinding::Type::MUTREF: - m_os << "ref mut "; - break; - } - m_os << p.binding().m_name << "/*"<print_pattern_tuple(v.tup_pat, is_refutable); - m_os << ")"; - ), - (Struct, { - const auto& v = p.data().as_Struct(); - m_os << v.path << "("; - for(const auto& sp : v.sub_patterns) { - m_os << sp.first << ": "; - print_pattern(sp.second, is_refutable); - m_os << ","; - } - m_os << ")"; - }), - (Tuple, - m_os << "("; - this->print_pattern_tuple(v, is_refutable); - m_os << ")"; - ), - (Slice, - m_os << "["; - m_os << v.sub_pats; - m_os << "]"; - ), - (SplitSlice, - m_os << "["; - bool needs_comma = false; - if(v.leading.size()) { - m_os << v.leading; - m_os << ", "; - } - - if(v.extra_bind.is_valid()) - { - const auto& b = v.extra_bind; - if( b.m_mutable ) - m_os << "mut "; - switch(b.m_type) - { - case ::AST::PatternBinding::Type::MOVE: - break; - case ::AST::PatternBinding::Type::REF: - m_os << "ref "; - break; - case ::AST::PatternBinding::Type::MUTREF: - m_os << "ref mut "; - break; - } - m_os << b.m_name << "/*"< " << f.rettype().print_pretty(); - } - - if( f.code().is_valid() ) - { - m_os << "\n"; - print_bounds(f.params()); - - m_os << indent(); - f.code().visit_nodes(*this); - m_os << "\n"; - //m_os << indent() << f.data.code() << "\n"; - } - else - { - print_bounds(f.params()); - m_os << ";\n"; - } -} - -void RustPrinter::inc_indent() -{ - m_indent_level ++; -} -RepeatLitStr RustPrinter::indent() -{ - return RepeatLitStr { " ", m_indent_level }; -} -void RustPrinter::dec_indent() -{ - m_indent_level --; -} diff --git a/gcc/rust/mrustc_parser/ast/expr.cpp b/gcc/rust/mrustc_parser/ast/expr.cpp deleted file mode 100644 index 1525ed1..0000000 --- a/gcc/rust/mrustc_parser/ast/expr.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/expr.cpp - * - AST Expression nodes - */ -#include "expr.hpp" -#include "ast.hpp" - -namespace AST { - - -Expr::Expr(unique_ptr node): - m_node(node.release()) -{ -} -Expr::Expr(ExprNode* node): - m_node(node) -{ -} -Expr::Expr(): - m_node(nullptr) -{ -} -void Expr::visit_nodes(NodeVisitor& v) -{ - if( m_node ) - { - m_node->visit(v); - } -} -void Expr::visit_nodes(NodeVisitor& v) const -{ - if( m_node ) - { - assert(v.is_const()); - //const_cast(m_node.get())->visit(v); - m_node->visit(v); - } -} - -Expr Expr::clone() const -{ - if( m_node ) { - return Expr( m_node->clone() ); - } - else { - return Expr(); - } -} - -::std::ostream& operator<<(::std::ostream& os, const Expr& pat) -{ - if( pat.m_node.get() ) - return os << *pat.m_node; - else - return os << "/* null */"; -} - -::std::ostream& operator<<(::std::ostream& os, const ExprNode& node) -{ - assert( static_cast(&node) != nullptr ); - node.print(os); - return os; -} -ExprNode::~ExprNode() { -} - -#define NODE(class, _print, _clone)\ - void class::visit(NodeVisitor& nv) { nv.visit(*this); } \ - void class::print(::std::ostream& os) const _print \ - ::std::unique_ptr class::clone() const _clone -#define OPT_CLONE(node) (node.get() ? node->clone() : ::AST::ExprNodeP()) - -namespace { - static inline ExprNodeP mk_exprnodep(const Span& pos, AST::ExprNode* en) { - en->set_span(pos); - return ExprNodeP(en); - } - #define NEWNODE(type, ...) mk_exprnodep(span(), new type(__VA_ARGS__)) -} - -NODE(ExprNode_Block, { - os << "{"; - for(const auto& n : m_nodes) - os << *n << ";"; - os << "}"; -},{ - ::std::vector nodes; - for(const auto& n : m_nodes) - nodes.push_back( n->clone() ); - return NEWNODE(ExprNode_Block, m_is_unsafe, m_yields_final_value, mv$(nodes), m_local_mod); -}) - -NODE(ExprNode_Macro, { - os << m_name << "!"; - if( m_ident.size() > 0 ) - { - os << " " << m_ident << " "; - } - os << "(" << " /*TODO*/ " << ")"; -},{ - return NEWNODE(ExprNode_Macro, m_name, m_ident, m_tokens.clone()); -}) - -NODE(ExprNode_Asm, { - os << "asm!( \"" << m_text << "\""; - os << " :"; - for(const auto& v : m_output) - os << " \"" << v.name << "\" (" << *v.value << "),"; - os << " :"; - for(const auto& v : m_input) - os << " \"" << v.name << "\" (" << *v.value << "),"; - os << " :"; - for(const auto& v : m_clobbers) - os << " \"" << v << "\","; - os << " :"; - for(const auto& v : m_flags) - os << " \"" << v << "\","; - os << " )"; -},{ - ::std::vector outputs; - for(const auto& v : m_output) - outputs.push_back( ExprNode_Asm::ValRef { v.name, v.value->clone() }); - ::std::vector inputs; - for(const auto& v : m_input) - inputs.push_back( ExprNode_Asm::ValRef { v.name, v.value->clone() }); - return NEWNODE(ExprNode_Asm, m_text, mv$(outputs), mv$(inputs), m_clobbers, m_flags); -}) - -NODE(ExprNode_Flow, { - switch(m_type) - { - case RETURN: os << "return"; break; - case BREAK: os << "break"; break; - case CONTINUE: os << "continue"; break; - } - if(m_value) - os << " " << *m_value; -},{ - return NEWNODE(ExprNode_Flow, m_type, m_target, m_value ? m_value->clone() : nullptr); -}) - - -NODE(ExprNode_LetBinding, { - os << "let " << m_pat << ": " << m_type; - if(m_value) - os << " = " << *m_value; -},{ - return NEWNODE(ExprNode_LetBinding, m_pat.clone(), m_type.clone(), OPT_CLONE(m_value)); -}) - -NODE(ExprNode_Assign, { - os << *m_slot << " = " << *m_value; -},{ - return NEWNODE(ExprNode_Assign, m_op, m_slot->clone(), m_value->clone()); -}) - -NODE(ExprNode_CallPath, { - os << m_path << "("; - for(const auto& a : m_args) { - os << *a << ","; - } - os << ")"; -},{ - ::std::vector args; - for(const auto& a : m_args) { - args.push_back( a->clone() ); - } - return NEWNODE(ExprNode_CallPath, AST::Path(m_path), mv$(args)); -}) - -NODE(ExprNode_CallMethod, { - os << "(" << *m_val << ")." << m_method << "("; - for(const auto& a : m_args) { - os << *a << ","; - } - os << ")"; -},{ - ::std::vector args; - for(const auto& a : m_args) { - args.push_back( a->clone() ); - } - return NEWNODE(ExprNode_CallMethod, m_val->clone(), m_method, mv$(args)); -}) - -NODE(ExprNode_CallObject, { - os << "(" << *m_val << ")("; - for(const auto& a : m_args) { - os << *a << ","; - } - os << ")"; -},{ - ::std::vector args; - for(const auto& a : m_args) { - args.push_back( a->clone() ); - } - return NEWNODE(ExprNode_CallObject, m_val->clone(), mv$(args)); -}) - -NODE(ExprNode_Loop, { - os << "LOOP [" << m_label << "] " << m_pattern; - if(m_cond) - os << " in/= " << *m_cond; - os << " " << *m_code; -},{ - return NEWNODE(ExprNode_Loop, m_label, m_type, m_pattern.clone(), OPT_CLONE(m_cond), m_code->clone()); -}) - -NODE(ExprNode_Match, { - os << "match ("<<*m_val<<") {"; - for(const auto& arm : m_arms) - { - for( const auto& pat : arm.m_patterns ) - os << " " << pat; - if( arm.m_cond ) - os << " if " << *arm.m_cond; - - os << " => " << *arm.m_code << ","; - } - os << "}"; -},{ - ::std::vector< ExprNode_Match_Arm> arms; - for(const auto& arm : m_arms) { - ::std::vector< AST::Pattern> patterns; - for( const auto& pat : arm.m_patterns ) { - patterns.push_back( pat.clone() ); - } - arms.push_back( ExprNode_Match_Arm( mv$(patterns), OPT_CLONE(arm.m_cond), arm.m_code->clone() ) ); - arms.back().m_attrs = arm.m_attrs.clone(); - } - return NEWNODE(ExprNode_Match, m_val->clone(), mv$(arms)); -}) - -NODE(ExprNode_If, { - os << "if " << *m_cond << " { " << *m_true << " }"; - if(m_false) - os << " else { " << *m_false << " }"; -},{ - return NEWNODE(ExprNode_If, m_cond->clone(), m_true->clone(), OPT_CLONE(m_false)); -}) -NODE(ExprNode_IfLet, { - os << "if let " << m_pattern << " = (" << *m_value << ") { " << *m_true << " }"; - if(m_false) os << " else { " << *m_false << " }"; -},{ - return NEWNODE(ExprNode_IfLet, m_pattern.clone(), m_value->clone(), m_true->clone(), OPT_CLONE(m_false)); -}) - -NODE(ExprNode_Integer, { - if( m_datatype == CORETYPE_CHAR ) - os << "'\\u{" << ::std::hex << m_value << ::std::dec << "}'"; - else - { - os << m_value; - if( m_datatype == CORETYPE_ANY ) - ; - else - os << "_" << coretype_name(m_datatype); - } -},{ - return NEWNODE(ExprNode_Integer, m_value, m_datatype); -}) -NODE(ExprNode_Float, { - os << m_value << "_" << m_datatype; -},{ - return NEWNODE(ExprNode_Float, m_value, m_datatype); -}) -NODE(ExprNode_Bool, { - os << m_value; -},{ - return NEWNODE(ExprNode_Bool, m_value); -}) -NODE(ExprNode_String, { - os << "\"" << m_value << "\""; -},{ - return NEWNODE(ExprNode_String, m_value); -}) -NODE(ExprNode_ByteString, { - os << "b\"" << m_value << "\""; -},{ - return NEWNODE(ExprNode_ByteString, m_value); -}) - -NODE(ExprNode_Closure, { - if( m_is_move ) - os << "move "; - os << "|"; - for(const auto& a : m_args) - { - os << a.first << ": " << a.second << ","; - } - os << "|"; - os << "->" << m_return; - os << " " << *m_code; -},{ - ExprNode_Closure::args_t args; - for(const auto& a : m_args) { - args.push_back( ::std::make_pair(a.first.clone(), a.second.clone()) ); - } - return NEWNODE(ExprNode_Closure, mv$(args), m_return.clone(), m_code->clone(), m_is_move); -}); - -NODE(ExprNode_StructLiteral, { - os << m_path << " { "; - for(const auto& v : m_values) - { - os << v.name << ": " << *v.value << ", "; - } - if(m_base_value) - { - os << ".." << *m_base_value; - } - os << "}"; -},{ - ExprNode_StructLiteral::t_values vals; - - for(const auto& v : m_values) { - vals.push_back({ v.attrs.clone(), v.name, v.value->clone() }); - } - - return NEWNODE(ExprNode_StructLiteral, AST::Path(m_path), OPT_CLONE(m_base_value), mv$(vals) ); -}) - -NODE(ExprNode_Array, { - os << "["; - if( m_size.get() ) - os << *m_values[0] << "; " << *m_size; - else - for(const auto& a : m_values) - os << *a << ","; - os << "]"; -},{ - if( m_size.get() ) - { - return NEWNODE(ExprNode_Array, m_values[0]->clone(), m_size->clone()); - } - else - { - ::std::vector nodes; - for(const auto& n : m_values) - nodes.push_back( n->clone() ); - return NEWNODE(ExprNode_Array, mv$(nodes)); - } -}) - -NODE(ExprNode_Tuple, { - os << "("; - for(const auto& a : m_values) { - os << *a << ","; - } - os << ")"; -},{ - ::std::vector nodes; - for(const auto& n : m_values) - nodes.push_back( n->clone() ); - return NEWNODE(ExprNode_Tuple, mv$(nodes)); -}) - -NODE(ExprNode_NamedValue, { - os << m_path; -},{ - return NEWNODE(ExprNode_NamedValue, AST::Path(m_path)); -}) - -NODE(ExprNode_Field, { - os << "(" << *m_obj << ")." << m_name; -},{ - return NEWNODE(ExprNode_Field, m_obj->clone(), m_name); -}) - -NODE(ExprNode_Index, { - os << "(" << *m_obj << ")[" << *m_idx << "]"; -},{ - return NEWNODE(ExprNode_Index, m_obj->clone(), m_idx->clone()); -}) - -NODE(ExprNode_Deref, { - os << "*(" << *m_value << ")"; -},{ - return NEWNODE(ExprNode_Deref, m_value->clone()); -}); - -NODE(ExprNode_Cast, { - os << "(" << *m_value << " as " << m_type << ")"; -},{ - return NEWNODE(ExprNode_Cast, m_value->clone(), m_type.clone()); -}) -NODE(ExprNode_TypeAnnotation, { - os << "(" << *m_value << ": " << m_type << ")"; -},{ - return NEWNODE(ExprNode_TypeAnnotation, m_value->clone(), m_type.clone()); -}) - -NODE(ExprNode_BinOp, { - if( m_type == RANGE_INC ) { - os << "("; - if( m_left ) { - os << *m_left << " "; - } - os << "... " << *m_right; - os << ")"; - return ; - } - if( m_type == RANGE ) { - os << "("; - if( m_left ) { - os << *m_left; - } - os << ".."; - if( m_right ) { - os << " " << *m_right; - } - os << ")"; - return ; - } - os << "(" << *m_left << " "; - switch(m_type) - { - case CMPEQU: os << "=="; break; - case CMPNEQU: os << "!="; break; - case CMPLT: os << "<"; break; - case CMPLTE: os << "<="; break; - case CMPGT: os << ">"; break; - case CMPGTE: os << ">="; break; - case BOOLAND: os << "&&"; break; - case BOOLOR: os << "||"; break; - case BITAND: os << "&"; break; - case BITOR: os << "|"; break; - case BITXOR: os << "^"; break; - case SHR: os << ">>"; break; - case SHL: os << "<<"; break; - case MULTIPLY: os << "*"; break; - case DIVIDE: os << "/"; break; - case MODULO: os << "%"; break; - case ADD: os << "+"; break; - case SUB: os << "-"; break; - case RANGE: os << ".."; break; - case RANGE_INC: os << "..."; break; - case PLACE_IN: os << "<-"; break; - } - os << " " << *m_right << ")"; -},{ - return NEWNODE(ExprNode_BinOp, m_type, OPT_CLONE(m_left), OPT_CLONE(m_right)); -}) - -NODE(ExprNode_UniOp, { - switch(m_type) - { - case NEGATE: os << "(-"; break; - case INVERT: os << "(!"; break; - case BOX: os << "(box "; break; - case REF: os << "(&"; break; - case REFMUT: os << "(&mut "; break; - case QMARK: os << "(" << *m_value << "?)"; return; - } - os << *m_value << ")"; -},{ - return NEWNODE(ExprNode_UniOp, m_type, m_value->clone()); -}) - - -#define NV(type, actions)\ - void NodeVisitorDef::visit(type& node) { /*DEBUG("DEF - "#type);*/ actions } -// void NodeVisitorDef::visit(const type& node) { DEBUG("DEF - "#type" (const)"); actions } - -NV(ExprNode_Block, { - //INDENT(); - for( auto& child : node.m_nodes ) - visit(child); - //UNINDENT(); -}) -NV(ExprNode_Macro, -{ - BUG(node.span(), "Hit unexpanded macro in expression - " << node); -}) -NV(ExprNode_Asm, -{ - for(auto& v : node.m_output) - visit(v.value); - for(auto& v : node.m_input) - visit(v.value); -}) -NV(ExprNode_Flow, -{ - visit(node.m_value); -}) -NV(ExprNode_LetBinding, -{ - // TODO: Handle recurse into Let pattern? - visit(node.m_value); -}) -NV(ExprNode_Assign, -{ - INDENT(); - visit(node.m_slot); - visit(node.m_value); - UNINDENT(); -}) -NV(ExprNode_CallPath, -{ - INDENT(); - for( auto& arg : node.m_args ) - visit(arg); - UNINDENT(); -}) -NV(ExprNode_CallMethod, -{ - INDENT(); - visit(node.m_val); - for( auto& arg : node.m_args ) - visit(arg); - UNINDENT(); -}) -NV(ExprNode_CallObject, -{ - INDENT(); - visit(node.m_val); - for( auto& arg : node.m_args ) - visit(arg); - UNINDENT(); -}) -NV(ExprNode_Loop, -{ - INDENT(); - visit(node.m_cond); - visit(node.m_code); - UNINDENT(); -}) -NV(ExprNode_Match, -{ - INDENT(); - visit(node.m_val); - for( auto& arm : node.m_arms ) - { - visit(arm.m_cond); - visit(arm.m_code); - } - UNINDENT(); -}) -NV(ExprNode_If, -{ - INDENT(); - visit(node.m_cond); - visit(node.m_true); - visit(node.m_false); - UNINDENT(); -}) -NV(ExprNode_IfLet, -{ - INDENT(); - visit(node.m_value); - visit(node.m_true); - visit(node.m_false); - UNINDENT(); -}) - -NV(ExprNode_Integer, {(void)node;}) -NV(ExprNode_Float, {(void)node;}) -NV(ExprNode_Bool, {(void)node;}) -NV(ExprNode_String, {(void)node;}) -NV(ExprNode_ByteString, {(void)node;}) - -NV(ExprNode_Closure, -{ - visit(node.m_code); -}); -NV(ExprNode_StructLiteral, -{ - visit(node.m_base_value); - for( auto& val : node.m_values ) - visit(val.value); -}) -NV(ExprNode_Array, -{ - visit(node.m_size); - for( auto& val : node.m_values ) - visit(val); -}) -NV(ExprNode_Tuple, -{ - for( auto& val : node.m_values ) - visit(val); -}) -NV(ExprNode_NamedValue, -{ - (void)node; - // LEAF -}) - -NV(ExprNode_Field, -{ - visit(node.m_obj); -}) -NV(ExprNode_Index, -{ - visit(node.m_obj); - visit(node.m_idx); -}) -NV(ExprNode_Deref, -{ - visit(node.m_value); -}) -NV(ExprNode_Cast, -{ - visit(node.m_value); -}) -NV(ExprNode_TypeAnnotation, -{ - visit(node.m_value); -}) -NV(ExprNode_BinOp, -{ - visit(node.m_left); - visit(node.m_right); -}) -NV(ExprNode_UniOp, -{ - visit(node.m_value); -}) -#undef NV - - -}; - diff --git a/gcc/rust/mrustc_parser/ast/expr.hpp b/gcc/rust/mrustc_parser/ast/expr.hpp deleted file mode 100644 index 264b37e..0000000 --- a/gcc/rust/mrustc_parser/ast/expr.hpp +++ /dev/null @@ -1,719 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/expr.hpp - * - AST Expression Nodes - */ -#ifndef AST_EXPR_INCLUDED -#define AST_EXPR_INCLUDED - -#include -#include // unique_ptr -#include - -#include "../parse/tokentree.hpp" -#include "types.hpp" -#include "pattern.hpp" -#include "attrs.hpp" - -namespace AST { - -using ::std::unique_ptr; - -class NodeVisitor; - -class ExprNode -{ - AttributeList m_attrs; - Span m_span; -public: - virtual ~ExprNode() = 0; - - virtual void visit(NodeVisitor& nv) = 0; - virtual void print(::std::ostream& os) const = 0; - virtual ::std::unique_ptr clone() const = 0; - - void set_span(Span s) { m_span = ::std::move(s); } - const Span& span() const { return m_span; } - - void set_attrs(AttributeList&& mi) { - m_attrs = mv$(mi); - } - AttributeList& attrs() { return m_attrs; } -}; -typedef ::std::unique_ptr ExprNodeP; - -#define NODE_METHODS() \ - void visit(NodeVisitor& nv) override;\ - void print(::std::ostream& os) const override; \ - ::std::unique_ptr clone() const override; - -struct ExprNode_Block: - public ExprNode -{ - bool m_is_unsafe; - bool m_yields_final_value; - ::std::shared_ptr m_local_mod; - ::std::vector m_nodes; - - ExprNode_Block(::std::vector nodes={}): - m_is_unsafe(false), - m_yields_final_value(true), - m_local_mod(), - m_nodes( mv$(nodes) ) - {} - ExprNode_Block(bool is_unsafe, bool yields_final_value, ::std::vector nodes, ::std::shared_ptr local_mod): - m_is_unsafe(is_unsafe), - m_yields_final_value(yields_final_value), - m_local_mod( move(local_mod) ), - m_nodes( move(nodes) ) - { - } - - NODE_METHODS(); -}; - -struct ExprNode_Macro: - public ExprNode -{ - ::std::string m_name; - ::std::string m_ident; - ::TokenTree m_tokens; - - ExprNode_Macro(::std::string name, ::std::string ident, ::TokenTree&& tokens): - m_name(name), - m_ident(ident), - m_tokens( move(tokens) ) - {} - - NODE_METHODS(); -}; - -// asm! macro -struct ExprNode_Asm: - public ExprNode -{ - struct ValRef - { - ::std::string name; - unique_ptr value; - }; - - ::std::string m_text; - ::std::vector m_output; - ::std::vector m_input; - ::std::vector<::std::string> m_clobbers; - ::std::vector<::std::string> m_flags; - - ExprNode_Asm(::std::string text, ::std::vector output, ::std::vector input, ::std::vector<::std::string> clobbers, ::std::vector<::std::string> flags): - m_text( move(text) ), - m_output( move(output) ), - m_input( move(input) ), - m_clobbers( move(clobbers) ), - m_flags( move(flags) ) - { - } - - NODE_METHODS(); -}; - -// Break/Continue/Return -struct ExprNode_Flow: - public ExprNode -{ - enum Type { - RETURN, - CONTINUE, - BREAK, - } m_type; - ::std::string m_target; - unique_ptr m_value; - - ExprNode_Flow(Type type, ::std::string target, unique_ptr&& value): - m_type(type), - m_target( move(target) ), - m_value( move(value) ) - { - } - - NODE_METHODS(); -}; -struct ExprNode_LetBinding: - public ExprNode -{ - Pattern m_pat; - TypeRef m_type; - unique_ptr m_value; - - ExprNode_LetBinding(Pattern pat, TypeRef type, unique_ptr&& value): - m_pat( move(pat) ), - m_type( move(type) ), - m_value( move(value) ) - { - } - - NODE_METHODS(); -}; -struct ExprNode_Assign: - public ExprNode -{ - enum Operation { - NONE, - ADD, SUB, - MUL, DIV, MOD, - AND, OR , XOR, - SHR, SHL, - } m_op; - unique_ptr m_slot; - unique_ptr m_value; - - ExprNode_Assign(): m_op(NONE) {} - ExprNode_Assign(Operation op, unique_ptr&& slot, unique_ptr&& value): - m_op(op), - m_slot( move(slot) ), - m_value( move(value) ) - { - } - - NODE_METHODS(); -}; -struct ExprNode_CallPath: - public ExprNode -{ - Path m_path; - ::std::vector> m_args; - - ExprNode_CallPath(Path&& path, ::std::vector>&& args): - m_path( move(path) ), - m_args( move(args) ) - { - } - - NODE_METHODS(); -}; -struct ExprNode_CallMethod: - public ExprNode -{ - unique_ptr m_val; - PathNode m_method; - ::std::vector> m_args; - - ExprNode_CallMethod(unique_ptr obj, PathNode method, ::std::vector> args): - m_val( move(obj) ), - m_method( move(method) ), - m_args( move(args) ) - { - } - - NODE_METHODS(); -}; -// Call an object (Fn/FnMut/FnOnce) -struct ExprNode_CallObject: - public ExprNode -{ - unique_ptr m_val; - ::std::vector> m_args; - - ExprNode_CallObject(unique_ptr&& val, ::std::vector< unique_ptr >&& args): - m_val( move(val) ), - m_args( move(args) ) - { - } - NODE_METHODS(); -}; - -struct ExprNode_Loop: - public ExprNode -{ - enum Type { - LOOP, - WHILE, - WHILELET, - FOR, - } m_type; - ::std::string m_label; - AST::Pattern m_pattern; - unique_ptr m_cond; // if NULL, loop is a 'loop' - unique_ptr m_code; - - ExprNode_Loop(): m_type(LOOP) {} - ExprNode_Loop(::std::string label, unique_ptr code): - m_type(LOOP), - m_label( ::std::move(label) ), - m_code( ::std::move(code) ) - {} - ExprNode_Loop(::std::string label, unique_ptr cond, unique_ptr code): - m_type(WHILE), - m_label( ::std::move(label) ), - m_cond( ::std::move(cond) ), - m_code( ::std::move(code) ) - {} - ExprNode_Loop(::std::string label, Type type, AST::Pattern pattern, unique_ptr val, unique_ptr code): - m_type(type), - m_label( ::std::move(label) ), - m_pattern( ::std::move(pattern) ), - m_cond( ::std::move(val) ), - m_code( ::std::move(code) ) - {} - NODE_METHODS(); -}; - -struct ExprNode_Match_Arm -{ - AttributeList m_attrs; - ::std::vector m_patterns; - unique_ptr m_cond; - - unique_ptr m_code; - - - ExprNode_Match_Arm() - {} - ExprNode_Match_Arm(::std::vector patterns, unique_ptr cond, unique_ptr code): - m_patterns( mv$(patterns) ), - m_cond( mv$(cond) ), - m_code( mv$(code) ) - {} -}; - -struct ExprNode_Match: - public ExprNode -{ - unique_ptr m_val; - ::std::vector m_arms; - - ExprNode_Match(unique_ptr val, ::std::vector arms): - m_val( ::std::move(val) ), - m_arms( ::std::move(arms) ) - { - } - NODE_METHODS(); -}; - -struct ExprNode_If: - public ExprNode -{ - unique_ptr m_cond; - unique_ptr m_true; - unique_ptr m_false; - - ExprNode_If(unique_ptr&& cond, unique_ptr&& true_code, unique_ptr&& false_code): - m_cond( ::std::move(cond) ), - m_true( ::std::move(true_code) ), - m_false( ::std::move(false_code) ) - { - } - NODE_METHODS(); -}; -struct ExprNode_IfLet: - public ExprNode -{ - AST::Pattern m_pattern; - unique_ptr m_value; - unique_ptr m_true; - unique_ptr m_false; - - ExprNode_IfLet(AST::Pattern pattern, unique_ptr&& cond, unique_ptr&& true_code, unique_ptr&& false_code): - m_pattern( ::std::move(pattern) ), - m_value( ::std::move(cond) ), - m_true( ::std::move(true_code) ), - m_false( ::std::move(false_code) ) - { - } - NODE_METHODS(); -}; -// Literal integer -struct ExprNode_Integer: - public ExprNode -{ - enum eCoreType m_datatype; - uint64_t m_value; - - ExprNode_Integer(uint64_t value, enum eCoreType datatype): - m_datatype(datatype), - m_value(value) - { - } - - NODE_METHODS(); -}; -// Literal float -struct ExprNode_Float: - public ExprNode -{ - enum eCoreType m_datatype; - double m_value; - - ExprNode_Float(double value, enum eCoreType datatype): - m_datatype(datatype), - m_value(value) - { - } - - NODE_METHODS(); -}; -// Literal boolean -struct ExprNode_Bool: - public ExprNode -{ - bool m_value; - - ExprNode_Bool(bool value): - m_value(value) - { - } - - NODE_METHODS(); -}; -// Literal string -struct ExprNode_String: - public ExprNode -{ - ::std::string m_value; - - ExprNode_String(::std::string value): - m_value( ::std::move(value) ) - {} - - NODE_METHODS(); -}; -// Literal byte string -struct ExprNode_ByteString: - public ExprNode -{ - ::std::string m_value; - - ExprNode_ByteString(::std::string value): - m_value( ::std::move(value) ) - {} - - NODE_METHODS(); -}; - -// Closure / Lambda -struct ExprNode_Closure: - public ExprNode -{ - typedef ::std::vector< ::std::pair > args_t; - - args_t m_args; - TypeRef m_return; - unique_ptr m_code; - bool m_is_move; - - ExprNode_Closure(args_t args, TypeRef rv, unique_ptr code, bool is_move): - m_args( ::std::move(args) ), - m_return( ::std::move(rv) ), - m_code( ::std::move(code) ), - m_is_move( is_move ) - {} - - NODE_METHODS(); -}; -// Literal structure -struct ExprNode_StructLiteral: - public ExprNode -{ - struct Ent { - AttributeList attrs; - ::std::string name; - unique_ptr value; - }; - typedef ::std::vector t_values; - Path m_path; - unique_ptr m_base_value; - t_values m_values; - - ExprNode_StructLiteral(Path path, unique_ptr&& base_value, t_values&& values ): - m_path( move(path) ), - m_base_value( move(base_value) ), - m_values( move(values) ) - {} - - NODE_METHODS(); -}; -// Array -struct ExprNode_Array: - public ExprNode -{ - unique_ptr m_size; // if non-NULL, it's a sized array - ::std::vector< unique_ptr > m_values; - - ExprNode_Array(::std::vector< unique_ptr > vals): - m_values( ::std::move(vals) ) - {} - ExprNode_Array(unique_ptr val, unique_ptr size): - m_size( ::std::move(size) ) - { - m_values.push_back( ::std::move(val) ); - } - - NODE_METHODS(); -}; -// Tuple -struct ExprNode_Tuple: - public ExprNode -{ - ::std::vector< unique_ptr > m_values; - - ExprNode_Tuple(::std::vector< unique_ptr > vals): - m_values( ::std::move(vals) ) - {} - - NODE_METHODS(); -}; -// Variable / Constant -struct ExprNode_NamedValue: - public ExprNode -{ - Path m_path; - - ExprNode_NamedValue(Path&& path): - m_path( ::std::move(path) ) - { - } - NODE_METHODS(); -}; -// Field dereference -struct ExprNode_Field: - public ExprNode -{ - ::std::unique_ptr m_obj; - ::std::string m_name; - - ExprNode_Field(::std::unique_ptr&& obj, ::std::string name): - m_obj( ::std::move(obj) ), - m_name( ::std::move(name) ) - { - } - NODE_METHODS(); -}; -struct ExprNode_Index: - public ExprNode -{ - ::std::unique_ptr m_obj; - ::std::unique_ptr m_idx; - - ExprNode_Index(::std::unique_ptr obj, ::std::unique_ptr idx): - m_obj( ::std::move(obj) ), - m_idx( ::std::move(idx) ) - {} - - NODE_METHODS(); -}; - -// Pointer dereference -struct ExprNode_Deref: - public ExprNode -{ - ::std::unique_ptr m_value; - - ExprNode_Deref(::std::unique_ptr value): - m_value( ::std::move(value) ) - { - } - - NODE_METHODS(); -}; - -// Type cast ('as') -struct ExprNode_Cast: - public ExprNode -{ - unique_ptr m_value; - TypeRef m_type; - - ExprNode_Cast(unique_ptr&& value, TypeRef&& dst_type): - m_value( move(value) ), - m_type( move(dst_type) ) - { - } - NODE_METHODS(); -}; - -// Type annotation (': _') -struct ExprNode_TypeAnnotation: - public ExprNode -{ - unique_ptr m_value; - TypeRef m_type; - - ExprNode_TypeAnnotation(unique_ptr&& value, TypeRef&& dst_type): - m_value( move(value) ), - m_type( move(dst_type) ) - { - } - NODE_METHODS(); -}; - -// Binary operation -struct ExprNode_BinOp: - public ExprNode -{ - enum Type { - CMPEQU, - CMPNEQU, - CMPLT, - CMPLTE, - CMPGT, - CMPGTE, - - RANGE, - RANGE_INC, - BOOLAND, - BOOLOR, - - BITAND, - BITOR, - BITXOR, - - SHL, - SHR, - - MULTIPLY, - DIVIDE, - MODULO, - ADD, - SUB, - - PLACE_IN, // `in PLACE { expr }` or `PLACE <- expr` - }; - - Type m_type; - ::std::unique_ptr m_left; - ::std::unique_ptr m_right; - - ExprNode_BinOp(Type type, ::std::unique_ptr left, ::std::unique_ptr right): - m_type(type), - m_left( ::std::move(left) ), - m_right( ::std::move(right) ) - { - } - - NODE_METHODS(); -}; - -struct ExprNode_UniOp: - public ExprNode -{ - enum Type { - REF, // '& ' - REFMUT, // '&mut ' - BOX, // 'box ' - INVERT, // '!' - NEGATE, // '-' - QMARK, // '?' - }; - - enum Type m_type; - ::std::unique_ptr m_value; - - ExprNode_UniOp(Type type, ::std::unique_ptr value): - m_type(type), - m_value( ::std::move(value) ) - { - } - - NODE_METHODS(); -}; - -#undef NODE_METHODS - -class NodeVisitor -{ -public: - virtual ~NodeVisitor() = default; - inline void visit(const unique_ptr& cnode) { - if(cnode.get()) - cnode->visit(*this); - } - virtual bool is_const() const { return false; } - - #define NT(nt) \ - virtual void visit(nt& node) = 0/*; \ - virtual void visit(const nt& node) = 0*/ - NT(ExprNode_Block); - NT(ExprNode_Macro); - NT(ExprNode_Asm); - NT(ExprNode_Flow); - NT(ExprNode_LetBinding); - NT(ExprNode_Assign); - NT(ExprNode_CallPath); - NT(ExprNode_CallMethod); - NT(ExprNode_CallObject); - NT(ExprNode_Loop); - NT(ExprNode_Match); - NT(ExprNode_If); - NT(ExprNode_IfLet); - - NT(ExprNode_Integer); - NT(ExprNode_Float); - NT(ExprNode_Bool); - NT(ExprNode_String); - NT(ExprNode_ByteString); - NT(ExprNode_Closure); - NT(ExprNode_StructLiteral); - NT(ExprNode_Array); - NT(ExprNode_Tuple); - NT(ExprNode_NamedValue); - - NT(ExprNode_Field); - NT(ExprNode_Index); - NT(ExprNode_Deref); - NT(ExprNode_Cast); - NT(ExprNode_TypeAnnotation); - NT(ExprNode_BinOp); - NT(ExprNode_UniOp); - #undef NT -}; -class NodeVisitorDef: - public NodeVisitor -{ -public: - inline void visit(const unique_ptr& cnode) { - if(cnode.get()) - cnode->visit(*this); - } - #define NT(nt) \ - virtual void visit(nt& node) override;/* \ - virtual void visit(const nt& node) override*/ - NT(ExprNode_Block); - NT(ExprNode_Macro); - NT(ExprNode_Asm); - NT(ExprNode_Flow); - NT(ExprNode_LetBinding); - NT(ExprNode_Assign); - NT(ExprNode_CallPath); - NT(ExprNode_CallMethod); - NT(ExprNode_CallObject); - NT(ExprNode_Loop); - NT(ExprNode_Match); - NT(ExprNode_If); - NT(ExprNode_IfLet); - - NT(ExprNode_Integer); - NT(ExprNode_Float); - NT(ExprNode_Bool); - NT(ExprNode_String); - NT(ExprNode_ByteString); - NT(ExprNode_Closure); - NT(ExprNode_StructLiteral); - NT(ExprNode_Array); - NT(ExprNode_Tuple); - NT(ExprNode_NamedValue); - - NT(ExprNode_Field); - NT(ExprNode_Index); - NT(ExprNode_Deref); - NT(ExprNode_Cast); - NT(ExprNode_TypeAnnotation); - NT(ExprNode_BinOp); - NT(ExprNode_UniOp); - #undef NT -}; - -} - -#endif - diff --git a/gcc/rust/mrustc_parser/ast/expr_ptr.hpp b/gcc/rust/mrustc_parser/ast/expr_ptr.hpp deleted file mode 100644 index cae519c..0000000 --- a/gcc/rust/mrustc_parser/ast/expr_ptr.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/expr_ptr.hpp - * - Pointer type wrapping AST::ExprNode (prevents need to know the full definition) - */ -#include - -namespace AST { - -class ExprNode; -class NodeVisitor; - -typedef ::std::unique_ptr ExprNodeP; -extern ::std::ostream& operator<<(::std::ostream& os, const ExprNode& node); - -class Expr -{ - ::std::shared_ptr m_node; -public: - Expr(unique_ptr node); - Expr(ExprNode* node); - Expr(); - - bool is_valid() const { return m_node.get() != nullptr; } - const ExprNode& node() const { assert(m_node.get()); return *m_node; } - ExprNode& node() { assert(m_node.get()); return *m_node; } - ::std::shared_ptr take_node() { assert(m_node.get()); return ::std::move(m_node); } - void visit_nodes(NodeVisitor& v); - void visit_nodes(NodeVisitor& v) const; - - Expr clone() const; - - friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat); -}; - -} diff --git a/gcc/rust/mrustc_parser/ast/generics.hpp b/gcc/rust/mrustc_parser/ast/generics.hpp deleted file mode 100644 index c222044..0000000 --- a/gcc/rust/mrustc_parser/ast/generics.hpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/generics.hpp - * - AST Generics (type parameters, bounds, ...) - */ -#pragma once - -#include -#include "types.hpp" - -namespace AST { - -class TypeParam -{ - ::AST::AttributeList m_attrs; - Span m_span; - // TODO: use an Ident? - ::std::string m_name; - ::TypeRef m_default; -public: - TypeParam(TypeParam&& x) = default; - TypeParam& operator=(TypeParam&& x) = default; - explicit TypeParam(const TypeParam& x): - m_attrs( x.m_attrs ), - m_span( x.m_span ), - m_name( x.m_name ), - m_default( x.m_default.clone() ) - { - } - - TypeParam(Span sp, ::AST::AttributeList attrs, ::std::string name): - m_attrs( ::std::move(attrs) ), - m_span( ::std::move(sp) ), - m_name( ::std::move(name) ), - m_default(m_span) - {} - - void setDefault(TypeRef type) { - assert(m_default.is_wildcard()); - m_default = ::std::move(type); - } - - const ::AST::AttributeList& attrs() const { return m_attrs; } - const Span& span() const { return m_span; } - const ::std::string& name() const { return m_name; } - - const TypeRef& get_default() const { return m_default; } - TypeRef& get_default() { return m_default; } - - friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp); -}; -class LifetimeParam -{ - ::AST::AttributeList m_attrs; - Span m_span; - Ident m_name; -public: - LifetimeParam(Span sp, ::AST::AttributeList attrs, Ident name): - m_attrs( ::std::move(attrs) ), - m_span( ::std::move(sp) ), - m_name( ::std::move(name) ) - { - } - LifetimeParam(LifetimeParam&&) = default; - LifetimeParam& operator=(LifetimeParam&&) = default; - explicit LifetimeParam(const LifetimeParam&) = default; - - const ::AST::AttributeList& attrs() const { return m_attrs; } - const Span& span() const { return m_span; } - const Ident& name() const { return m_name; } - - friend ::std::ostream& operator<<(::std::ostream& os, const LifetimeParam& p); -}; - -// HigherRankedBounds is defined in `types.hpp` - -TAGGED_UNION_EX( GenericBound, (), None, - ( - (None, struct{}), - // Lifetime bound: 'test must be valid for 'bound - (Lifetime, struct { - LifetimeRef test; - LifetimeRef bound; - }), - // Type lifetime bound - (TypeLifetime, struct { - TypeRef type; - LifetimeRef bound; - }), - // Standard trait bound: "Type: [for<'a>] Trait" - (IsTrait, struct { - HigherRankedBounds outer_hrbs; - TypeRef type; - HigherRankedBounds inner_hrbs; - AST::Path trait; - }), - // Removed trait bound: "Type: ?Trait" - (MaybeTrait, struct { - TypeRef type; - AST::Path trait; - }), - // Negative trait bound: "Type: !Trait" - (NotTrait, struct { - TypeRef type; - AST::Path trait; - }), - // Type equality: "Type = Replacement" - (Equality, struct { - TypeRef type; - TypeRef replacement; - }) - ), - - (, span(x.span) ), ( span = x.span; ), - ( - public: - - Span span; - - GenericBound clone() const { - TU_MATCH(GenericBound, ( (*this) ), (ent), - (None, return make_None({}); ), - (Lifetime, return make_Lifetime({ent.test, ent.bound}); ), - (TypeLifetime, return make_TypeLifetime({ent.type.clone(), ent.bound}); ), - (IsTrait, return make_IsTrait({ent.outer_hrbs, ent.type.clone(), ent.inner_hrbs, ent.trait}); ), - (MaybeTrait, return make_MaybeTrait({ent.type.clone(), ent.trait}); ), - (NotTrait, return make_NotTrait({ent.type.clone(), ent.trait}); ), - (Equality, return make_Equality({ent.type.clone(), ent.replacement.clone()}); ) - ) - return GenericBound(); - } - ) - ); - -::std::ostream& operator<<(::std::ostream& os, const GenericBound& x); - -class GenericParams -{ - ::std::vector m_type_params; - ::std::vector m_lifetime_params; - ::std::vector m_bounds; -public: - GenericParams() {} - GenericParams(GenericParams&& x) = default; - GenericParams& operator=(GenericParams&& x) = default; - GenericParams(const GenericParams& x) = delete; - - GenericParams clone() const { - GenericParams rv; - rv.m_type_params = ::std::vector( m_type_params ); // Copy-constructable - rv.m_lifetime_params = ::std::vector(m_lifetime_params); - rv.m_bounds.reserve( m_bounds.size() ); - for(auto& e: m_bounds) - rv.m_bounds.push_back( e.clone() ); - return rv; - } - - const ::std::vector& ty_params() const { return m_type_params; } - ::std::vector& ty_params() { return m_type_params; } - const ::std::vector& lft_params() const { return m_lifetime_params; } - const ::std::vector& bounds() const { return m_bounds; } - ::std::vector& bounds() { return m_bounds; } - - void add_ty_param(TypeParam param) { m_type_params.push_back( ::std::move(param) ); } - void add_lft_param(LifetimeParam lft) { m_lifetime_params.push_back( ::std::move(lft) ); } - void add_bound(GenericBound bound) { - m_bounds.push_back( ::std::move(bound) ); - } - - int find_name(const char* name) const; - bool check_params(Crate& crate, const ::std::vector& types) const; - bool check_params(Crate& crate, ::std::vector& types, bool allow_infer) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const GenericParams& tp); -}; - - -} - diff --git a/gcc/rust/mrustc_parser/ast/item.hpp b/gcc/rust/mrustc_parser/ast/item.hpp deleted file mode 100644 index 0074ce9..0000000 --- a/gcc/rust/mrustc_parser/ast/item.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/item.hpp - * - AST named item wrapper - */ -#pragma once - -#include -#include - -namespace AST { - -template -struct Named -{ - ::std::string name; - T data; - bool is_pub; - - Named(): - is_pub(false) - {} - Named(Named&&) = default; - Named(const Named&) = default; - Named& operator=(Named&&) = default; - Named(::std::string name, T data, bool is_pub): - name( ::std::move(name) ), - data( ::std::move(data) ), - is_pub( is_pub ) - { - } -}; - -template -using NamedList = ::std::vector >; - -} // namespace AST - diff --git a/gcc/rust/mrustc_parser/ast/macro.hpp b/gcc/rust/mrustc_parser/ast/macro.hpp deleted file mode 100644 index 5b2223c..0000000 --- a/gcc/rust/mrustc_parser/ast/macro.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/macro.hpp - * - AST representation of a macro invocation - */ -#ifndef _AST_MACRO_HPP_ -#define _AST_MACRO_HPP_ - -#include "../parse/tokentree.hpp" -#include -#include "attrs.hpp" - -namespace AST { - -class MacroInvocation -{ - Span m_span; - - ::std::string m_macro_name; - ::std::string m_ident; - TokenTree m_input; -public: - MacroInvocation(MacroInvocation&&) = default; - MacroInvocation& operator=(MacroInvocation&&) = default; - MacroInvocation(const MacroInvocation&) = delete; - MacroInvocation& operator=(const MacroInvocation&) = delete; - - MacroInvocation() - { - } - - MacroInvocation(Span span, ::std::string macro, ::std::string ident, TokenTree input): - m_span( mv$(span) ), - m_macro_name( mv$(macro) ), - m_ident( mv$(ident) ), - m_input( mv$(input) ) - { - } - - MacroInvocation clone() const; - - void clear() { - m_macro_name = ""; - m_ident = ""; - m_input = TokenTree(); - } - - const Span& span() const { return m_span; } - const ::std::string& name() const { return m_macro_name; } - - const ::std::string& input_ident() const { return m_ident; } - const TokenTree& input_tt() const { return m_input; } - TokenTree& input_tt() { return m_input; } - - friend ::std::ostream& operator<<(::std::ostream& os, const MacroInvocation& x) { - os << x.m_macro_name << "! " << x.m_ident << x.m_input; - return os; - } -}; - - -} - -#endif - diff --git a/gcc/rust/mrustc_parser/ast/path.cpp b/gcc/rust/mrustc_parser/ast/path.cpp deleted file mode 100644 index 6fdf1e4..0000000 --- a/gcc/rust/mrustc_parser/ast/path.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/path.cpp - * - AST::Path and friends - */ -#include "path.hpp" -#include "ast.hpp" -#include "types.hpp" -#include -#include "../parse/parseerror.hpp" -#include - -#define PRETTY_PATH_PRINT 1 - -namespace AST { - -// --- AST::PathBinding -::std::ostream& operator<<(::std::ostream& os, const PathBinding& x) { - TU_MATCH(PathBinding, (x), (i), - (Unbound, os << "_"; ), - (Crate , os << "Crate"; ), - (Module, os << "Module"; ), - (Trait, os << "Trait"; ), - (Struct, os << "Struct"; ), - (Enum, os << "Enum"; ), - (Union, os << "Union"; ), - (Static, os << "Static"; ), - (Function, os << "Function";), - (EnumVar, os << "EnumVar(" << i.idx << ")"; ), - (TypeAlias, os << "TypeAlias";), - (StructMethod, os << "StructMethod"; ), - (TraitMethod, os << "TraitMethod"; ), - - (TypeParameter, os << "TyParam(" << i.level << " # " << i.idx << ")"; ), - (Variable, os << "Var(" << i.slot << ")"; ) - ) - return os; -} -PathBinding PathBinding::clone() const -{ - TU_MATCH(::AST::PathBinding, (*this), (e), - (Unbound , return PathBinding::make_Unbound({}); ), - (Module , return PathBinding::make_Module(e); ), - (Crate , return PathBinding(e); ), - (Trait , return PathBinding(e); ), - (Struct , return PathBinding(e); ), - (Enum , return PathBinding(e); ), - (Union , return PathBinding(e); ), - (Static , return PathBinding(e); ), - (Function, return PathBinding(e); ), - (TypeAlias, return PathBinding::make_TypeAlias(e); ), - (EnumVar , return PathBinding::make_EnumVar(e); ), - (StructMethod, return PathBinding::make_StructMethod(e); ), - (TraitMethod, return PathBinding::make_TraitMethod(e); ), - - (TypeParameter, return PathBinding::make_TypeParameter(e); ), - (Variable, return PathBinding::make_Variable(e); ) - ) - throw "BUG: Fell off the end of PathBinding::clone"; -} - -::std::ostream& operator<<(::std::ostream& os, const PathParams& x) -{ - bool needs_comma = false; - os << "<"; - for(const auto& v : x.m_lifetimes) { - if(needs_comma) os << ", "; - needs_comma = true; - os << "'" << v; - } - for(const auto& v : x.m_types) { - if(needs_comma) os << ", "; - needs_comma = true; - os << v; - } - for(const auto& v : x.m_assoc) { - if(needs_comma) os << ", "; - needs_comma = true; - os << v.first << "=" << v.second; - } - os << ">"; - return os; -} -PathParams::PathParams(const PathParams& x): - m_lifetimes( x.m_lifetimes ) -{ - m_types.reserve( x.m_types.size() ); - for(const auto& t : x.m_types) - m_types.push_back(t.clone()); - - m_assoc.reserve( x.m_assoc.size() ); - for(const auto& t : x.m_assoc) - m_assoc.push_back( ::std::make_pair(t.first, t.second.clone()) ); -} -Ordering PathParams::ord(const PathParams& x) const -{ - Ordering rv; - rv = ::ord(m_lifetimes, x.m_lifetimes); - if(rv != OrdEqual) return rv; - rv = ::ord(m_types, x.m_types); - if(rv != OrdEqual) return rv; - rv = ::ord(m_assoc, x.m_assoc); - if(rv != OrdEqual) return rv; - return rv; -} - -// --- AST::PathNode -PathNode::PathNode(::std::string name, PathParams args): - m_name( mv$(name) ), - m_params( mv$(args) ) -{ -} -Ordering PathNode::ord(const PathNode& x) const -{ - Ordering rv; - rv = ::ord(m_name, x.m_name); - if(rv != OrdEqual) return rv; - rv = m_params.ord(x.m_params); - if(rv != OrdEqual) return rv; - return OrdEqual; -} -void PathNode::print_pretty(::std::ostream& os, bool is_type_context) const -{ - os << m_name; - if( ! m_params.is_empty() ) - { - if( ! is_type_context ) - os << "::"; - os << m_params; - } -} -::std::ostream& operator<<(::std::ostream& os, const PathNode& pn) { - pn.print_pretty(os, false); - return os; -} - -/// Return an iterator to the named item -template -typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) -{ - return ::std::find_if(vec.begin(), vec.end(), [&name](const Named& x) { - return x.name == name; - }); -} - -// --- AST::Path -AST::Path::~Path() -{ -} -AST::Path::Path(TagUfcs, TypeRef type, ::std::vector nodes): - m_class( AST::Path::Class::make_UFCS({box$(type), nullptr, nodes}) ) -{ -} -AST::Path::Path(TagUfcs, TypeRef type, Path trait, ::std::vector nodes): - m_class( AST::Path::Class::make_UFCS({box$(type), box$(trait), nodes}) ) -{ -} -AST::Path::Path(const Path& x): - m_class() - //m_binding(x.m_binding) -{ - TU_MATCH(Class, (x.m_class), (ent), - (Invalid, m_class = Class::make_Invalid({});), - (Local, - m_class = Class::make_Local({ent.name}); - ), - (Relative, - m_class = Class::make_Relative({ent.hygiene, ent.nodes}); - ), - (Self, - m_class = Class::make_Self({ent.nodes}); - ), - (Super, - m_class = Class::make_Super({ent.count, ent.nodes}); - ), - (Absolute, - m_class = Class::make_Absolute({ent.crate, ent.nodes}); - ), - (UFCS, - if( ent.trait ) - m_class = Class::make_UFCS({ box$(ent.type->clone()), ::std::unique_ptr(new Path(*ent.trait)), ent.nodes }); - else - m_class = Class::make_UFCS({ box$(ent.type->clone()), nullptr, ent.nodes }); - ) - ) - - memcpy(&m_binding, &x.m_binding, sizeof(PathBinding)); -} - -void Path::bind_variable(unsigned int slot) -{ - m_binding = PathBinding::make_Variable({slot}); -} -void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector& /*args*/) -{ - auto it = ::std::find_if(ent.variants().begin(), ent.variants().end(), [&](const auto& x) { return x.m_name == name; }); - if( it == ent.variants().end() ) - { - throw ParseError::Generic("Enum variant not found"); - } - unsigned int idx = it - ent.variants().begin(); - - DEBUG("Bound to enum variant '" << name << "' (#" << idx << ")"); - ::AST::PathBinding::Data_EnumVar tmp = {}; - tmp.enum_ = &ent; - tmp.idx = idx; - m_binding = PathBinding::make_EnumVar( mv$(tmp) ); -} - -Path& Path::operator+=(const Path& other) -{ - for(auto& node : other.nodes()) - append(node); - // If the path is modified, clear the binding - m_binding = PathBinding(); - return *this; -} - -Ordering Path::ord(const Path& x) const -{ - Ordering rv; - - rv = ::ord( (unsigned)m_class.tag(), (unsigned)x.m_class.tag() ); - if( rv != OrdEqual ) return rv; - - TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent), - (Invalid, - return OrdEqual; - ), - (Local, - return ::ord(ent.name, x_ent.name); - ), - (Relative, - return ::ord(ent.nodes, x_ent.nodes); - ), - (Self, - return ::ord(ent.nodes, x_ent.nodes); - ), - (Super, - return ::ord(ent.nodes, x_ent.nodes); - ), - (Absolute, - rv = ::ord( ent.crate, x_ent.crate ); - if( rv != OrdEqual ) return rv; - return ::ord(ent.nodes, x_ent.nodes); - ), - (UFCS, - rv = ent.type->ord( *x_ent.type ); - if( rv != OrdEqual ) return rv; - rv = ent.trait->ord( *x_ent.trait ); - if( rv != OrdEqual ) return rv; - return ::ord(ent.nodes, x_ent.nodes); - ) - ) - - return OrdEqual; -} - -void Path::print_pretty(::std::ostream& os, bool is_type_context, bool is_debug) const -{ - TU_MATCH(Path::Class, (m_class), (ent), - (Invalid, - os << "/*inv*/"; - // NOTE: Don't print the binding for invalid paths - return ; - ), - (Local, - // Only print comment if there's no binding - if( m_binding.is_Unbound() ) - { - if( is_debug ) - os << "/*var*/"; - } - else - assert( m_binding.is_Variable() ); - os << ent.name; - ), - (Relative, - if( is_debug ) - os << ent.hygiene; - for(const auto& n : ent.nodes) - { - if( &n != &ent.nodes[0] ) { - os << "::"; - } - n.print_pretty(os, is_type_context); - } - ), - (Self, - os << "self"; - for(const auto& n : ent.nodes) - { - os << "::"; - n.print_pretty(os, is_type_context); - } - ), - (Super, - os << "super"; - for(const auto& n : ent.nodes) - { - os << "::"; - n.print_pretty(os, is_type_context); - } - ), - (Absolute, - if( ent.crate != "" ) - os << "::\"" << ent.crate << "\""; - for(const auto& n : ent.nodes) - { - os << "::"; - n.print_pretty(os, is_type_context); - } - ), - (UFCS, - //os << "/*ufcs*/"; - if( ent.trait ) { - os << "<" << *ent.type << " as "; - if( ent.trait->m_class.is_Invalid() ) { - os << "_"; - } - else { - os << *ent.trait; - } - os << ">"; - } - else { - os << "<" << *ent.type << ">"; - } - for(const auto& n : ent.nodes) { - os << "::"; - n.print_pretty(os, is_type_context); - } - ) - ) - if( is_debug ) - os << "/*" << m_binding << "*/"; -} - -::std::ostream& operator<<(::std::ostream& os, const Path& path) -{ - path.print_pretty(os, false, true); - return os; -} - -} diff --git a/gcc/rust/mrustc_parser/ast/path.hpp b/gcc/rust/mrustc_parser/ast/path.hpp deleted file mode 100644 index c2d13d7..0000000 --- a/gcc/rust/mrustc_parser/ast/path.hpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/path.hpp - * - AST::Path and helper types - */ -#ifndef AST_PATH_HPP_INCLUDED -#define AST_PATH_HPP_INCLUDED - -#include "../common.hpp" -#include -#include -#include -#include -#include -#include -#include -#include "../include/span.hpp" -#include "../include/ident.hpp" - -class TypeRef; - -namespace HIR { -class Module; -class Trait; -class Enum; -class Struct; -class Union; -class Static; -} // namespace HIR - -namespace AST { - -class LifetimeRef; -class GenericParams; -class Crate; -class Module; -class TypeAlias; -class Enum; -class Struct; -class Union; -class Trait; -class Static; -class Function; -class ExternCrate; - -TAGGED_UNION_EX(PathBinding, (), Unbound, ( - (Unbound, struct { - }), - (Crate, struct { - const ExternCrate* crate_; - }), - (Module, struct { - const Module* module_; - const ::HIR::Module* hir; - }), - (Struct, struct { - const Struct* struct_; - const ::HIR::Struct* hir; - }), - (Enum, struct { - const Enum* enum_; - const ::HIR::Enum* hir; - }), - (Union, struct { - const Union* union_; - const ::HIR::Union* hir; - }), - (Trait, struct { - const Trait* trait_; - const ::HIR::Trait* hir; - }), - (Static, struct { - const Static* static_; - const ::HIR::Static* hir; // if nullptr and static_ == nullptr, points to a `const` - }), - (Function, struct { - const Function* func_; - }), - (EnumVar, struct { - const Enum* enum_; - unsigned int idx; - const ::HIR::Enum* hir; - }), - (TypeAlias, struct { - const TypeAlias* alias_; - }), - (StructMethod, struct { - const Struct* struct_; - ::std::string name; - }), - (TraitMethod, struct { - const Trait* trait_; - ::std::string name; - }), - - (TypeParameter, struct { - unsigned int level; - unsigned int idx; - }), - (Variable, struct { - unsigned int slot; - }) - ), - (), (), - ( - public: - PathBinding clone() const; - ) - ); - -extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x); - -struct PathParams -{ - ::std::vector< LifetimeRef > m_lifetimes; - ::std::vector< TypeRef > m_types; - ::std::vector< ::std::pair< ::std::string, TypeRef> > m_assoc; - - PathParams(PathParams&& x) = default; - PathParams(const PathParams& x); - PathParams() {} - PathParams(::std::vector lfts, ::std::vector tys, ::std::vector<::std::pair<::std::string,TypeRef>> a): - m_lifetimes(mv$(lfts)), - m_types(mv$(tys)), - m_assoc(mv$(a)) - {} - - PathParams& operator=(PathParams&& x) = default; - PathParams& operator=(const PathParams& x) = delete; - - bool is_empty() const { - return m_lifetimes.empty() && m_types.empty() && m_assoc.empty(); - } - - Ordering ord(const PathParams& x) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x); -}; - -class PathNode -{ - ::std::string m_name; - PathParams m_params; -public: - PathNode() {} - PathNode(::std::string name, PathParams args = {}); - const ::std::string& name() const { return m_name; } - - const ::AST::PathParams& args() const { return m_params; } - ::AST::PathParams& args() { return m_params; } - - Ordering ord(const PathNode& x) const; - void print_pretty(::std::ostream& os, bool is_type_context) const; - - bool operator==(const PathNode& x) const { return ord(x) == OrdEqual; } - friend ::std::ostream& operator<<(::std::ostream& os, const PathNode& pn); -}; - -class Path -{ -public: - TAGGED_UNION(Class, Invalid, - (Invalid, struct {}), - (Local, struct { // Variable / Type param (resolved) - ::std::string name; - } ), - (Relative, struct { // General relative - Ident::Hygiene hygiene; - ::std::vector nodes; - } ), - (Self, struct { // Module-relative - ::std::vector nodes; - } ), - (Super, struct { // Parent-relative - unsigned int count; // Number of `super` keywords, must be >= 1 - ::std::vector nodes; - } ), - (Absolute, struct { // Absolute - ::std::string crate; - ::std::vector nodes; - } ), - (UFCS, struct { // Type-relative - ::std::unique_ptr type; // always non-null - ::std::unique_ptr trait; // nullptr = inherent, Invalid = unknown trait - ::std::vector nodes; - } ) - ); - -public: - Class m_class; - -private: - PathBinding m_binding; -public: - virtual ~Path(); - // INVALID - Path(): - m_class() - {} - Path(Path&&) = default; - Path& operator=(AST::Path&& x) { - m_class = mv$(x.m_class); - m_binding = mv$(x.m_binding); - //DEBUG("Path, " << x); - return *this; - } - - Path(const Path& x); - Path& operator=(const AST::Path&) = delete; - - // ABSOLUTE - Path(::std::string crate, ::std::vector nodes): - m_class( Class::make_Absolute({ mv$(crate), mv$(nodes)}) ) - {} - - // UFCS - struct TagUfcs {}; - Path(TagUfcs, TypeRef type, ::std::vector nodes={}); - Path(TagUfcs, TypeRef type, Path trait, ::std::vector nodes={}); - - // VARIABLE - struct TagLocal {}; - Path(TagLocal, ::std::string name): - m_class( Class::make_Local({ mv$(name) }) ) - {} - Path(::std::string name): - m_class( Class::make_Local({ mv$(name) }) ) - {} - - // RELATIVE - struct TagRelative {}; - Path(TagRelative, Ident::Hygiene hygiene, ::std::vector nodes): - m_class( Class::make_Relative({ mv$(hygiene), mv$(nodes) }) ) - {} - // SELF - struct TagSelf {}; - Path(TagSelf, ::std::vector nodes): - m_class( Class::make_Self({ mv$(nodes) }) ) - {} - // SUPER - struct TagSuper {}; - Path(TagSuper, unsigned int count, ::std::vector nodes): - m_class( Class::make_Super({ count, mv$(nodes) }) ) - {} - - //void set_crate(::std::string crate) { - // if( m_crate == "" ) { - // m_crate = crate; - // DEBUG("crate set to " << m_crate); - // } - //} - - - Class::Tag class_tag() const { - return m_class.tag(); - } - - Path operator+(PathNode pn) const { - Path tmp = Path(*this); - tmp.nodes().push_back( mv$(pn) ); - return tmp; - } - Path operator+(const ::std::string& s) const { - Path tmp = Path(*this); - tmp.append(PathNode(s, {})); - return tmp; - } - Path operator+(const Path& x) const { - return Path(*this) += x; - } - Path& operator+=(const Path& x); - - void append(PathNode node) { - assert( !m_class.is_Invalid() ); - //if( m_class.is_Invalid() ) - // m_class = Class::make_Relative({}); - nodes().push_back( mv$(node) ); - m_binding = PathBinding(); - } - - bool is_trivial() const { - TU_MATCH_DEF(Class, (m_class), (e), - ( - return false; - ), - (Local, - return true; - ), - (Relative, - return e.nodes.size() == 1 && e.nodes[0].args().is_empty(); - ) - ) - } - - bool is_valid() const { return !m_class.is_Invalid(); } - bool is_absolute() const { return m_class.is_Absolute(); } - bool is_relative() const { return m_class.is_Relative() || m_class.is_Super() || m_class.is_Self(); } - - size_t size() const { - TU_MATCH(Class, (m_class), (ent), - (Invalid, assert(!m_class.is_Invalid()); throw ::std::runtime_error("Path::nodes() on Invalid"); ), - (Local, return 1;), - (Relative, return ent.nodes.size();), - (Self, return ent.nodes.size();), - (Super, return ent.nodes.size();), - (Absolute, return ent.nodes.size();), - (UFCS, return ent.nodes.size();) - ) - throw ::std::runtime_error("Path::nodes() fell off"); - } - //const ::std::string& crate() const { return m_crate; } - - bool is_concrete() const; - - bool is_bound() const { return !m_binding.is_Unbound(); } - const PathBinding& binding() const { return m_binding; } - void bind_variable(unsigned int slot); - - ::std::vector& nodes() { - TU_MATCH(Class, (m_class), (ent), - (Invalid, assert(!m_class.is_Invalid()); throw ::std::runtime_error("Path::nodes() on Invalid"); ), - (Local, assert(!m_class.is_Local()); throw ::std::runtime_error("Path::nodes() on Local"); ), - (Relative, return ent.nodes;), - (Self, return ent.nodes;), - (Super, return ent.nodes;), - (Absolute, return ent.nodes;), - (UFCS, return ent.nodes;) - ) - throw ::std::runtime_error("Path::nodes() fell off"); - } - const ::std::vector& nodes() const { - return ((Path*)this)->nodes(); - } - - PathNode& operator[](int idx) { if(idx>=0) return nodes()[idx]; else return nodes()[size()+idx]; } - const PathNode& operator[](int idx) const { return (*(Path*)this)[idx]; } - - Ordering ord(const Path& x) const; - bool operator==(const Path& x) const { return ord(x) == OrdEqual; } - bool operator!=(const Path& x) const { return ord(x) != OrdEqual; } - bool operator<(const Path& x) const { return ord(x) != OrdLess; } - - void print_pretty(::std::ostream& os, bool is_type_context, bool is_debug=false) const; - friend ::std::ostream& operator<<(::std::ostream& os, const Path& path); -private: - static void resolve_args_nl(::std::vector& nodes, ::std::function fcn); - - void check_param_counts(const GenericParams& params, bool expect_params, PathNode& node); -public: - void bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector& args={}); - void bind_function(const Function& ent, const ::std::vector& args={}) { - (void)args; - m_binding = PathBinding::make_Function({&ent}); - } - - void bind(::AST::PathBinding pb) { - m_binding = mv$(pb); - } -}; - -} // namespace AST - -#endif diff --git a/gcc/rust/mrustc_parser/ast/pattern.cpp b/gcc/rust/mrustc_parser/ast/pattern.cpp deleted file mode 100644 index 72087d9..0000000 --- a/gcc/rust/mrustc_parser/ast/pattern.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/pattern.cpp - * - AST::Pattern support/implementation code - */ -#include "../common.hpp" -#include "ast.hpp" -#include "pattern.hpp" - -namespace AST { - -::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val) -{ - TU_MATCH(Pattern::Value, (val), (e), - (Invalid, - os << "/*BAD PAT VAL*/"; - ), - (Integer, - switch(e.type) - { - case CORETYPE_BOOL: - os << (e.value ? "true" : "false"); - break; - case CORETYPE_F32: - case CORETYPE_F64: - BUG(Span(), "Hit F32/f64 in printing pattern literal"); - break; - default: - os << e.value; - break; - } - ), - (Float, - switch(e.type) - { - case CORETYPE_BOOL: - os << (e.value ? "true" : "false"); - break; - case CORETYPE_ANY: - case CORETYPE_F32: - case CORETYPE_F64: - os << e.value; - break; - default: - BUG(Span(), "Hit integer in printing pattern literal"); - break; - } - ), - (String, - os << "\"" << e << "\""; - ), - (ByteString, - os << "b\"" << e.v << "\""; - ), - (Named, - os << e; - ) - ) - return os; -} -::std::ostream& operator<<(::std::ostream& os, const Pattern::TuplePat& val) -{ - if( val.has_wildcard ) - { - os << val.start; - os << ".., "; - os << val.end; - } - else - { - os << val.start; - assert(val.end.size() == 0); - } - return os; -} -::std::ostream& operator<<(::std::ostream& os, const PatternBinding& pb) -{ - if( pb.m_mutable ) - os << "mut "; - switch(pb.m_type) - { - case PatternBinding::Type::MOVE: break; - case PatternBinding::Type::REF: os << "ref "; break; - case PatternBinding::Type::MUTREF: os << "ref mut "; break; - } - os << pb.m_name; - return os; -} -::std::ostream& operator<<(::std::ostream& os, const Pattern& pat) -{ - if( pat.m_binding.is_valid() ) { - os << pat.m_binding << " @ "; - } - TU_MATCH(Pattern::Data, (pat.m_data), (ent), - (MaybeBind, - os << ent.name << "?"; - ), - (Macro, - os << *ent.inv; - ), - (Any, - os << "_"; - ), - (Box, - os << "box " << *ent.sub; - ), - (Ref, - os << "&" << (ent.mut ? "mut " : "") << *ent.sub; - ), - (Value, - os << ent.start; - if( ! ent.end.is_Invalid() ) - os << " ... " << ent.end; - ), - (Tuple, - os << "(" << ent << ")"; - ), - (StructTuple, - os << ent.path << " (" << ent.tup_pat << ")"; - ), - (Struct, - os << ent.path << " {" << ent.sub_patterns << "}"; - ), - (Slice, - os << "["; - os << ent.sub_pats; - os << "]"; - ), - (SplitSlice, - os << "["; - bool needs_comma = false; - if(ent.leading.size()) { - os << ent.leading; - needs_comma = true; - } - - if( needs_comma ) { - os << ", "; - } - if( ent.extra_bind.is_valid() ) - os << ent.extra_bind; - os << ".."; - needs_comma = true; - - if(ent.trailing.size()) { - if( needs_comma ) { - os << ", "; - } - os << ent.trailing; - } - os << "]"; - ) - ) - return os; -} - -Pattern::~Pattern() -{ -} - -AST::Pattern AST::Pattern::clone() const -{ - AST::Pattern rv; - rv.m_span = m_span; - rv.m_binding = PatternBinding(m_binding); - - struct H { - static ::std::unique_ptr clone_sp(const ::std::unique_ptr& p) { - return ::std::make_unique( p->clone() ); - } - static ::std::vector clone_list(const ::std::vector& list) { - ::std::vector rv; - rv.reserve(list.size()); - for(const auto& p : list) - rv.push_back( p.clone() ); - return rv; - } - static TuplePat clone_tup(const TuplePat& p) { - return TuplePat { - H::clone_list(p.start), - p.has_wildcard, - H::clone_list(p.end) - }; - } - static AST::Pattern::Value clone_val(const AST::Pattern::Value& v) { - TU_MATCH(::AST::Pattern::Value, (v), (e), - (Invalid, return Value(e);), - (Integer, return Value(e);), - (Float, return Value(e);), - (String, return Value(e);), - (ByteString, return Value(e);), - (Named, return Value::make_Named( AST::Path(e) );) - ) - throw ""; - } - }; - - TU_MATCH(Pattern::Data, (m_data), (e), - (Any, - rv.m_data = Data::make_Any(e); - ), - (MaybeBind, - rv.m_data = Data::make_MaybeBind(e); - ), - (Macro, - rv.m_data = Data::make_Macro({ ::std::make_unique( e.inv->clone() ) }); - ), - (Box, - rv.m_data = Data::make_Box({ H::clone_sp(e.sub) }); - ), - (Ref, - rv.m_data = Data::make_Ref({ e.mut, H::clone_sp(e.sub) }); - ), - (Value, - rv.m_data = Data::make_Value({ H::clone_val(e.start), H::clone_val(e.end) }); - ), - (Tuple, - rv.m_data = Data::make_Tuple( H::clone_tup(e) ); - ), - (StructTuple, - rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_tup(e.tup_pat) }); - ), - (Struct, - ::std::vector< ::std::pair< ::std::string, Pattern> > sps; - for(const auto& sp : e.sub_patterns) - sps.push_back( ::std::make_pair(sp.first, sp.second.clone()) ); - rv.m_data = Data::make_Struct({ ::AST::Path(e.path), mv$(sps) }); - ), - (Slice, - rv.m_data = Data::make_Slice({ H::clone_list(e.sub_pats) }); - ), - (SplitSlice, - rv.m_data = Data::make_SplitSlice({ H::clone_list(e.leading), e.extra_bind, H::clone_list(e.trailing) }); - ) - ) - - return rv; -} - -} // namespace AST - diff --git a/gcc/rust/mrustc_parser/ast/pattern.hpp b/gcc/rust/mrustc_parser/ast/pattern.hpp deleted file mode 100644 index 40cfa92..0000000 --- a/gcc/rust/mrustc_parser/ast/pattern.hpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * ast/pattern.hpp - * - AST Pattern representation - */ - -#ifndef _AST__PATTERN_HPP_INCLUDED_ -#define _AST__PATTERN_HPP_INCLUDED_ - -#include -#include -#include -#include -#include -#include "path.hpp" - -namespace AST { - -using ::std::unique_ptr; -using ::std::move; -class MacroInvocation; - -class PatternBinding -{ -public: - enum class Type { - MOVE, - REF, - MUTREF, - }; - Ident m_name; - Type m_type; - bool m_mutable; - unsigned int m_slot; - - PatternBinding(): - m_name({}, ""), - m_type(Type::MOVE), - m_mutable(false), - m_slot( ~0u ) - {} - PatternBinding(Ident name, Type ty, bool ismut): - m_name(::std::move(name)), - m_type(ty), - m_mutable(ismut), - m_slot( ~0u ) - {} - - PatternBinding(PatternBinding&& x) = default; - PatternBinding(const PatternBinding& x) = default; - PatternBinding& operator=(PatternBinding&& x) = default; - - bool is_valid() const { return m_name.name != ""; } -}; - -class Pattern -{ -public: - TAGGED_UNION(Value, Invalid, - (Invalid, struct {}), - (Integer, struct { - enum eCoreType type; - uint64_t value; // Signed numbers are encoded as 2's complement - }), - (Float, struct { - enum eCoreType type; - double value; - }), - (String, ::std::string), - (ByteString, struct { ::std::string v; }), - (Named, Path) - ); - - struct TuplePat { - ::std::vector start; - bool has_wildcard; - ::std::vector end; - }; - - TAGGED_UNION(Data, Any, - (MaybeBind, struct { Ident name; } ), - (Macro, struct { unique_ptr<::AST::MacroInvocation> inv; } ), - (Any, struct { } ), - (Box, struct { unique_ptr sub; } ), - (Ref, struct { bool mut; unique_ptr sub; } ), - (Value, struct { Value start; Value end; } ), - (Tuple, TuplePat ), - (StructTuple, struct { Path path; TuplePat tup_pat; } ), - (Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; bool is_exhaustive; } ), - (Slice, struct { ::std::vector sub_pats; }), - (SplitSlice, struct { ::std::vector leading; PatternBinding extra_bind; ::std::vector trailing; } ) - ); -private: - Span m_span; - PatternBinding m_binding; - Data m_data; - -public: - virtual ~Pattern(); - - Pattern() - {} - Pattern(Pattern&&) = default; - Pattern& operator=(Pattern&&) = default; - - Pattern(Span sp, Data dat): - m_span( mv$(sp) ), - m_data( mv$(dat) ) - {}; - - struct TagMaybeBind {}; - Pattern(TagMaybeBind, Span sp, Ident name): - m_span( mv$(sp) ), - m_data( Data::make_MaybeBind({ mv$(name) }) ) - {} - - struct TagMacro {}; - Pattern(TagMacro, Span sp, unique_ptr<::AST::MacroInvocation> inv): - m_span( mv$(sp) ), - m_data( Data::make_Macro({ mv$(inv) }) ) - {} - - struct TagBind {}; - Pattern(TagBind, Span sp, Ident name, PatternBinding::Type ty = PatternBinding::Type::MOVE, bool is_mut=false): - m_span( mv$(sp) ), - m_binding( PatternBinding(mv$(name), ty, is_mut) ) - {} - - struct TagBox {}; - Pattern(TagBox, Span sp, Pattern sub): - m_span( mv$(sp) ), - m_data( Data::make_Box({ unique_ptr(new Pattern(mv$(sub))) }) ) - {} - - struct TagValue {}; - Pattern(TagValue, Span sp, Value val, Value end = Value()): - m_span( mv$(sp) ), - m_data( Data::make_Value({ ::std::move(val), ::std::move(end) }) ) - {} - - - struct TagReference {}; - Pattern(TagReference, Span sp, bool is_mutable, Pattern sub_pattern): - m_span( mv$(sp) ), - m_data( Data::make_Ref( /*Data::Data_Ref */ { - is_mutable, unique_ptr(new Pattern(::std::move(sub_pattern))) - }) ) - { - } - - struct TagTuple {}; - Pattern(TagTuple, Span sp, ::std::vector pats): - m_span( mv$(sp) ), - m_data( Data::make_Tuple( TuplePat { mv$(pats), false, {} } ) ) - {} - Pattern(TagTuple, Span sp, TuplePat pat): - m_span( mv$(sp) ), - m_data( Data::make_Tuple( mv$(pat) ) ) - {} - - struct TagNamedTuple {}; - Pattern(TagNamedTuple, Span sp, Path path, ::std::vector pats): - m_span( mv$(sp) ), - m_data( Data::make_StructTuple( { mv$(path), TuplePat { mv$(pats), false, {} } } ) ) - {} - Pattern(TagNamedTuple, Span sp, Path path, TuplePat pat = TuplePat { {}, false, {} }): - m_span( mv$(sp) ), - m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(pat) } ) ) - {} - - struct TagStruct {}; - Pattern(TagStruct, Span sp, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns, bool is_exhaustive): - m_span( mv$(sp) ), - m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) ) - {} - - // Mutators - void set_bind(Ident name, PatternBinding::Type type, bool is_mut) { - m_binding = PatternBinding(mv$(name), type, is_mut); - } - - - const Span& span() const { return m_span; } - - Pattern clone() const; - - // Accessors - PatternBinding& binding() { return m_binding; } - const PatternBinding& binding() const { return m_binding; } - Data& data() { return m_data; } - const Data& data() const { return m_data; } - Path& path() { return m_data.as_StructTuple().path; } - const Path& path() const { return m_data.as_StructTuple().path; } - - friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat); -}; - -extern ::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val); -extern ::std::ostream& operator<<(::std::ostream& os, const Pattern::TuplePat& val); - -}; - -#endif diff --git a/gcc/rust/mrustc_parser/ast/types.cpp b/gcc/rust/mrustc_parser/ast/types.cpp deleted file mode 100644 index 98bc6ee..0000000 --- a/gcc/rust/mrustc_parser/ast/types.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * types.cpp - * - Backing code for the TypeRef class - * - * Handles a chunk of type resolution (merging) and matching/comparing types - */ -#include "types.hpp" -#include "ast/ast.hpp" -#include -#include - -/// Mappings from internal type names to the core type enum -static const struct { - const char* name; - enum eCoreType type; -} CORETYPES[] = { - // NOTE: Sorted - {"_", CORETYPE_ANY}, - {"bool", CORETYPE_BOOL}, - {"char", CORETYPE_CHAR}, - {"f32", CORETYPE_F32}, - {"f64", CORETYPE_F64}, - {"i128", CORETYPE_I128}, - {"i16", CORETYPE_I16}, - {"i32", CORETYPE_I32}, - {"i64", CORETYPE_I64}, - {"i8", CORETYPE_I8}, - {"int", CORETYPE_INT}, - {"isize", CORETYPE_INT}, - {"str", CORETYPE_STR}, - {"u128", CORETYPE_U128}, - {"u16", CORETYPE_U16}, - {"u32", CORETYPE_U32}, - {"u64", CORETYPE_U64}, - {"u8", CORETYPE_U8}, - {"uint", CORETYPE_UINT}, - {"usize", CORETYPE_UINT}, -}; - -enum eCoreType coretype_fromstring(const ::std::string& name) -{ - for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++) - { - if( name < CORETYPES[i].name ) - break; - if( name == CORETYPES[i].name ) - return CORETYPES[i].type; - } - return CORETYPE_INVAL; -} - -const char* coretype_name(const eCoreType ct ) { - switch(ct) - { - case CORETYPE_INVAL:return "INVAL"; - case CORETYPE_ANY: return "_"; - case CORETYPE_CHAR: return "char"; - case CORETYPE_STR: return "str"; - case CORETYPE_BOOL: return "bool"; - case CORETYPE_UINT: return "usize"; - case CORETYPE_INT: return "isize"; - case CORETYPE_U8: return "u8"; - case CORETYPE_I8: return "i8"; - case CORETYPE_U16: return "u16"; - case CORETYPE_I16: return "i16"; - case CORETYPE_U32: return "u32"; - case CORETYPE_I32: return "i32"; - case CORETYPE_U64: return "u64"; - case CORETYPE_I64: return "i64"; - case CORETYPE_U128: return "u128"; - case CORETYPE_I128: return "i128"; - case CORETYPE_F32: return "f32"; - case CORETYPE_F64: return "f64"; - } - DEBUG("Unknown core type?! " << ct); - return "NFI"; -} - -Type_Function::Type_Function(const Type_Function& other): - is_unsafe(other.is_unsafe), - m_abi(other.m_abi), - m_rettype( box$( other.m_rettype->clone() ) ) -{ - for( const auto& at : other.m_arg_types ) - m_arg_types.push_back( at.clone() ); -} - -Ordering Type_Function::ord(const Type_Function& x) const -{ - Ordering rv; - - rv = ::ord(m_abi, x.m_abi); - if(rv != OrdEqual) return rv; - rv = ::ord(m_arg_types, x.m_arg_types); - if(rv != OrdEqual) return rv; - return (*m_rettype).ord( *x.m_rettype ); -} - -TypeRef::~TypeRef() -{ -} - -TypeRef TypeRef::clone() const -{ - struct H { - static ::std::vector< ::TypeRef> clone_ty_vec(const ::std::vector& x) { - ::std::vector rv; - rv.reserve(x.size()); - for(const auto& t : x) - rv.push_back( t.clone() ); - return rv; - } - }; - switch( m_data.tag() ) - { - case TypeData::TAGDEAD: assert(!"Copying a destructed type"); - #define _COPY(VAR) case TypeData::TAG_##VAR: return TypeRef(m_span, TypeData::make_##VAR(m_data.as_##VAR()) ); break; - #define _CLONE(VAR, ...) case TypeData::TAG_##VAR: { auto& old = m_data.as_##VAR(); return TypeRef(m_span, TypeData::make_##VAR(__VA_ARGS__) ); } break; - _COPY(None) - _COPY(Any) - _COPY(Bang) - _CLONE(Macro, { old.inv.clone() }) - //case TypeData::TAG_Macro: assert( !"Copying an unexpanded type macro" ); - _COPY(Unit) - _COPY(Primitive) - _COPY(Function) - _CLONE(Tuple, { H::clone_ty_vec(old.inner_types) }) - _CLONE(Borrow, { AST::LifetimeRef(old.lifetime), old.is_mut, box$(old.inner->clone()) }) - _CLONE(Pointer, { old.is_mut, box$(old.inner->clone()) }) - _CLONE(Array, { box$(old.inner->clone()), old.size }) - _COPY(Generic) - _COPY(Path) - _COPY(TraitObject) - _COPY(ErasedType) - #undef _COPY - #undef _CLONE - } - throw ""; -} - -Ordering Type_TraitPath::ord(const Type_TraitPath& x) const -{ - Ordering rv; - - rv = ::ord( this->path, x.path ); - if(rv != OrdEqual) return rv; - - return rv; -} -Ordering TypeRef::ord(const TypeRef& x) const -{ - Ordering rv; - - rv = ::ord( (unsigned)m_data.tag(), (unsigned)x.m_data.tag() ); - if(rv != OrdEqual) return rv; - - TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent), - (None, return OrdEqual;), - (Macro, throw CompileError::BugCheck("TypeRef::ord - unexpanded macro");), - (Any, return OrdEqual;), - (Unit, return OrdEqual;), - (Bang, return OrdEqual;), - (Primitive, - return ::ord( (unsigned)ent.core_type, (unsigned)x_ent.core_type ); - ), - (Function, - return ent.info.ord( x_ent.info ); - ), - (Tuple, - return ::ord(ent.inner_types, x_ent.inner_types); - ), - (Borrow, - rv = ::ord(ent.is_mut, x_ent.is_mut); - if(rv != OrdEqual) return rv; - return (*ent.inner).ord(*x_ent.inner); - ), - (Pointer, - rv = ::ord(ent.is_mut, x_ent.is_mut); - if(rv != OrdEqual) return rv; - return (*ent.inner).ord(*x_ent.inner); - ), - (Array, - rv = (*ent.inner).ord( *x_ent.inner ); - if(rv != OrdEqual) return rv; - if(ent.size.get()) - { - throw ::std::runtime_error("TODO: Sized array comparisons"); - } - return OrdEqual; - ), - (Generic, - return ::ord(ent.name, x_ent.name); - ), - (Path, - return ent.path.ord( x_ent.path ); - ), - (TraitObject, - return ::ord(ent.traits, x_ent.traits); - ), - (ErasedType, - return ::ord(ent.traits, x_ent.traits); - ) - ) - throw ::std::runtime_error(FMT("BUGCHECK - Unhandled TypeRef class '" << m_data.tag() << "'")); -} - -::std::ostream& operator<<(::std::ostream& os, const eCoreType ct) { - return os << coretype_name(ct); -} - -void TypeRef::print(::std::ostream& os, bool is_debug/*=false*/) const -{ - //os << "TypeRef("; - #define _(VAR, ...) case TypeData::TAG_##VAR: { const auto &ent = this->m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; - switch(this->m_data.tag()) - { - case TypeData::TAGDEAD: throw ""; - _(None, - os << "!!"; - ) - _(Any, - os << "_"; - ) - _(Bang, - os << "!"; - ) - _(Macro, - os << ent.inv; - ) - _(Unit, - os << "()"; - ) - _(Primitive, - os << ent.core_type; - ) - _(Function, - if( ent.info.m_abi != "" ) - os << "extern \"" << ent.info.m_abi << "\" "; - os << "fn ("; - for( const auto& arg : ent.info.m_arg_types ) - { - arg.print(os, is_debug); - os << ", "; - } - os << ") -> " << *ent.info.m_rettype; - ) - _(Tuple, - os << "( "; - for( const auto& it : ent.inner_types ) - { - it.print(os, is_debug); - os << ", "; - } - os << ")"; - ) - _(Borrow, - os << "&" << (ent.is_mut ? "mut " : ""); - ent.inner->print(os, is_debug); - ) - _(Pointer, - os << "*" << (ent.is_mut ? "mut" : "const"); - ent.inner->print(os, is_debug); - ) - _(Array, - os << "["; - ent.inner->print(os, is_debug); - if( ent.size.get() ) - os << "; " << *ent.size; - os << "]"; - ) - _(Generic, - if(is_debug) - os << "/* arg */ "; - os << ent.name; - if(is_debug) - os << "/*"< - -#include "../common.hpp" -#include "coretypes.hpp" -#include "ast/path.hpp" -#include "ast/macro.hpp" -#include - -namespace AST { -class ExprNode; -class Expr; -class LifetimeParam; -} - -namespace AST { - - // Defined here for dependency reasons - class HigherRankedBounds - { - public: - ::std::vector m_lifetimes; - //::std::vector m_types; - //::std::vector m_bounds; - - bool empty() const { - return m_lifetimes.empty(); - } - - friend ::std::ostream& operator<<(::std::ostream& os, const HigherRankedBounds& x); - }; - - class LifetimeRef - { - static const uint16_t BINDING_STATIC = 0xFFFF; - static const uint16_t BINDING_UNBOUND = 0xFFFE; - static const uint16_t BINDING_INFER = 0xFFFD; - - Ident m_name; - uint16_t m_binding; - - LifetimeRef(Ident name, uint32_t binding): - m_name( ::std::move(name) ), - m_binding( binding ) - { - } - public: - LifetimeRef(): - LifetimeRef("", BINDING_INFER) - { - } - LifetimeRef(Ident name): - LifetimeRef(::std::move(name), BINDING_UNBOUND) - { - } - static LifetimeRef new_static() { - return LifetimeRef("static", BINDING_STATIC); - } - - void set_binding(uint16_t b) { assert(m_binding == BINDING_UNBOUND); m_binding = b; } - bool is_unbound() const { return m_binding == BINDING_UNBOUND; } - bool is_infer() const { return m_binding == BINDING_INFER; } - - const Ident& name() const { return m_name; } - Ordering ord(const LifetimeRef& x) const { return ::ord(m_name.name, x.m_name.name); } - bool operator==(const LifetimeRef& x) const { return ord(x) == OrdEqual; } - bool operator!=(const LifetimeRef& x) const { return ord(x) != OrdEqual; } - bool operator<(const LifetimeRef& x) const { return ord(x) == OrdLess; }; - - friend ::std::ostream& operator<<(::std::ostream& os, const LifetimeRef& x); - }; -} - -class PrettyPrintType -{ - const TypeRef& m_type; -public: - PrettyPrintType(const TypeRef& ty): - m_type(ty) - {} - - void print(::std::ostream& os) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v); -}; - -struct TypeArgRef -{ - ::std::string name; - unsigned int level; - const AST::GenericParams* params; -}; - -struct Type_Function -{ - AST::HigherRankedBounds hrbs; - bool is_unsafe; - ::std::string m_abi; - ::std::unique_ptr m_rettype; - ::std::vector m_arg_types; - bool is_variadic; - - Type_Function() {} - Type_Function(AST::HigherRankedBounds hrbs, bool is_unsafe, ::std::string abi, ::std::unique_ptr ret, ::std::vector args, bool is_variadic): - hrbs(mv$(hrbs)), - is_unsafe(is_unsafe), - m_abi(mv$(abi)), - m_rettype(mv$(ret)), - m_arg_types(mv$(args)), - is_variadic(is_variadic) - {} - Type_Function(Type_Function&& other) = default; - Type_Function(const Type_Function& other); - - Ordering ord(const Type_Function& x) const; -}; - -struct Type_TraitPath -{ - AST::HigherRankedBounds hrbs; - AST::Path path; - - Ordering ord(const Type_TraitPath& x) const; -}; - -TAGGED_UNION(TypeData, None, - (None, struct { }), - (Any, struct { }), - (Bang, struct { }), - (Unit, struct { }), - (Macro, struct { - ::AST::MacroInvocation inv; - }), - (Primitive, struct { - enum eCoreType core_type; - }), - (Function, struct { - Type_Function info; - }), - (Tuple, struct { - ::std::vector inner_types; - }), - (Borrow, struct { - AST::LifetimeRef lifetime; - bool is_mut; - ::std::unique_ptr inner; - }), - (Pointer, struct { - bool is_mut; - ::std::unique_ptr inner; - }), - (Array, struct { - ::std::unique_ptr inner; - ::std::shared_ptr size; - }), - (Generic, struct { - ::std::string name; - unsigned int index; - }), - (Path, struct { - AST::Path path; - }), - (TraitObject, struct { - ::std::vector traits; - ::std::vector lifetimes; - }), - (ErasedType, struct { - ::std::vector traits; - ::std::vector lifetimes; - }) - ); - -/// A type -class TypeRef -{ - Span m_span; -public: - TypeData m_data; - - ~TypeRef(); - - TypeRef(TypeRef&& other) = default; - TypeRef& operator=(TypeRef&& other) = default; - - #if 1 - TypeRef(const TypeRef& other) = delete; - TypeRef& operator=(const TypeRef& other) = delete; - #else - TypeRef(const TypeRef& other): m_span(other.m_span) { - *this = other.clone(); - } - TypeRef& operator=(const TypeRef& other) { - m_data = mv$(other.clone().m_data); - return *this; - } - #endif - - TypeRef(Span sp): - m_span( mv$(sp) ), - m_data( TypeData::make_Any({}) ) - {} - TypeRef(Span sp, TypeData data): - m_span( mv$(sp) ), - m_data( mv$(data) ) - {} - - struct TagInvalid {}; - TypeRef(TagInvalid, Span sp): - m_span(mv$(sp)), - m_data(TypeData::make_None({})) - {} - - struct TagMacro {}; - TypeRef(TagMacro, ::AST::MacroInvocation inv): - m_span(inv.span()), - m_data(TypeData::make_Macro({mv$(inv)})) - {} - - struct TagUnit {}; // unit maps to a zero-length tuple, just easier to type - TypeRef(TagUnit, Span sp): - m_span(mv$(sp)), - m_data(TypeData::make_Unit({})) - {} - - struct TagPrimitive {}; - TypeRef(TagPrimitive, Span sp, enum eCoreType type): - m_span(mv$(sp)), - m_data(TypeData::make_Primitive({type})) - {} - TypeRef(Span sp, enum eCoreType type): - m_span(mv$(sp)), - m_data(TypeData::make_Primitive({type})) - {} - - struct TagTuple {}; - TypeRef(TagTuple , Span sp, ::std::vector inner_types): - m_span(mv$(sp)), - m_data(TypeData::make_Tuple({::std::move(inner_types)})) - {} - struct TagFunction {}; - TypeRef(TagFunction, Span sp, AST::HigherRankedBounds hrbs, bool is_unsafe, ::std::string abi, ::std::vector args, bool is_variadic, TypeRef ret): - m_span(mv$(sp)), - m_data(TypeData::make_Function({ Type_Function( mv$(hrbs), is_unsafe, abi, box$(ret), mv$(args), is_variadic ) })) - {} - - struct TagReference {}; - TypeRef(TagReference , Span sp, AST::LifetimeRef lft, bool is_mut, TypeRef inner_type): - m_span(mv$(sp)), - m_data(TypeData::make_Borrow({ ::std::move(lft), is_mut, ::make_unique_ptr(mv$(inner_type)) })) - {} - struct TagPointer {}; - TypeRef(TagPointer , Span sp, bool is_mut, TypeRef inner_type): - m_span(mv$(sp)), - m_data(TypeData::make_Pointer({ is_mut, ::make_unique_ptr(mv$(inner_type)) })) - {} - struct TagSizedArray {}; - TypeRef(TagSizedArray , Span sp, TypeRef inner_type, ::std::shared_ptr size): - m_span(mv$(sp)), - m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), mv$(size) })) - {} - struct TagUnsizedArray {}; - TypeRef(TagUnsizedArray , Span sp, TypeRef inner_type): - m_span(mv$(sp)), - m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), ::std::shared_ptr() })) - {} - - struct TagArg {}; - TypeRef(TagArg, Span sp, ::std::string name, unsigned int binding = ~0u): - m_span( mv$(sp) ), - m_data(TypeData::make_Generic({ name, binding })) - {} - TypeRef(Span sp, ::std::string name, unsigned int binding = ~0u): - TypeRef(TagArg(), mv$(sp), mv$(name), binding) - {} - - struct TagPath {}; - TypeRef(TagPath, Span sp, AST::Path path): - m_span(mv$(sp)), - m_data(TypeData::make_Path({ ::std::move(path) })) - {} - TypeRef(Span sp, AST::Path path): - TypeRef(TagPath(), mv$(sp), mv$(path)) - {} - - TypeRef( Span sp, ::std::vector traits, ::std::vector lifetimes ): - m_span(mv$(sp)), - m_data(TypeData::make_TraitObject({ ::std::move(traits), mv$(lifetimes) })) - {} - - - const Span& span() const { return m_span; } - - bool is_valid() const { return ! m_data.is_None(); } - - bool is_unbounded() const { return m_data.is_Any(); } - bool is_wildcard() const { return m_data.is_Any(); } - - bool is_unit() const { return m_data.is_Unit(); } - bool is_primitive() const { return m_data.is_Primitive(); } - - bool is_path() const { return m_data.is_Path(); } - const AST::Path& path() const { return m_data.as_Path().path; } - AST::Path& path() { return m_data.as_Path().path; } - - bool is_type_param() const { return m_data.is_Generic(); } - const ::std::string& type_param() const { return m_data.as_Generic().name; } - - bool is_reference() const { return m_data.is_Borrow(); } - bool is_pointer() const { return m_data.is_Pointer(); } - bool is_tuple() const { return m_data.is_Tuple(); } - - TypeRef clone() const; - - const TypeRef& inner_type() const { - TU_MATCH_DEF(TypeData, (m_data), (e), - ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ), - (Borrow, return *e.inner; ), - (Pointer, return *e.inner; ), - (Array, return *e.inner; ) - ) - } - TypeRef& inner_type() { - TU_MATCH_DEF(TypeData, (m_data), (e), - ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ), - (Borrow, return *e.inner; ), - (Pointer, return *e.inner; ), - (Array, return *e.inner; ) - ) - } - - Ordering ord(const TypeRef& x) const; - bool operator==(const TypeRef& x) const { return ord(x) == OrdEqual; } - bool operator!=(const TypeRef& x) const { return ord(x) != OrdEqual; } - bool operator<(const TypeRef& x) const { return ord(x) == OrdLess; }; - - void print(::std::ostream& os, bool is_debug=false) const; - - PrettyPrintType print_pretty() const { return PrettyPrintType(*this); } - - friend class PrettyPrintType; - - friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr); -}; - -#endif // TYPES_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/gcc-interface-test/gcc-interface.cc b/gcc/rust/mrustc_parser/gcc-interface-test/gcc-interface.cc deleted file mode 100644 index 31a212a..0000000 --- a/gcc/rust/mrustc_parser/gcc-interface-test/gcc-interface.cc +++ /dev/null @@ -1,434 +0,0 @@ -// gcc interface main - do stuff here - -#include "common/common-target.h" -#include "config.h" -#include "convert.h" -#include "coretypes.h" -#include "debug.h" -#include "diagnostic.h" -#include "fold-const.h" -#include "gimple-expr.h" -#include "gimplify.h" -#include "langhooks-def.h" -#include "langhooks.h" -#include "opts.h" -#include "stor-layout.h" -#include "system.h" -#include "target.h" -#include "tree.h" - -#include - -#include "rust-c-interface.h" - -/* Language-dependent contents of a type. */ -// seems to be a "gengtype" of some kind -struct GTY(()) lang_type { - char dummy; -}; - -/* Language-dependent contents of a decl. */ - -struct GTY(()) lang_decl { - char dummy; -}; - -/* Language-dependent contents of an identifier. This must include a - tree_identifier. */ - -struct GTY(()) lang_identifier { - struct tree_identifier common; -}; - -/* The resulting tree type. */ -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? - ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) - lang_tree_node { - union tree_node GTY((tag("0"), - desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; -}; - -/* We don't use language_function. */ -struct GTY(()) language_function { - int dummy; -}; - -/* Option information we need to pass to rust_create_grs. */ - -static const char* rust_pkgpath = NULL; -static const char* rust_prefix = NULL; -static const char* rust_relative_import_path = NULL; -static const char* rust_c_header = NULL; - -/* Language hooks. */ - -static bool grs_langhook_init(void) { - build_common_tree_nodes(false); - - /* I don't know why this has to be done explicitly. */ - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - // not currently relevant - /* We must create the grs IR after calling build_common_tree_nodes - (because Gorust::define_builtin_function_trees refers indirectly - to, e.g., unsigned_char_type_node) but before calling - build_common_builtin_nodes (because it calls, indirectly, - rust_type_for_size). */ - /* struct rust_create_grs_args args; - args.int_type_size = INT_TYPE_SIZE; - args.pointer_size = POINTER_SIZE; - args.pkgpath = rust_pkgpath; - args.prefix = rust_prefix; - args.relative_import_path = rust_relative_import_path; - args.c_header = rust_c_header; - args.check_divide_by_zero = rust_check_divide_zero; - args.check_divide_overflow = rust_check_divide_overflow; - args.compiling_runtime = rust_compiling_runtime; - args.debug_escape_level = rust_debug_escape_level; - args.debug_escape_hash = rust_debug_escape_hash; - args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096; - args.debug_optimization = rust_debug_optimization; - args.linemap = rust_get_linemap(); - args.backend = rust_get_backend(); - rust_create_grs(&args);*/ - - build_common_builtin_nodes(); - - /* The default precision for floating point numbers. This is used - for floating point constants with abstract type. This may - eventually be controllable by a command line option. */ - mpfr_set_default_prec(128); - - /* Rust uses exceptions. */ - using_eh_for_cleanups(); - - // maybe get rid of this? - rdot_init(); - - return true; -} - -/* Initialize the options structure before parsing options. */ -static void grs_langhook_init_options_struct(struct gcc_options* opts) { - /* Go says that signed overflow is precisely defined. */ - opts->x_flag_wrapv = 1; - - /* We default to using strict aliasing, since Go pointers are safe. - This is turned off for code that imports the "unsafe" package, - because using unsafe.pointer violates C style aliasing - requirements. */ - opts->x_flag_strict_aliasing = 1; - - /* Default to avoiding range issues for complex multiply and - divide. */ - opts->x_flag_complex_method = 2; - - /* The builtin math functions should not set errno. */ - opts->x_flag_errno_math = 0; - opts->frontend_set_flag_errno_math = true; - - /* Turn on stack splitting if possible? */ - // no definition for that anymore, apparently - /* if (targetm_common.supports_split_stack(false, opts)) - opts->x_flag_split_stack = 1; */ - - /* Exceptions are used to handle recovering from panics. */ - opts->x_flag_exceptions = 1; - opts->x_flag_non_call_exceptions = 1; - - // nope, don't need this because no gc - /* We need to keep pointers live for the garbage collector. */ - //opts->x_flag_keep_gc_roots_live = 1; - - /* Go programs expect runtime.Callers to work, and that uses - libbacktrace that uses debug info. Set the debug info level to 1 - by default. In post_options we will set the debug type if the - debug info level was not set back to 0 on the command line. */ - opts->x_debug_info_level = DINFO_LEVEL_TERSE; -} - -// doesn't seem to be needed, currently -/* Infrastructure for a vector of char * pointers. */ -/* typedef const char* rust_char_p;*/ - -/* The list of directories to search after all the Go specific - directories have been searched. */ -/* static vec rust_search_dirs;*/ - -/* Handle grs specific options. Return 0 if we didn't do anything. */ -static bool grs_langhook_handle_option(size_t scode, const char* arg ATTRIBUTE_UNUSED, - int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, - const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - enum opt_code code = (enum opt_code)scode; - bool ret = true; - - // ignore options... - switch (code) { - - default: - /* Just return 1 to indicate that the option is valid. */ - break; - } - - return ret; -} - -/* Run after parsing options. */ -static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { - - if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT) - flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD; - - /* We turn on stack splitting if we can. */ - if (!global_options_set.x_flag_split_stack && targetm_common.supports_split_stack(false, - &global_options)) - global_options.x_flag_split_stack = 1; - - /* If stack splitting is turned on, and the user did not explicitly - request function partitioning, turn off partitioning, as it - confuses the linker when trying to handle partitioned split-stack - code that calls a non-split-stack function. */ - if (global_options.x_flag_split_stack && global_options.x_flag_reorder_blocks_and_partition - && !global_options_set.x_flag_reorder_blocks_and_partition) - global_options.x_flag_reorder_blocks_and_partition = 0; - - /* Returning false means that the backend should be used. */ - return false; -} - -static void grs_langhook_parse_file(void) { - //grs_parse_input_files(in_fnames, num_in_fnames, flag_syntax_only, rust_require_return_statement); - - /* Final processing of globals and early debug info generation. */ - //rust_write_globals(); - - // loop through all input file names - for (size_t idx = 0; idx < num_in_fnames; idx++) { - // get input file string for index - const char* in = in_fnames[idx]; - GRS_current_infname = xstrdup(in); - GRS_current_infile = basename(GRS_current_infname); - grs_do_compile(in); // calls lexer? - } -} - -static tree grs_langhook_type_for_size(unsigned int bits ATTRIBUTE_UNUSED, - int unsignedp ATTRIBUTE_UNUSED) { - /* tree type; - if (unsignedp) { - if (bits == INT_TYPE_SIZE) - type = unsigned_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = unsigned_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_unsigned_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_unsigned_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_unsigned_type_node; - else - type = make_unsigned_type(bits); - } else { - if (bits == INT_TYPE_SIZE) - type = integer_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = signed_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_integer_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_integer_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_integer_type_node; - else - type = make_signed_type(bits); - } - return type;*/ - - gcc_unreachable(); - - return NULL_TREE; -} - -static tree grs_langhook_type_for_mode(enum machine_mode mode, int unsignedp) { - if (mode == TYPE_MODE(float_type_node)) - return float_type_node; - - if (mode == TYPE_MODE(double_type_node)) - return double_type_node; - - if (mode == TYPE_MODE(integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - - if (mode == TYPE_MODE(long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - - if (COMPLEX_MODE_P(mode)) { - if (mode == TYPE_MODE(complex_float_type_node)) - return complex_float_type_node; - - if (mode == TYPE_MODE(complex_double_type_node)) - return complex_double_type_node; - - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - - if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) - return complex_integer_type_node; - } - - /* gcc unreachable */ - return NULL; -} - -/* Record a builtin function. We just ignore builtin functions. */ -static tree grs_langhook_builtin_function(tree decl) { - return decl; -} - -/* Return true if we are in the global binding level. */ -static bool grs_langhook_global_bindings_p(void) { - return current_function_decl == NULL_TREE; -} - -/* Push a declaration into the current binding level. We can't - usefully implement this since we don't want to convert from tree - back to one of our internal data structures. I think the only way - this is used is to record a decl which is to be returned by - getdecls, and we could implement it for that purpose if - necessary. */ -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL; -} - -/* This hook is used to get the current list of declarations as trees. - We don't support that; instead we use the write_globals hook. This - can't simply crash because it is called by -gstabs. */ -static tree grs_langhook_getdecls(void) { - gcc_unreachable(); - return NULL; -} - -/* Write out globals. */ -static void grs_langhook_write_globals(void) { - // pass off to middle-end function, basically - dot_pass_WriteGlobals(); -} - -static unsigned int grs_langhook_option_lang_mask(void) { - return CL_Rust; -} - -/* Return a decl for the exception personality function. The function - itself is implemented in librust/runtime/rust-unwind.c. */ -static tree grs_langhook_eh_personality(void) { - static tree personality_decl; - - if (personality_decl == NULL_TREE) { - personality_decl = build_personality_function("gccrs"); - grs_preserve_from_gc(personality_decl); - } - - return personality_decl; -} - -/* Rust-specific gimplification. We need to gimplify - CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle - it. */ -static int grs_langhook_gimplify_expr(tree* expr_p ATTRIBUTE_UNUSED, - gimple_seq* pre_p ATTRIBUTE_UNUSED, gimple_seq* post_p ATTRIBUTE_UNUSED) { - if (TREE_CODE(*expr_p) == CALL_EXPR && CALL_EXPR_STATIC_CHAIN(*expr_p) != NULL_TREE) - gimplify_expr(&CALL_EXPR_STATIC_CHAIN(*expr_p), pre_p, post_p, is_gimple_val, fb_rvalue); - - /* Often useful to use debug_tree here to see what's going on because every gimplification calls - this. */ - //debug_tree(*expr_p) - return GS_UNHANDLED; -} - -/* Functions called directly by the generic backend. */ -tree convert(tree type, tree expr) { - if (type == error_mark_node || expr == error_mark_node || TREE_TYPE(expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE(expr)) - return expr; - - if (TYPE_MAIN_VARIANT(type) == TYPE_MAIN_VARIANT(TREE_TYPE(expr))) - return fold_convert(type, expr); - - switch (TREE_CODE(type)) { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert(type, expr); - case INTEGER_TYPE: - return fold(convert_to_integer(type, expr)); - case POINTER_TYPE: - return fold(convert_to_pointer(type, expr)); - case REAL_TYPE: - return fold(convert_to_real(type, expr)); - case COMPLEX_TYPE: - return fold(convert_to_complex(type, expr)); - default: - break; - } - - gcc_unreachable(); -} - -static GTY(()) tree grs_gc_root; -void grs_preserve_from_gc(tree t) { - grs_gc_root = tree_cons(NULL_TREE, t, grs_gc_root); -} - -// seems to be unused -/* Convert an identifier for use in an error message. */ -/* const char* rust_localize_identifier(const char* ident) { - return identifier_to_locale(ident); -}*/ - -/* The language hooks data structure. This is the main interface between the GCC front-end - * and the GCC middle-end/back-end. A list of language hooks could be found in - * /langhooks.h - */ -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -#undef LANG_HOOKS_OPTION_LANG_MASK -#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -#undef LANG_HOOKS_HANDLE_OPTION -#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -#undef LANG_HOOKS_WRITE_GLOBALS -#undef LANG_HOOKS_GIMPLIFY_EXPR -#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT grs_langhook_init -#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask -#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct -#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option -#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl -#define LANG_HOOKS_GETDECLS grs_langhook_getdecls -#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals -#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr -#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality - -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -#include "gt-rust-rs-lang.h" -#include "gtype-rust.h" -// TODO: something to do with this, maybe diff --git a/gcc/rust/mrustc_parser/gcc-interface-test/rust-c-interface.h b/gcc/rust/mrustc_parser/gcc-interface-test/rust-c-interface.h deleted file mode 100644 index 2a8eecf..0000000 --- a/gcc/rust/mrustc_parser/gcc-interface-test/rust-c-interface.h +++ /dev/null @@ -1,58 +0,0 @@ -// mrustc-GCC interface header - -#ifndef RUST_C_INT_H -#define RUST_C_INT_H - -/* Functions defined in the Rust frontend proper called by the GCC - interface. TODO move around */ - -extern int rust_enable_dump(const char*); -extern int rust_enable_optimize(const char*, int); - -extern void grs_add_search_path(const char*); - -struct rust_create_grs_args { - int int_type_size; - int pointer_size; - const char* pkgpath; - const char* prefix; - const char* relative_import_path; - const char* c_header; - //Backend* backend; - //Linemap* linemap; - bool check_divide_by_zero; - bool check_divide_overflow; - bool compiling_runtime; - int debug_escape_level; - const char* debug_escape_hash; - int64_t nil_check_size_threshold; - bool debug_optimization; -}; - -extern void rust_create_gsr(const struct rust_create_grs_args*); - -extern void grs_parse_input_files(const char**, unsigned int, bool only_check_syntax, - bool require_return_statement); -extern void grs_write_globals(void); - -/* Functions defined in the GCC interface called by the Rust frontend - proper. TODO: move around */ - -extern void grs_preserve_from_gc(tree); - -extern bool saw_errors(void); - -extern const char* rust_localize_identifier(const char*); - -extern unsigned int rust_field_alignment(tree); - -extern void rust_imported_unsafe(void); - -extern void rust_write_export_data(const char*, unsigned int); - -extern const char* rust_read_export_data(int, off_t, char**, size_t*, int*); - -extern GTY(()) tree rust_non_zero_struct; - - -#endif \ No newline at end of file diff --git a/gcc/rust/mrustc_parser/parse/common.hpp b/gcc/rust/mrustc_parser/parse/common.hpp deleted file mode 100644 index 49499c8..0000000 --- a/gcc/rust/mrustc_parser/parse/common.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/common.hpp - * - Common definitions used by the parser - */ -#ifndef PARSE_COMMON_HPP_INCLUDED -#define PARSE_COMMON_HPP_INCLUDED -#include -#include "tokenstream.hpp" -#include "../ast/ast.hpp" - -#define GET_TOK(tok, lex) ((tok = lex.getToken()).type()) -#define PUTBACK(tok, lex) lex.putback( ::std::move(tok) ) -#define LOOK_AHEAD(lex) (lex.lookahead(0)) -#define GET_CHECK_TOK(tok, lex, exp) do {\ - if((tok = lex.getToken()).type() != exp) { \ - DEBUG("GET_CHECK_TOK " << __FILE__ << ":" << __LINE__); \ - throw ParseError::Unexpected(lex, tok, Token(exp));\ - }\ -} while(0) -#define CHECK_TOK(tok, exp) do {\ - if(tok.type() != exp) { \ - DEBUG("CHECK_TOK " << __FILE__ << ":" << __LINE__); \ - throw ParseError::Unexpected(lex, tok, Token(exp));\ - } \ -} while(0) - -// --- path.cpp -enum eParsePathGenericMode -{ - PATH_GENERIC_NONE, - PATH_GENERIC_EXPR, - PATH_GENERIC_TYPE -}; -extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines -extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode); -extern ::std::vector Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode); -extern AST::PathParams Parse_Path_GenericList(TokenStream& lex); - - -extern AST::HigherRankedBounds Parse_HRB(TokenStream& lex); -extern AST::AttributeList Parse_ItemAttrs(TokenStream& lex); -extern void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out); -extern AST::Attribute Parse_MetaItem(TokenStream& lex); -extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::std::string name, TokenStream& lex); -extern TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list = true); -extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable); - -extern void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl); -extern void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::AttributeList meta_items); -extern ::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::AttributeList meta_items); -extern void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod); - - -extern AST::Expr Parse_Expr(TokenStream& lex); -extern AST::Expr Parse_ExprBlock(TokenStream& lex); -extern AST::ExprNodeP Parse_Expr0(TokenStream& lex); -extern AST::ExprNodeP Parse_ExprVal(TokenStream& lex); -extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); -extern AST::ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence); -extern AST::ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr& local_mod, bool& add_silence_if_end); -extern AST::ExprNodeP Parse_Stmt(TokenStream& lex); - -// unwrapped = Exclude the enclosing brackets (used by macro parse code) -extern TokenTree Parse_TT(TokenStream& lex, bool unwrapped); - - -extern bool Parse_IsTokValue(eTokenType tok_type); - -#endif // PARSE_COMMON_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/parse/eTokenType.enum.h b/gcc/rust/mrustc_parser/parse/eTokenType.enum.h deleted file mode 100644 index 5104142..0000000 --- a/gcc/rust/mrustc_parser/parse/eTokenType.enum.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/eTokenType.enum.h - * - Multi-include file for defining the eTokenType enum - */ -_(TOK_NULL) -_(TOK_EOF) - -_(TOK_NEWLINE) -_(TOK_WHITESPACE) -_(TOK_COMMENT) - -_(TOK_INTERPOLATED_IDENT) -_(TOK_INTERPOLATED_PATH) -_(TOK_INTERPOLATED_TYPE) -_(TOK_INTERPOLATED_PATTERN) -_(TOK_INTERPOLATED_EXPR) -_(TOK_INTERPOLATED_STMT) -_(TOK_INTERPOLATED_BLOCK) -_(TOK_INTERPOLATED_META) -_(TOK_INTERPOLATED_ITEM) - -// Value tokens -_(TOK_IDENT) -_(TOK_LIFETIME) -_(TOK_INTEGER) -_(TOK_CHAR) -_(TOK_FLOAT) -_(TOK_STRING) -_(TOK_BYTESTRING) - -_(TOK_HASH) - -_(TOK_UNDERSCORE) - -// Symbols -_(TOK_PAREN_OPEN) _(TOK_PAREN_CLOSE) -_(TOK_BRACE_OPEN) _(TOK_BRACE_CLOSE) -_(TOK_LT) _(TOK_GT) -_(TOK_SQUARE_OPEN) _(TOK_SQUARE_CLOSE) -_(TOK_COMMA) -_(TOK_SEMICOLON) -_(TOK_COLON) -_(TOK_DOUBLE_COLON) -_(TOK_STAR) _(TOK_AMP) -_(TOK_PIPE) - -_(TOK_FATARROW) // => -_(TOK_THINARROW) // -> -_(TOK_THINARROW_LEFT) // <- - -_(TOK_PLUS) _(TOK_DASH) -_(TOK_EXCLAM) -_(TOK_PERCENT) -_(TOK_SLASH) - -_(TOK_DOT) -_(TOK_DOUBLE_DOT) -_(TOK_TRIPLE_DOT) - -_(TOK_EQUAL) -_(TOK_PLUS_EQUAL) -_(TOK_DASH_EQUAL) -_(TOK_PERCENT_EQUAL) -_(TOK_SLASH_EQUAL) -_(TOK_STAR_EQUAL) -_(TOK_AMP_EQUAL) -_(TOK_PIPE_EQUAL) - -_(TOK_DOUBLE_EQUAL) -_(TOK_EXCLAM_EQUAL) -_(TOK_GTE) -_(TOK_LTE) - -_(TOK_DOUBLE_AMP) -_(TOK_DOUBLE_PIPE) -_(TOK_DOUBLE_LT) -_(TOK_DOUBLE_GT) -_(TOK_DOUBLE_LT_EQUAL) -_(TOK_DOUBLE_GT_EQUAL) - -_(TOK_DOLLAR) - -_(TOK_QMARK) -_(TOK_AT) -_(TOK_TILDE) -_(TOK_BACKSLASH) -_(TOK_CARET) -_(TOK_CARET_EQUAL) -_(TOK_BACKTICK) - -// Reserved Words -// NOTE: ORDERING MATTERS! _PUB must be the first, and no non-rword tokens should follow -_(TOK_RWORD_PUB) -_(TOK_RWORD_PRIV) -_(TOK_RWORD_MUT) -_(TOK_RWORD_CONST) -_(TOK_RWORD_STATIC) -_(TOK_RWORD_UNSAFE) -_(TOK_RWORD_EXTERN) - -_(TOK_RWORD_CRATE) -_(TOK_RWORD_MOD) -_(TOK_RWORD_STRUCT) -_(TOK_RWORD_ENUM) -_(TOK_RWORD_TRAIT) -_(TOK_RWORD_FN) -_(TOK_RWORD_USE) -_(TOK_RWORD_IMPL) -_(TOK_RWORD_TYPE) - -_(TOK_RWORD_WHERE) -_(TOK_RWORD_AS) - -_(TOK_RWORD_LET) -_(TOK_RWORD_MATCH) -_(TOK_RWORD_IF) -_(TOK_RWORD_ELSE) -_(TOK_RWORD_LOOP) -_(TOK_RWORD_WHILE) -_(TOK_RWORD_FOR) -_(TOK_RWORD_IN) -_(TOK_RWORD_DO) - -_(TOK_RWORD_CONTINUE) -_(TOK_RWORD_BREAK) -_(TOK_RWORD_RETURN) -_(TOK_RWORD_YIELD) -_(TOK_RWORD_BOX) -_(TOK_RWORD_REF) - -_(TOK_RWORD_FALSE) -_(TOK_RWORD_TRUE) -_(TOK_RWORD_SELF) -_(TOK_RWORD_SUPER) - -_(TOK_RWORD_PROC) -_(TOK_RWORD_MOVE) - -_(TOK_RWORD_ABSTRACT) -_(TOK_RWORD_FINAL) -_(TOK_RWORD_PURE) -_(TOK_RWORD_OVERRIDE) -_(TOK_RWORD_VIRTUAL) - -_(TOK_RWORD_ALIGNOF) -_(TOK_RWORD_OFFSETOF) -_(TOK_RWORD_SIZEOF) -_(TOK_RWORD_TYPEOF) - -_(TOK_RWORD_BE) -_(TOK_RWORD_UNSIZED) diff --git a/gcc/rust/mrustc_parser/parse/expr.cpp b/gcc/rust/mrustc_parser/parse/expr.cpp deleted file mode 100644 index 5194e1d..0000000 --- a/gcc/rust/mrustc_parser/parse/expr.cpp +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/expr.cpp - * - Expression (i.e. code) parsing - * - * Start points: - * - Parse_ExprBlockNode : Parses a block - * - Parse_Stmt : Parse a single statement - * - Parse_Expr0 : Parse a single expression - */ -#include "parseerror.hpp" -#include -#include -#include "common.hpp" -#include -#include "tokentree.hpp" -#include "interpolated_fragment.hpp" - -using AST::ExprNode; -using AST::ExprNodeP; -// TODO: Use a ProtoSpan instead of a point span? -static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_span(lex.point_span()); return ExprNodeP(en); } -#define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__)) - -//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); // common.hpp -//ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr& local_mod, bool& add_silence_if_end); -//ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence); -ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon); -//ExprNodeP Parse_Stmt(TokenStream& lex); // common.hpp -ExprNodeP Parse_Stmt_Let(TokenStream& lex); -ExprNodeP Parse_Expr0(TokenStream& lex); -ExprNodeP Parse_IfStmt(TokenStream& lex); -ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime); -ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime); -ExprNodeP Parse_Expr_Match(TokenStream& lex); -ExprNodeP Parse_Expr1(TokenStream& lex); -ExprNodeP Parse_ExprMacro(TokenStream& lex, AST::Path tok); - -AST::Expr Parse_Expr(TokenStream& lex) -{ - return ::AST::Expr( Parse_Expr0(lex) ); -} - -AST::Expr Parse_ExprBlock(TokenStream& lex) -{ - return ::AST::Expr( Parse_ExprBlockNode(lex) ); -} - -ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/) -{ - TRACE_FUNCTION; - Token tok; - - ::std::vector nodes; - - ::std::shared_ptr local_mod; - - GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - - bool last_value_yielded = false; - while( LOOK_AHEAD(lex) != TOK_BRACE_CLOSE ) - { - last_value_yielded = false; - DEBUG("tok = " << tok); - - // NOTE: Doc comments can appear within a function and apply to the function - if( lex.parse_state().parent_attrs ) - { - Parse_ParentAttrs(lex, *lex.parse_state().parent_attrs); - } - if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) - break; - - bool add_silence_if_end = false; - // `add_silence_if_end` indicates that the statement had a semicolon. - auto rv = Parse_ExprBlockLine_WithItems(lex, local_mod, add_silence_if_end); - if( rv ) - { - // Set to TRUE if there was no semicolon after a statement - last_value_yielded = !add_silence_if_end; - nodes.push_back( mv$(rv) ); - } - else { - assert( !add_silence_if_end ); - last_value_yielded = false; - } - } - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - - return NEWNODE( AST::ExprNode_Block, is_unsafe, last_value_yielded, mv$(nodes), mv$(local_mod) ); -} - -/// Parse a single line in a block, handling items added to the local module -/// -/// - If an item was parsed, this returns an empty ExprNodeP -ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr& local_mod, bool& add_silence_if_end) -{ - Token tok; - - auto item_attrs = Parse_ItemAttrs(lex); - GET_TOK(tok, lex); - - // `union Ident` - contextual keyword - if( tok.type() == TOK_IDENT && tok.str() == "union" && lex.lookahead(0) == TOK_IDENT ) { - PUTBACK(tok, lex); - if( !local_mod ) { - local_mod = lex.parse_state().get_current_mod().add_anon(); - } - Parse_Mod_Item(lex, *local_mod, mv$(item_attrs)); - return ExprNodeP(); - } - - if( tok.type() == TOK_IDENT && tok.str() == "macro_rules" && lex.lookahead(0) == TOK_EXCLAM ) - { - // Special case - create a local module if macro_rules! is seen - // - Allows correct scoping of defined macros - if( !local_mod ) { - local_mod = lex.parse_state().get_current_mod().add_anon(); - } - } - - switch(tok.type()) - { - // Items: - case TOK_RWORD_PUB: - // NOTE: Allowed, but doesn't do much - case TOK_RWORD_TYPE: - case TOK_RWORD_USE: - case TOK_RWORD_EXTERN: - case TOK_RWORD_CONST: - case TOK_RWORD_STATIC: - case TOK_RWORD_STRUCT: - case TOK_RWORD_ENUM: - case TOK_RWORD_TRAIT: - case TOK_RWORD_IMPL: - case TOK_RWORD_FN: - case TOK_RWORD_MOD: - PUTBACK(tok, lex); - if( !local_mod ) { - local_mod = lex.parse_state().get_current_mod().add_anon(); - } - Parse_Mod_Item(lex, *local_mod, mv$(item_attrs)); - return ExprNodeP(); - // 'unsafe' - Check if the next token isn't a `{`, if so it's an item. Otherwise, fall through - case TOK_RWORD_UNSAFE: - if( LOOK_AHEAD(lex) != TOK_BRACE_OPEN ) - { - PUTBACK(tok, lex); - if( !local_mod ) { - local_mod = lex.parse_state().get_current_mod().add_anon(); - } - Parse_Mod_Item(lex, *local_mod, mv$(item_attrs)); - return ExprNodeP(); - } - // fall - default: { - PUTBACK(tok, lex); - auto rv = Parse_ExprBlockLine(lex, &add_silence_if_end); - if( rv ) { - rv->set_attrs( mv$(item_attrs) ); - } - else if( item_attrs.m_items.size() > 0 ) { - // TODO: Is this an error? - Attributes on a expression that didn't yeild a node. - // - They should have applied to the item that was parsed? - } - else { - } - return rv; - } break; - } -} - -/// Parse a single line from a block -/// -/// Handles: -/// - Block-level constructs (with lifetime annotations) -/// - use/extern/const/let -ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence) -{ - Token tok; - ExprNodeP ret; - - if( GET_TOK(tok, lex) == TOK_LIFETIME ) - { - // Lifetimes can only precede loops... and blocks? - ::std::string lifetime = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_COLON); - - switch( GET_TOK(tok, lex) ) - { - case TOK_RWORD_LOOP: - return NEWNODE( AST::ExprNode_Loop, lifetime, Parse_ExprBlockNode(lex) ); - case TOK_RWORD_WHILE: - return Parse_WhileStmt(lex, lifetime); - case TOK_RWORD_FOR: - return Parse_ForStmt(lex, lifetime); - //case TOK_RWORD_IF: - // return Parse_IfStmt(lex); - //case TOK_RWORD_MATCH: - // return Parse_Expr_Match(lex); - //case TOK_BRACE_OPEN: - // PUTBACK(tok, lex); - // return Parse_ExprBlockNode(lex); - - default: - throw ParseError::Unexpected(lex, tok); - } - } - else - { - switch( tok.type() ) - { - case TOK_INTERPOLATED_BLOCK: - return tok.take_frag_node(); - case TOK_SEMICOLON: - // Return a NULL expression, nothing here. - return nullptr; - - // let binding - case TOK_RWORD_LET: - ret = Parse_Stmt_Let(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - return ret; - - // Blocks that don't need semicolons - // NOTE: If these are followed by a small set of tokens (`.` and `?`) then they are actually the start of an expression - // HACK: Parse here, but if the next token is one of the set store in a TOK_INTERPOLATED_EXPR and invoke the statement parser - case TOK_RWORD_LOOP: - ret = NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) ); - if(0) - case TOK_RWORD_WHILE: - ret = Parse_WhileStmt(lex, ""); - if(0) - case TOK_RWORD_FOR: - ret = Parse_ForStmt(lex, ""); - if(0) - case TOK_RWORD_IF: - ret = Parse_IfStmt(lex); - if(0) - case TOK_RWORD_MATCH: - ret = Parse_Expr_Match(lex); - if(0) - case TOK_RWORD_UNSAFE: - ret = Parse_ExprBlockNode(lex, true); - if(0) - case TOK_BRACE_OPEN: - { PUTBACK(tok, lex); ret = Parse_ExprBlockNode(lex); } - - if( lex.lookahead(0) == TOK_DOT || lex.lookahead(0) == TOK_QMARK ) { - lex.putback( Token(Token::TagTakeIP(), InterpolatedFragment(InterpolatedFragment::EXPR, ret.release())) ); - return Parse_ExprBlockLine_Stmt(lex, *add_silence); - } - - if( LOOK_AHEAD(lex) == TOK_SEMICOLON ) { - GET_TOK(tok, lex); - *add_silence = true; - } - - return ret; - - // Flow control - case TOK_RWORD_RETURN: - case TOK_RWORD_CONTINUE: - case TOK_RWORD_BREAK: { - PUTBACK(tok, lex); - auto ret = Parse_Stmt(lex); - if( LOOK_AHEAD(lex) == TOK_EOF ) { - } - else if( GET_TOK(tok, lex) != TOK_SEMICOLON ) { - CHECK_TOK(tok, TOK_BRACE_CLOSE); - PUTBACK(tok, lex); - } - else { - // return/continue/break don't need silencing - } - return ret; - } - - case TOK_IDENT: - if( lex.lookahead(0) == TOK_EXCLAM ) - { - // If a braced macro invocation is the first part of a statement, don't expect a semicolon - if( lex.lookahead(1) == TOK_BRACE_OPEN || (lex.lookahead(1) == TOK_IDENT && lex.lookahead(2) == TOK_BRACE_OPEN) ) { - lex.getToken(); - return Parse_ExprMacro(lex, tok.str()); - } - } - // Fall through to the statement code - default: - PUTBACK(tok, lex); - return Parse_ExprBlockLine_Stmt(lex, *add_silence); - } - } -} - -ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon) -{ - Token tok; - auto ret = Parse_Stmt(lex); - // If this expression statement wasn't followed by a semicolon, then it's yielding its value out of the block. - // - I.e. The block should be ending - if( GET_TOK(tok, lex) != TOK_SEMICOLON ) { - // - Allow TOK_EOF for macro expansion. - if( tok.type() == TOK_EOF ) - ; - else - CHECK_TOK(tok, TOK_BRACE_CLOSE); - PUTBACK(tok, lex); - } - else { - has_semicolon = true; - } - return ret; -} - -/// While loop (either as a statement, or as part of an expression) -ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime) -{ - Token tok; - - if( GET_TOK(tok, lex) == TOK_RWORD_LET ) { - auto pat = Parse_Pattern(lex, true); // Refutable pattern - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - ExprNodeP val; - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - val = Parse_Expr0(lex); - } - return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::WHILELET, - ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) ); - } - else { - PUTBACK(tok, lex); - ExprNodeP cnd; - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - cnd = Parse_Expr1(lex); - } - return NEWNODE( AST::ExprNode_Loop, lifetime, ::std::move(cnd), Parse_ExprBlockNode(lex) ); - } -} -/// For loop (either as a statement, or as part of an expression) -ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime) -{ - Token tok; - - // Irrefutable pattern - AST::Pattern pat = Parse_Pattern(lex, false); - GET_CHECK_TOK(tok, lex, TOK_RWORD_IN); - ExprNodeP val; - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - val = Parse_Expr0(lex); - } - return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::FOR, - ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) ); -} -/// Parse an 'if' statement -// Note: TOK_RWORD_IF has already been eaten -ExprNodeP Parse_IfStmt(TokenStream& lex) -{ - TRACE_FUNCTION; - - Token tok; - ExprNodeP cond; - AST::Pattern pat; - bool if_let = false; - - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - if( GET_TOK(tok, lex) == TOK_RWORD_LET ) { - if_let = true; - // Refutable pattern - pat = Parse_Pattern(lex, true); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - cond = Parse_Expr0(lex); - } - else { - PUTBACK(tok, lex); - cond = Parse_Expr0(lex); - } - } - - // Contents - ExprNodeP code = Parse_ExprBlockNode(lex); - - // Handle else: - ExprNodeP altcode; - if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) - { - // Recurse for 'else if' - if( GET_TOK(tok, lex) == TOK_RWORD_IF ) { - altcode = Parse_IfStmt(lex); - } - // - or get block - else { - PUTBACK(tok, lex); - altcode = Parse_ExprBlockNode(lex); - } - } - // - or nothing - else { - PUTBACK(tok, lex); - } - - if( if_let ) - return NEWNODE( AST::ExprNode_IfLet, ::std::move(pat), ::std::move(cond), ::std::move(code), ::std::move(altcode) ); - else - return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) ); -} -/// "match" block -ExprNodeP Parse_Expr_Match(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - CLEAR_PARSE_FLAG(lex, disallow_struct_literal); - // 1. Get expression - ExprNodeP switch_val; - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - switch_val = Parse_Expr1(lex); - } - //ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) ); - GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - - ::std::vector< AST::ExprNode_Match_Arm > arms; - do { - if( GET_TOK(tok, lex) == TOK_BRACE_CLOSE ) - break; - PUTBACK(tok, lex); - AST::ExprNode_Match_Arm arm; - - arm.m_attrs = Parse_ItemAttrs(lex); - - do { - // Refutable pattern - arm.m_patterns.push_back( Parse_Pattern(lex, true) ); - } while( GET_TOK(tok, lex) == TOK_PIPE ); - - if( tok.type() == TOK_RWORD_IF ) - { - arm.m_cond = Parse_Expr1(lex); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_FATARROW); - - arm.m_code = Parse_Stmt(lex); - - arms.push_back( ::std::move(arm) ); - - if( GET_TOK(tok, lex) == TOK_COMMA ) - continue; - PUTBACK(tok, lex); - - } while( 1 ); - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) ); -} - -/// Parses the 'stmt' fragment specifier -/// - Flow control -/// - Expressions -ExprNodeP Parse_Stmt(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - switch(GET_TOK(tok, lex)) - { - case TOK_INTERPOLATED_STMT: - return tok.take_frag_node(); - // Duplicated here for the :stmt pattern fragment. - case TOK_RWORD_LET: - return Parse_Stmt_Let(lex); - case TOK_RWORD_RETURN: { - ExprNodeP val; - switch(LOOK_AHEAD(lex)) - { - case TOK_EOF: - case TOK_SEMICOLON: - case TOK_COMMA: - case TOK_BRACE_CLOSE: - case TOK_PAREN_CLOSE: - case TOK_SQUARE_CLOSE: - break; - default: - val = Parse_Expr0(lex); - break; - } - return NEWNODE( AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", ::std::move(val) ); - } - case TOK_RWORD_CONTINUE: - case TOK_RWORD_BREAK: - { - AST::ExprNode_Flow::Type type; - switch(tok.type()) - { - case TOK_RWORD_CONTINUE: type = AST::ExprNode_Flow::CONTINUE; break; - case TOK_RWORD_BREAK: type = AST::ExprNode_Flow::BREAK; break; - default: throw ParseError::BugCheck(/*lex,*/ "continue/break"); - } - ::std::string lifetime; - if( GET_TOK(tok, lex) == TOK_LIFETIME ) - { - lifetime = tok.str(); - GET_TOK(tok, lex); - } - ExprNodeP val; - switch(tok.type()) - { - case TOK_EOF: - case TOK_SEMICOLON: - case TOK_COMMA: - case TOK_BRACE_OPEN: - case TOK_BRACE_CLOSE: - case TOK_PAREN_CLOSE: - case TOK_SQUARE_CLOSE: - PUTBACK(tok, lex); - break; - default: - PUTBACK(tok, lex); - val = Parse_Expr1(lex); - break; - } - return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) ); - } - case TOK_BRACE_OPEN: - PUTBACK(tok, lex); - return Parse_ExprBlockNode(lex); - default: - PUTBACK(tok, lex); - return Parse_Expr0(lex); - } -} - -ExprNodeP Parse_Stmt_Let(TokenStream& lex) -{ - Token tok; - AST::Pattern pat = Parse_Pattern(lex, false); // irrefutable - TypeRef type { lex.point_span() }; - if( GET_TOK(tok, lex) == TOK_COLON ) { - type = Parse_Type(lex); - GET_TOK(tok, lex); - } - ExprNodeP val; - if( tok.type() == TOK_EQUAL ) { - val = Parse_Expr0(lex); - } - else { - PUTBACK(tok, lex); - } - return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), mv$(type), ::std::move(val) ); -} - -::std::vector Parse_ParenList(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - CLEAR_PARSE_FLAG(lex, disallow_struct_literal); - - ::std::vector rv; - GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); - if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE ) - { - PUTBACK(tok, lex); - do { - if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) { - GET_TOK(tok, lex); - break; - } - rv.push_back( Parse_Expr0(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - } - return rv; -} - -// 0: Assign -ExprNodeP Parse_Expr0(TokenStream& lex) -{ - //TRACE_FUNCTION; - Token tok; - - auto expr_attrs = Parse_ItemAttrs(lex); - - ExprNodeP rv = Parse_Expr1(lex); - auto op = AST::ExprNode_Assign::NONE; - switch( GET_TOK(tok, lex) ) - { - case TOK_PLUS_EQUAL: - op = AST::ExprNode_Assign::ADD; if(0) - case TOK_DASH_EQUAL: - op = AST::ExprNode_Assign::SUB; if(0) - case TOK_STAR_EQUAL: - op = AST::ExprNode_Assign::MUL; if(0) - case TOK_SLASH_EQUAL: - op = AST::ExprNode_Assign::DIV; if(0) - case TOK_PERCENT_EQUAL: - op = AST::ExprNode_Assign::MOD; if(0) - - case TOK_AMP_EQUAL: - op = AST::ExprNode_Assign::AND; if(0) - case TOK_PIPE_EQUAL: - op = AST::ExprNode_Assign::OR ; if(0) - case TOK_CARET_EQUAL: - op = AST::ExprNode_Assign::XOR; if(0) - - case TOK_DOUBLE_GT_EQUAL: - op = AST::ExprNode_Assign::SHR; if(0) - case TOK_DOUBLE_LT_EQUAL: - op = AST::ExprNode_Assign::SHL; if(0) - - case TOK_EQUAL: - op = AST::ExprNode_Assign::NONE; - rv = NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr0(lex) ); - rv->set_attrs(mv$(expr_attrs)); - return rv; - - default: - PUTBACK(tok, lex); - rv->set_attrs(mv$(expr_attrs)); - return rv; - } -} - - -#define LEFTASSOC(cur, _next, cases) \ -ExprNodeP _next(TokenStream& lex); \ -ExprNodeP cur(TokenStream& lex) \ -{ \ - ExprNodeP (*next)(TokenStream&) = _next;\ - ExprNodeP rv = next(lex); \ - while(true) \ - { \ - Token tok; \ - switch((tok = lex.getToken()).type()) \ - { \ - cases \ - default: \ - /*::std::cout << "<<" << #cur << ::std::endl; */\ - PUTBACK(tok, lex); \ - return rv; \ - } \ - } \ -} -bool Parse_IsTokValue(eTokenType tok_type) -{ - switch( tok_type ) - { - case TOK_DOUBLE_COLON: - case TOK_IDENT: - case TOK_INTEGER: - case TOK_FLOAT: - case TOK_STRING: - case TOK_RWORD_TRUE: - case TOK_RWORD_FALSE: - case TOK_RWORD_SELF: - case TOK_RWORD_SUPER: - case TOK_RWORD_BOX: - case TOK_RWORD_IN: - case TOK_PAREN_OPEN: - case TOK_SQUARE_OPEN: - - case TOK_INTERPOLATED_PATH: - case TOK_INTERPOLATED_EXPR: - - case TOK_PIPE: - case TOK_EXCLAM: - case TOK_DASH: - case TOK_STAR: - case TOK_AMP: - return true; - default: - return false; - } -} -ExprNodeP Parse_Expr1_1(TokenStream& lex); -ExprNodeP Parse_Expr1(TokenStream& lex) -{ - Token tok; - ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1; - - auto dest = next(lex); - if( lex.lookahead(0) == TOK_THINARROW_LEFT ) - { - GET_TOK(tok, lex); - auto val = Parse_Expr1(lex); - return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::PLACE_IN, mv$(dest), mv$(val)); - } - else - { - return dest; - } -} -ExprNodeP Parse_Expr1_2(TokenStream& lex); -// Very evil handling for '..' -ExprNodeP Parse_Expr1_1(TokenStream& lex) -{ - Token tok; - ExprNodeP (*next)(TokenStream&) = Parse_Expr1_2; - ExprNodeP left, right; - - // Inclusive range to a value - if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) { - right = next(lex); - return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, nullptr, mv$(right) ); - } - else { - PUTBACK(tok, lex); - } - - // Exclusive ranges - // - If NOT `.. `, parse a leading value - if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT ) - { - PUTBACK(tok, lex); - - left = next(lex); - - // - If NOT ` ..`, return the value - if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT ) - { - PUTBACK(tok, lex); - return ::std::move(left); - } - } - assert( tok.type() == TOK_DOUBLE_DOT ); - // If the next token is part of a value, parse that value - if( Parse_IsTokValue( LOOK_AHEAD(lex) ) ) - { - right = next(lex); - } - else - { - // Otherwise, leave `right` as nullptr - } - - return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) ); -} -LEFTASSOC(Parse_Expr1_2, Parse_Expr1_5, - case TOK_TRIPLE_DOT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) ); - break; -) -// 1: Bool OR -LEFTASSOC(Parse_Expr1_5, Parse_Expr2, - case TOK_DOUBLE_PIPE: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLOR, ::std::move(rv), next(lex)); - break; -) -// 2: Bool AND -LEFTASSOC(Parse_Expr2, Parse_Expr3, - case TOK_DOUBLE_AMP: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLAND, ::std::move(rv), next(lex)); - break; -) -// 3: (In)Equality -LEFTASSOC(Parse_Expr3, Parse_Expr4, - case TOK_DOUBLE_EQUAL: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPEQU, ::std::move(rv), next(lex)); - break; - case TOK_EXCLAM_EQUAL: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPNEQU, ::std::move(rv), next(lex)); - break; -) -// 4: Comparisons -LEFTASSOC(Parse_Expr4, Parse_Expr5, - case TOK_LT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLT, ::std::move(rv), next(lex)); - break; - case TOK_GT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGT, ::std::move(rv), next(lex)); - break; - case TOK_LTE: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLTE, ::std::move(rv), next(lex)); - break; - case TOK_GTE: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGTE, ::std::move(rv), next(lex)); - break; -) -// 5: Bit OR -LEFTASSOC(Parse_Expr5, Parse_Expr6, - case TOK_PIPE: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITOR, ::std::move(rv), next(lex)); - break; -) -// 6: Bit XOR -LEFTASSOC(Parse_Expr6, Parse_Expr7, - case TOK_CARET: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITXOR, ::std::move(rv), next(lex)); - break; -) -// 7: Bit AND -LEFTASSOC(Parse_Expr7, Parse_Expr8, - case TOK_AMP: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITAND, ::std::move(rv), next(lex)); - break; -) -// 8: Bit Shifts -LEFTASSOC(Parse_Expr8, Parse_Expr9, - case TOK_DOUBLE_LT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHL, ::std::move(rv), next(lex)); - break; - case TOK_DOUBLE_GT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHR, ::std::move(rv), next(lex)); - break; -) -// 9: Add / Subtract -LEFTASSOC(Parse_Expr9, Parse_Expr10, - case TOK_PLUS: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::ADD, ::std::move(rv), next(lex)); - break; - case TOK_DASH: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex)); - break; -) -// 10: Times / Divide / Modulo -LEFTASSOC(Parse_Expr10, Parse_Expr11, - case TOK_STAR: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MULTIPLY, ::std::move(rv), next(lex)); - break; - case TOK_SLASH: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::DIVIDE, ::std::move(rv), next(lex)); - break; - case TOK_PERCENT: - rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MODULO, ::std::move(rv), next(lex)); - break; -) -// 11: Cast -LEFTASSOC(Parse_Expr11, Parse_Expr12, - case TOK_RWORD_AS: - rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex, false) ); - break; -) -// 12: Type Ascription -ExprNodeP Parse_Expr13(TokenStream& lex); -ExprNodeP Parse_Expr12(TokenStream& lex) -{ - Token tok; - auto rv = Parse_Expr13(lex); - if(GET_TOK(tok, lex) == TOK_COLON) - { - rv = NEWNODE( AST::ExprNode_TypeAnnotation, mv$(rv), Parse_Type(lex) ); - } - else - { - PUTBACK(tok, lex); - } - return rv; -} -// 13: Unaries -ExprNodeP Parse_ExprFC(TokenStream& lex); -ExprNodeP Parse_Expr13(TokenStream& lex) -{ - Token tok; - switch(GET_TOK(tok, lex)) - { - case TOK_DASH: - return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::NEGATE, Parse_Expr12(lex) ); - case TOK_EXCLAM: - return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::INVERT, Parse_Expr12(lex) ); - case TOK_STAR: - return NEWNODE( AST::ExprNode_Deref, Parse_Expr12(lex) ); - case TOK_RWORD_BOX: - return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::BOX, Parse_Expr12(lex) ); - case TOK_RWORD_IN: { - ExprNodeP dest; - { - SET_PARSE_FLAG(lex, disallow_struct_literal); - dest = Parse_Expr1(lex); - } - auto val = Parse_ExprBlockNode(lex); - return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::PLACE_IN, mv$(dest), mv$(val)); - } - case TOK_DOUBLE_AMP: - // HACK: Split && into & & - lex.putback( Token(TOK_AMP) ); - case TOK_AMP: - if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) - return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REFMUT, Parse_Expr12(lex) ); - else { - PUTBACK(tok, lex); - return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, Parse_Expr12(lex) ); - } - default: - PUTBACK(tok, lex); - return Parse_ExprFC(lex); - } -} - -ExprNodeP Parse_ExprVal(TokenStream& lex); -ExprNodeP Parse_ExprFC(TokenStream& lex) -{ - ExprNodeP val = Parse_ExprVal(lex); - while(true) - { - Token tok; - switch(GET_TOK(tok, lex)) - { - case TOK_QMARK: - val = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::QMARK, mv$(val) ); - break; - - case TOK_PAREN_OPEN: - // Expression method call - PUTBACK(tok, lex); - val = NEWNODE( AST::ExprNode_CallObject, ::std::move(val), Parse_ParenList(lex) ); - break; - case TOK_SQUARE_OPEN: - val = NEWNODE( AST::ExprNode_Index, ::std::move(val), Parse_Expr0(lex) ); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - break; - case TOK_DOT: - // Field access / method call / tuple index - switch(GET_TOK(tok, lex)) - { - case TOK_IDENT: { - AST::PathNode path( mv$(tok.str()) , {}); - switch( GET_TOK(tok, lex) ) - { - case TOK_PAREN_OPEN: - PUTBACK(tok, lex); - val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) ); - break; - case TOK_DOUBLE_COLON: - GET_CHECK_TOK(tok, lex, TOK_LT); - path.args() = Parse_Path_GenericList(lex); - val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) ); - break; - default: - val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(path.name()) ); - PUTBACK(tok, lex); - break; - } - break; } - case TOK_INTEGER: - val = NEWNODE( AST::ExprNode_Field, ::std::move(val), FMT(tok.intval()) ); - break; - default: - throw ParseError::Unexpected(lex, mv$(tok)); - } - break; - default: - PUTBACK(tok, lex); - return val; - } - } -} - -ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path) -{ - TRACE_FUNCTION; - Token tok; - - // #![feature(relaxed_adts)] - if( LOOK_AHEAD(lex) == TOK_INTEGER ) - { - ::std::map nodes; - while( GET_TOK(tok, lex) == TOK_INTEGER ) - { - unsigned int ofs = static_cast(tok.intval()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - ExprNodeP val = Parse_Stmt(lex); - if( ! nodes.insert( ::std::make_pair(ofs, mv$(val)) ).second ) { - ERROR(lex.point_span(), E0000, "Duplicate index"); - } - - if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE ) - break; - CHECK_TOK(tok, TOK_COMMA); - } - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - ::std::vector items; - unsigned int i = 0; - for(auto& p : nodes) - { - if( p.first != i ) { - ERROR(lex.point_span(), E0000, "Missing index " << i); - } - items.push_back( mv$(p.second) ); - i ++; - } - - return NEWNODE( AST::ExprNode_CallPath, mv$(path), mv$(items) ); - } - - // Braced structure literal - // - A series of 0 or more pairs of : , - // - '..' - ::AST::ExprNode_StructLiteral::t_values items; - while( GET_TOK(tok, lex) == TOK_IDENT || tok.type() == TOK_HASH ) - { - ::AST::AttributeList attrs; // Note: Parse_ItemAttrs uses lookahead, so can't use it here. - if( tok.type() == TOK_HASH ) - { - PUTBACK(tok, lex); - attrs = Parse_ItemAttrs(lex); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_IDENT); - auto h = lex.getHygiene(); - auto name = mv$(tok.str()); - - ExprNodeP val; - if( lex.lookahead(0) != TOK_COLON ) - { - val = NEWNODE( AST::ExprNode_NamedValue, ::AST::Path(::AST::Path::TagRelative{}, h, { ::AST::PathNode(name) }) ); - } - else - { - GET_CHECK_TOK(tok, lex, TOK_COLON); - val = Parse_Stmt(lex); - } - items.push_back(::AST::ExprNode_StructLiteral::Ent { mv$(attrs), mv$(name), mv$(val) }); - - if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE ) - break; - CHECK_TOK(tok, TOK_COMMA); - } - ExprNodeP base_val; - if( tok.type() == TOK_DOUBLE_DOT ) - { - // default - base_val = Parse_Expr0(lex); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) ); -} - -ExprNodeP Parse_ExprVal_Closure(TokenStream& lex, bool is_move) -{ - TRACE_FUNCTION; - Token tok; - - ::std::vector< ::std::pair > args; - - while( GET_TOK(tok, lex) != TOK_PIPE ) - { - PUTBACK(tok, lex); - // Irrefutable pattern - AST::Pattern pat = Parse_Pattern(lex, false); - - TypeRef type { lex.point_span() }; - if( GET_TOK(tok, lex) == TOK_COLON ) - type = Parse_Type(lex); - else - PUTBACK(tok, lex); - - args.push_back( ::std::make_pair( ::std::move(pat), ::std::move(type) ) ); - - if( GET_TOK(tok, lex) != TOK_COMMA ) - break; - } - CHECK_TOK(tok, TOK_PIPE); - - auto rt = TypeRef(lex.point_span()); - if( GET_TOK(tok, lex) == TOK_THINARROW ) { - - if( GET_TOK(tok, lex) == TOK_EXCLAM ) { - rt = TypeRef(TypeRef::TagInvalid(), Span(tok.get_pos())); - } - else { - PUTBACK(tok, lex); - rt = Parse_Type(lex); - } - } - else - PUTBACK(tok, lex); - - auto code = Parse_Expr0(lex); - - return NEWNODE( AST::ExprNode_Closure, ::std::move(args), ::std::move(rt), ::std::move(code), is_move ); -} - -ExprNodeP Parse_ExprVal(TokenStream& lex) -{ - TRACE_FUNCTION; - - Token tok; - AST::Path path; - switch( GET_TOK(tok, lex) ) - { - case TOK_BRACE_OPEN: - PUTBACK(tok, lex); - return Parse_ExprBlockNode(lex); - - case TOK_INTERPOLATED_EXPR: - case TOK_INTERPOLATED_BLOCK: - return tok.take_frag_node(); - - - // Return/break/continue/... also parsed here (but recurses back up to actually handle them) - case TOK_RWORD_RETURN: - case TOK_RWORD_CONTINUE: - case TOK_RWORD_BREAK: - PUTBACK(tok, lex); - return Parse_Stmt(lex); - - case TOK_RWORD_LOOP: - return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) ); - case TOK_RWORD_WHILE: - return Parse_WhileStmt(lex, ""); - case TOK_RWORD_FOR: - return Parse_ForStmt(lex, ""); - case TOK_RWORD_MATCH: - return Parse_Expr_Match(lex); - case TOK_RWORD_IF: - return Parse_IfStmt(lex); - case TOK_RWORD_UNSAFE: - return Parse_ExprBlockNode(lex, true); - - // UFCS - case TOK_DOUBLE_LT: - case TOK_LT: - PUTBACK(tok, lex); - path = Parse_Path(lex, PATH_GENERIC_EXPR); - // Skip down to method - if(0) - case TOK_RWORD_SELF: - { - if( LOOK_AHEAD(lex) != TOK_DOUBLE_COLON ) { - return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") ); - } - else - { - PUTBACK(tok, lex); - path = Parse_Path(lex, PATH_GENERIC_EXPR); - } - } - if(0) - case TOK_RWORD_SUPER: - { - PUTBACK(tok, lex); - path = Parse_Path(lex, PATH_GENERIC_EXPR); - } - if(0) - case TOK_IDENT: - // Get path - { - PUTBACK(tok, lex); - path = Parse_Path(lex, false, PATH_GENERIC_EXPR); - } - if(0) - case TOK_INTERPOLATED_PATH: - { - path = mv$(tok.frag_path()); - } - if(0) - case TOK_DOUBLE_COLON: - path = Parse_Path(lex, true, PATH_GENERIC_EXPR); - DEBUG("path = " << path << ", lookahead=" << Token::typestr(lex.lookahead(0))); - // SKIP TARGET - switch( GET_TOK(tok, lex) ) - { - case TOK_EXCLAM: - return Parse_ExprMacro(lex, mv$(path)); - case TOK_PAREN_OPEN: - // Function call - PUTBACK(tok, lex); - return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), Parse_ParenList(lex) ); - case TOK_BRACE_OPEN: - if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) ) - return Parse_ExprVal_StructLiteral(lex, ::std::move(path)); - else - DEBUG("Not parsing struct literal"); - default: - // Value - PUTBACK(tok, lex); - return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) ); - } - case TOK_RWORD_MOVE: - GET_TOK(tok, lex); - if(tok.type() == TOK_PIPE) - return Parse_ExprVal_Closure(lex, true); - else if(tok.type() == TOK_DOUBLE_PIPE) { - lex.putback(Token(TOK_PIPE)); - return Parse_ExprVal_Closure(lex, true); - } - else { - CHECK_TOK(tok, TOK_PIPE); - } - case TOK_DOUBLE_PIPE: - lex.putback(Token(TOK_PIPE)); - case TOK_PIPE: - return Parse_ExprVal_Closure(lex, false); - case TOK_INTEGER: - return NEWNODE( AST::ExprNode_Integer, tok.intval(), tok.datatype() ); - case TOK_FLOAT: - return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() ); - case TOK_STRING: - return NEWNODE( AST::ExprNode_String, tok.str() ); - case TOK_BYTESTRING: - return NEWNODE( AST::ExprNode_ByteString, tok.str() ); - case TOK_RWORD_TRUE: - return NEWNODE( AST::ExprNode_Bool, true ); - case TOK_RWORD_FALSE: - return NEWNODE( AST::ExprNode_Bool, false ); - case TOK_PAREN_OPEN: - if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - { - DEBUG("Unit"); - return NEWNODE( AST::ExprNode_Tuple, ::std::vector() ); - } - else - { - CLEAR_PARSE_FLAG(lex, disallow_struct_literal); - PUTBACK(tok, lex); - - ExprNodeP rv = Parse_Expr0(lex); - if( GET_TOK(tok, lex) == TOK_COMMA ) { - ::std::vector ents; - ents.push_back( ::std::move(rv) ); - do { - if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - break; - PUTBACK(tok, lex); - ents.push_back( Parse_Expr0(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) ); - } - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return rv; - } - case TOK_SQUARE_OPEN: - if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE ) - { - // Empty literal - return NEWNODE( AST::ExprNode_Array, ::std::vector() ); - } - else - { - PUTBACK(tok, lex); - auto first = Parse_Expr0(lex); - if( GET_TOK(tok, lex) == TOK_SEMICOLON ) - { - // Repetiion - auto count = Parse_Expr0(lex); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - return NEWNODE( AST::ExprNode_Array, ::std::move(first), ::std::move(count) ); - } - else - { - ::std::vector items; - items.push_back( ::std::move(first) ); - while( tok.type() == TOK_COMMA ) - { - if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE ) - break; - else - PUTBACK(tok, lex); - items.push_back( Parse_Expr0(lex) ); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_SQUARE_CLOSE); - return NEWNODE( AST::ExprNode_Array, ::std::move(items) ); - } - } - throw ParseError::BugCheck(lex, "Array literal fell"); - default: - throw ParseError::Unexpected(lex, tok); - } -} -ExprNodeP Parse_ExprMacro(TokenStream& lex, AST::Path path) -{ - if( !path.is_trivial() ) { - TODO(lex.point_span(), "Support path macros - " << path); - } - - Token tok; - ::std::string name = path.m_class.is_Local() ? path.m_class.as_Local().name : path.nodes()[0].name(); - ::std::string ident; - if( GET_TOK(tok, lex) == TOK_IDENT ) { - ident = mv$(tok.str()); - } - else { - PUTBACK(tok, lex); - } - TokenTree tt = Parse_TT(lex, true); - if( tt.is_token() ) { - throw ParseError::Unexpected(lex, tt.tok()); - } - return NEWNODE(AST::ExprNode_Macro, mv$(name), mv$(ident), mv$(tt)); -} - -// Token Tree Parsing -TokenTree Parse_TT(TokenStream& lex, bool unwrapped) -{ - TokenTree rv; - TRACE_FUNCTION_FR("", rv); - - Token tok = lex.getToken(); - eTokenType closer = TOK_PAREN_CLOSE; - switch(tok.type()) - { - case TOK_PAREN_OPEN: - closer = TOK_PAREN_CLOSE; - break; - case TOK_SQUARE_OPEN: - closer = TOK_SQUARE_CLOSE; - break; - case TOK_BRACE_OPEN: - closer = TOK_BRACE_CLOSE; - break; - - case TOK_EOF: - case TOK_NULL: - case TOK_PAREN_CLOSE: - case TOK_SQUARE_CLOSE: - case TOK_BRACE_CLOSE: - throw ParseError::Unexpected(lex, tok); - default: - rv = TokenTree(lex.getHygiene(), mv$(tok) ); - return rv; - } - - ::std::vector items; - if( !unwrapped ) - items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) ); - while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF) - { - if( tok.type() == TOK_NULL ) - throw ParseError::Unexpected(lex, tok); - PUTBACK(tok, lex); - items.push_back(Parse_TT(lex, false)); - } - if( !unwrapped ) - items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) ); - rv = TokenTree(lex.getHygiene(), mv$(items)); - return rv; -} diff --git a/gcc/rust/mrustc_parser/parse/interpolated_fragment.cpp b/gcc/rust/mrustc_parser/parse/interpolated_fragment.cpp deleted file mode 100644 index d8a8bc4..0000000 --- a/gcc/rust/mrustc_parser/parse/interpolated_fragment.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/interpolated_fragment.cpp - * - An "interpolated fragment", result of parsing e.g. :expr in a macro invocation - */ -#include -#include "interpolated_fragment.hpp" -#include -#include // For definition of ExprNode - -InterpolatedFragment::~InterpolatedFragment() -{ - if( m_ptr ) - { - switch(m_type) - { - case InterpolatedFragment::TT: delete reinterpret_cast(m_ptr); break; - case InterpolatedFragment::PAT: delete reinterpret_cast(m_ptr); break; - case InterpolatedFragment::PATH:delete reinterpret_cast(m_ptr); break; - case InterpolatedFragment::TYPE:delete reinterpret_cast(m_ptr); break; - case InterpolatedFragment::EXPR: - case InterpolatedFragment::STMT: - case InterpolatedFragment::BLOCK: - delete reinterpret_cast(m_ptr); - break; - case InterpolatedFragment::META: - delete reinterpret_cast(m_ptr); - break; - case InterpolatedFragment::ITEM: - delete reinterpret_cast*>(m_ptr); - break; - } - } -} - -InterpolatedFragment::InterpolatedFragment(InterpolatedFragment&& x): - m_type( x.m_type ) -{ - m_ptr = x.m_ptr, x.m_ptr = nullptr; -} -InterpolatedFragment& InterpolatedFragment::operator=(InterpolatedFragment&& x) -{ - m_type = x.m_type; - m_ptr = x.m_ptr, x.m_ptr = nullptr; - return *this; -} - -InterpolatedFragment::InterpolatedFragment(InterpolatedFragment::Type type, AST::ExprNode* ptr): - m_type( type ), - m_ptr( ptr ) -{ -} -InterpolatedFragment::InterpolatedFragment(AST::Attribute v): - m_type( InterpolatedFragment::META ), - m_ptr( new AST::Attribute(mv$(v)) ) -{ -} -InterpolatedFragment::InterpolatedFragment(::AST::Named<::AST::Item> v): - m_type( InterpolatedFragment::ITEM ), - m_ptr( new ::AST::Named<::AST::Item>( mv$(v) ) ) -{ -} -InterpolatedFragment::InterpolatedFragment(TokenTree v): - m_type( InterpolatedFragment::TT ), - m_ptr( new TokenTree(mv$(v)) ) -{ -} -InterpolatedFragment::InterpolatedFragment(AST::Path v): - m_type( InterpolatedFragment::PATH ), - m_ptr( new AST::Path(mv$(v)) ) -{ -} -InterpolatedFragment::InterpolatedFragment(AST::Pattern v): - m_type( InterpolatedFragment::PAT ), - m_ptr( new AST::Pattern(mv$(v)) ) -{ -} -InterpolatedFragment::InterpolatedFragment(TypeRef v): - m_type( InterpolatedFragment::TYPE ), - m_ptr( new TypeRef(mv$(v)) ) -{ -} - -::std::ostream& operator<<(::std::ostream& os, InterpolatedFragment const& x) -{ - switch(x.m_type) - { - case InterpolatedFragment::TT: - os << "tt[" << x.as_tt() << "]"; - break; - case InterpolatedFragment::PAT: - os << "pat[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - case InterpolatedFragment::PATH: - os << "path[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - case InterpolatedFragment::TYPE: - os << "type[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - - case InterpolatedFragment::EXPR: - os << "expr[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - case InterpolatedFragment::STMT: - os << "stmt[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - case InterpolatedFragment::BLOCK: - os << "block[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - - case InterpolatedFragment::META: - os << "meta[" << *reinterpret_cast(x.m_ptr) << "]"; - break; - case InterpolatedFragment::ITEM: { - const auto& named_item = *reinterpret_cast*>(x.m_ptr); - os << "item[" << named_item.data.tag_str() << "(" << named_item.name << ")]"; - } break; - } - return os; -} - diff --git a/gcc/rust/mrustc_parser/parse/interpolated_fragment.hpp b/gcc/rust/mrustc_parser/parse/interpolated_fragment.hpp deleted file mode 100644 index 36539fb..0000000 --- a/gcc/rust/mrustc_parser/parse/interpolated_fragment.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/interpolated_fragment.hpp - * - An "interpolated fragment", result of parsing e.g. :expr in a macro invocation - */ -#pragma once - -#include - -class TypeRef; -class TokenTree; -namespace AST { - class Pattern; - class Path; - class ExprNode; - class Attribute; - template struct Named; - class Item; -}; - - -class InterpolatedFragment -{ -public: - enum Type - { - TT, - PAT, - PATH, - TYPE, - - EXPR, - STMT, - BLOCK, - - META, - ITEM, - } m_type; - - // Owned type-pruned pointer - void* m_ptr; - - InterpolatedFragment(InterpolatedFragment&& ); - InterpolatedFragment& operator=(InterpolatedFragment&& ); - //InterpolatedFragment(const InterpolatedFragment& ); - InterpolatedFragment(TokenTree ); - InterpolatedFragment(::AST::Pattern); - InterpolatedFragment(::AST::Path); - InterpolatedFragment(::TypeRef); - InterpolatedFragment(::AST::Attribute ); - InterpolatedFragment(::AST::Named ); - ~InterpolatedFragment(); - InterpolatedFragment(Type , ::AST::ExprNode*); - - TokenTree& as_tt() { assert(m_type == TT); return *reinterpret_cast(m_ptr); } - const TokenTree& as_tt() const { assert(m_type == TT); return *reinterpret_cast(m_ptr); } - - friend ::std::ostream& operator<<(::std::ostream& os, const InterpolatedFragment& x); -}; diff --git a/gcc/rust/mrustc_parser/parse/lex.cpp b/gcc/rust/mrustc_parser/parse/lex.cpp deleted file mode 100644 index a71289e..0000000 --- a/gcc/rust/mrustc_parser/parse/lex.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/lex.cpp - * - Lexer (converts input file to token stream) - */ -#include "lex.hpp" -#include "../common.hpp" -#include "parseerror.hpp" -#include "tokentree.hpp" -#include // std::count -#include -#include -#include // strtol -#include -#include -//#define TRACE_CHARS -//#define TRACE_RAW_TOKENS - -Lexer::Lexer(const ::std::string& filename) - : m_path(filename.c_str()) - , m_line(1) - , m_line_ofs(0) - , m_istream(filename.c_str()) - , m_last_char_valid(false) - , m_hygiene(Ident::Hygiene::new_scope()) { - if (!m_istream.is_open()) { - throw ::std::runtime_error("Unable to open file '" + filename + "'"); - } - // Consume the BOM - if (this->getc_byte() == '\xef') { - if (this->getc_byte() != '\xbb') { - throw ::std::runtime_error("Incomplete BOM - missing \\xBB in second position"); - } - if (this->getc_byte() != '\xbf') { - throw ::std::runtime_error("Incomplete BOM - missing \\xBF in second position"); - } - m_line_ofs = 0; - } else { - m_istream.unget(); - } -} - -#define LINECOMMENT -1 -#define BLOCKCOMMENT -2 -#define SINGLEQUOTE -3 -#define DOUBLEQUOTE -4 -#define SHEBANG -5 - -// NOTE: This array must be kept sorted, or symbols are will be skipped -#define TOKENT(str, sym) \ - { sizeof(str) - 1, str, sym } -static const struct { - unsigned char len; - const char* chars; - signed int type; -} TOKENMAP[] = { - TOKENT("!", TOK_EXCLAM), - TOKENT("!=", TOK_EXCLAM_EQUAL), - TOKENT("\"", DOUBLEQUOTE), - TOKENT("#", TOK_HASH), - TOKENT("$", TOK_DOLLAR), - TOKENT("%", TOK_PERCENT), - TOKENT("%=", TOK_PERCENT_EQUAL), - TOKENT("&", TOK_AMP), - TOKENT("&&", TOK_DOUBLE_AMP), - TOKENT("&=", TOK_AMP_EQUAL), - TOKENT("'", SINGLEQUOTE), - TOKENT("(", TOK_PAREN_OPEN), - TOKENT(")", TOK_PAREN_CLOSE), - TOKENT("*", TOK_STAR), - TOKENT("*=", TOK_STAR_EQUAL), - TOKENT("+", TOK_PLUS), - TOKENT("+=", TOK_PLUS_EQUAL), - TOKENT(",", TOK_COMMA), - TOKENT("-", TOK_DASH), - TOKENT("-=", TOK_DASH_EQUAL), - TOKENT("->", TOK_THINARROW), - TOKENT(".", TOK_DOT), - TOKENT("..", TOK_DOUBLE_DOT), - TOKENT("...", TOK_TRIPLE_DOT), - TOKENT("/", TOK_SLASH), - TOKENT("/*", BLOCKCOMMENT), - TOKENT("//", LINECOMMENT), - TOKENT("/=", TOK_SLASH_EQUAL), - // 0-9 :: Elsewhere - TOKENT(":", TOK_COLON), - TOKENT("::", TOK_DOUBLE_COLON), - TOKENT(";", TOK_SEMICOLON), - TOKENT("<", TOK_LT), - TOKENT("<-", TOK_THINARROW_LEFT), - TOKENT("<<", TOK_DOUBLE_LT), - TOKENT("<<=", TOK_DOUBLE_LT_EQUAL), - TOKENT("<=", TOK_LTE), - TOKENT("=", TOK_EQUAL), - TOKENT("==", TOK_DOUBLE_EQUAL), - TOKENT("=>", TOK_FATARROW), - TOKENT(">", TOK_GT), - TOKENT(">=", TOK_GTE), - TOKENT(">>", TOK_DOUBLE_GT), - TOKENT(">>=", TOK_DOUBLE_GT_EQUAL), - TOKENT("?", TOK_QMARK), - TOKENT("@", TOK_AT), - // A-Z :: Elsewhere - TOKENT("[", TOK_SQUARE_OPEN), - TOKENT("\\", TOK_BACKSLASH), - TOKENT("]", TOK_SQUARE_CLOSE), - TOKENT("^", TOK_CARET), - TOKENT("^=", TOK_CARET_EQUAL), - TOKENT("`", TOK_BACKTICK), - // a-z :: Elsewhere - //TOKENT("b\"", DOUBLEQUOTE), - - TOKENT("{", TOK_BRACE_OPEN), - TOKENT("|", TOK_PIPE), - TOKENT("|=", TOK_PIPE_EQUAL), - TOKENT("||", TOK_DOUBLE_PIPE), - TOKENT("}", TOK_BRACE_CLOSE), - TOKENT("~", TOK_TILDE), -}; -#define LEN(arr) (sizeof(arr) / sizeof(arr[0])) -static const struct { - unsigned char len; - const char* chars; - signed int type; -} RWORDS[] = { - TOKENT("_", TOK_UNDERSCORE), - TOKENT("abstract", TOK_RWORD_ABSTRACT), - TOKENT("alignof", TOK_RWORD_ALIGNOF), - TOKENT("as", TOK_RWORD_AS), - TOKENT("be", TOK_RWORD_BE), - TOKENT("box", TOK_RWORD_BOX), - TOKENT("break", TOK_RWORD_BREAK), - TOKENT("const", TOK_RWORD_CONST), - TOKENT("continue", TOK_RWORD_CONTINUE), - TOKENT("crate", TOK_RWORD_CRATE), - TOKENT("do", TOK_RWORD_DO), - TOKENT("else", TOK_RWORD_ELSE), - TOKENT("enum", TOK_RWORD_ENUM), - TOKENT("extern", TOK_RWORD_EXTERN), - TOKENT("false", TOK_RWORD_FALSE), - TOKENT("final", TOK_RWORD_FINAL), - TOKENT("fn", TOK_RWORD_FN), - TOKENT("for", TOK_RWORD_FOR), - TOKENT("if", TOK_RWORD_IF), - TOKENT("impl", TOK_RWORD_IMPL), - TOKENT("in", TOK_RWORD_IN), - TOKENT("let", TOK_RWORD_LET), - TOKENT("loop", TOK_RWORD_LOOP), - TOKENT("match", TOK_RWORD_MATCH), - TOKENT("mod", TOK_RWORD_MOD), - TOKENT("move", TOK_RWORD_MOVE), - TOKENT("mut", TOK_RWORD_MUT), - TOKENT("offsetof", TOK_RWORD_OFFSETOF), - TOKENT("override", TOK_RWORD_OVERRIDE), - TOKENT("priv", TOK_RWORD_PRIV), - TOKENT("proc", TOK_RWORD_PROC), - TOKENT("pub", TOK_RWORD_PUB), - TOKENT("pure", TOK_RWORD_PURE), - TOKENT("ref", TOK_RWORD_REF), - TOKENT("return", TOK_RWORD_RETURN), - TOKENT("self", TOK_RWORD_SELF), - TOKENT("sizeof", TOK_RWORD_SIZEOF), - TOKENT("static", TOK_RWORD_STATIC), - TOKENT("struct", TOK_RWORD_STRUCT), - TOKENT("super", TOK_RWORD_SUPER), - TOKENT("trait", TOK_RWORD_TRAIT), - TOKENT("true", TOK_RWORD_TRUE), - TOKENT("type", TOK_RWORD_TYPE), - TOKENT("typeof", TOK_RWORD_TYPEOF), - TOKENT("unsafe", TOK_RWORD_UNSAFE), - TOKENT("unsized", TOK_RWORD_UNSIZED), - TOKENT("use", TOK_RWORD_USE), - TOKENT("virtual", TOK_RWORD_VIRTUAL), - TOKENT("where", TOK_RWORD_WHERE), - TOKENT("while", TOK_RWORD_WHILE), - TOKENT("yield", TOK_RWORD_YIELD), -}; - -signed int Lexer::getSymbol() { - Codepoint ch = this->getc(); - // 1. lsearch for character - // 2. Consume as many characters as currently match - // 3. IF: a smaller character or, EOS is hit - Return current best - unsigned ofs = 0; - signed int best = 0; - bool hit_eof = false; - for (unsigned i = 0; i < LEN(TOKENMAP); i++) { - const char* const chars = TOKENMAP[i].chars; - const size_t len = TOKENMAP[i].len; - - if (ofs >= len || static_cast(chars[ofs]) > ch.v) { - break; - } - - while (chars[ofs] && ch == chars[ofs]) { - try { - ch = this->getc(); - } catch (Lexer::EndOfFile) { - ch = 0; - // Prevent `ungetc` if EOF was hit - hit_eof = true; - } - ofs++; - } - if (chars[ofs] == 0) { - best = TOKENMAP[i].type; - } - } - - if (!hit_eof) { - this->ungetc(); - } - - return best; -} - -bool issym(Codepoint ch) { - if ('0' <= ch.v && ch.v <= '9') - return true; - if (::std::isalpha(ch.v)) - return true; - if (ch == '_') - return true; - if (ch.v >= 128) - return !ch.isspace(); - return false; -} - -Position Lexer::getPosition() const { - return Position(m_path, m_line, m_line_ofs); -} - -Ident::Hygiene Lexer::realGetHygiene() const { - return m_hygiene; -} - -Token Lexer::realGetToken() { - while (true) { - Token tok = getTokenInt(); -#ifdef TRACE_RAW_TOKENS - ::std::cout << "getTokenInt: tok = " << tok << ::std::endl; -#endif - switch (tok.type()) { - case TOK_NEWLINE: - continue; - case TOK_WHITESPACE: - continue; - case TOK_COMMENT: { - continue; - } - default: - return tok; - } - } -} - -Token Lexer::getTokenInt() { - if (!this->m_next_tokens.empty()) { - auto rv = ::std::move(this->m_next_tokens.back()); - m_next_tokens.pop_back(); - return rv; - } - try { - Codepoint ch = this->getc(); - - if (m_line == 1 && m_line_ofs == 1 && ch == '#') { - switch ((ch = this->getc()).v) { - case '!': - switch ((ch = this->getc()).v) { - case '/': - // SHEBANG! - while (ch != '\n') - ch = this->getc(); - return Token(TOK_NEWLINE); - case '[': - this->ungetc(); - this->m_next_tokens.push_back(TOK_EXCLAM); - return Token(TOK_HASH); - default: - throw ParseError::BadChar(*this, ch.v); - } - case '[': - this->ungetc(); - return Token(TOK_HASH); - default: - this->ungetc(); - //return Token(TOK_HASH); - throw ParseError::BadChar(*this, ch.v); - } - } - - if (ch == '\n') - return Token(TOK_NEWLINE); - if (ch.isspace()) { - while ((ch = this->getc()).isspace() && ch != '\n') - ; - this->ungetc(); - return Token(TOK_WHITESPACE); - } - this->ungetc(); - - const signed int sym = this->getSymbol(); - if (sym == 0) { - // No match at all, check for symbol - auto ch = this->getc(); - if (ch.isdigit()) { - enum eCoreType num_type = CORETYPE_ANY; - enum { - BIN, - OCT, - DEC, - HEX, - } num_mode = DEC; - - // Handle integers/floats - uint64_t val = 0; - if (ch == '0') { - // Octal/hex handling - ch = this->getc_num(); - if (ch == 'x') { - num_mode = HEX; - while ((ch = this->getc_num()).isxdigit()) { - val *= 16; - if (ch.v <= '9') - val += ch.v - '0'; - else if (ch.v <= 'F') - val += ch.v - 'A' + 10; - else if (ch.v <= 'f') - val += ch.v - 'a' + 10; - } - } else if (ch == 'b') { - num_mode = BIN; - while ((ch = this->getc_num()).isdigit()) { - val *= 2; - if (ch.v == '0') - val += 0; - else if (ch.v == '1') - val += 1; - else - throw ParseError::Generic("Invalid digit in binary literal"); - } - } else if (ch == 'o') { - num_mode = OCT; - while ((ch = this->getc_num()).isdigit()) { - val *= 8; - if ('0' <= ch.v && ch.v <= '7') - val += ch.v - '0'; - else - throw ParseError::Generic("Invalid digit in octal literal"); - } - } else { - num_mode = DEC; - while (ch.isdigit()) { - val *= 10; - val += ch.v - '0'; - ch = this->getc_num(); - } - } - } else { - while (ch.isdigit()) { - val *= 10; - val += ch.v - '0'; - ch = this->getc_num(); - } - } - - if (ch == 'e' || ch == 'E' || ch == '.') { - if (ch == '.') { - ch = this->getc(); - - // Double/Triple Dot - if (ch == '.') { - if (this->getc() == '.') { - this->m_next_tokens.push_back(TOK_TRIPLE_DOT); - } else { - this->ungetc(); - this->m_next_tokens.push_back(TOK_DOUBLE_DOT); - } - return Token(val, CORETYPE_ANY); - } - - // Single dot followed by a non-digit, could be a float or an integer with a method/field access - if (!ch.isdigit()) { - this->ungetc(); - if (issym(ch)) { - this->m_next_tokens.push_back(TOK_DOT); - return Token(val, CORETYPE_ANY); - } else { - double fval = static_cast(val); - return Token(fval, CORETYPE_ANY); - } - } else { - // Digit, continue - // NOTE: parseFloat assumes that the '.' has been consumed, and reads digits until it hits a non-digit and then parses exponents - // - Thus, continuing here and letting the below 'ungetc' push a digit back is correct. - } - } - if (num_mode != DEC) - TODO(this->getPosition(), "Non-decimal floats"); - - this->ungetc(); - double fval = this->parseFloat(val); - if (issym(ch = this->getc())) { - ::std::string suffix; - while (issym(ch)) { - suffix += ch; - ch = this->getc(); - } - this->ungetc(); - - if (0) - ; - else if (suffix == "f32") - num_type = CORETYPE_F32; - else if (suffix == "f64") - num_type = CORETYPE_F64; - else - throw ParseError::Generic(FMT("Unknown number suffix " << suffix)); - } else { - this->ungetc(); - } - return Token(fval, num_type); - - } else if (issym(ch)) { - // Unsigned - ::std::string suffix; - while (issym(ch)) { - suffix += ch; - ch = this->getc(); - } - this->ungetc(); - - if (0) - ; - else if (suffix == "i8") - num_type = CORETYPE_I8; - else if (suffix == "i16") - num_type = CORETYPE_I16; - else if (suffix == "i32") - num_type = CORETYPE_I32; - else if (suffix == "i64") - num_type = CORETYPE_I64; - else if (suffix == "i128") - num_type = CORETYPE_I128; - else if (suffix == "isize") - num_type = CORETYPE_INT; - else if (suffix == "u8") - num_type = CORETYPE_U8; - else if (suffix == "u16") - num_type = CORETYPE_U16; - else if (suffix == "u32") - num_type = CORETYPE_U32; - else if (suffix == "u64") - num_type = CORETYPE_U64; - else if (suffix == "u128") - num_type = CORETYPE_U128; - else if (suffix == "usize") - num_type = CORETYPE_UINT; - else if (suffix == "f32") - num_type = CORETYPE_F32; - else if (suffix == "f64") - num_type = CORETYPE_F64; - else - throw ParseError::Generic(*this, FMT("Unknown integer suffix '" << suffix << "'")); - return Token(val, num_type); - } else { - this->ungetc(); - return Token(val, num_type); - } - } - // Byte/Raw strings - else if (ch == 'b' || ch == 'r') { - bool is_byte = false; - if (ch == 'b') { - is_byte = true; - ch = this->getc(); - } - - if (ch == 'r') { - return this->getTokenInt_RawString(is_byte); - } else { - assert(is_byte); - - // Byte string - if (ch == '"') { - ::std::string str; - while ((ch = this->getc()) != '"') { - if (ch == '\\') { - auto v = this->parseEscape('"'); - if (v != ~0u) { - if (v > 256) - throw ParseError::Generic(*this, "Value out of range for byte literal"); - str += (char)v; - } - } else { - str += ch; - } - } - return Token(TOK_BYTESTRING, str); - } - // Byte constant - else if (ch == '\'') { - // Byte constant - ch = this->getc(); - if (ch == '\\') { - uint32_t val = this->parseEscape('\''); - if (this->getc() != '\'') - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)val, CORETYPE_U8); - } else { - if (this->getc() != '\'') - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)ch.v, CORETYPE_U8); - } - } else { - assert(is_byte); - this->ungetc(); - return this->getTokenInt_Identifier('b'); - } - } - } - // Symbols - else if (issym(ch)) { - return this->getTokenInt_Identifier(ch); - } else { - throw ParseError::BadChar(*this, ch.v); - } - } else if (sym > 0) { - return Token((enum eTokenType)sym); - } else { - switch (sym) { - case LINECOMMENT: { - // Line comment - ::std::string str; - auto ch = this->getc(); - bool is_doc = false; - bool is_pdoc = false; - if (ch == '/') { - ch = this->getc(); - if (ch == '/') - str += "/"; - else - is_doc = true; - } else if (ch == '!') { - is_pdoc = true; - ch = this->getc(); - } - while (ch != '\n' && ch != '\r') { - str += ch; - ch = this->getc(); - } - this->ungetc(); - if (is_doc || is_pdoc) { - //# [ doc = "commment data" ] - m_next_tokens.push_back(TOK_SQUARE_CLOSE); - m_next_tokens.push_back(Token(TOK_STRING, mv$(str))); - m_next_tokens.push_back(TOK_EQUAL); - m_next_tokens.push_back(Token(TOK_IDENT, "doc")); - m_next_tokens.push_back(TOK_SQUARE_OPEN); - if (is_pdoc) - m_next_tokens.push_back(TOK_EXCLAM); - return TOK_HASH; - } - return Token(TOK_COMMENT, str); - } - case BLOCKCOMMENT: { - ::std::string str; - bool is_doc = false; - bool is_pdoc = false; - ch = this->getc(); - if (ch == '*') { - ch = this->getc(); - if (ch == '*') { - str += "*"; - } else - is_doc = true; - } else if (ch == '!') { - is_pdoc = true; - ch = this->getc(); - } - unsigned int level = 0; - while (true) { - if (ch == '/') { - str += ch; - ch = this->getc(); - if (ch == '*') { - level++; - } - str += ch; - } else { - if (ch == '*') { - ch = this->getc(); - if (ch == '/') { - if (level == 0) - break; - level--; - str.push_back('*'); - str.push_back('/'); - } else { - str.push_back('*'); - str += ch; - } - } else { - str += ch; - } - } - ch = this->getc(); - } - if (is_doc || is_pdoc) { - //# [ doc = "commment data" ] - m_next_tokens.push_back(TOK_SQUARE_CLOSE); - m_next_tokens.push_back(Token(TOK_STRING, mv$(str))); - m_next_tokens.push_back(TOK_EQUAL); - m_next_tokens.push_back(Token(TOK_IDENT, "doc")); - m_next_tokens.push_back(TOK_SQUARE_OPEN); - if (is_pdoc) - m_next_tokens.push_back(TOK_EXCLAM); - return TOK_HASH; - } - return Token(TOK_COMMENT, str); - } - case SINGLEQUOTE: { - auto firstchar = this->getc(); - if (firstchar.v == '\\') { - // Character constant with an escape code - uint32_t val = this->parseEscape('\''); - if (this->getc() != '\'') { - throw ParseError::Todo("Proper error for lex failures"); - } - return Token((uint64_t)val, CORETYPE_CHAR); - } else { - ch = this->getc(); - if (ch == '\'') { - // Character constant - return Token((uint64_t)firstchar.v, CORETYPE_CHAR); - } else if (issym(firstchar.v)) { - // Lifetime name - ::std::string str; - str += firstchar; - while (issym(ch)) { - str += ch; - ch = this->getc(); - } - this->ungetc(); - return Token(TOK_LIFETIME, str); - } else { - throw ParseError::Todo("Lex Fail - Expected ' after character constant"); - } - } - break; - } - case DOUBLEQUOTE: { - ::std::string str; - while ((ch = this->getc()) != '"') { - if (ch == '\\') { - auto v = this->parseEscape('"'); - if (v != ~0u) { - str += Codepoint(v); - } - } else { - str += ch; - } - } - return Token(TOK_STRING, str); - } - default: - assert(!"bugcheck"); - } - } - } catch (const Lexer::EndOfFile& /*e*/) { - return Token(TOK_EOF); - } - - throw "Fell off the end of getTokenInt"; -} - -Token Lexer::getTokenInt_RawString(bool is_byte) { - // Raw string (possibly byte) - Codepoint ch = this->getc(); - unsigned int hashes = 0; - while (ch == '#') { - hashes++; - ch = this->getc(); - } - - if (hashes == 0 && ch != '"') { - this->ungetc(); // Unget the not '"' - if (is_byte) - return this->getTokenInt_Identifier('b', 'r'); - else - return this->getTokenInt_Identifier('r'); - } - auto terminator = ch; - ::std::string val; - DEBUG("terminator = '" << terminator << "', hashes = " << hashes); - - unsigned terminating_hashes = 0; - - for (;;) { - try { - ch = this->getc(); - } catch (const Lexer::EndOfFile& /*e*/) { - throw ParseError::Generic(*this, "EOF reached in raw string"); - } - - if (terminating_hashes > 0) { - assert(terminating_hashes > 0); - if (ch != '#') { - val += terminator; - while (terminating_hashes < hashes) { - val += '#'; - terminating_hashes += 1; - } - terminating_hashes = 0; - - this->ungetc(); - } else { - terminating_hashes -= 1; - if (terminating_hashes == 0) { - break; - } - } - } else { - if (ch == terminator) { - if (hashes == 0) { - break; - } - terminating_hashes = hashes; - } else { - val += ch; - } - } - } - - return Token(is_byte ? TOK_BYTESTRING : TOK_STRING, val); -} -Token Lexer::getTokenInt_Identifier(Codepoint leader, Codepoint leader2) { - ::std::string str; - - if (leader2 != '\0') - str += leader; - - auto ch = leader2 == '\0' ? leader : leader2; - - while (issym(ch)) { - str += ch; - ch = this->getc(); - } - - this->ungetc(); - for (unsigned int i = 0; i < LEN(RWORDS); i++) { - if (str < RWORDS[i].chars) - break; - if (str == RWORDS[i].chars) - return Token((enum eTokenType)RWORDS[i].type); - } - return Token(TOK_IDENT, mv$(str)); -} - -// Takes the VERY lazy way of reading the float into a string then passing to strtod -double Lexer::parseFloat(uint64_t whole) { - const int MAX_LEN = 63; - const int MAX_SIG = MAX_LEN - 1 - 4; - char buf[MAX_LEN + 1]; - int ofs = snprintf(buf, MAX_LEN + 1, "%llu.", (unsigned long long)whole); - - auto ch = this->getc_num(); -#define PUTC(ch) \ - do { \ - if (ofs < MAX_SIG) { \ - assert(ch.v < 127); \ - buf[ofs] = ch.v; \ - ofs++; \ - } else { \ - throw ParseError::Generic("Oversized float"); \ - } \ - } while (0) - while (ch.isdigit()) { - PUTC(ch); - ch = this->getc_num(); - } - - if (ch == 'e' || ch == 'E') { - PUTC(ch); - ch = this->getc_num(); - if (ch == '-' || ch == '+') { - PUTC(ch); - ch = this->getc_num(); - } - if (!ch.isdigit()) - throw ParseError::Generic(FMT("Non-numeric '" << ch << "' in float exponent")); - do { - PUTC(ch); - ch = this->getc_num(); - } while (ch.isdigit()); - } - - this->ungetc(); - buf[ofs] = 0; - - DEBUG("buf = " << buf << ", ch = '" << ch << "'"); - - return ::std::strtod(buf, NULL); -} - -uint32_t Lexer::parseEscape(char enclosing) { - auto ch = this->getc(); - - switch (ch.v) { - case 'x': { - ch = this->getc(); - if (!ch.isxdigit()) - throw ParseError::Generic(*this, FMT("Found invalid character '\\x" << ::std::hex << ch.v << "' in \\u sequence")); - char tmp[3] = { static_cast(ch.v), 0, 0 }; - ch = this->getc(); - if (!ch.isxdigit()) - throw ParseError::Generic(*this, FMT("Found invalid character '\\x" << ::std::hex << ch.v << "' in \\u sequence")); - tmp[1] = static_cast(ch.v); - return ::std::strtol(tmp, NULL, 16); - } break; - case 'u': { - // Unicode (up to six hex digits) - uint32_t val = 0; - ch = this->getc(); - bool req_close_brace = false; - if (ch == '{') { - req_close_brace = true; - ch = this->getc(); - } - if (!ch.isxdigit()) - throw ParseError::Generic(*this, FMT("Found invalid character '\\x" << ::std::hex << ch.v << "' in \\u sequence")); - while (ch.isxdigit()) { - char tmp[2] = { static_cast(ch.v), 0 }; - val *= 16; - val += ::std::strtol(tmp, NULL, 16); - ch = this->getc(); - } - if (!req_close_brace) - this->ungetc(); - else if (ch != '}') - throw ParseError::Generic(*this, "Expected terminating } in \\u sequence"); - else { - } - return val; - } - - case '0': - return '\0'; - case '\\': - return '\\'; - case '\'': - return '\''; - case '"': - return '"'; - case 'r': - return '\r'; - case 'n': - return '\n'; - case 't': - return '\t'; - case '\r': - case '\n': - while (ch.isspace()) - ch = this->getc(); - if (ch == '\\') - return parseEscape(enclosing); - else if (ch == enclosing) { - this->ungetc(); - return ~0; - } else - return ch.v; - default: - throw ParseError::Todo(FMT("Unknown escape sequence \\" << ch)); - } -} - -char Lexer::getc_byte() { - int rv = m_istream.get(); - if (rv == EOF || m_istream.eof()) - throw Lexer::EndOfFile(); - - if (rv == '\n') { - m_line++; - m_line_ofs = 0; - } - - return rv; -} - -Codepoint Lexer::getc() { - if (m_last_char_valid) { - m_last_char_valid = false; -#ifdef TRACE_CHARS - ::std::cout << "getc(): U+" << ::std::hex << m_last_char.v << " (cached)" << ::std::endl; -#endif - } else { - m_last_char = this->getc_cp(); - m_line_ofs += 1; -#ifdef TRACE_CHARS - ::std::cout << "getc(): U+" << ::std::hex << m_last_char.v << ::std::endl; -#endif - } - - return m_last_char; -} - -Codepoint Lexer::getc_num() { - Codepoint ch; - - do { - ch = this->getc(); - } while (ch == '_'); - - return ch; -} -Codepoint Lexer::getc_cp() { - uint8_t v1 = this->getc_byte(); - - if (v1 < 128) { - return { v1 }; - } else if ((v1 & 0xC0) == 0x80) { - // Invalid (continuation) - return { 0xFFFE }; - } else if ((v1 & 0xE0) == 0xC0) { - // Two bytes - uint8_t e1 = this->getc_byte(); - if ((e1 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t outval = ((v1 & 0x1F) << 6) | ((e1 & 0x3F) << 0); - return { outval }; - } else if ((v1 & 0xF0) == 0xE0) { - // Three bytes - uint8_t e1 = this->getc_byte(); - if ((e1 & 0xC0) != 0x80) - return { 0xFFFE }; - uint8_t e2 = this->getc_byte(); - if ((e2 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t outval = ((v1 & 0x0F) << 12) | ((e1 & 0x3F) << 6) | ((e2 & 0x3F) << 0); - return { outval }; - } else if ((v1 & 0xF8) == 0xF0) { - // Four bytes - uint8_t e1 = this->getc_byte(); - if ((e1 & 0xC0) != 0x80) - return { 0xFFFE }; - uint8_t e2 = this->getc_byte(); - if ((e2 & 0xC0) != 0x80) - return { 0xFFFE }; - uint8_t e3 = this->getc_byte(); - if ((e3 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t outval = ((v1 & 0x07) << 18) | ((e1 & 0x3F) << 12) | ((e2 & 0x3F) << 6) | ((e3 & 0x3F) << 0); - return { outval }; - } else { - throw ParseError::Generic("Invalid UTF-8 (too long)"); - } -} - -void Lexer::ungetc() { -#ifdef TRACE_CHARS - ::std::cout << "ungetc(): cache U+" << ::std::hex << m_last_char.v << ::std::endl; -#endif - assert(!m_last_char_valid); - m_last_char_valid = true; -} - -// -------------------------------------------------------------------- -// Codepoint - Unicode codepoint. -// -------------------------------------------------------------------- - -bool Codepoint::isspace() const { - switch (this->v) { - case '\t': - case '\r': - case '\n': - case ' ': - case 0xC: // ^L - case 0x85: - case 0x200E: - case 0x200F: // LTR / RTL markers - case 0x2028: // Line Separator - case 0x2029: // Paragrah Separator - return true; - default: - return false; - } -} - -bool Codepoint::isdigit() const { - return this->v < 128 && std::isdigit(static_cast(this->v)); -} - -bool Codepoint::isxdigit() const { - return this->v < 128 && std::isxdigit(static_cast(this->v)); -} - -::std::string& operator+=(::std::string& s, const Codepoint& cp) { - if (cp.v < 0x80) { - s += (char)cp.v; - } else if (cp.v < (0x1F + 1) << (1 * 6)) { - - s += (char)(0xC0 | ((cp.v >> 6) & 0x1F)); - s += (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else if (cp.v < (0x0F + 1) << (2 * 6)) { - s += (char)(0xE0 | ((cp.v >> 12) & 0x0F)); - s += (char)(0x80 | ((cp.v >> 6) & 0x3F)); - s += (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else if (cp.v < (0x07 + 1) << (3 * 6)) { - s += (char)(0xF0 | ((cp.v >> 18) & 0x07)); - s += (char)(0x80 | ((cp.v >> 12) & 0x3F)); - s += (char)(0x80 | ((cp.v >> 6) & 0x3F)); - s += (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else { - throw ::std::runtime_error(FMT("BUGCHECK: Bad unicode codepoint encountered - " << ::std::hex << cp.v)); - } - return s; -} -::std::ostream& operator<<(::std::ostream& os, const Codepoint& cp) { - if (cp.v < 0x80) { - os << (char)cp.v; - } else if (cp.v < (0x1F + 1) << (1 * 6)) { - os << (char)(0xC0 | ((cp.v >> 6) & 0x1F)); - os << (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else if (cp.v < (0x0F + 1) << (2 * 6)) { - os << (char)(0xE0 | ((cp.v >> 12) & 0x0F)); - os << (char)(0x80 | ((cp.v >> 6) & 0x3F)); - os << (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else if (cp.v < (0x07 + 1) << (2 * 6)) { - os << (char)(0xF0 | ((cp.v >> 18) & 0x07)); - os << (char)(0x80 | ((cp.v >> 12) & 0x3F)); - os << (char)(0x80 | ((cp.v >> 6) & 0x3F)); - os << (char)(0x80 | ((cp.v >> 0) & 0x3F)); - } else { - throw ::std::runtime_error("BUGCHECK: Bad unicode codepoint encountered"); - } - return os; -} - -Token Lex_FindOperator(const ::std::string& s) { - if (s == "_") - return TOK_UNDERSCORE; - for (size_t i = 0; i < LEN(TOKENMAP); i++) { - const auto& e = TOKENMAP[i]; - if (s < e.chars) - break; - if (s == e.chars) { - if (e.type < 0) - break; - return static_cast(e.type); - } - } - return TOK_NULL; -} - -Token Lex_FindReservedWord(const ::std::string& s) { - for (size_t i = 0; i < LEN(RWORDS); i++) { - const auto& e = RWORDS[i]; - if (s < e.chars) - break; - if (s == e.chars) { - assert(e.type > 0); - return static_cast(e.type); - } - } - return TOK_NULL; -} diff --git a/gcc/rust/mrustc_parser/parse/lex.hpp b/gcc/rust/mrustc_parser/parse/lex.hpp deleted file mode 100644 index 7ff0003e..0000000 --- a/gcc/rust/mrustc_parser/parse/lex.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/lex.hpp - * - Lexer header - */ -#ifndef LEX_HPP_INCLUDED -#define LEX_HPP_INCLUDED - -#include -#include -#include "tokenstream.hpp" - -struct Codepoint { - uint32_t v; - Codepoint(): v(0) { } - Codepoint(uint32_t v): v(v) { } - bool isspace() const; - bool isdigit() const; - bool isxdigit() const; - bool operator==(char x) { return v == static_cast(x); } - bool operator!=(char x) { return v != static_cast(x); } - bool operator==(Codepoint x) { return v == x.v; } - bool operator!=(Codepoint x) { return v != x.v; } -}; -extern ::std::string& operator+=(::std::string& s, const Codepoint& cp); -extern ::std::ostream& operator<<(::std::ostream& s, const Codepoint& cp); - -extern Token Lex_FindOperator(const ::std::string& s); -extern Token Lex_FindReservedWord(const ::std::string& s); - -typedef Codepoint uchar; - -class Lexer: - public TokenStream -{ - RcString m_path; - unsigned int m_line; - unsigned int m_line_ofs; - - ::std::ifstream m_istream; - bool m_last_char_valid; - Codepoint m_last_char; - ::std::vector m_next_tokens; - - Ident::Hygiene m_hygiene; -public: - Lexer(const ::std::string& filename); - - Position getPosition() const override; - Ident::Hygiene realGetHygiene() const override; - Token realGetToken() override; - -private: - Token getTokenInt(); - - signed int getSymbol(); - Token getTokenInt_RawString(bool is_byte); - Token getTokenInt_Identifier(Codepoint ch, Codepoint ch2='\0'); - double parseFloat(uint64_t whole); - uint32_t parseEscape(char enclosing); - - void push_hygine() override { - m_hygiene = Ident::Hygiene::new_scope_chained(m_hygiene); - } - void pop_hygine() override { - m_hygiene = m_hygiene.get_parent(); - } - - void ungetc(); - Codepoint getc_num(); - Codepoint getc(); - Codepoint getc_cp(); - char getc_byte(); - - class EndOfFile {}; -}; - -#endif // LEX_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/parse/parseerror.cpp b/gcc/rust/mrustc_parser/parse/parseerror.cpp deleted file mode 100644 index 1bb3098..0000000 --- a/gcc/rust/mrustc_parser/parse/parseerror.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/parseerror.cpp - * - Exceptions thrown for different types of parsing errors - */ -#include "parseerror.hpp" -#include - -CompileError::Base::~Base() throw() -{ -} - -CompileError::Generic::Generic(::std::string message): - m_message(message) -{ - ::std::cout << "Generic(" << message << ")" << ::std::endl; -} -CompileError::Generic::Generic(const TokenStream& lex, ::std::string message) -{ - ::std::cout << lex.point_span() << ": Generic(" << message << ")" << ::std::endl; -} - -CompileError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message): - m_message(message) -{ - ::std::cout << lex.point_span() << "BugCheck(" << message << ")" << ::std::endl; -} -CompileError::BugCheck::BugCheck(::std::string message): - m_message(message) -{ - ::std::cout << "BugCheck(" << message << ")" << ::std::endl; -} - -CompileError::Todo::Todo(::std::string message): - m_message(message) -{ - ::std::cout << "Todo(" << message << ")" << ::std::endl; -} -CompileError::Todo::Todo(const TokenStream& lex, ::std::string message): - m_message(message) -{ - ::std::cout << lex.point_span() << ": Todo(" << message << ")" << ::std::endl; -} -CompileError::Todo::~Todo() throw() -{ -} - -ParseError::BadChar::BadChar(const TokenStream& lex, char character) -{ - ::std::cout << lex.point_span() << ": BadChar(" << character << ")" << ::std::endl; -} -ParseError::BadChar::~BadChar() throw() -{ -} - -ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok)//: -// m_tok( mv$(tok) ) -{ - Span pos = tok.get_pos(); - if(pos.filename == "") - pos = lex.point_span(); - ::std::cout << pos << ": Unexpected(" << tok << ")" << ::std::endl; -} -ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, Token exp)//: -// m_tok( mv$(tok) ) -{ - Span pos = tok.get_pos(); - if(pos.filename == "") - pos = lex.point_span(); - ::std::cout << pos << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl; -} -ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, ::std::vector exp) -{ - Span pos = tok.get_pos(); - if(pos.filename == "") - pos = lex.point_span(); - ::std::cout << pos << ": Unexpected " << tok << ", expected "; - bool f = true; - for(auto v: exp) { - if(!f) - ::std::cout << " or "; - f = false; - ::std::cout << Token::typestr(v); - } - ::std::cout << ::std::endl; -} -ParseError::Unexpected::~Unexpected() throw() -{ -} diff --git a/gcc/rust/mrustc_parser/parse/parseerror.hpp b/gcc/rust/mrustc_parser/parse/parseerror.hpp deleted file mode 100644 index d6e2b03..0000000 --- a/gcc/rust/mrustc_parser/parse/parseerror.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/parseerror.hpp - * - Exception classes for parsing/lexing errors - */ -#ifndef PARSEERROR_HPP_INCLUDED -#define PARSEERROR_HPP_INCLUDED - -#include -#include "tokenstream.hpp" -#include - -namespace ParseError { - -using CompileError::Generic; -using CompileError::BugCheck; -using CompileError::Todo; - -class BadChar: - public CompileError::Base -{ - //char m_char; -public: - BadChar(const TokenStream& lex, char character); - virtual ~BadChar() throw (); - -}; - -class Unexpected: - public CompileError::Base -{ - Token m_tok; -public: - Unexpected(const TokenStream& lex, const Token& tok); - Unexpected(const TokenStream& lex, const Token& tok, Token exp); - Unexpected(const TokenStream& lex, const Token& tok, ::std::vector exp); - virtual ~Unexpected() throw (); - -}; - -#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: " __FILE__ " - " #cnd); } while(0) - -} - -#endif // PARSEERROR_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/parse/paths.cpp b/gcc/rust/mrustc_parser/parse/paths.cpp deleted file mode 100644 index d103840..0000000 --- a/gcc/rust/mrustc_parser/parse/paths.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/paths.cpp - * - Parsing for module paths - */ -#include "parseerror.hpp" -#include "common.hpp" -#include "../ast/ast.hpp" - -AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); -AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode); -::std::vector Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode); -AST::PathParams Parse_Path_GenericList(TokenStream& lex); - -AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode) -{ - TRACE_FUNCTION_F("generic_mode="<::BAR is actually `::BAR` (in mrustc parleance) - //return AST::Path(AST::Path::TagUfcs(), mv$(ty), Parse_PathNodes(lex, generic_mode)); - return AST::Path(AST::Path::TagUfcs(), mv$(ty), AST::Path(), Parse_PathNodes(lex, generic_mode)); - } - throw ""; } - - default: - PUTBACK(tok, lex); - return Parse_Path(lex, false, generic_mode); - } -} -AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode) -{ - Token tok; - if( is_abs ) - { - if( GET_TOK(tok, lex) == TOK_STRING ) { - ::std::string cratename = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); - return AST::Path(cratename, Parse_PathNodes(lex, generic_mode)); - } - else { - PUTBACK(tok, lex); - return AST::Path("", Parse_PathNodes(lex, generic_mode)); - } - } - else { - // TODO: TOK_INTERPOLATED_IDENT? - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto hygine = lex.getHygiene(); - PUTBACK(tok, lex); - return AST::Path(AST::Path::TagRelative(), mv$(hygine), Parse_PathNodes(lex, generic_mode)); - } -} - -::std::vector Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode) -{ - TRACE_FUNCTION_F("generic_mode="< ret; - - tok = lex.getToken(); - while(true) - { - ::AST::PathParams params; - - CHECK_TOK(tok, TOK_IDENT); - auto component = mv$( tok.str() ); - - GET_TOK(tok, lex); - if( generic_mode == PATH_GENERIC_TYPE ) - { - if( tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT ) - { - // HACK! Handle breaking << into < < - if( tok.type() == TOK_DOUBLE_LT ) - lex.putback( Token(TOK_LT) ); - - // Type-mode generics "::path::to::Type" - params = Parse_Path_GenericList(lex); - GET_TOK(tok, lex); - } - // HACK - 'Fn*(...) -> ...' notation - else if( tok.type() == TOK_PAREN_OPEN ) - { - auto ps = lex.start_span(); - DEBUG("Fn() hack"); - ::std::vector args; - if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - { - // Empty list - } - else - { - PUTBACK(tok, lex); - do { - // TODO: Trailing commas - args.push_back( Parse_Type(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - } - CHECK_TOK(tok, TOK_PAREN_CLOSE); - - TypeRef ret_type = TypeRef( TypeRef::TagUnit(), Span(tok.get_pos()) ); - if( GET_TOK(tok, lex) == TOK_THINARROW ) { - ret_type = Parse_Type(lex, false); - } - else { - PUTBACK(tok, lex); - } - DEBUG("- Fn("<"<C into Fn<(A,B),Ret=C> - params = ::AST::PathParams { - {}, - ::make_vec1( TypeRef(TypeRef::TagTuple(), lex.end_span(ps), mv$(args)) ), - ::make_vec1( ::std::make_pair( ::std::string("Output"), mv$(ret_type) ) ) - }; - - GET_TOK(tok, lex); - } - else - { - } - } - if( tok.type() != TOK_DOUBLE_COLON ) { - ret.push_back( AST::PathNode(component, mv$(params)) ); - break; - } - tok = lex.getToken(); - if( generic_mode == PATH_GENERIC_EXPR && (tok.type() == TOK_LT || tok.type() == TOK_DOUBLE_LT) ) - { - // HACK! Handle breaking << into < < - if( tok.type() == TOK_DOUBLE_LT ) - lex.putback( Token(TOK_LT) ); - - // Expr-mode generics "::path::to::function::(arg1, arg2)" - params = Parse_Path_GenericList(lex); - if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) { - ret.push_back( AST::PathNode(component, mv$(params)) ); - // Break out of loop down to return - break; - } - // Match with CHECK_TOK at start of loop - GET_TOK(tok, lex); - } - ret.push_back( AST::PathNode(component, mv$(params)) ); - } - PUTBACK(tok, lex); - DEBUG("ret = " << ret); - return ret; -} -/// Parse a list of parameters within a path -::AST::PathParams Parse_Path_GenericList(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - ::std::vector types; - ::std::vector lifetimes; - ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds; - - do { - if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT || LOOK_AHEAD(lex) == TOK_GTE || LOOK_AHEAD(lex) == TOK_DOUBLE_GT_EQUAL ) { - GET_TOK(tok, lex); - break; - } - switch(GET_TOK(tok, lex)) - { - case TOK_LIFETIME: - lifetimes.push_back(AST::LifetimeRef(/*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); - break; - case TOK_IDENT: - if( LOOK_AHEAD(lex) == TOK_EQUAL ) - { - ::std::string name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - assoc_bounds.push_back( ::std::make_pair( mv$(name), Parse_Type(lex,false) ) ); - break; - } - default: - PUTBACK(tok, lex); - types.push_back( Parse_Type(lex) ); - break; - } - } while( GET_TOK(tok, lex) == TOK_COMMA ); - - // HACK: Split >> into > - if(tok.type() == TOK_DOUBLE_GT_EQUAL) { - lex.putback(Token(TOK_GTE)); - } - else if(tok.type() == TOK_GTE) { - lex.putback(Token(TOK_EQUAL)); - } - else if(tok.type() == TOK_DOUBLE_GT) { - lex.putback(Token(TOK_GT)); - } - else { - CHECK_TOK(tok, TOK_GT); - } - - return ::AST::PathParams { - mv$( lifetimes ), - mv$( types ), - mv$( assoc_bounds ) - }; -} - diff --git a/gcc/rust/mrustc_parser/parse/pattern.cpp b/gcc/rust/mrustc_parser/parse/pattern.cpp deleted file mode 100644 index e2949a6..0000000 --- a/gcc/rust/mrustc_parser/parse/pattern.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/pattern.cpp - * - Parsing for patterns - */ -#include "common.hpp" -#include "parseerror.hpp" -#include // To convert :expr - -// NEWNODE is needed for the Value pattern type -typedef ::std::unique_ptr ExprNodeP; -#define NEWNODE(type, ...) ExprNodeP(new type(__VA_ARGS__)) -using AST::ExprNode; - - - -::AST::Pattern::TuplePat Parse_PatternTuple(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable); -AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable); - -AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable); - - -/// Parse a pattern -/// -/// Examples: -/// - `Enum::Variant(a)` -/// - `(1, a)` -/// - `1 ... 2` -/// - `"string"` -/// - `mut x` -/// - `mut x @ 1 ... 2` -AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) -{ - TRACE_FUNCTION; - auto ps = lex.start_span(); - - Token tok; - tok = lex.getToken(); - - if( tok.type() == TOK_IDENT && lex.lookahead(0) == TOK_EXCLAM ) - { - lex.getToken(); - return AST::Pattern( AST::Pattern::TagMacro(), lex.end_span(ps), box$(Parse_MacroInvocation(ps, tok.str(), lex))); - } - if( tok.type() == TOK_INTERPOLATED_PATTERN ) - { - return mv$(tok.frag_pattern()); - } - - bool expect_bind = false; - auto bind_type = AST::PatternBinding::Type::MOVE; - bool is_mut = false; - // 1. Mutablity + Reference - if( tok.type() == TOK_RWORD_REF ) - { - expect_bind = true; - tok = lex.getToken(); - if( tok.type() == TOK_RWORD_MUT ) - { - bind_type = AST::PatternBinding::Type::MUTREF; - GET_TOK(tok, lex); - } - else - { - bind_type = AST::PatternBinding::Type::REF; - } - } - else if( tok.type() == TOK_RWORD_MUT ) - { - is_mut = true; - expect_bind = true; - GET_TOK(tok, lex); - } - else - { - // Fall through - } - - AST::PatternBinding binding; - // If a 'ref' or 'mut' annotation was seen, the next name must be a binding name - if( expect_bind ) - { - CHECK_TOK(tok, TOK_IDENT); - auto bind_name = Ident(lex.getHygiene(), mv$(tok.str())); - // If there's no '@' after it, it's a name binding only (_ pattern) - if( GET_TOK(tok, lex) != TOK_AT ) - { - PUTBACK(tok, lex); - return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(mv$(ps)), mv$(bind_name), bind_type, is_mut); - } - binding = AST::PatternBinding( mv$(bind_name), bind_type, is_mut ); - - // '@' consumed, move on to next token - GET_TOK(tok, lex); - } - // Otherwise, handle MaybeBind - else if( tok.type() == TOK_IDENT ) - { - switch( LOOK_AHEAD(lex) ) - { - // Known path `ident::` - case TOK_DOUBLE_COLON: - break; - // Known struct `Ident {` or `Ident (` - case TOK_BRACE_OPEN: - case TOK_PAREN_OPEN: - break; - // Known value `IDENT ...` - case TOK_TRIPLE_DOT: - break; - // Known binding `ident @` - case TOK_AT: - binding = AST::PatternBinding( Ident(lex.getHygiene(), mv$(tok.str())), bind_type/*MOVE*/, is_mut/*false*/ ); - GET_TOK(tok, lex); // '@' - GET_TOK(tok, lex); // Match lex.putback() below - break; - default: { // Maybe bind - Ident name = Ident(lex.getHygiene(), mv$(tok.str())); - // if the pattern can be refuted (i.e this could be an enum variant), return MaybeBind - if( is_refutable ) { - assert(bind_type == ::AST::PatternBinding::Type::MOVE); - assert(is_mut == false); - return AST::Pattern(AST::Pattern::TagMaybeBind(), lex.end_span(mv$(ps)), mv$(name)); - } - // Otherwise, it IS a binding - else { - return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(mv$(ps)), mv$(name), bind_type, is_mut); - } - break;} - } - } - else - { - // Otherwise, fall through - } - - PUTBACK(tok, lex); - auto pat = Parse_PatternReal(lex, is_refutable); - pat.binding() = mv$(binding); - return pat; -} - -AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) -{ - Token tok; - if( LOOK_AHEAD(lex) == TOK_INTERPOLATED_PATTERN ) - { - GET_TOK(tok, lex); - return mv$(tok.frag_pattern()); - } - auto ps = lex.start_span(); - AST::Pattern ret = Parse_PatternReal1(lex, is_refutable); - if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) - { - if( !ret.data().is_Value() ) - throw ParseError::Generic(lex, "Using '...' with a non-value on left"); - auto& ret_v = ret.data().as_Value(); - - auto right_pat = Parse_PatternReal1(lex, is_refutable); - if( !right_pat.data().is_Value() ) - throw ParseError::Generic(lex, "Using '...' with a non-value on right"); - auto rightval = mv$( right_pat.data().as_Value().start ); - ret_v.end = mv$(rightval); - // TODO: use `ps` here? - - return ret; - } - else - { - PUTBACK(tok, lex); - return ret; - } -} -AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) -{ - TRACE_FUNCTION; - auto ps = lex.start_span(); - - Token tok; - AST::Path path; - - switch( GET_TOK(tok, lex) ) - { - case TOK_UNDERSCORE: - return AST::Pattern( lex.end_span(mv$(ps)), AST::Pattern::Data() ); - //case TOK_DOUBLE_DOT: - // return AST::Pattern( AST::Pattern::TagWildcard() ); - case TOK_RWORD_BOX: - return AST::Pattern( AST::Pattern::TagBox(), lex.end_span(mv$(ps)), Parse_Pattern(lex, is_refutable) ); - case TOK_DOUBLE_AMP: - lex.putback(TOK_AMP); - case TOK_AMP: { - DEBUG("Ref"); - // NOTE: Falls back into "Pattern" not "PatternReal" to handle MaybeBind again - bool is_mut = false; - if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) - is_mut = true; - else - PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagReference(), lex.end_span(mv$(ps)), is_mut, Parse_Pattern(lex, is_refutable) ); - } - case TOK_RWORD_SELF: - case TOK_RWORD_SUPER: - case TOK_IDENT: - case TOK_LT: - case TOK_DOUBLE_LT: - case TOK_INTERPOLATED_PATH: - PUTBACK(tok, lex); - return Parse_PatternReal_Path( lex, ps, Parse_Path(lex, PATH_GENERIC_EXPR), is_refutable ); - case TOK_DOUBLE_COLON: - // 2. Paths are enum/struct names - return Parse_PatternReal_Path( lex, ps, Parse_Path(lex, true, PATH_GENERIC_EXPR), is_refutable ); - case TOK_DASH: - if(GET_TOK(tok, lex) == TOK_INTEGER) - { - auto dt = tok.datatype(); - // TODO: Ensure that the type is ANY or a signed integer - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); - } - else if( tok.type() == TOK_FLOAT ) - { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({tok.datatype(), -tok.floatval()}) ); - } - else - { - throw ParseError::Unexpected(lex, tok, {TOK_INTEGER, TOK_FLOAT}); - } - case TOK_FLOAT: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({tok.datatype(), tok.floatval()}) ); - case TOK_INTEGER: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); - case TOK_RWORD_TRUE: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); - case TOK_RWORD_FALSE: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); - case TOK_STRING: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); - case TOK_BYTESTRING: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_ByteString({ mv$(tok.str()) }) ); - case TOK_INTERPOLATED_EXPR: { - auto e = tok.take_frag_node(); - if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_String( mv$(n->m_value) ) ); - } - //else if( auto* n = dynamic_cast(e.get()) ) { - // return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_ByteString( mv$(n->m_value) ) ); - //} - else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, n->m_value}) ); - } - else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({n->m_datatype, n->m_value}) ); - } - else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({n->m_datatype, n->m_value}) ); - } - else { - TODO(lex.point_span(), "Convert :expr into a pattern value - " << *e); - } - } break; - - case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagTuple(), lex.end_span(mv$(ps)), Parse_PatternTuple(lex, is_refutable) ); - case TOK_SQUARE_OPEN: - return Parse_PatternReal_Slice(lex, is_refutable); - default: - throw ParseError::Unexpected(lex, tok); - } -} -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable) -{ - Token tok; - - switch( GET_TOK(tok, lex) ) - { - case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagNamedTuple(), lex.end_span(mv$(ps)), mv$(path), Parse_PatternTuple(lex, is_refutable) ); - case TOK_BRACE_OPEN: - return Parse_PatternStruct(lex, ps, mv$(path), is_refutable); - default: - PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Named(mv$(path)) ); - } -} - -AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) -{ - auto ps = lex.start_span(); - Token tok; - - ::std::vector< ::AST::Pattern> leading; - ::std::vector< ::AST::Pattern> trailing; - ::AST::PatternBinding inner_binding; - bool is_split = false; - - while(GET_TOK(tok, lex) != TOK_SQUARE_CLOSE) - { - bool has_binding = true; - ::AST::PatternBinding binding; - if( tok.type() == TOK_RWORD_REF && lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_DOUBLE_DOT ) { - GET_TOK(tok, lex); - binding = ::AST::PatternBinding( lex.get_ident(mv$(tok)), ::AST::PatternBinding::Type::REF, false ); - } - else if( tok.type() == TOK_IDENT && lex.lookahead(0) == TOK_DOUBLE_DOT) { - binding = ::AST::PatternBinding( lex.get_ident(mv$(tok)), ::AST::PatternBinding::Type::MOVE, false ); - } - else if( tok.type() == TOK_UNDERSCORE && lex.lookahead(0) == TOK_DOUBLE_DOT) { - // No binding, but switching to trailing - } - else if( tok.type() == TOK_DOUBLE_DOT ) { - // No binding, but switching to trailing - PUTBACK(tok, lex); - } - else { - has_binding = false; - } - - if( has_binding ) { - if(is_split) - ERROR(lex.end_span(mv$(ps)), E0000, "Multiple instances of .. in a slice pattern"); - - inner_binding = mv$(binding); - is_split = true; - GET_TOK(tok, lex); // TOK_DOUBLE_DOT - } - else { - PUTBACK(tok, lex); - if(!is_split) { - leading.push_back( Parse_Pattern(lex, is_refutable) ); - } - else { - trailing.push_back( Parse_Pattern(lex, is_refutable) ); - } - } - - if( GET_TOK(tok, lex) != TOK_COMMA ) - break; - } - CHECK_TOK(tok, TOK_SQUARE_CLOSE); - - if( is_split ) - { - return ::AST::Pattern( lex.end_span(mv$(ps)), ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) ); - } - else - { - assert( !inner_binding.is_valid() ); - assert( trailing.empty() ); - return ::AST::Pattern( lex.end_span(mv$(ps)), ::AST::Pattern::Data::make_Slice({ mv$(leading) }) ); - } -} - -::AST::Pattern::TuplePat Parse_PatternTuple(TokenStream& lex, bool is_refutable) -{ - TRACE_FUNCTION; - auto sp = lex.start_span(); - Token tok; - - ::std::vector leading; - while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE && LOOK_AHEAD(lex) != TOK_DOUBLE_DOT ) - { - leading.push_back( Parse_Pattern(lex, is_refutable) ); - - if( GET_TOK(tok, lex) != TOK_COMMA ) { - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return AST::Pattern::TuplePat { mv$(leading), false, {} }; - } - } - - if( LOOK_AHEAD(lex) != TOK_DOUBLE_DOT ) - { - GET_TOK(tok, lex); - - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return AST::Pattern::TuplePat { mv$(leading), false, {} }; - } - GET_CHECK_TOK(tok, lex, TOK_DOUBLE_DOT); - - ::std::vector trailing; - if( GET_TOK(tok, lex) == TOK_COMMA ) - { - while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) - { - trailing.push_back( Parse_Pattern(lex, is_refutable) ); - - if( GET_TOK(tok, lex) != TOK_COMMA ) { - PUTBACK(tok, lex); - break; - } - } - GET_TOK(tok, lex); - } - - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return ::AST::Pattern::TuplePat { mv$(leading), true, mv$(trailing) }; -} - -AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable) -{ - TRACE_FUNCTION; - Token tok; - - // #![feature(relaxed_adts)] - if( LOOK_AHEAD(lex) == TOK_INTEGER ) - { - bool split_allowed = false; - ::std::map pats; - while( GET_TOK(tok, lex) == TOK_INTEGER ) - { - unsigned int ofs = static_cast(tok.intval()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto val = Parse_Pattern(lex, is_refutable); - if( ! pats.insert( ::std::make_pair(ofs, mv$(val)) ).second ) { - ERROR(lex.point_span(), E0000, "Duplicate index"); - } - - if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE ) - break; - CHECK_TOK(tok, TOK_COMMA); - } - if( tok.type() == TOK_DOUBLE_DOT ) { - split_allowed = true; - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - bool has_split = false; - ::std::vector leading; - ::std::vector trailing; - unsigned int i = 0; - for(auto& p : pats) - { - if( p.first != i ) { - if( has_split || !split_allowed ) { - ERROR(lex.point_span(), E0000, "Missing index " << i); - } - has_split = true; - i = p.first; - } - if( ! has_split ) { - leading.push_back( mv$(p.second) ); - } - else { - trailing.push_back( mv$(p.second) ); - } - i ++; - } - - return AST::Pattern(AST::Pattern::TagNamedTuple(), lex.end_span(mv$(ps)), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) }); - } - - bool is_exhaustive = true; - ::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats; - do { - GET_TOK(tok, lex); - DEBUG("tok = " << tok); - if( tok.type() == TOK_BRACE_CLOSE ) - break; - if( tok.type() == TOK_DOUBLE_DOT ) { - is_exhaustive = false; - GET_TOK(tok, lex); - break; - } - - auto inner_ps = lex.start_span(); - bool is_short_bind = false; - bool is_box = false; - auto bind_type = AST::PatternBinding::Type::MOVE; - bool is_mut = false; - if( tok.type() == TOK_RWORD_BOX ) { - is_box = true; - is_short_bind = true; - GET_TOK(tok, lex); - } - if( tok.type() == TOK_RWORD_REF ) { - is_short_bind = true; - GET_TOK(tok, lex); - if( tok.type() == TOK_RWORD_MUT ) { - bind_type = AST::PatternBinding::Type::MUTREF; - GET_TOK(tok, lex); - } - else { - bind_type = AST::PatternBinding::Type::REF; - } - } - else if( tok.type() == TOK_RWORD_MUT ) { - is_mut = true; - is_short_bind = true; - GET_TOK(tok, lex); - } - - CHECK_TOK(tok, TOK_IDENT); - auto field_ident = lex.get_ident(mv$(tok)); - ::std::string field_name; - GET_TOK(tok, lex); - - AST::Pattern pat; - if( is_short_bind || tok.type() != TOK_COLON ) { - PUTBACK(tok, lex); - pat = AST::Pattern(lex.end_span(inner_ps), {}); - field_name = field_ident.name; - pat.set_bind(mv$(field_ident), bind_type, is_mut); - if( is_box ) - { - pat = AST::Pattern(AST::Pattern::TagBox(), lex.end_span(inner_ps), mv$(pat)); - } - } - else { - CHECK_TOK(tok, TOK_COLON); - field_name = mv$(field_ident.name); - pat = Parse_Pattern(lex, is_refutable); - } - - subpats.push_back( ::std::make_pair(mv$(field_name), mv$(pat)) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - return AST::Pattern(AST::Pattern::TagStruct(), lex.end_span(mv$(ps)), ::std::move(path), ::std::move(subpats), is_exhaustive); -} - diff --git a/gcc/rust/mrustc_parser/parse/root.cpp b/gcc/rust/mrustc_parser/parse/root.cpp deleted file mode 100644 index d799f09..0000000 --- a/gcc/rust/mrustc_parser/parse/root.cpp +++ /dev/null @@ -1,1999 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/root.cpp - * - Parsing at the module level (highest-level parsing) - * - * Entrypoint: - * - Parse_Crate : Handles crate attrbutes, and passes on to Parse_ModRoot - * - Parse_ModRoot - */ -#include -#include -#include "parseerror.hpp" -#include "common.hpp" -#include -#include // ABI_RUST - TODO: Move elsewhere? -#include // check_cfg - for `mod nonexistant;` -#include // Used by directory path -#include "lex.hpp" // New file lexer -#include - -template -Spanned get_spanned(TokenStream& lex, ::std::function f) { - auto ps = lex.start_span(); - auto v = f(); - return Spanned { - lex.end_span( mv$(ps) ), - mv$(v) - }; -} -#define GET_SPANNED(type, lex, val) get_spanned< type >(lex, [&](){ return val; }) - -// Check the next two tokens -#define LOOKAHEAD2(lex, tok1, tok2) ((lex).lookahead(0) == (tok1) && (lex).lookahead(1) == (tok2)) - -::std::string dirname(::std::string input) { - while( input.size() > 0 && input.back() != '/' && input.back() != '\\' ) { - input.pop_back(); - } - return input; -} - -AST::AttributeList Parse_ItemAttrs(TokenStream& lex); -void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out); -AST::Attribute Parse_MetaItem(TokenStream& lex); -void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::AttributeList& mod_attrs); -bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv); - -//::AST::Path Parse_Publicity(TokenStream& lex) -bool Parse_Publicity(TokenStream& lex, bool allow_restricted=true) -{ - Token tok; - if( LOOK_AHEAD(lex) == TOK_RWORD_PUB ) - { - GET_TOK(tok, lex); - if( LOOK_AHEAD(lex) == TOK_PAREN_OPEN ) - { - // HACK: tuple structs have a parsing ambiguity around `pub (self::Type,)` - if( !allow_restricted ) - { - if( lex.lookahead(1) == TOK_RWORD_IN ) - ; - else if( lex.lookahead(1) == TOK_RWORD_CRATE && lex.lookahead(2) == TOK_PAREN_CLOSE ) - ; - else if( lex.lookahead(1) == TOK_RWORD_SUPER && lex.lookahead(2) == TOK_PAREN_CLOSE ) - ; - else if( lex.lookahead(1) == TOK_RWORD_SELF && lex.lookahead(2) == TOK_PAREN_CLOSE ) - ; - else - return true; - } - auto path = AST::Path("", {}); - // Restricted publicity. - GET_TOK(tok, lex); // '(' - - switch(GET_TOK(tok, lex)) - { - case TOK_RWORD_CRATE: - // Crate visibility - break; - case TOK_RWORD_SELF: - // Private! - path = AST::Path( lex.parse_state().get_current_mod().path() ); - break; - case TOK_RWORD_SUPER: - path = AST::Path( lex.parse_state().get_current_mod().path() ); - path.nodes().pop_back(); - while( lex.lookahead(0) == TOK_DOUBLE_COLON && lex.lookahead(1) == TOK_RWORD_SUPER ) - { - GET_TOK(tok, lex); - GET_TOK(tok, lex); - path.nodes().pop_back(); - } - if( lex.lookahead(0) != TOK_DOUBLE_COLON ) - break; - GET_TOK(tok, lex); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - case TOK_RWORD_IN: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - path.nodes().push_back( AST::PathNode(tok.str()) ); - while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON ) - { - GET_TOK(tok, lex); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - path.nodes().push_back( AST::PathNode(tok.str()) ); - } - break; - default: - throw ParseError::Unexpected(lex, tok); - } - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); - } - return true; - } - else - { - return false; - } -} - -::AST::HigherRankedBounds Parse_HRB(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - - ::AST::HigherRankedBounds rv; - GET_CHECK_TOK(tok, lex, TOK_LT); - do { - // Support empty lists and comma-terminated lists - if( lex.lookahead(0) == TOK_GT ) { - GET_TOK(tok, lex); - break; - } - auto attrs = Parse_ItemAttrs(lex); - - switch(GET_TOK(tok, lex)) - { - case TOK_LIFETIME: - rv.m_lifetimes.push_back(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), tok.str()))); - break; - default: - throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME)); - } - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_GT); - return rv; -} -::AST::HigherRankedBounds Parse_HRB_Opt(TokenStream& lex) -{ - if( lex.lookahead(0) == TOK_RWORD_FOR ) - { - lex.getToken(); // Consume - return Parse_HRB(lex); - } - else - { - return ::AST::HigherRankedBounds(); - } -} - -namespace { - AST::LifetimeRef get_LifetimeRef(TokenStream& lex, Token tok) - { - CHECK_TOK(tok, TOK_LIFETIME); - return AST::LifetimeRef(/*lex.point_span(), */Ident(lex.getHygiene(), mv$(tok.str()))); - } -} -/// Parse type parameters in a definition -void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, - AST::HigherRankedBounds outer_hrbs = {}) -{ - TRACE_FUNCTION; - Token tok; - - do - { - // If an item terminator is seen (end of item, start of body, list separator), return early. - //if( LOOK_AHEAD(lex) == TOK_SEMICOLON || LOOK_AHEAD(lex) == TOK_COMMA ) - //{ - // return; - //} - - if(GET_TOK(tok, lex) == TOK_LIFETIME) { - ret.add_bound(AST::GenericBound::make_TypeLifetime( { - checked_type.clone(), get_LifetimeRef(lex, mv$(tok)) - } )); - } - else if( tok.type() == TOK_QMARK ) { - auto hrbs = Parse_HRB_Opt(lex); - (void)hrbs; // The only valid ?Trait is Sized, which doesn't have any generics - ret.add_bound(AST::GenericBound::make_MaybeTrait( { - checked_type.clone(), Parse_Path(lex, PATH_GENERIC_TYPE) - } )); - } - else { - ::AST::HigherRankedBounds inner_hrls; - if( tok.type() == TOK_RWORD_FOR ) - { - inner_hrls = Parse_HRB(lex); - } - else { - PUTBACK(tok, lex); - } - auto trait_path = Parse_Path(lex, PATH_GENERIC_TYPE); - - auto this_outer_hrbs = (lex.lookahead(0) == TOK_PLUS ? - AST::HigherRankedBounds(outer_hrbs) : mv$(outer_hrbs)); - ret.add_bound( AST::GenericBound::make_IsTrait({ - mv$(this_outer_hrbs), checked_type.clone(), mv$(inner_hrls), mv$(trait_path) - }) ); - } - } while( GET_TOK(tok, lex) == TOK_PLUS ); - PUTBACK(tok, lex); -} - -/// Parse type parameters within '<' and '>' (definition) -AST::GenericParams Parse_GenericParams(TokenStream& lex) -{ - TRACE_FUNCTION; - - AST::GenericParams ret; - Token tok; - do { - if( GET_TOK(tok, lex) == TOK_GT ) { - break ; - } - - PUTBACK(tok, lex); - auto attrs = Parse_ItemAttrs(lex); - - GET_TOK(tok, lex); - if( tok.type() == TOK_IDENT ) - { - ::std::string param_name = mv$(tok.str()); - ret.add_ty_param( AST::TypeParam( lex.point_span(), ::std::move(attrs), param_name ) ); - - auto param_ty = TypeRef(lex.point_span(), param_name); - if( GET_TOK(tok, lex) == TOK_COLON ) - { - Parse_TypeBound(lex, ret, mv$(param_ty)); - GET_TOK(tok, lex); - } - - if( tok.type() == TOK_EQUAL ) - { - ret.ty_params().back().setDefault( Parse_Type(lex) ); - GET_TOK(tok, lex); - } - } - else if( tok.type() == TOK_LIFETIME ) - { - auto param_name = tok.str(); - auto ref = get_LifetimeRef(lex, mv$(tok)); - ret.add_lft_param(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), - Ident(lex.getHygiene(), param_name) )); - if( GET_TOK(tok, lex) == TOK_COLON ) - { - do { - GET_CHECK_TOK(tok, lex, TOK_LIFETIME); - ret.add_bound(AST::GenericBound::make_Lifetime({ AST::LifetimeRef(ref), - get_LifetimeRef(lex, mv$(tok)) })); - } while( GET_TOK(tok, lex) == TOK_PLUS ); - } - } - else - { - throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_LIFETIME}); - } - } while( tok.type() == TOK_COMMA ); - PUTBACK(tok, lex); - return ret; -} - - -/// Parse the contents of a 'where' clause -void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params) -{ - TRACE_FUNCTION; - Token tok; - - do { - GET_TOK(tok, lex); - if( tok.type() == TOK_BRACE_OPEN ) { - break; - } - - if( tok.type() == TOK_LIFETIME ) - { - auto lhs = get_LifetimeRef(lex, mv$(tok)); - GET_CHECK_TOK(tok, lex, TOK_COLON); - do { - GET_CHECK_TOK(tok, lex, TOK_LIFETIME); - auto rhs = get_LifetimeRef(lex, mv$(tok)); - params.add_bound( AST::GenericBound::make_Lifetime({lhs, rhs}) ); - } while( GET_TOK(tok, lex) == TOK_PLUS ); - PUTBACK(tok, lex); - } - // Higher-ranked types/lifetimes - else if( tok.type() == TOK_RWORD_FOR ) - { - auto hrbs = Parse_HRB(lex); - - TypeRef type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_COLON); - Parse_TypeBound(lex,params, mv$(type), mv$(hrbs)); - } - else - { - PUTBACK(tok, lex); - TypeRef type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_COLON); - Parse_TypeBound(lex, params, mv$(type)); - } - } while( GET_TOK(tok, lex) == TOK_COMMA ); - PUTBACK(tok, lex); -} - -// Parse a single function argument -::std::pair< AST::Pattern, TypeRef> Parse_Function_Arg(TokenStream& lex, bool expect_named) -{ - TRACE_FUNCTION_F("expect_named = " << expect_named); - Token tok; - - AST::Pattern pat; - - // If any of the following - // - Expecting a named parameter (i.e. defining a function in root or impl) - // - Next token is an underscore (only valid as a pattern here) - // - Next token is 'mut' (a mutable parameter slot) - // - Next two are ':' (a trivial named parameter) - // NOTE: When not expecting a named param, destructuring patterns are not allowed - if( expect_named - || LOOK_AHEAD(lex) == TOK_UNDERSCORE - || LOOK_AHEAD(lex) == TOK_RWORD_MUT - || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) - ) - { - // Function args can't be refuted - pat = Parse_Pattern(lex, false); - GET_CHECK_TOK(tok, lex, TOK_COLON); - } - - TypeRef type = Parse_Type(lex); - - - return ::std::make_pair( ::std::move(pat), ::std::move(type) ); -} - -/// Parse a function definition (after the 'fn ') -AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_self, - bool can_be_prototype, bool is_unsafe, bool is_const) -{ - TRACE_FUNCTION; - ProtoSpan ps = lex.start_span(); - - Token tok; - - // Parameters - AST::GenericParams params; - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - } - else { - PUTBACK(tok, lex); - } - - AST::Function::Arglist args; - - GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); - GET_TOK(tok, lex); - - // Handle self - if( tok.type() == TOK_AMP ) - { - // By-reference method? - - unsigned int ofs = 0; - // Handle a lifetime parameter name - if( lex.lookahead(0) == TOK_LIFETIME ) - ofs ++; - - if( lex.lookahead(ofs) == TOK_RWORD_SELF || (lex.lookahead(ofs) == TOK_RWORD_MUT - && lex.lookahead(ofs+1) == TOK_RWORD_SELF) ) - { - auto ps = lex.start_span(); - AST::LifetimeRef lifetime; - if( GET_TOK(tok, lex) == TOK_LIFETIME ) { - lifetime = get_LifetimeRef(lex, mv$(tok)); - GET_TOK(tok, lex); - } - - bool is_mut = false; - if( tok.type() == TOK_RWORD_MUT ) - { - is_mut = true; - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_RWORD_SELF); - auto sp = lex.end_span(ps); - args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), sp, "self"), - TypeRef(TypeRef::TagReference(), sp, ::std::move(lifetime), is_mut, - TypeRef(sp, "Self", 0xFFFF))) ); - if( allow_self == false ) - throw ParseError::Generic(lex, "Self binding not expected"); - - // Prime tok for next step - GET_TOK(tok, lex); - } - else - { - // Unbound method - } - } - else if( tok.type() == TOK_RWORD_MUT ) - { - if( LOOK_AHEAD(lex) == TOK_RWORD_SELF ) - { - GET_TOK(tok, lex); - if( allow_self == false ) - throw ParseError::Generic(lex, "Self binding not expected"); - auto binding_sp = lex.end_span(ps); - TypeRef ty = TypeRef( lex.point_span(), "Self", 0xFFFF ); - if( GET_TOK(tok, lex) == TOK_COLON ) { - // Typed mut self - ty = Parse_Type(lex); - } - else { - PUTBACK(tok, lex); - } - args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), binding_sp, - "self"), mv$(ty)) ); - GET_TOK(tok, lex); - } - } - else if( tok.type() == TOK_RWORD_SELF ) - { - // By-value method - if( allow_self == false ) - throw ParseError::Generic(lex, "Self binding not expected"); - auto binding_sp = lex.end_span(ps); - TypeRef ty = TypeRef( lex.point_span(), "Self", 0xFFFF ); - if( GET_TOK(tok, lex) == TOK_COLON ) { - // Typed mut self - ty = Parse_Type(lex); - } - else { - PUTBACK(tok, lex); - } - args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), binding_sp, "self"), - mv$(ty)) ); - GET_TOK(tok, lex); - } - else - { - // Unbound method - } - - bool is_variadic = false; - if( tok.type() != TOK_PAREN_CLOSE ) - { - // Comma after self - if( args.size() ) - { - CHECK_TOK(tok, TOK_COMMA); - } - else { - PUTBACK(tok, lex); - } - - // Argument list - do { - if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) { - GET_TOK(tok, lex); - break; - } - if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) { - GET_TOK(tok, lex); - is_variadic = true; - GET_TOK(tok, lex); - break; - } - args.push_back( Parse_Function_Arg(lex, !can_be_prototype) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - } - else { - // Eat 'tok', negative comparison - } - - TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos())); - if( GET_TOK(tok, lex) == TOK_THINARROW ) - { - // Return type - ret_type = Parse_Type(lex); - } - else - { - PUTBACK(tok, lex); - } - - if( GET_TOK(tok, lex) == TOK_RWORD_WHERE ) - { - Parse_WhereClause(lex, params); - } - else { - PUTBACK(tok, lex); - } - - return AST::Function(lex.end_span( mv$(ps) ), mv$(params), mv$(abi), is_unsafe, is_const, - is_variadic, mv$(ret_type), mv$(args)); -} - -AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, bool allow_self, - bool is_unsafe, bool is_const) -{ - Token tok; - auto ret = Parse_FunctionDef(lex, abi, allow_self, false, is_unsafe, is_const); - GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - // Enter a new hygine scope for the function (TODO: Should this be in Parse_ExprBlock?) - lex.push_hygine(); - PUTBACK(tok, lex); - ret.set_code( Parse_ExprBlock(lex) ); - lex.pop_hygine(); - return ret; -} - -AST::TypeAlias Parse_TypeAlias(TokenStream& lex) -{ - TRACE_FUNCTION; - - Token tok; - - // Params - AST::GenericParams params; - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - GET_TOK(tok, lex); - } - - if( tok.type() == TOK_RWORD_WHERE ) - { - Parse_WhereClause(lex, params); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_EQUAL); - - // Type - TypeRef type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - return AST::TypeAlias( ::std::move(params), ::std::move(type) ); -} - -AST::Struct Parse_Struct(TokenStream& lex, const AST::AttributeList& meta_items) -{ - TRACE_FUNCTION; - - Token tok; - - tok = lex.getToken(); - AST::GenericParams params; - if( tok.type() == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - if(GET_TOK(tok, lex) == TOK_RWORD_WHERE) - { - Parse_WhereClause(lex, params); - tok = lex.getToken(); - } - } - if(tok.type() == TOK_PAREN_OPEN) - { - // Tuple structs - ::std::vector refs; - while(lex.lookahead(0) != TOK_PAREN_CLOSE) - { - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - bool is_pub = Parse_Publicity(lex, /*allow_restricted=*/false); // HACK: Disable `pub(restricted)` syntax in tuple structs, due to ambiguity - - refs.push_back( AST::TupleItem( mv$(item_attrs), is_pub, Parse_Type(lex) ) ); - if( GET_TOK(tok, lex) != TOK_COMMA ) { - PUTBACK(tok, lex); - break; - } - } - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); - - if(LOOK_AHEAD(lex) == TOK_RWORD_WHERE) - { - GET_TOK(tok, lex); - Parse_WhereClause(lex, params); - } - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - //if( refs.size() == 0 ) - // WARNING( , W000, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong"); - return AST::Struct(mv$(params), mv$(refs)); - } - else if(tok.type() == TOK_SEMICOLON) - { - // Unit-like struct - return AST::Struct(mv$(params)); - } - else if(tok.type() == TOK_BRACE_OPEN) - { - ::std::vector items; - while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - PUTBACK(tok, lex); - - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - bool is_pub = Parse_Publicity(lex); - - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - TypeRef type = Parse_Type(lex); - - items.push_back( AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(type) ) ); - if(GET_TOK(tok, lex) == TOK_BRACE_CLOSE) - break; - CHECK_TOK(tok, TOK_COMMA); - } - //if( items.size() == 0 ) - // WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong"); - return AST::Struct(mv$(params), mv$(items)); - } - else - { - throw ParseError::Unexpected(lex, tok); - } -} - -AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items) -{ - TRACE_FUNCTION; - - Token tok; - - AST::GenericParams params; - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - tok = lex.getToken(); - } - - // Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2" - ::std::vector > supertraits; - if(tok.type() == TOK_COLON) - { - // TODO: Just add these as `where Self: ` (would that break typecheck?) - do { - if( GET_TOK(tok, lex) == TOK_LIFETIME ) { - // TODO: Need a better way of indiciating 'static than just an invalid path - ASSERT_BUG(lex.point_span(), tok.str() == "static", - "TODO: Support lifetimes other than 'static in trait bounds"); - supertraits.push_back( make_spanned( Span(tok.get_pos()), Type_TraitPath{ {}, - AST::Path() } ) ); - } - else if( tok.type() == TOK_BRACE_OPEN ) { - break; - } - else { - PUTBACK(tok, lex); - auto hrbs = Parse_HRB_Opt(lex); - supertraits.push_back( GET_SPANNED(Type_TraitPath, lex, (Type_TraitPath{ mv$(hrbs), - Parse_Path(lex, PATH_GENERIC_TYPE) })) ); - } - } while( GET_TOK(tok, lex) == TOK_PLUS ); - } - - if(tok.type() == TOK_RWORD_WHERE) - { - //if( params.ty_params().size() == 0 ) - // throw ParseError::Generic("Where clause with no generic params"); - Parse_WhereClause(lex, params); - tok = lex.getToken(); - } - - - AST::Trait trait( mv$(params), mv$(supertraits) ); - - CHECK_TOK(tok, TOK_BRACE_OPEN); - while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - PUTBACK(tok, lex); - - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - auto ps = lex.start_span(); - { - ::AST::MacroInvocation inv; - if( Parse_MacroInvocation_Opt(lex, inv) ) - { - trait.items().push_back( AST::Named("", AST::Item(mv$(inv)), false) ); - continue ; - } - GET_TOK(tok, lex); - } - - bool is_specialisable = false; - if( tok.type() == TOK_IDENT && tok.str() == "default" ) { - is_specialisable = true; - GET_TOK(tok, lex); - } - // TODO: Mark specialisation - (void)is_specialisable; - - bool fn_is_const = false; - bool fn_is_unsafe = false; - ::std::string abi = ABI_RUST; - switch(tok.type()) - { - case TOK_RWORD_STATIC: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto ty = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - ::AST::Expr val; - if(GET_TOK(tok, lex) == TOK_EQUAL) { - val = Parse_Expr(lex); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_SEMICOLON); - - trait.add_static( mv$(name), mv$(item_attrs), ::AST::Static(AST::Static::STATIC, mv$(ty), - val) ); - break; } - case TOK_RWORD_CONST: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto ty = Parse_Type(lex); - - ::AST::Expr val; - if(GET_TOK(tok, lex) == TOK_EQUAL) { - val = Parse_Expr(lex); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_SEMICOLON); - - trait.add_static( mv$(name), mv$(item_attrs), ::AST::Static(AST::Static::CONST, mv$(ty), - val) ); - break; } - // Associated type - case TOK_RWORD_TYPE: { - auto atype_params = ::AST::GenericParams { }; - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - if( GET_TOK(tok, lex) == TOK_COLON ) - { - // Bounded associated type - Parse_TypeBound(lex, atype_params, TypeRef(lex.point_span(), "Self", 0xFFFF)); - GET_TOK(tok, lex); - } - if( tok.type() == TOK_RWORD_WHERE ) { - throw ParseError::Todo(lex, "Where clause on associated type"); - } - - TypeRef default_type = TypeRef( lex.point_span() ); - if( tok.type() == TOK_EQUAL ) { - default_type = Parse_Type(lex); - GET_TOK(tok, lex); - } - - CHECK_TOK(tok, TOK_SEMICOLON); - trait.add_type( ::std::move(name), mv$(item_attrs), ::std::move(default_type) ); - trait.items().back().data.as_Type().params() = mv$(atype_params); - break; } - - // Functions (possibly unsafe) - case TOK_RWORD_UNSAFE: - fn_is_unsafe = true; - if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN ) - case TOK_RWORD_EXTERN: - { - abi = "C"; - if( GET_TOK(tok, lex) == TOK_STRING ) - abi = tok.str(); - else - PUTBACK(tok, lex); - - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_RWORD_FN); - case TOK_RWORD_FN: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = mv$(tok.str()); - // Self allowed, prototype-form allowed (optional names and no code) - auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const); - if( GET_TOK(tok, lex) == TOK_BRACE_OPEN ) - { - PUTBACK(tok, lex); - // Enter a new hygine scope for the function body. (TODO: Should this be in Parse_ExprBlock?) - lex.push_hygine(); - fcn.set_code( Parse_ExprBlock(lex) ); - lex.pop_hygine(); - } - else if( tok.type() == TOK_SEMICOLON ) - { - // Accept it - } - else - { - throw ParseError::Unexpected(lex, tok); - } - trait.add_function( ::std::move(name), mv$(item_attrs), ::std::move(fcn) ); - break; } - default: - throw ParseError::Unexpected(lex, tok); - } - } - - return trait; -} - -AST::Enum Parse_EnumDef(TokenStream& lex, const AST::AttributeList& meta_items) -{ - TRACE_FUNCTION; - - Token tok; - - tok = lex.getToken(); - // Type params supporting "where" - AST::GenericParams params; - if( tok.type() == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - if(GET_TOK(tok, lex) == TOK_RWORD_WHERE) - { - Parse_WhereClause(lex, params); - tok = lex.getToken(); - } - } - - // Body - CHECK_TOK(tok, TOK_BRACE_OPEN); - ::std::vector variants; - while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - auto sp = lex.start_span(); - PUTBACK(tok, lex); - - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = mv$(tok.str()); - // Tuple-like variants - if( GET_TOK(tok, lex) == TOK_PAREN_OPEN ) - { - ::std::vector types; - // Get type list - do - { - if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE) - { - GET_TOK(tok, lex); - break; - } - - auto field_attrs = Parse_ItemAttrs(lex); - (void)field_attrs; // TODO: Store field_attrs - - types.push_back( Parse_Type(lex) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - GET_TOK(tok, lex); - variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) ); - } - // Struct-like variants - else if( tok.type() == TOK_BRACE_OPEN ) - { - ::std::vector<::AST::StructItem> fields; - do - { - if(LOOK_AHEAD(lex) == TOK_BRACE_CLOSE) - { - GET_TOK(tok, lex); - break; - } - - auto field_attrs = Parse_ItemAttrs(lex); - - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto ty = Parse_Type(lex); - fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_BRACE_CLOSE); - GET_TOK(tok, lex); - - variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) ); - } - // Value variants - else if( tok.type() == TOK_EQUAL ) - { - auto node = Parse_Expr(lex); - variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) ); - GET_TOK(tok, lex); - } - // Unit variants - else - { - variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), ::AST::Expr()) ); - } - - if( tok.type() != TOK_COMMA ) - break; - } - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - - return AST::Enum( mv$(params), mv$(variants) ); -} - -::AST::Union Parse_Union(TokenStream& lex, AST::AttributeList& meta_items) -{ - Token tok; - - TRACE_FUNCTION; - - AST::GenericParams params; - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - if(GET_TOK(tok, lex) == TOK_RWORD_WHERE) - { - Parse_WhereClause(lex, params); - tok = lex.getToken(); - } - } - - ::std::vector< ::AST::StructItem> variants; - - CHECK_TOK(tok, TOK_BRACE_OPEN); - do { - if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) { - GET_TOK(tok, lex); - break ; - } - - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - bool is_pub = Parse_Publicity(lex); - - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - - auto ty = Parse_Type(lex); - - variants.push_back( ::AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(ty) ) ); - - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_BRACE_CLOSE); - - return ::AST::Union( mv$(params), mv$(variants) ); -} - -AST::AttributeList Parse_ItemAttrs(TokenStream& lex) -{ - AST::AttributeList rv; - Token tok; - while( lex.lookahead(0) == TOK_HASH ) - { - GET_CHECK_TOK(tok, lex, TOK_HASH); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_OPEN); - rv.push_back( Parse_MetaItem(lex) ); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - } - return rv; -} -void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out) -{ - Token tok; - while( lex.lookahead(0) == TOK_HASH && lex.lookahead(1) == TOK_EXCLAM ) - { - GET_CHECK_TOK(tok, lex, TOK_HASH); - GET_CHECK_TOK(tok, lex, TOK_EXCLAM); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_OPEN); - out.push_back( Parse_MetaItem(lex) ); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - } -} -/// Parse a meta-item declaration (either #![ or #[) -AST::Attribute Parse_MetaItem(TokenStream& lex) -{ - TRACE_FUNCTION; - Token tok; - GET_TOK(tok, lex); - - if( tok.type() == TOK_INTERPOLATED_META ) { - return mv$(tok.frag_meta()); - } - - auto ps = lex.start_span(); - CHECK_TOK(tok, TOK_IDENT); - ::std::string name = mv$(tok.str()); - switch(GET_TOK(tok, lex)) - { - case TOK_EQUAL: - switch(GET_TOK(tok, lex)) - { - case TOK_STRING: - return AST::Attribute(lex.end_span(mv$(ps)), name, tok.str()); - case TOK_INTERPOLATED_EXPR: { - auto n = tok.take_frag_node(); - if( auto* v = dynamic_cast<::AST::ExprNode_String*>(&*n) ) - { - return AST::Attribute(lex.end_span(mv$(ps)), name, mv$(v->m_value)); - } - else - { - // - Force an error. - CHECK_TOK(tok, TOK_STRING); - } - break; } - default: - // - Force an error. - CHECK_TOK(tok, TOK_STRING); - } - throw ""; - case TOK_PAREN_OPEN: { - ::std::vector items; - do { - if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE) { - GET_TOK(tok, lex); - break; - } - items.push_back(Parse_MetaItem(lex)); - } while(GET_TOK(tok, lex) == TOK_COMMA); - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return AST::Attribute(lex.end_span(mv$(ps)), name, mv$(items)); } - default: - PUTBACK(tok, lex); - return AST::Attribute(lex.end_span(mv$(ps)), name); - } -} - -::AST::Item Parse_Impl(TokenStream& lex, AST::AttributeList attrs, bool is_unsafe=false) -{ - TRACE_FUNCTION; - Token tok; - auto ps = lex.start_span(); - - AST::GenericParams params; - // 1. (optional) type parameters - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_GenericParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - } - else { - PUTBACK(tok, lex); - } - // 2. Either a trait name (with type params), or the type to impl - - Spanned trait_path; - - // - Handle negative impls specially, which must be a trait - // "impl !Trait for Type {}" - if( GET_TOK(tok, lex) == TOK_EXCLAM ) - { - trait_path = GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE)); - GET_CHECK_TOK(tok, lex, TOK_RWORD_FOR); - auto impl_type = Parse_Type(lex, true); - - if( GET_TOK(tok, lex) == TOK_RWORD_WHERE ) - { - Parse_WhereClause(lex, params); - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_BRACE_OPEN); - // negative impls can't have any content - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - - return ::AST::Item::make_NegImpl(AST::ImplDef( mv$(attrs), mv$(params), mv$(trait_path), - mv$(impl_type) )); - } - - // - Don't care which at this stage - PUTBACK(tok, lex); - - auto impl_type = Parse_Type(lex, true); - - if( GET_TOK(tok, lex) == TOK_RWORD_FOR ) - { - // Trickery! All traits parse as valid types, so this works. - if( !impl_type.is_path() ) - throw ParseError::Generic(lex, "Trait was not a path"); - trait_path = Spanned< AST::Path> { - impl_type.span(), - mv$(impl_type.path()) - }; - // Implementing a trait for another type, get the target type - if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT ) - { - // Default impl - impl_type = TypeRef(TypeRef::TagInvalid(), lex.point_span()); - } - else - { - PUTBACK(tok, lex); - impl_type = Parse_Type(lex, true); - } - } - else { - PUTBACK(tok, lex); - } - - // Where clause - if( GET_TOK(tok, lex) == TOK_RWORD_WHERE ) - { - Parse_WhereClause(lex, params); - } - else { - PUTBACK(tok, lex); - } - GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - - Parse_ParentAttrs(lex, attrs); - - auto impl = AST::Impl(AST::ImplDef( mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) )); - - // A sequence of method implementations - while( lex.lookahead(0) != TOK_BRACE_CLOSE ) - { - Parse_Impl_Item(lex, impl); - } - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - - return ::AST::Item::make_Impl( mv$(impl) ); -} - -void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) -{ - TRACE_FUNCTION; - Token tok; - - auto item_attrs = Parse_ItemAttrs(lex); - SET_ATTRS(lex, item_attrs); - - { - ::AST::MacroInvocation inv; - if( Parse_MacroInvocation_Opt(lex, inv) ) - { - impl.add_macro_invocation( mv$(inv) ); - impl.items().back().data->attrs = mv$(item_attrs); - return ; - } - } - - auto ps = lex.start_span(); - - bool is_public = Parse_Publicity(lex); - GET_TOK(tok, lex); - - bool is_specialisable = false; - if( tok.type() == TOK_IDENT && tok.str() == "default" ) { - is_specialisable = true; - GET_TOK(tok, lex); - } - - ::std::string abi = ABI_RUST; - bool fn_is_unsafe = false; - bool fn_is_const = false; - switch(tok.type()) - { - case TOK_RWORD_TYPE: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - impl.add_type(is_public, is_specialisable, name, Parse_Type(lex)); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - break; } - case TOK_RWORD_UNSAFE: - fn_is_unsafe = true; - GET_TOK(tok, lex); - if( tok.type() == TOK_RWORD_CONST ) - case TOK_RWORD_CONST: - { - GET_TOK(tok, lex); - if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE && !fn_is_unsafe ) - { - CHECK_TOK(tok, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto ty = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - auto val = Parse_Expr(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val)); - impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) ); - break ; - } - else if( tok.type() == TOK_RWORD_UNSAFE ) - { - fn_is_unsafe = true; - GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); - } - fn_is_const = true; - } - if( tok.type() == TOK_RWORD_EXTERN ) - // FALL - case TOK_RWORD_EXTERN: - { - abi = "C"; - if( GET_TOK(tok, lex) == TOK_STRING ) - abi = tok.str(); - else - PUTBACK(tok, lex); - - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_RWORD_FN); - // FALL - case TOK_RWORD_FN: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - // TODO: Hygine on function names? - Not in impl blocks? - ::std::string name = mv$(tok.str()); - DEBUG("Function " << name); - // - Self allowed, can't be prototype-form - auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const); - impl.add_function(is_public, is_specialisable, mv$(name), mv$(fcn)); - break; } - - default: - throw ParseError::Unexpected(lex, tok); - } - - impl.items().back().data->span = lex.end_span(mv$(ps)); - impl.items().back().data->attrs = mv$(item_attrs); // Empty for functions -} - -AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, - ::AST::AttributeList& block_attrs) -{ - TRACE_FUNCTION; - Token tok; - - Parse_ParentAttrs(lex, block_attrs); - - AST::ExternBlock rv { abi }; - - while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - PUTBACK(tok, lex); - auto meta_items = Parse_ItemAttrs(lex); - SET_ATTRS(lex, meta_items); - - auto ps = lex.start_span(); - - bool is_public = Parse_Publicity(lex); - switch( GET_TOK(tok, lex) ) - { - case TOK_RWORD_FN: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - // parse function as prototype - // - no self, is prototype, is unsafe and not const - auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, true,false) ); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - i.attrs = mv$(meta_items); - i.span = lex.end_span(mv$(ps)); - - rv.add_item( AST::Named { mv$(name), mv$(i), is_public } ); - break; } - case TOK_RWORD_STATIC: { - bool is_mut = false; - if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) - is_mut = true; - else - PUTBACK(tok, lex); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - GET_CHECK_TOK(tok, lex, TOK_COLON); - auto type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - - auto i = ::AST::Item(::AST::Static( (is_mut ? ::AST::Static::MUT : ::AST::Static::STATIC), - mv$(type), ::AST::Expr() )); - i.attrs = mv$(meta_items); - i.span = lex.end_span(mv$(ps)); - rv.add_item( AST::Named { mv$(name), mv$(i), is_public } ); - break; } - default: - throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_STATIC}); - } - } - - return rv; -} - -void Parse_Use_Wildcard(Span sp, AST::Path base_path, ::std::function fcn) -{ - fcn( AST::UseStmt(mv$(sp), mv$(base_path)), "" ); // HACK! Empty path indicates wilcard import -} -void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_path, - ::std::function fcn) -{ - TRACE_FUNCTION; - - Token tok; - do { - AST::Path path; - ::std::string name; - if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) { - path = ::AST::Path(base_path); - name = base_path[base_path.size()-1].name(); - } - else if( tok.type() == TOK_BRACE_CLOSE ) { - break ; - } - else { - CHECK_TOK(tok, TOK_IDENT); - path = base_path + AST::PathNode(tok.str(), {}); - name = mv$(tok.str()); - } - - if( GET_TOK(tok, lex) == TOK_RWORD_AS ) { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); - } - else { - PUTBACK(tok, lex); - } - fcn(AST::UseStmt(lex.end_span(ps), mv$(path)), mv$(name)); - } while( GET_TOK(tok, lex) == TOK_COMMA ); - PUTBACK(tok, lex); -} - -void Parse_Use(TokenStream& lex, ::std::function fcn) -{ - TRACE_FUNCTION; - - Token tok; - AST::Path path = AST::Path("", {}); - ::std::vector nodes; - ProtoSpan span_start = lex.start_span(); - - switch( GET_TOK(tok, lex) ) - { - case TOK_RWORD_SELF: - path = AST::Path( AST::Path::TagSelf(), {} ); // relative path - break; - case TOK_RWORD_SUPER: { - unsigned int count = 1; - while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON && lex.lookahead(1) == TOK_RWORD_SUPER ) { - GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); - GET_CHECK_TOK(tok, lex, TOK_RWORD_SUPER); - count += 1; - } - path = AST::Path( AST::Path::TagSuper(), count, {} ); - break; } - case TOK_IDENT: - path.append( AST::PathNode(mv$(tok.str()), {}) ); - break; - // Leading :: is allowed and ignored for the $crate feature - case TOK_DOUBLE_COLON: - // Absolute path - // HACK! mrustc emits $crate as `::"crate-name"` - if( LOOK_AHEAD(lex) == TOK_STRING ) - { - GET_CHECK_TOK(tok, lex, TOK_STRING); - path = ::AST::Path(tok.str(), {}); - } - else { - PUTBACK(tok, lex); - } - break; - case TOK_BRACE_OPEN: - Parse_Use_Set(lex, span_start, path, fcn); - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - return; - case TOK_STAR: - Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn ); - return; - case TOK_INTERPOLATED_PATH: - path = mv$(tok.frag_path()); - break; - default: - throw ParseError::Unexpected(lex, tok); - } - while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ) - { - if( GET_TOK(tok, lex) == TOK_IDENT ) - { - path.append( AST::PathNode( mv$(tok.str()), {}) ); - } - else - { - //path.set_span( lex.end_span(span_start) ); - switch( tok.type() ) - { - case TOK_BRACE_OPEN: - Parse_Use_Set(lex, span_start, mv$(path), fcn); - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - break ; - case TOK_STAR: - Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn ); - break ; - default: - throw ParseError::Unexpected(lex, tok); - } - // early return - This branch is either the end of the use statement, or a syntax error - return ; - } - } - //path.set_span( lex.end_span(span_start) ); - - ::std::string name; - // This should only be allowed if the last token was an ident - // - Above checks ensure this - if( tok.type() == TOK_RWORD_AS ) - { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - name = mv$(tok.str()); - } - else - { - PUTBACK(tok, lex); - ASSERT_BUG(lex.point_span(), path.nodes().size() > 0, "`use` with no path"); - name = path.nodes().back().name(); - } - - fcn( AST::UseStmt(lex.end_span(span_start), mv$(path)), name); -} - - -::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, ::std::string name, - TokenStream& lex) -{ - Token tok; - ::std::string ident; - if( GET_TOK(tok, lex) == TOK_IDENT ) { - ident = mv$(tok.str()); - } - else { - PUTBACK(tok, lex); - } - DEBUG("name=" << name << ", ident=" << ident); - TokenTree tt = Parse_TT(lex, true); - return ::AST::MacroInvocation( lex.end_span(span_start), mv$(name), mv$(ident), mv$(tt)); -} - -bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv) -{ - Token tok; - if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_EXCLAM ) - { - // Good - } - else - { - return false; - } - - auto ps = lex.start_span(); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_EXCLAM); - - bool is_braced = (lex.lookahead(0) == TOK_BRACE_OPEN || (lex.lookahead(0) == TOK_IDENT - && lex.lookahead(1) == TOK_BRACE_OPEN)); - - out_inv = Parse_MacroInvocation(ps, name, lex); - - if(!is_braced ) - { - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - } - return true; -} - -::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, - const ::AST::Path& mod_path, AST::AttributeList meta_items) -{ - TRACE_FUNCTION_F("mod_path="<" fn ...` - // `extern "" { ...` - case TOK_STRING: { - ::std::string abi = tok.str(); - switch(GET_TOK(tok, lex)) - { - // `extern "" fn ...` - case TOK_RWORD_FN: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, false,false) ); - break; } - // `extern "ABI" {` - case TOK_BRACE_OPEN: - item_name = ""; - item_data = ::AST::Item( Parse_ExternBlock(lex, mv$(abi), meta_items) ); - break; - default: - throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_BRACE_OPEN}); - } - break; } - // `extern fn ...` - case TOK_RWORD_FN: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, "C", false, false,false) ); - break; - - // NOTE: `extern { ...` is handled in caller - case TOK_BRACE_OPEN: - item_name = ""; - item_data = ::AST::Item( Parse_ExternBlock(lex, "C", meta_items) ); - break; - - // `extern crate "crate-name" as crate_name;` - // `extern crate crate_name;` - // `extern crate crate_name as other_name;` - case TOK_RWORD_CRATE: - switch( GET_TOK(tok, lex) ) - { - // `extern crate "crate-name" as crate_name;` - // NOTE: rustc doesn't allow this, keep in mrustc for for reparse support - case TOK_STRING: - item_data = ::AST::Item::make_Crate({ tok.str() }); - GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - break; - // `extern crate crate_name;` - // `extern crate crate_name as other_name;` - case TOK_IDENT: - item_name = mv$(tok.str()); - if(GET_TOK(tok, lex) == TOK_RWORD_AS) { - item_data = ::AST::Item::make_Crate({ mv$(item_name) }); - - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - } - else { - PUTBACK(tok, lex); - item_data = ::AST::Item::make_Crate({ item_name }); - } - break; - default: - throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT}); - } - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - break; - default: - throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_RWORD_FN, TOK_BRACE_OPEN, - TOK_RWORD_CRATE}); - } - break; - - // `const NAME` - // `const [unsafe] fn` - case TOK_RWORD_CONST: - switch( GET_TOK(tok, lex) ) - { - case TOK_IDENT: { - item_name = mv$(tok.str()); - - GET_CHECK_TOK(tok, lex, TOK_COLON); - TypeRef type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - AST::Expr val = Parse_Expr(lex); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - item_data = ::AST::Item( ::AST::Static(AST::Static::CONST, mv$(type), mv$(val)) ); - break; } - case TOK_RWORD_UNSAFE: - GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, - true,true/*unsafe,const*/) ); - break; - case TOK_RWORD_FN: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - // - self not allowed, not prototype - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, - false,true/*unsafe,const*/) ); - break; - default: - throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_RWORD_FN}); - } - break; - // `static NAME` - // `static mut NAME` - case TOK_RWORD_STATIC: { - bool is_mut = false; - if(GET_TOK(tok, lex) == TOK_RWORD_MUT) { - is_mut = true; - GET_TOK(tok, lex); - } - CHECK_TOK(tok, TOK_IDENT); - item_name = mv$(tok.str()); - - GET_CHECK_TOK(tok, lex, TOK_COLON); - TypeRef type = Parse_Type(lex); - - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - - AST::Expr val = Parse_Expr(lex); - - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - item_data = ::AST::Item( ::AST::Static( (is_mut ? AST::Static::MUT : AST::Static::STATIC), - mv$(type), mv$(val)) ); - break; } - - // `unsafe fn` - // `unsafe trait` - // `unsafe impl` - case TOK_RWORD_UNSAFE: - switch(GET_TOK(tok, lex)) - { - // `unsafe extern fn` - case TOK_RWORD_EXTERN: { - ::std::string abi = "C"; - if(GET_TOK(tok, lex) == TOK_STRING) { - abi = mv$(tok.str()); - } - else { - PUTBACK(tok, lex); - } - GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, - true,false/*unsafe,const*/) ); - break; } - // `unsafe fn` - case TOK_RWORD_FN: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - // - self not allowed, not prototype - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, - true,false/*unsafe,const*/) ); - break; - // `unsafe trait` - case TOK_RWORD_TRAIT: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - auto tr = Parse_TraitDef(lex, meta_items); - tr.set_is_unsafe(); - item_data = ::AST::Item( ::std::move(tr) ); - break; } - // `unsafe impl` - case TOK_RWORD_IMPL: { - auto impl = Parse_Impl(lex, mv$(meta_items), true); - if( impl.is_Impl() ) { - impl.as_Impl().def().set_is_unsafe(); - } - else if( impl.is_NegImpl() ) { - impl.as_NegImpl().set_is_unsafe(); - } - else { - BUG(lex.point_span(), "Parse_Impl returned a variant other than Impl or NegImpl"); - } - return ::AST::Named< ::AST::Item> { "", mv$(impl), false }; - } - default: - throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL}); - } - break; - // `fn` - case TOK_RWORD_FN: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - // - self not allowed, not prototype - item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, - false,false/*unsafe,const*/) ); - break; - // `type` - case TOK_RWORD_TYPE: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_TypeAlias(lex) ); - break; - // `struct` - case TOK_RWORD_STRUCT: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_Struct(lex, meta_items) ); - break; - // `enum` - case TOK_RWORD_ENUM: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_EnumDef(lex, meta_items) ); - break; - // Contextual keywords - case TOK_IDENT: - if( tok.str() == "union" ) { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_Union(lex, meta_items) ); - } - else { - throw ParseError::Unexpected(lex, tok); - } - break; - // `impl` - case TOK_RWORD_IMPL: - return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items)), false }; - // `trait` - case TOK_RWORD_TRAIT: - GET_CHECK_TOK(tok, lex, TOK_IDENT); - item_name = mv$(tok.str()); - item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) ); - break; - - case TOK_RWORD_MOD: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - auto name = mv$(tok.str()); - DEBUG("Sub module '" << name << "'"); - AST::Module submod( mod_path + name ); - - // Rules for external files (/ path handling): - // - IF using stdin (path='-') - Disallow and propagate '-' as path - // - IF a #[path] attribute was passed, allow - // - IF in crate root or mod.rs, allow (input flag) - // - else, disallow and set flag - ::std::string path_attr = (meta_items.has("path") ? meta_items.get("path")->string() : ""); - - //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON); - - ::std::string sub_path; - bool sub_file_controls_dir = true; - if( mod_fileinfo.path == "-" ) { - if( path_attr.size() ) { - ERROR(lex.point_span(), E0000, "Cannot load module from file when reading stdin"); - } - sub_path = "-"; - } - else if( path_attr.size() > 0 ) - { - sub_path = dirname(mod_fileinfo.path) + path_attr; - } - else if( mod_fileinfo.controls_dir ) - { - sub_path = dirname(mod_fileinfo.path) + name; - } - else - { - sub_path = mod_fileinfo.path; - sub_file_controls_dir = false; - } - DEBUG("Mod '" << name << "', sub_path = " << sub_path); - - submod.m_file_info.path = sub_path; - submod.m_file_info.controls_dir = sub_file_controls_dir; - - // Check #[cfg] and don't load if it fails - struct H { - static bool check_item_cfg(const ::AST::AttributeList& attrs) - { - for(const auto& at : attrs.m_items) { - if( at.name() == "cfg" && !check_cfg(at.span(), at) ) { - return false; - } - } - return true; - } - }; - - switch( GET_TOK(tok, lex) ) - { - case TOK_BRACE_OPEN: - submod.m_file_info.path = sub_path + "/"; - Parse_ModRoot(lex, submod, meta_items); - GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); - break; - case TOK_SEMICOLON: - if( sub_path == "-" ) { - ERROR(lex.point_span(), E0000, "Cannot load module from file when reading stdin"); - } - else if( path_attr.size() == 0 && ! mod_fileinfo.controls_dir ) - { - ERROR(lex.point_span(), E0000, "Can't load from files outside of mod.rs or crate root"); - } - else if( !H::check_item_cfg(meta_items) ) { - // Ignore - emit Item::None - item_name = mv$(name); - item_data = ::AST::Item( ); - break ; - } - else - { - ::std::string newpath_dir = sub_path + "/"; - ::std::string newpath_file = path_attr.size() > 0 ? sub_path : sub_path + ".rs"; - DEBUG("newpath_dir = '" << newpath_dir << "', newpath_file = '" << newpath_file << "'"); - ::std::ifstream ifs_dir (newpath_dir + "mod.rs"); - ::std::ifstream ifs_file(newpath_file); - if( ifs_dir.is_open() && ifs_file.is_open() ) - { - // Collision - ERROR(lex.point_span(), E0000, "Both modname.rs and modname/mod.rs exist"); - } - else if( ifs_dir.is_open() ) - { - // Load from dir - submod.m_file_info.path = newpath_dir + "mod.rs"; - } - else if( ifs_file.is_open() ) - { - submod.m_file_info.path = newpath_file; - } - else - { - // Can't find file - ERROR(lex.point_span(), E0000, "Can't find file for '" << name << "' in '" << mod_fileinfo.path << "'"); - } - DEBUG("- path = " << submod.m_file_info.path); - Lexer sub_lex(submod.m_file_info.path); - Parse_ModRoot(sub_lex, submod, meta_items); - GET_CHECK_TOK(tok, sub_lex, TOK_EOF); - } - break; - default: - throw ParseError::Generic("Expected { or ; after module name"); - } - item_name = mv$(name); - item_data = ::AST::Item( mv$(submod) ); - break; } - - default: - throw ParseError::Unexpected(lex, tok); - } - - item_data.attrs = mv$(meta_items); - item_data.span = lex.end_span(mv$(ps)); - - return ::AST::Named< ::AST::Item> { mv$(item_name), mv$(item_data), is_public }; -} - -void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::AttributeList meta_items) -{ - SET_MODULE(lex, mod); - lex.parse_state().parent_attrs = &meta_items; - - //TRACE_FUNCTION; - Token tok; - - // `use ...` - // TODO: This doesn't spot `pub(path) use`. - if( LOOK_AHEAD(lex) == TOK_RWORD_USE || (lex.lookahead(0) == TOK_RWORD_PUB - && lex.lookahead(1) == TOK_RWORD_USE) ) - { - bool is_public = Parse_Publicity(lex); - GET_CHECK_TOK(tok, lex, TOK_RWORD_USE); - - Parse_Use(lex, [&mod,is_public,&meta_items](AST::UseStmt p, std::string s) { - DEBUG(mod.path() << " - use " << p << " as '" << s << "'"); - mod.add_alias(is_public, mv$(p), s, meta_items.clone()); - }); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - } - else - { - mod.add_item( Parse_Mod_Item_S(lex, mod.m_file_info, mod.path(), mv$(meta_items)) ); - } -} - -void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod) -{ - Token tok; - - for(;;) - { - // Check 1 - End of module (either via a closing brace, or EOF) - switch(GET_TOK(tok, lex)) - { - case TOK_BRACE_CLOSE: - case TOK_EOF: - PUTBACK(tok, lex); - return; - default: - PUTBACK(tok, lex); - break; - } - - // Attributes on the following item - auto meta_items = Parse_ItemAttrs(lex); - DEBUG("meta_items = " << meta_items); - - Parse_Mod_Item(lex, mod, mv$(meta_items)); - } -} - -void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::AttributeList& mod_attrs) -{ - TRACE_FUNCTION; - - // Attributes on module/crate (will continue loop) - Parse_ParentAttrs(lex, mod_attrs); - - Parse_ModRoot_Items(lex, mod); -} - -AST::Crate Parse_Crate(::std::string mainfile) -{ - Token tok; - - Lexer lex(mainfile); - - size_t p = mainfile.find_last_of('/'); - p = (p == ::std::string::npos ? mainfile.find_last_of('\\') : p); - ::std::string mainpath = (p != ::std::string::npos ? ::std::string(mainfile.begin(), - mainfile.begin()+p+1) : "./"); - - AST::Crate crate; - - //crate.root_module().m_file_info.file_path = mainfile; - crate.root_module().m_file_info.path = mainpath; - crate.root_module().m_file_info.controls_dir = true; - - Parse_ModRoot(lex, crate.root_module(), crate.m_attrs); - - return crate; -} diff --git a/gcc/rust/mrustc_parser/parse/token.cpp b/gcc/rust/mrustc_parser/parse/token.cpp deleted file mode 100644 index 2e5a61d..0000000 --- a/gcc/rust/mrustc_parser/parse/token.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - */ -#include "token.hpp" -#include -#include -#include "interpolated_fragment.hpp" -#include -#include -#include // for reasons - -Token::~Token() -{ - switch(m_type) - { - case TOK_INTERPOLATED_TYPE: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_PATTERN: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_PATH: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_EXPR: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_STMT: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_BLOCK: - delete reinterpret_cast(m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_META: - delete reinterpret_cast(m_data.as_Fragment()); - break; - default: - break; - } - -} - -Token::Token(): - m_type(TOK_NULL) -{ -} -Token::Token(enum eTokenType type): - m_type(type) -{ -} -Token::Token(enum eTokenType type, ::std::string str): - m_type(type), - m_data(Data::make_String(mv$(str))) -{ -} -Token::Token(uint64_t val, enum eCoreType datatype): - m_type(TOK_INTEGER), - m_data( Data::make_Integer({datatype, val}) ) -{ -} -Token::Token(double val, enum eCoreType datatype): - m_type(TOK_FLOAT), - m_data( Data::make_Float({datatype, val}) ) -{ -} -Token::Token(const InterpolatedFragment& frag) -{ - switch(frag.m_type) - { - case InterpolatedFragment::TT: throw ""; - case InterpolatedFragment::TYPE: - m_type = TOK_INTERPOLATED_TYPE; - m_data = new TypeRef( reinterpret_cast(frag.m_ptr)->clone() ); - break; - case InterpolatedFragment::PAT: - m_type = TOK_INTERPOLATED_PATTERN; - m_data = new AST::Pattern( reinterpret_cast(frag.m_ptr)->clone() ); - break; - case InterpolatedFragment::PATH: - m_type = TOK_INTERPOLATED_PATH; - m_data = new AST::Path( *reinterpret_cast(frag.m_ptr) ); - break; - case InterpolatedFragment::EXPR: - m_type = TOK_INTERPOLATED_EXPR; if(0) - case InterpolatedFragment::STMT: - m_type = TOK_INTERPOLATED_STMT; if(0) - case InterpolatedFragment::BLOCK: - m_type = TOK_INTERPOLATED_BLOCK; - - m_data = reinterpret_cast(frag.m_ptr)->clone().release(); - break; - case InterpolatedFragment::META: - m_type = TOK_INTERPOLATED_META; - m_data = new AST::Attribute( reinterpret_cast(frag.m_ptr)->clone() ); - break; - case InterpolatedFragment::ITEM: { - m_type = TOK_INTERPOLATED_ITEM; - const auto& named = *reinterpret_cast*>(frag.m_ptr); - ::AST::Item item = named.data.clone(); - m_data = new AST::Named( named.name, mv$(item), named.is_pub ); - break; } - } -} -Token::Token(TagTakeIP, InterpolatedFragment frag) -{ - switch(frag.m_type) - { - case InterpolatedFragment::TT: throw ""; - case InterpolatedFragment::TYPE: - m_type = TOK_INTERPOLATED_TYPE; - m_data = new TypeRef( mv$(*reinterpret_cast(frag.m_ptr)) ); - break; - case InterpolatedFragment::PAT: - m_type = TOK_INTERPOLATED_PATTERN; - m_data = new AST::Pattern( mv$(*reinterpret_cast(frag.m_ptr)) ); - break; - case InterpolatedFragment::PATH: - m_type = TOK_INTERPOLATED_PATH; - m_data = new AST::Path( mv$(*reinterpret_cast(frag.m_ptr)) ); - break; - case InterpolatedFragment::EXPR: - m_type = TOK_INTERPOLATED_EXPR; if(0) - case InterpolatedFragment::STMT: - m_type = TOK_INTERPOLATED_STMT; if(0) - case InterpolatedFragment::BLOCK: - m_type = TOK_INTERPOLATED_BLOCK; - - m_data = reinterpret_cast(frag.m_ptr); - frag.m_ptr = nullptr; - break; - case InterpolatedFragment::ITEM: - m_type = TOK_INTERPOLATED_ITEM; - m_data = frag.m_ptr; - frag.m_ptr = nullptr; - break; - case InterpolatedFragment::META: - m_type = TOK_INTERPOLATED_META; - m_data = frag.m_ptr; - frag.m_ptr = nullptr; - break; - } -} - -Token::Token(const Token& t): - m_type(t.m_type), - m_data( Data::make_None({}) ), - m_pos( t.m_pos ) -{ - assert( t.m_data.tag() != Data::TAGDEAD ); - TU_MATCH(Data, (t.m_data), (e), - (None, ), - (String, m_data = Data::make_String(e); ), - (Integer, m_data = Data::make_Integer(e);), - (Float, m_data = Data::make_Float(e);), - (Fragment, BUG(t.m_pos, "Attempted to copy a fragment - " << t);) - ) -} -Token Token::clone() const -{ - Token rv(m_type); - rv.m_pos = m_pos; - - assert( m_data.tag() != Data::TAGDEAD ); - TU_MATCH(Data, (m_data), (e), - (None, - ), - (String, - rv.m_data = Data::make_String(e); - ), - (Integer, - rv.m_data = Data::make_Integer(e); - ), - (Float, - rv.m_data = Data::make_Float(e); - ), - (Fragment, - assert(e); - switch(m_type) - { - case TOK_INTERPOLATED_TYPE: - rv.m_data = new TypeRef( reinterpret_cast(e)->clone() ); - break; - case TOK_INTERPOLATED_PATTERN: - rv.m_data = new AST::Pattern( reinterpret_cast(e)->clone() ); - break; - case TOK_INTERPOLATED_PATH: - rv.m_data = new AST::Path( *reinterpret_cast(e) ); - break; - case TOK_INTERPOLATED_EXPR: - rv.m_data = reinterpret_cast(e)->clone().release(); - break; - case TOK_INTERPOLATED_STMT: - rv.m_data = reinterpret_cast(e)->clone().release(); - break; - case TOK_INTERPOLATED_BLOCK: - rv.m_data = reinterpret_cast(e)->clone().release(); - break; - case TOK_INTERPOLATED_META: - rv.m_data = new AST::Attribute( reinterpret_cast(e)->clone() ); - break; - case TOK_INTERPOLATED_ITEM: - TODO(m_pos, "clone interpolated item"); - //rv.m_data = new AST::Named( AST::Item( reinterpret_cast(e)->clone() ) ); - break; - default: - BUG(m_pos, "Fragment with invalid token type (" << *this << ")"); - break; - } - assert(rv.m_data.is_Fragment()); - ) - ) - return rv; -} - -::std::unique_ptr Token::take_frag_node() -{ - assert( m_type == TOK_INTERPOLATED_EXPR || m_type == TOK_INTERPOLATED_STMT || m_type == TOK_INTERPOLATED_BLOCK ); - auto ptr = m_data.as_Fragment(); - m_data.as_Fragment() = nullptr; - return ::std::unique_ptr( reinterpret_cast( ptr ) ); -} -::AST::Named Token::take_frag_item() -{ - assert( m_type == TOK_INTERPOLATED_ITEM ); - auto ptr = reinterpret_cast*>(m_data.as_Fragment()); - m_data.as_Fragment() = nullptr; - auto rv = mv$( *ptr ); - delete ptr; - return mv$(rv); -} - -const char* Token::typestr(enum eTokenType type) -{ - switch(type) - { - #define _(t) case t: return #t; - #include "eTokenType.enum.h" - #undef _ - } - return ">>BUGCHECK: BADTOK<<"; -} - -enum eTokenType Token::typefromstr(const ::std::string& s) -{ - if(s == "") - return TOK_NULL; - #define _(t) if( s == #t ) return t; - #include "eTokenType.enum.h" - #undef _ - return TOK_NULL; -} - -struct EscapedString { - const ::std::string& s; - EscapedString(const ::std::string& s): s(s) {} - - friend ::std::ostream& operator<<(::std::ostream& os, const EscapedString& x) { - for(auto b : x.s) { - switch(b) - { - case '"': - os << "\\\""; - break; - case '\\': - os << "\\\\"; - break; - case '\n': - os << "\\n"; - break; - default: - if( ' ' <= b && b < 0x7F ) - os << b; - else - os << "\\u{" << ::std::hex << (unsigned int)b << "}"; - break; - } - } - return os; - } -}; - -::std::string Token::to_str() const -{ - ::std::stringstream ss; - switch(m_type) - { - case TOK_NULL: return "/*null*/"; - case TOK_EOF: return "/*eof*/"; - - case TOK_NEWLINE: return "\n"; - case TOK_WHITESPACE: return " "; - case TOK_COMMENT: return "/*" + m_data.as_String() + "*/"; - case TOK_INTERPOLATED_TYPE: - reinterpret_cast(m_data.as_Fragment())->print(ss, false); - return ss.str(); - case TOK_INTERPOLATED_PATH: - reinterpret_cast(m_data.as_Fragment())->print_pretty(ss, true); - return ss.str(); - case TOK_INTERPOLATED_PATTERN: - // TODO: Use a pretty printer too? - return FMT( *reinterpret_cast(m_data.as_Fragment()) ); - case TOK_INTERPOLATED_STMT: - case TOK_INTERPOLATED_BLOCK: - case TOK_INTERPOLATED_EXPR: { - ::std::stringstream ss; - reinterpret_cast(m_data.as_Fragment())->print(ss); - return ss.str(); - } - case TOK_INTERPOLATED_META: return "/*:meta*/"; - case TOK_INTERPOLATED_ITEM: return "/*:item*/"; - case TOK_INTERPOLATED_IDENT: return "/*:ident*/"; - // Value tokens - case TOK_IDENT: return m_data.as_String(); - case TOK_LIFETIME: return "'" + m_data.as_String(); - case TOK_INTEGER: - if( m_data.as_Integer().m_datatype == CORETYPE_ANY ) { - return FMT(m_data.as_Integer().m_intval); - } - else { - return FMT(m_data.as_Integer().m_intval << "_" << m_data.as_Integer().m_datatype); - } - case TOK_CHAR: return FMT("'\\u{"<< ::std::hex << m_data.as_Integer().m_intval << "}"); - case TOK_FLOAT: - if( m_data.as_Float().m_datatype == CORETYPE_ANY ) { - return FMT(m_data.as_Float().m_floatval); - } - else { - return FMT(m_data.as_Float().m_floatval << "_" << m_data.as_Float().m_datatype); - } - case TOK_STRING: return FMT("\"" << EscapedString(m_data.as_String()) << "\""); - case TOK_BYTESTRING:return FMT("b\"" << m_data.as_String() << "\""); - case TOK_HASH: return "#"; - case TOK_UNDERSCORE:return "_"; - // Symbols - case TOK_PAREN_OPEN: return "("; - case TOK_PAREN_CLOSE: return ")"; - case TOK_BRACE_OPEN: return "{"; - case TOK_BRACE_CLOSE: return "}"; - case TOK_LT: return "<"; - case TOK_GT: return ">"; - case TOK_SQUARE_OPEN: return "["; - case TOK_SQUARE_CLOSE: return "]"; - case TOK_COMMA: return ","; - case TOK_SEMICOLON: return ";"; - case TOK_COLON: return ":"; - case TOK_DOUBLE_COLON: return "::"; - case TOK_STAR: return "*"; - case TOK_AMP: return "&"; - case TOK_PIPE: return "|"; - - case TOK_FATARROW: return "=>"; - case TOK_THINARROW: return "->"; - case TOK_THINARROW_LEFT: return "<-"; - - case TOK_PLUS: return "+"; - case TOK_DASH: return "-"; - case TOK_EXCLAM: return "!"; - case TOK_PERCENT: return "%"; - case TOK_SLASH: return "/"; - - case TOK_DOT: return "."; - case TOK_DOUBLE_DOT: return "..."; - case TOK_TRIPLE_DOT: return ".."; - - case TOK_EQUAL: return "="; - case TOK_PLUS_EQUAL: return "+="; - case TOK_DASH_EQUAL: return "-"; - case TOK_PERCENT_EQUAL: return "%="; - case TOK_SLASH_EQUAL: return "/="; - case TOK_STAR_EQUAL: return "*="; - case TOK_AMP_EQUAL: return "&="; - case TOK_PIPE_EQUAL: return "|="; - - case TOK_DOUBLE_EQUAL: return "=="; - case TOK_EXCLAM_EQUAL: return "!="; - case TOK_GTE: return ">="; - case TOK_LTE: return "<="; - - case TOK_DOUBLE_AMP: return "&&"; - case TOK_DOUBLE_PIPE: return "||"; - case TOK_DOUBLE_LT: return "<<"; - case TOK_DOUBLE_GT: return ">>"; - case TOK_DOUBLE_LT_EQUAL: return "<="; - case TOK_DOUBLE_GT_EQUAL: return ">="; - - case TOK_DOLLAR: return "$"; - - case TOK_QMARK: return "?"; - case TOK_AT: return "@"; - case TOK_TILDE: return "~"; - case TOK_BACKSLASH: return "\\"; - case TOK_CARET: return "^"; - case TOK_CARET_EQUAL: return "^="; - case TOK_BACKTICK: return "`"; - - // Reserved Words - case TOK_RWORD_PUB: return "pub"; - case TOK_RWORD_PRIV: return "priv"; - case TOK_RWORD_MUT: return "mut"; - case TOK_RWORD_CONST: return "const"; - case TOK_RWORD_STATIC: return "static"; - case TOK_RWORD_UNSAFE: return "unsafe"; - case TOK_RWORD_EXTERN: return "extern"; - - case TOK_RWORD_CRATE: return "crate"; - case TOK_RWORD_MOD: return "mod"; - case TOK_RWORD_STRUCT: return "struct"; - case TOK_RWORD_ENUM: return "enum"; - case TOK_RWORD_TRAIT: return "trait"; - case TOK_RWORD_FN: return "fn"; - case TOK_RWORD_USE: return "use"; - case TOK_RWORD_IMPL: return "impl"; - case TOK_RWORD_TYPE: return "type"; - - case TOK_RWORD_WHERE: return "where"; - case TOK_RWORD_AS: return "as"; - - case TOK_RWORD_LET: return "let"; - case TOK_RWORD_MATCH: return "match"; - case TOK_RWORD_IF: return "if"; - case TOK_RWORD_ELSE: return "else"; - case TOK_RWORD_LOOP: return "loop"; - case TOK_RWORD_WHILE: return "while"; - case TOK_RWORD_FOR: return "for"; - case TOK_RWORD_IN: return "in"; - case TOK_RWORD_DO: return "do"; - - case TOK_RWORD_CONTINUE:return "continue"; - case TOK_RWORD_BREAK: return "break"; - case TOK_RWORD_RETURN: return "return"; - case TOK_RWORD_YIELD: return "yeild"; - case TOK_RWORD_BOX: return "box"; - case TOK_RWORD_REF: return "ref"; - - case TOK_RWORD_FALSE: return "false"; - case TOK_RWORD_TRUE: return "true"; - case TOK_RWORD_SELF: return "self"; - case TOK_RWORD_SUPER: return "super"; - - case TOK_RWORD_PROC: return "proc"; - case TOK_RWORD_MOVE: return "move"; - - case TOK_RWORD_ABSTRACT:return "abstract"; - case TOK_RWORD_FINAL: return "final"; - case TOK_RWORD_PURE: return "pure"; - case TOK_RWORD_OVERRIDE:return "override"; - case TOK_RWORD_VIRTUAL: return "virtual"; - - case TOK_RWORD_ALIGNOF: return "alignof"; - case TOK_RWORD_OFFSETOF:return "offsetof"; - case TOK_RWORD_SIZEOF: return "sizeof"; - case TOK_RWORD_TYPEOF: return "typeof"; - - case TOK_RWORD_BE: return "be"; - case TOK_RWORD_UNSIZED: return "unsized"; - } - throw ParseError::BugCheck("Reached end of Token::to_str"); -} - - -::std::ostream& operator<<(::std::ostream& os, const Token& tok) -{ - os << Token::typestr(tok.type()); - switch(tok.type()) - { - case TOK_STRING: - case TOK_BYTESTRING: - case TOK_IDENT: - case TOK_LIFETIME: - if( tok.m_data.is_String() ) - os << "\"" << EscapedString(tok.str()) << "\""; - break; - case TOK_INTEGER: - if( tok.m_data.is_Integer() ) - os << ":" << tok.intval(); - break; - case TOK_INTERPOLATED_TYPE: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_PATTERN: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_PATH: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_EXPR: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_STMT: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_BLOCK: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_META: - os << ":" << *reinterpret_cast(tok.m_data.as_Fragment()); - break; - case TOK_INTERPOLATED_ITEM: { - const auto& named_item = *reinterpret_cast*>(tok.m_data.as_Fragment()); - os << ":" << named_item.data.tag_str() << "(" << named_item.name << ")"; - } break; - default: - break; - } - return os; -} -::std::ostream& operator<<(::std::ostream& os, const Position& p) -{ - return os << ::std::dec << p.filename << ":" << p.line; -} - diff --git a/gcc/rust/mrustc_parser/parse/token.hpp b/gcc/rust/mrustc_parser/parse/token.hpp deleted file mode 100644 index af27804..0000000 --- a/gcc/rust/mrustc_parser/parse/token.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/token.hpp - * - Lexer Tokens - */ -#pragma once - -#include "../coretypes.hpp" -#include -#include -#include -#include - -enum eTokenType { -#define _(t) t, -#include "eTokenType.enum.h" -#undef _ -}; - -class Position { - public: - RcString filename; - unsigned int line; - unsigned int ofs; - - Position() - : filename("") - , line(0) - , ofs(0) {} - Position(RcString filename, unsigned int line, unsigned int ofs) - : filename(filename) - , line(line) - , ofs(ofs) { - } -}; -extern ::std::ostream& operator<<(::std::ostream& os, const Position& p); - -class TypeRef; -class TokenTree; -namespace AST { - class Pattern; - class Path; - class ExprNode; - class Attribute; - class Item; - - template - struct Named; -}; - -class InterpolatedFragment; - -class Token { - friend class HirSerialiser; - friend class HirDeserialiser; - - TAGGED_UNION(Data, None, (None, struct {}), (String, ::std::string), (Integer, struct { - enum eCoreType m_datatype; - uint64_t m_intval; - }), - (Float, struct { - enum eCoreType m_datatype; - double m_floatval; - }), - (Fragment, void*)); - - enum eTokenType m_type; - Data m_data; - Position m_pos; - - Token(enum eTokenType t, Data d, Position p) - : m_type(t) - , m_data(::std::move(d)) - , m_pos(::std::move(p)) { - } - - public: - virtual ~Token(); - Token(); - Token& operator=(Token&& t) { - m_type = t.m_type; - t.m_type = TOK_NULL; - m_data = ::std::move(t.m_data); - m_pos = ::std::move(t.m_pos); - return *this; - } - Token(Token&& t) - : m_type(t.m_type) - , m_data(::std::move(t.m_data)) - , m_pos(::std::move(t.m_pos)) { - t.m_type = TOK_NULL; - } - Token(const Token& t); - Token clone() const; - - Token(enum eTokenType type); - Token(enum eTokenType type, ::std::string str); - Token(uint64_t val, enum eCoreType datatype); - Token(double val, enum eCoreType datatype); - Token(const InterpolatedFragment&); - struct TagTakeIP {}; - Token(TagTakeIP, InterpolatedFragment); - - enum eTokenType type() const { return m_type; } - ::std::string& str() { return m_data.as_String(); } - const ::std::string& str() const { return m_data.as_String(); } - enum eCoreType datatype() const { - TU_MATCH_DEF(Data, (m_data), (e), (assert(!"Getting datatype of invalid token type");), - (Integer, return e.m_datatype;), (Float, return e.m_datatype;)) throw ""; } - uint64_t intval() const { return m_data.as_Integer().m_intval; } - double floatval() const { return m_data.as_Float().m_floatval; } - - TypeRef& frag_type() { - assert(m_type == TOK_INTERPOLATED_TYPE); - return *reinterpret_cast(m_data.as_Fragment()); - } - - AST::Path& frag_path() { - assert(m_type == TOK_INTERPOLATED_PATH); - return *reinterpret_cast(m_data.as_Fragment()); - } - - AST::Pattern& frag_pattern() { - assert(m_type == TOK_INTERPOLATED_PATTERN); - return *reinterpret_cast(m_data.as_Fragment()); - } - - AST::Attribute& frag_meta() { - assert(m_type == TOK_INTERPOLATED_META); - return *reinterpret_cast(m_data.as_Fragment()); - } - - ::std::unique_ptr take_frag_node(); - ::AST::Named take_frag_item(); - - bool operator==(const Token& r) const { - if (type() != r.type()) - return false; - TU_MATCH(Data, (m_data, r.m_data), (e, re), (None, return true;), (String, return e == re;), (Integer, return e.m_datatype == re.m_datatype && e.m_intval == re.m_intval;), (Float, return e.m_datatype == re.m_datatype && e.m_floatval == re.m_floatval;), (Fragment, assert(!"Token equality on Fragment");)) - throw ""; - } - - bool operator!=(const Token& r) const { return !(*this == r); } - - ::std::string to_str() const; - - void set_pos(Position pos) { m_pos = pos; } - const Position& get_pos() const { return m_pos; } - - static const char* typestr(enum eTokenType type); - static eTokenType typefromstr(const ::std::string& s); - - friend ::std::ostream& operator<<(::std::ostream& os, const Token& tok); -}; - -extern ::std::ostream& operator<<(::std::ostream& os, const Token& tok); diff --git a/gcc/rust/mrustc_parser/parse/tokenstream.cpp b/gcc/rust/mrustc_parser/parse/tokenstream.cpp deleted file mode 100644 index 889c626..0000000 --- a/gcc/rust/mrustc_parser/parse/tokenstream.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/tokenstream.cpp - * - TokenStream - Parser token source interface - */ -#include "tokenstream.hpp" -#include -#include "parseerror.hpp" - -const bool DEBUG_PRINT_TOKENS = false; -//const bool DEBUG_PRINT_TOKENS = true; -//#define DEBUG_PRINT_TOKENS debug_enabled("Lexer Tokens") -//#define FULL_TRACE - -TokenStream::TokenStream(): - m_cache_valid(false) -{ -} -TokenStream::~TokenStream() -{ -} - -Token TokenStream::innerGetToken() -{ - Token ret = this->realGetToken(); - if( ret != TOK_EOF && ret.get_pos().filename == "" ) - ret.set_pos( this->getPosition() ); - //DEBUG("ret.get_pos() = " << ret.get_pos()); - return ret; -} -Token TokenStream::getToken() -{ - if( m_cache_valid ) - { -#ifdef FULL_TRACE - DEBUG("<<< " << m_cache << " (cache)"); -#endif - m_cache_valid = false; - return mv$(m_cache); - } - else if( m_lookahead.size() ) - { - Token ret = mv$( m_lookahead.front().first ); - m_hygiene = m_lookahead.front().second; - m_lookahead.erase(m_lookahead.begin()); -#ifdef FULL_TRACE - DEBUG("<<< " << ret << " (lookahead)"); -#endif - if( DEBUG_PRINT_TOKENS ) { - ::std::cout << "getToken[" << typeid(*this).name() << "] - " << ret.get_pos() << "-" << ret << ::std::endl; - } - return ret; - } - else - { - Token ret = this->innerGetToken(); - m_hygiene = this->realGetHygiene(); -#ifdef FULL_TRACE - DEBUG("<<< " << ret << " (new)"); -#endif - if( DEBUG_PRINT_TOKENS ) { - ::std::cout << "getToken[" << typeid(*this).name() << "] - " << ret.get_pos() << "-" << ret << ::std::endl; - } - return ret; - } -} -void TokenStream::putback(Token tok) -{ - if( m_cache_valid ) - { - DEBUG("" << getPosition() << " - Double putback: " << tok << " but " << m_cache); - throw ParseError::BugCheck("Double putback"); - } - else - { -#ifdef FULL_TRACE - DEBUG(">>> " << tok); -#endif - m_cache_valid = true; - m_cache = mv$(tok); - } -} - -eTokenType TokenStream::lookahead(unsigned int i) -{ - const unsigned int MAX_LOOKAHEAD = 3; - - if( m_cache_valid ) - { - if( i == 0 ) - return m_cache.type(); - i --; - } - - if( i >= MAX_LOOKAHEAD ) - throw ParseError::BugCheck("Excessive lookahead"); - - while( i >= m_lookahead.size() ) - { - DEBUG("lookahead - read #" << m_lookahead.size()); - auto tok = this->innerGetToken(); - auto hygiene = this->realGetHygiene(); - m_lookahead.push_back( ::std::make_pair(mv$(tok), mv$(hygiene)) ); - } - - DEBUG("lookahead(" << i << ") = " << m_lookahead[i]); - return m_lookahead[i].first.type(); -} - -Ident::Hygiene TokenStream::getHygiene() const -{ - return m_hygiene; -} - -ProtoSpan TokenStream::start_span() const -{ - auto p = this->getPosition(); - return ProtoSpan { - p.filename, - p.line, p.ofs - }; -} -Span TokenStream::end_span(ProtoSpan ps) const -{ - auto p = this->getPosition(); - auto rv = Span( ::std::move(ps.filename), ps.start_line, ps.start_ofs, p.line, p.ofs ); - rv.outer_span = this->outerSpan(); - return rv; -} -Span TokenStream::point_span() const -{ - Span rv = this->getPosition(); - rv.outer_span = this->outerSpan(); - return rv; -} -Ident TokenStream::get_ident(Token tok) const -{ - if(tok.type() == TOK_IDENT) { - return Ident(getHygiene(), tok.str()); - } - else if(tok.type() == TOK_LIFETIME) { - // TODO: Maybe only when it's explicitly asked for? - return Ident(getHygiene(), tok.str()); - } - else if( tok.type() == TOK_INTERPOLATED_IDENT ) { - TODO(getPosition(), "get_ident from TOK_INTERPOLATED_IDENT"); - } - else { - throw ParseError::Unexpected(*this, tok); - } -} diff --git a/gcc/rust/mrustc_parser/parse/tokenstream.hpp b/gcc/rust/mrustc_parser/parse/tokenstream.hpp deleted file mode 100644 index a9d325c..0000000 --- a/gcc/rust/mrustc_parser/parse/tokenstream.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/tokenstream.hpp - * - Parser stream (TokenStream) header - */ -#pragma once - -#include -#include -#include -#include -#include -#include "token.hpp" - -namespace AST { - class Module; - class AttributeList; -} - -/// State the parser needs to pass down via a second channel. -struct ParseState -{ - // Used for "for/if/while" to handle ambiguity - bool disallow_struct_literal = false; - // A debugging hook that disables expansion of macros - bool no_expand_macros = false; - - ::AST::Module* module = nullptr; - ::AST::AttributeList* parent_attrs = nullptr; - - ::AST::Module& get_current_mod() { - assert(this->module); - return *this->module; - } - - friend ::std::ostream& operator<<(::std::ostream& os, const ParseState& ps) { - os << "ParseState {"; - if(ps.disallow_struct_literal) os << " disallow_struct_literal"; - if(ps.no_expand_macros) os << " no_expand_macros"; - os << " }"; - return os; - } -}; - -class TokenStream -{ - friend class TTLexer; // needs access to internals to know what was consumed - - bool m_cache_valid; - Token m_cache; - Ident::Hygiene m_hygiene; - ::std::vector< ::std::pair > m_lookahead; - ParseState m_parse_state; -public: - TokenStream(); - virtual ~TokenStream(); - Token getToken(); - void putback(Token tok); - eTokenType lookahead(unsigned int count); - - Ident::Hygiene getHygiene() const; - virtual void push_hygine() {} - virtual void pop_hygine() {} - - ParseState& parse_state() { return m_parse_state; } - - ProtoSpan start_span() const; - Span end_span(ProtoSpan ps) const; - Span point_span() const; - - Ident get_ident(Token tok) const; - -protected: - virtual Position getPosition() const = 0; - virtual ::std::shared_ptr outerSpan() const { return ::std::shared_ptr(0); } - virtual Token realGetToken() = 0; - virtual Ident::Hygiene realGetHygiene() const = 0; -private: - Token innerGetToken(); -}; - -class SavedParseState -{ - TokenStream& m_lex; - ParseState m_state; -public: - SavedParseState(TokenStream& lex, ParseState state): - m_lex(lex), - m_state(state) - { - } - ~SavedParseState() - { - DEBUG("Restoring " << m_state); - m_lex.parse_state() = m_state; - } -}; - -#define SET_MODULE(lex, mod) SavedParseState _sps(lex, lex.parse_state()); lex.parse_state().module = &(mod) -#define SET_ATTRS(lex, attrs) SavedParseState _sps(lex, lex.parse_state()); lex.parse_state().parent_attrs = &(attrs) -#define SET_PARSE_FLAG(lex, flag) SavedParseState _sps(lex, lex.parse_state()); lex.parse_state().flag = true -#define CLEAR_PARSE_FLAG(lex, flag) SavedParseState _sps(lex, lex.parse_state()); lex.parse_state().flag = false -#define CHECK_PARSE_FLAG(lex, flag) (lex.parse_state().flag == true) diff --git a/gcc/rust/mrustc_parser/parse/tokentree.cpp b/gcc/rust/mrustc_parser/parse/tokentree.cpp deleted file mode 100644 index 2d807f7..0000000 --- a/gcc/rust/mrustc_parser/parse/tokentree.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/tokentree.cpp - * - Token Tree (collection of tokens) - */ -#include "tokentree.hpp" -#include - -TokenTree TokenTree::clone() const -{ - if( m_subtrees.size() == 0 ) { - return TokenTree(m_hygiene, m_tok.clone()); - } - else { - ::std::vector< TokenTree> ents; - ents.reserve( m_subtrees.size() ); - for(const auto& sub : m_subtrees) - ents.push_back( sub.clone() ); - return TokenTree( m_hygiene, mv$(ents) ); - } -} - -::std::ostream& operator<<(::std::ostream& os, const TokenTree& tt) -{ - if( tt.m_subtrees.size() == 0 ) - { - switch(tt.m_tok.type()) - { - case TOK_IDENT: - case TOK_LIFETIME: - os << "/*" << tt.m_hygiene << "*/"; - break; - default: - if( TOK_INTERPOLATED_IDENT <= tt.m_tok.type() && tt.m_tok.type() <= TOK_INTERPOLATED_ITEM ) { - os << "/*int*/"; - } - break; - } - return os << tt.m_tok.to_str(); - } - else { - os << "/*" << tt.m_hygiene << " TT*/"; - // NOTE: All TTs (except the outer tt on a macro invocation) include the grouping - bool first = true; - for(const auto& i : tt.m_subtrees) { - if(!first) - os << " "; - os << i; - first = false; - } - return os; - } -} diff --git a/gcc/rust/mrustc_parser/parse/tokentree.hpp b/gcc/rust/mrustc_parser/parse/tokentree.hpp deleted file mode 100644 index 3d6e63d..0000000 --- a/gcc/rust/mrustc_parser/parse/tokentree.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/tokentree.hpp - * - Token Trees (groups of tokens - */ -#ifndef TOKENTREE_HPP_INCLUDED -#define TOKENTREE_HPP_INCLUDED - -#include "token.hpp" -#include -#include - -class TokenTree -{ - Ident::Hygiene m_hygiene; - Token m_tok; - ::std::vector m_subtrees; -public: - virtual ~TokenTree() {} - TokenTree() {} - TokenTree(TokenTree&&) = default; - TokenTree& operator=(TokenTree&&) = default; - TokenTree(enum eTokenType ty): - m_tok( Token(ty) ) - { - } - TokenTree(Token tok): - m_tok( ::std::move(tok) ) - { - } - TokenTree(Ident::Hygiene hygiene, Token tok): - m_hygiene( ::std::move(hygiene) ), - m_tok( ::std::move(tok) ) - { - } - TokenTree(Ident::Hygiene hygiene, ::std::vector subtrees): - m_hygiene( ::std::move(hygiene) ), - m_subtrees( ::std::move(subtrees) ) - { - } - - TokenTree clone() const; - - bool is_token() const { - return m_tok.type() != TOK_NULL; - } - unsigned int size() const { - return m_subtrees.size(); - } - const TokenTree& operator[](unsigned int idx) const { assert(idx < m_subtrees.size()); return m_subtrees[idx]; } - TokenTree& operator[](unsigned int idx) { assert(idx < m_subtrees.size()); return m_subtrees[idx]; } - const Token& tok() const { return m_tok; } - Token& tok() { return m_tok; } - const Ident::Hygiene& hygiene() const { return m_hygiene; } - - friend ::std::ostream& operator<<(::std::ostream& os, const TokenTree& tt); -}; - -#endif // TOKENTREE_HPP_INCLUDED diff --git a/gcc/rust/mrustc_parser/parse/ttstream.cpp b/gcc/rust/mrustc_parser/parse/ttstream.cpp deleted file mode 100644 index 32c9a90..0000000 --- a/gcc/rust/mrustc_parser/parse/ttstream.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/ttstream.cpp - * - Token-Tree backed token streams - */ -#include "ttstream.hpp" -#include - -TTStream::TTStream(Span parent, const TokenTree& input_tt): - m_parent_span( new Span(mv$(parent)) ) -{ - DEBUG("input_tt = [" << input_tt << "]"); - m_stack.push_back( ::std::make_pair(0, &input_tt) ); -} -TTStream::~TTStream() -{ -} -Token TTStream::realGetToken() -{ - while(m_stack.size() > 0) - { - // If current index is above TT size, go up - unsigned int& idx = m_stack.back().first; - assert( m_stack.back().second ); - const TokenTree& tree = *m_stack.back().second; - - if(idx == 0 && tree.is_token()) { - idx ++; - m_hygiene_ptr = &tree.hygiene(); - return tree.tok(); - } - - if(idx < tree.size()) - { - const TokenTree& subtree = tree[idx]; - idx ++; - if( subtree.size() == 0 ) { - m_hygiene_ptr = &subtree.hygiene(); - return subtree.tok().clone(); - } - else { - m_stack.push_back( ::std::make_pair(0, &subtree) ); - } - } - else { - m_stack.pop_back(); - } - } - //m_hygiene = nullptr; - return Token(TOK_EOF); -} -Position TTStream::getPosition() const -{ - // TODO: Position associated with the previous/next token? - return Position("TTStream", 0,0); -} -Ident::Hygiene TTStream::realGetHygiene() const -{ - // Empty. - if(!m_hygiene_ptr) - return Ident::Hygiene(); - return *m_hygiene_ptr; -} - - -TTStreamO::TTStreamO(Span parent, TokenTree input_tt): - m_input_tt( mv$(input_tt) ), - m_parent_span( new Span(mv$(parent)) ) -{ - m_stack.push_back( ::std::make_pair(0, nullptr) ); -} -TTStreamO::~TTStreamO() -{ -} -Token TTStreamO::realGetToken() -{ - while(m_stack.size() > 0) - { - // If current index is above TT size, go up - unsigned int& idx = m_stack.back().first; - TokenTree& tree = (m_stack.back().second ? *m_stack.back().second : m_input_tt); - - if(idx == 0 && tree.is_token()) { - idx ++; - m_last_pos = tree.tok().get_pos(); - m_hygiene_ptr = &tree.hygiene(); - return mv$(tree.tok()); - } - - if(idx < tree.size()) - { - TokenTree& subtree = tree[idx]; - idx ++; - if( subtree.size() == 0 ) { - m_last_pos = subtree.tok().get_pos(); - m_hygiene_ptr = &subtree.hygiene(); - return mv$( subtree.tok() ); - } - else { - m_stack.push_back( ::std::make_pair(0, &subtree) ); - } - } - else { - m_stack.pop_back(); - } - } - return Token(TOK_EOF); -} -Position TTStreamO::getPosition() const -{ - return m_last_pos; -} -Ident::Hygiene TTStreamO::realGetHygiene() const -{ - // Empty. - if(!m_hygiene_ptr) - return Ident::Hygiene(); - return *m_hygiene_ptr; -} diff --git a/gcc/rust/mrustc_parser/parse/ttstream.hpp b/gcc/rust/mrustc_parser/parse/ttstream.hpp deleted file mode 100644 index 530a177..0000000 --- a/gcc/rust/mrustc_parser/parse/ttstream.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/ttstrea.hpp - * - Token tree streams (for post-lex parsing) - */ -#pragma once - -#include "tokentree.hpp" -#include "tokenstream.hpp" - -/// Borrowed TTStream -class TTStream: - public TokenStream -{ - ::std::vector< ::std::pair > m_stack; - ::std::shared_ptr m_parent_span; - const Ident::Hygiene* m_hygiene_ptr = nullptr; -public: - TTStream(Span parent, const TokenTree& input_tt); - ~TTStream(); - - TTStream& operator=(const TTStream& x) { m_stack = x.m_stack; return *this; } - - Position getPosition() const override; - ::std::shared_ptr outerSpan() const override { return m_parent_span; } - -protected: - Ident::Hygiene realGetHygiene() const override; - Token realGetToken() override; -}; - -/// Owned TTStream -class TTStreamO: - public TokenStream -{ - Position m_last_pos; - TokenTree m_input_tt; - ::std::vector< ::std::pair > m_stack; - const Ident::Hygiene* m_hygiene_ptr = nullptr; -public: - ::std::shared_ptr m_parent_span; - TTStreamO(Span parent, TokenTree input_tt); - TTStreamO(TTStreamO&& x) = default; - ~TTStreamO(); - - TTStreamO& operator=(const TTStreamO& x) { m_stack = x.m_stack; return *this; } - TTStreamO& operator=(TTStreamO&& x) = default; - - Position getPosition() const override; - ::std::shared_ptr outerSpan() const override { return m_parent_span; } - -protected: - Ident::Hygiene realGetHygiene() const override; - Token realGetToken() override; -}; diff --git a/gcc/rust/mrustc_parser/parse/types.cpp b/gcc/rust/mrustc_parser/parse/types.cpp deleted file mode 100644 index ca5b789..0000000 --- a/gcc/rust/mrustc_parser/parse/types.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/types.cpp - * - Parsing for type usages - */ -#include "common.hpp" -#include "parseerror.hpp" -#include -#include - -// === PROTOTYPES === -//TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list); -TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list); -TypeRef Parse_Type_Fn(TokenStream& lex, AST::HigherRankedBounds hrbs = {}); -TypeRef Parse_Type_Path(TokenStream& lex, AST::HigherRankedBounds hrbs, bool allow_trait_list); -TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list); - -// === CODE === -TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list) -{ - ProtoSpan ps = lex.start_span(); - TypeRef rv = Parse_Type_Int(lex, allow_trait_list); - //rv.set_span(lex.end_span(ps)); - return rv; -} - -TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) -{ - //TRACE_FUNCTION; - auto ps = lex.start_span(); - - Token tok; - - switch( GET_TOK(tok, lex) ) - { - case TOK_INTERPOLATED_TYPE: - return mv$(tok.frag_type()); - // '!' - Only ever used as part of function prototypes, but is kinda a type... not allowed here though - case TOK_EXCLAM: - return TypeRef( Span(tok.get_pos()), TypeData::make_Bang({}) ); - // '_' = Wildcard (type inferrence variable) - case TOK_UNDERSCORE: - return TypeRef(Span(tok.get_pos())); - - // 'unsafe' - An unsafe function type - case TOK_RWORD_UNSAFE: - // 'extern' - A function type with an ABI - case TOK_RWORD_EXTERN: - // 'fn' - Rust function - case TOK_RWORD_FN: - PUTBACK(tok, lex); - return Parse_Type_Fn(lex); - - case TOK_RWORD_IMPL: - return Parse_Type_ErasedType(lex, allow_trait_list); - - // '<' - An associated type cast - case TOK_LT: - case TOK_DOUBLE_LT: { - PUTBACK(tok, lex); - auto path = Parse_Path(lex, PATH_GENERIC_TYPE); - return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), mv$(path)); - } - // - case TOK_RWORD_FOR: { - auto hrls = Parse_HRB(lex); - switch(LOOK_AHEAD(lex)) - { - case TOK_RWORD_UNSAFE: - case TOK_RWORD_EXTERN: - case TOK_RWORD_FN: - return Parse_Type_Fn(lex, hrls); - default: - return Parse_Type_Path(lex, hrls, true); - } - } - // - Either a primitive, or a path - case TOK_IDENT: - if( lex.lookahead(0) == TOK_EXCLAM ) - { - lex.getToken(); - // TODO: path macros - return TypeRef(TypeRef::TagMacro(), Parse_MacroInvocation(ps, mv$(tok.str()), lex)); - } - // or a primitive - //if( auto ct = coretype_fromstring(tok.str()) ) - //{ - // return TypeRef(TypeRef::TagPrimitive(), Span(tok.get_pos()), ct); - //} - PUTBACK(tok, lex); - return Parse_Type_Path(lex, {}, allow_trait_list); - // - Fall through to path handling - // '::' - Absolute path - case TOK_DOUBLE_COLON: - // 'self' - This relative path - case TOK_RWORD_SELF: - // 'super' - Parent relative path - case TOK_RWORD_SUPER: - // ':path' fragment - case TOK_INTERPOLATED_PATH: - PUTBACK(tok, lex); - return Parse_Type_Path(lex, {}, allow_trait_list); - - // HACK! Convert && into & & - case TOK_DOUBLE_AMP: - lex.putback(Token(TOK_AMP)); - // '&' - Reference type - case TOK_AMP: { - AST::LifetimeRef lifetime; - // Reference - tok = lex.getToken(); - if( tok.type() == TOK_LIFETIME ) { - lifetime = AST::LifetimeRef(/*lex.point_span(), */lex.get_ident(::std::move(tok))); - tok = lex.getToken(); - } - bool is_mut = false; - if( tok.type() == TOK_RWORD_MUT ) { - is_mut = true; - } - else { - PUTBACK(tok, lex); - } - return TypeRef(TypeRef::TagReference(), lex.end_span(mv$(ps)), ::std::move(lifetime), is_mut, Parse_Type(lex, false)); - } - // '*' - Raw pointer - case TOK_STAR: - // Pointer - switch( GET_TOK(tok, lex) ) - { - case TOK_RWORD_MUT: - // Mutable pointer - return TypeRef(TypeRef::TagPointer(), lex.end_span(mv$(ps)), true, Parse_Type(lex, false)); - case TOK_RWORD_CONST: - // Immutable pointer - return TypeRef(TypeRef::TagPointer(), lex.end_span(mv$(ps)), false, Parse_Type(lex, false)); - default: - throw ParseError::Unexpected(lex, tok, {TOK_RWORD_CONST, TOK_RWORD_MUT}); - } - throw ParseError::BugCheck("Reached end of Parse_Type:STAR"); - // '[' - Array type - case TOK_SQUARE_OPEN: { - // Array - TypeRef inner = Parse_Type(lex); - if( GET_TOK(tok, lex) == TOK_SEMICOLON ) { - // Sized array - AST::Expr array_size = Parse_Expr(lex); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - return TypeRef(TypeRef::TagSizedArray(), lex.end_span(mv$(ps)), mv$(inner), array_size.take_node()); - } - else if( tok.type() == TOK_SQUARE_CLOSE ) - { - return TypeRef(TypeRef::TagUnsizedArray(), lex.end_span(mv$(ps)), mv$(inner)); - } - else { - throw ParseError::Unexpected(lex, tok/*, "; or ]"*/); - } - } - - // '(' - Tuple (or lifetime bounded trait) - case TOK_PAREN_OPEN: { - DEBUG("Tuple"); - if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - return TypeRef(TypeRef::TagTuple(), lex.end_span(mv$(ps)), {}); - PUTBACK(tok, lex); - - TypeRef inner = Parse_Type(lex, true); - if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) - { - // Type in parens, NOT a tuple - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); - return inner; - } - else - { - ::std::vector types; - types.push_back( mv$(inner) ); - while( GET_TOK(tok, lex) == TOK_COMMA ) - { - if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - break; - else - PUTBACK(tok, lex); - types.push_back( Parse_Type(lex) ); - } - CHECK_TOK(tok, TOK_PAREN_CLOSE); - return TypeRef(TypeRef::TagTuple(), lex.end_span(mv$(ps)), mv$(types)); } - } - default: - throw ParseError::Unexpected(lex, tok); - } - throw ParseError::BugCheck("Reached end of Parse_Type"); -} - -TypeRef Parse_Type_Fn(TokenStream& lex, ::AST::HigherRankedBounds hrbs) -{ - auto ps = lex.start_span(); - TRACE_FUNCTION; - Token tok; - - ::std::string abi = ""; - bool is_unsafe = false; - - GET_TOK(tok, lex); - - // `unsafe` - if( tok.type() == TOK_RWORD_UNSAFE ) - { - is_unsafe = true; - GET_TOK(tok, lex); - } - // `exern` - if( tok.type() == TOK_RWORD_EXTERN ) - { - if( GET_TOK(tok, lex) == TOK_STRING ) { - abi = tok.str(); - if( abi == "" ) - ERROR(lex.point_span(), E0000, "Empty ABI"); - GET_TOK(tok, lex); - } - else { - abi = "C"; - } - } - // `fn` - CHECK_TOK(tok, TOK_RWORD_FN); - - ::std::vector args; - bool is_variadic = false; - GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); - while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) - { - if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) { - GET_TOK(tok, lex); - is_variadic = true; - break; - } - // Handle `ident: ` - if( (lex.lookahead(0) == TOK_IDENT || lex.lookahead(0) == TOK_UNDERSCORE) && lex.lookahead(1) == TOK_COLON ) { - GET_TOK(tok, lex); - GET_TOK(tok, lex); - } - args.push_back( Parse_Type(lex) ); - if( GET_TOK(tok, lex) != TOK_COMMA ) { - PUTBACK(tok, lex); - break; - } - } - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); - - // `-> RetType` - TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos())); - if( GET_TOK(tok, lex) == TOK_THINARROW ) - { - ret_type = Parse_Type(lex, false); - } - else { - PUTBACK(tok, lex); - } - - return TypeRef(TypeRef::TagFunction(), lex.end_span(mv$(ps)), mv$(hrbs), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); -} - -TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool allow_trait_list) -{ - Token tok; - - auto ps = lex.start_span(); - - if( hrbs.empty() && !allow_trait_list ) - { - return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), Parse_Path(lex, PATH_GENERIC_TYPE)); - } - else - { - ::std::vector traits; - ::std::vector lifetimes; - - traits.push_back(Type_TraitPath { mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); - - if( allow_trait_list ) - { - while( GET_TOK(tok, lex) == TOK_PLUS ) - { - if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { - GET_TOK(tok, lex); - lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); - } - else - { - if( lex.lookahead(0) == TOK_RWORD_FOR ) - { - hrbs = Parse_HRB(lex); - } - traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); - } - } - PUTBACK(tok, lex); - } - - if( !traits[0].hrbs.empty() || traits.size() > 1 || lifetimes.size() > 0 ) - { - if( lifetimes.empty()) - lifetimes.push_back(AST::LifetimeRef()); - return TypeRef(lex.end_span(mv$(ps)), mv$(traits), mv$(lifetimes)); - } - else - { - return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), mv$(traits.at(0).path)); - } - } -} -TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list) -{ - Token tok; - - auto ps = lex.start_span(); - ::std::vector traits; - ::std::vector lifetimes; - do { - if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { - GET_TOK(tok, lex); - lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); - } - else - { - AST::HigherRankedBounds hrbs; - if( lex.lookahead(0) == TOK_RWORD_FOR ) - { - hrbs = Parse_HRB(lex); - } - traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); - } - } while( GET_TOK(tok, lex) == TOK_PLUS ); - PUTBACK(tok, lex); - - return TypeRef(lex.end_span(mv$(ps)), TypeData::make_ErasedType({ mv$(traits), mv$(lifetimes) })); -} - diff --git a/gcc/rust/old/lang-specs.h b/gcc/rust/old/lang-specs.h deleted file mode 100644 index 7ac9301..0000000 --- a/gcc/rust/old/lang-specs.h +++ /dev/null @@ -1,19 +0,0 @@ -/* This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -{".rs", "@rs", 0, 1, 0}, -{"@rs", "grs1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", - 0, 1, 0}, diff --git a/gcc/rust/old/rdot-dataflow.cc b/gcc/rust/old/rdot-dataflow.cc deleted file mode 100644 index f63afb8..0000000 --- a/gcc/rust/old/rdot-dataflow.cc +++ /dev/null @@ -1,883 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -static std::vector *> context; -static rdot dot_pass_typeifyExprNode (rdot); -static bool dot_pass_typeCompare (const rdot, const rdot); -static rdot impl_master = NULL_DOT; - -static -void dot_pass_dataFlow_pushCtx (void) -{ - std::map * ctx = new std::map; - context.push_back (ctx); -} - -static -void dot_pass_dataFlow_popCtx (void) -{ - std::map * ctx = context.back (); - context.pop_back (); - delete ctx; -} - -static -rdot dot_pass_dataFlow_lookup (const char * id) -{ - rdot retval = NULL_DOT; - std::vector *>::reverse_iterator it; - for (it = context.rbegin (); it != context.rend (); ++it) - { - std::map * ctx = *it; - if (ctx->count (std::string (id))) - { - retval = (*ctx)[std::string (id)]; - break; - } - } - return retval; -} - -static -bool dot_pass_dataFlow_pushDecl (rdot node, const char * id) -{ - rdot check = dot_pass_dataFlow_lookup (id); - if (check != NULL_DOT) - { - error ("DataFlow duplicate declaration [%s]\n", id); - return true; - } - - bool retval = false; - if ((RDOT_TYPE (node) == D_VAR_DECL) - || (RDOT_TYPE (node) == D_STRUCT_METHOD) - || (RDOT_TYPE (node) == D_STRUCT_TYPE)) - { - std::map * ctx = context.back (); - (*ctx) [std::string (id)] = node; - } - else - { - error ("Invalid dataflow declaration pushing to context [%s]\n", - RDOT_OPCODE_STR (node)); - retval = true; - } - return retval; -} - -static void dot_pass_dataFlowToplevel (rdot); -static void dot_pass_dataFlowFunction (rdot); -static void dot_pass_dataFlowBlock (rdot); - -static -bool verifyType (rdot node) -{ - bool retval = false; - switch (RDOT_TYPE (node)) - { - case RTYPE_BOOL: - case RTYPE_INT: - case RTYPE_FLOAT: - case RTYPE_UINT: - retval = true; - break; - - default: - break; - } - return retval; -} - -static -rdot dot_pass_dataFlow_getDecl (rdot node) -{ - rdot retval = NULL_DOT; - if (RDOT_T_FIELD (node) == D_D_EXPR) - { - // only if its a modify expr - if (RDOT_TYPE (node) == D_MODIFY_EXPR) - { - rdot decl = RDOT_lhs_TT (node); - if (RDOT_TYPE (decl) == D_VAR_DECL) - retval = decl; - } - else if (RDOT_TYPE (node) == D_VAR_DECL) - retval = node; - } - return retval; -} - -static -void dot_pass_dataFlowBlock_retvals (rdot suite, std::vector * retval) -{ - rdot next; - for (next = suite; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - if (RDOT_T_FIELD (next) == D_D_EXPR) - { - if (DOT_RETVAL (next)) - retval->push_back (next); - } - else - { - switch (RDOT_TYPE (next)) - { - case D_STRUCT_WHILE: - dot_pass_dataFlowBlock_retvals (RDOT_rhs_TT (next), retval); - break; - - case D_STRUCT_IF: - { - rdot ifblock = RDOT_lhs_TT (next); - rdot elseblock = RDOT_rhs_TT (next); - dot_pass_dataFlowBlock_retvals (RDOT_rhs_TT (ifblock), retval); - if (elseblock != NULL_DOT) - dot_pass_dataFlowBlock_retvals (RDOT_lhs_TT (elseblock), retval); - } - break; - - default: - error ("unable to figure out what to do with [%s]", - RDOT_OPCODE_STR (next)); - break; - } - } - } -} - -/* - Takes a var_decl and returns the rhs of assignment to try and infer a type on. - eg1 : - let x; - x = 1 + 2 - will return the NULL on the decl and RDOT (1+2) on the expression - - eg2: - let x = 1; - ruturns RDOT (1) -*/ -static -rdot dot_pass_dataFlow_getRef (rdot decl, rdot var_decl) -{ - rdot retval = NULL_DOT; - if (RDOT_TYPE (decl) == D_MODIFY_EXPR) - { - rdot lhs = RDOT_lhs_TT (decl); - rdot rhs = RDOT_rhs_TT (decl); - - switch (RDOT_TYPE (lhs)) - { - case D_VAR_DECL: - { - if (var_decl == lhs) - retval = rhs; - } - break; - - case D_IDENTIFIER: - { - const char * vid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (var_decl)); - const char * cid = RDOT_IDENTIFIER_POINTER (lhs); - // we found a reference assignment... - if (strcmp (vid, cid) == 0) - retval = rhs; - } - break; - - default: - break; - } - } - return retval; -} - -static -std::vector * dot_pass_getReferences (rdot vDecl, rdot suite) -{ - std::vector * retval = new std::vector; - rdot node; - for (node = suite; node != NULL_DOT; node = RDOT_CHAIN (node)) - { - switch (RDOT_TYPE (node)) - { - case D_PRIMITIVE: - case D_CALL_EXPR: - case D_ATTRIB_REF: - break; - - case D_MODIFY_EXPR: - { - rdot ref = dot_pass_dataFlow_getRef (node, vDecl); - if (ref != NULL_DOT) - retval->push_back (ref); - } - break; - - case D_STRUCT_WHILE: - { - rdot wsuite = RDOT_rhs_TT (node); - std::vector * refs = dot_pass_getReferences (vDecl, wsuite); - // append to the list - std::vector::iterator it; - for (it = refs->begin (); it != refs->end (); ++it) - retval->push_back (*it); - delete refs; - } - break; - - case D_STRUCT_IF: - { - rdot ifb = RDOT_lhs_TT (node); - rdot elb = RDOT_rhs_TT (node); - - rdot ifsuite = RDOT_rhs_TT (ifb); - std::vector * refs = dot_pass_getReferences (vDecl, ifsuite); - - // append to the list - std::vector::iterator it; - for (it = refs->begin (); it != refs->end (); ++it) - retval->push_back (*it); - delete refs; - - if (elb != NULL_DOT) - { - refs = dot_pass_getReferences (vDecl, RDOT_lhs_TT (elb)); - for (it = refs->begin (); it != refs->end (); ++it) - retval->push_back (*it); - delete refs; - } - } - - default: - break; - } - } - return retval; -} - -static bool -dot_pass_typeCompare (const rdot x, const rdot y) -{ - bool retval = false; - if (RDOT_TYPE (x) == RDOT_TYPE (y)) - if (RDOT_MEM_MODIFIER (x)->size () == RDOT_MEM_MODIFIER (y)->size ()) - { - retval = true; - std::vector::iterator xit; - std::vector::iterator yit; - for (xit = RDOT_MEM_MODIFIER (x)->begin (), - yit = RDOT_MEM_MODIFIER (y)->begin (); - xit != RDOT_MEM_MODIFIER (x)->end (); - ++xit, ++yit) - { - if (*xit != *yit) - { - retval = false; - break; - } - } - } - return retval; -} - -static char * -dot_pass_typeString (const rdot node) -{ - char buffer [128]; - size_t offset = 0; - - std::vector::iterator it; - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it ) - { - switch (*it) - { - case ALLOC_DEREF: - buffer [offset++] = '*'; - break; - case ALLOC_HEAP: - buffer [offset++] = '~'; - break; - case ALLOC_REF: - buffer [offset++] = '&'; - break; - } - } - strcpy (buffer+offset, RDOT_OPCODE_STR (node)); - return xstrdup (buffer); -} - -/** - * WARN: - * This really needs more analysis on why, if you have : infered something has: - * infer, int, string - * infer, int, infer. Does it mean its an int probably. - * Currently it drops any possible type to be an int - **/ -static -rdot dot_pass_inferTheType (std::vector * refs, const char * id) -{ - rdot retval = NULL_DOT; - rdot _retval = rdot_build_decl1 (RTYPE_INFER, NULL_DOT); - gcc_assert (refs->size () > 0); - - std::vector possible_types; - std::vector::iterator it; - for (it = refs->begin (); it != refs->end (); ++it) - { - rdot pos = dot_pass_typeifyExprNode (*it); - if (RDOT_TYPE (pos) != RTYPE_INFER) - possible_types.push_back (pos); - } - - if (possible_types.size () == 0) - retval = _retval; - else - { - bool first = true; - std::vector::iterator pit; - for (pit = possible_types.begin (); pit != possible_types.end (); ++pit) - { - if (first == true) - { - retval = *pit; - first = false; - } - if (!dot_pass_typeCompare (retval, *pit)) - { - char * t1 = dot_pass_typeString (retval); - char * t2 = dot_pass_typeString (*pit); - error ("Ambigious types found for [%s] -> [%s] OR [%s]", id, t1, t2); - retval = _retval; - free (t1); - free (t2); - break; - } - } - } - return retval; -} - -static -rdot dot_pass_typeifyPrimitive (rdot node) -{ - rdot retval = rdot_build_decl1 (RTYPE_INFER, NULL_DOT); - gcc_assert (RDOT_TYPE (node) == D_PRIMITIVE); - - switch (node->opa.tc.T == D_T_INTEGER) - { - case D_T_INTEGER: - RDOT_TYPE (retval) = RTYPE_INT; - break; - - default: - error ("Unable to figure out type for this primitive [%s]!", - RDOT_CODE_STR (node->opa.tc.T)); - break; - } - std::vector::iterator it; - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - return retval; -} - -/* FIXME maybe i feel this isn't done very well at all here */ -static -rdot dot_pass_typeifyExprNode (rdot node) -{ - rdot retval = rdot_build_decl1 (RTYPE_INFER, NULL_DOT); - switch (RDOT_TYPE (node)) - { - case D_PRIMITIVE: - retval = dot_pass_typeifyPrimitive (node); - break; - - case D_IDENTIFIER: - { - rdot lookup = dot_pass_dataFlow_lookup (RDOT_IDENTIFIER_POINTER (node)); - if (lookup == NULL_DOT) - error ("unable to find declaration of [%s] in current scope", - RDOT_IDENTIFIER_POINTER (node)); - else - { - gcc_assert (RDOT_TYPE (lookup) == D_VAR_DECL); - RDOT_TYPE (retval) = RDOT_TYPE (RDOT_rhs_TT (lookup)); - if (RDOT_TYPE (retval) == RTYPE_USER_STRUCT) - { - RDOT_lhs_TT (retval) = RDOT_lhs_TT (RDOT_rhs_TT (lookup)); - RDOT_rhs_TT (retval) = RDOT_rhs_TT (RDOT_rhs_TT (lookup)); - } - std::vector::iterator it; - if (RDOT_MEM_MODIFIER (node)) - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - if (RDOT_MEM_MODIFIER (RDOT_rhs_TT (lookup))) - for (it = RDOT_MEM_MODIFIER (RDOT_rhs_TT (lookup))->begin (); - it != RDOT_MEM_MODIFIER (RDOT_rhs_TT (lookup))->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - } - } - break; - - case D_STRUCT_INIT: - { - const char * slookup = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - rdot lookup = dot_pass_dataFlow_lookup (slookup); - if (lookup != NULL_DOT) - { - if (RDOT_TYPE (lookup) == D_STRUCT_TYPE) - { - RDOT_TYPE (retval) = RTYPE_USER_STRUCT; - RDOT_lhs_TT (retval) = RDOT_lhs_TT (lookup); // identifier node - RDOT_rhs_TT (retval) = RDOT_rhs_TT (lookup); // struct layout - std::vector::iterator it; - if (RDOT_MEM_MODIFIER (node)) - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - if (RDOT_MEM_MODIFIER (lookup)) - for (it = RDOT_MEM_MODIFIER (lookup)->begin (); - it != RDOT_MEM_MODIFIER (lookup)->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - } - else - error ("unable to determine type of [%s] struct initilization, " - "[%s] was found in this scope", - slookup, RDOT_OPCODE_STR (lookup)); - } - else - error ("[%s] does not name a type in scope", slookup); - } - break; - - case D_CALL_EXPR: - { - const char * callid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - rdot lookup = dot_pass_dataFlow_lookup (callid); - if (lookup != NULL_DOT) - { - gcc_assert (RDOT_TYPE (lookup) == D_STRUCT_METHOD); - RDOT_TYPE (retval) = RDOT_TYPE (RDOT_FIELD2 (lookup)); - std::vector * mods = RDOT_MEM_MODIFIER (RDOT_FIELD2 (lookup)); - std::vector::iterator it; - if (RDOT_MEM_MODIFIER (node)) - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - if (mods) - for (it = mods->begin (); it != mods->end (); ++it) - RDOT_MEM_MODIFIER (retval)->push_back (*it); - } - else - error ("unable to find declaration of [%s] in current scope", - callid); - } - break; - - case D_ATTRIB_REF: - { - rdot lhs = RDOT_lhs_TT (node); - rdot base_type = dot_pass_typeifyExprNode (lhs); - gcc_assert (RDOT_TYPE (base_type) == RTYPE_USER_STRUCT); - } - break; - - case D_ACC_EXPR: - { - rdot impl = RDOT_lhs_TT (node); - char * implid = RDOT_IDENTIFIER_POINTER (impl); - rdot lookup = dot_pass_dataFlow_lookup (implid); - - bool found = false; - rdot next; - for (next = RDOT_rhs_TT (RDOT_FIELD (lookup)); - next != NULL_DOT; next = RDOT_CHAIN (next)) - { - switch (RDOT_TYPE (next)) - { - case D_STRUCT_METHOD: - RDOT_TYPE (retval) = RDOT_TYPE (RDOT_FIELD2 (next)); - break; - - default: - error_at (RDOT_LOCATION (next), "unable to identify [%s] for type inferance", - RDOT_OPCODE_STR (next)); - break; - } - } - if (!found) - break; - } - break; - - case D_ADD_EXPR: - case D_MINUS_EXPR: - case D_MULT_EXPR: - case D_DIVD_EXPR: - { - rdot lhs = RDOT_lhs_TT (node); - rdot rhs = RDOT_rhs_TT (node); - - rdot lt = dot_pass_typeifyExprNode (lhs); - rdot rt = dot_pass_typeifyExprNode (rhs); - - if (RDOT_TYPE (lt) != RTYPE_INFER - || RDOT_TYPE (rt) != RTYPE_INFER) - { - if (RDOT_TYPE (lt) == RDOT_TYPE (rt)) - retval = lt; - else - { - if (RDOT_TYPE (lt) == RTYPE_INFER || RDOT_TYPE (rt) == RTYPE_INFER) - retval = RDOT_TYPE (lt) == RTYPE_INFER ? rt : lt; - else - error ("unable to coerce types [%s] and [%s]", - RDOT_OPCODE_STR (lt), RDOT_OPCODE_STR (rt)); - } - } - } - break; - - default: - error ("Unable to figure out the type of this [%s]", - RDOT_OPCODE_STR (node)); - break; - } - - bool skip_next = false; - std::vector nmods; - std::vector * pmods = RDOT_MEM_MODIFIER (retval); - - std::vector::iterator it; - for (it = pmods->begin (); it != pmods->end (); ++it) - { - switch (*it) - { - case ALLOC_DEREF: - skip_next = true; - break; - - default: - { - if (!skip_next) - { - nmods.push_back (*it); - skip_next = false; - } - } - break; - } - } - RDOT_MMEM_COPY ((&nmods), RDOT_MEM_MODIFIER (retval)); - return retval; -} - -static -void dot_pass_mutability (const rdot node) -{ - rdot lhs = RDOT_lhs_TT (node); - if (RDOT_TYPE (lhs) != D_VAR_DECL) - { - // check the nodes mutability - switch (RDOT_TYPE (lhs)) - { - case D_IDENTIFIER: - { - const char * ident = RDOT_IDENTIFIER_POINTER (lhs); - const rdot node = dot_pass_dataFlow_lookup (ident); - if (node == NULL_DOT) - error_at (RDOT_LOCATION (node), "Unable to find decl [%s] in current scope", ident); - else if (RDOT_qual (node) == true) - error_at (RDOT_LOCATION (node), "Unable to modify [%s] it is immutable", ident); - } - break; - - default: - { - const char * nstr = RDOT_OPCODE_STR (lhs); - warning_at (RDOT_LOCATION (node), 0, "TODO unable to verify assignment" - "mutability for [%s]", nstr); - } - break; - } - } -} - -static -void dot_pass_dataFlowBlock_ (rdot suite, std::vector * decls) -{ - rdot node; - for (node = suite; node != NULL_DOT; node = RDOT_CHAIN (node)) - { - if (RDOT_T_FIELD (node) == D_D_EXPR) - { - if (RDOT_TYPE (node) == D_MODIFY_EXPR) - dot_pass_mutability (node); - - const char * id = NULL; - rdot decl = dot_pass_dataFlow_getDecl (node); - if (decl != NULL_DOT) - { - gcc_assert (RDOT_TYPE (decl) == D_VAR_DECL); - id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (decl)); - decls->push_back (decl); - - // push it into the current context... - rdot lookup = dot_pass_dataFlow_lookup (id); - if (lookup != NULL_DOT) - error ("Duplicate declaration of [%s] to [%s]", - id, RDOT_OPCODE_STR (lookup)); - else - gcc_assert (!dot_pass_dataFlow_pushDecl (decl, id)); - } - } - else - { - switch (RDOT_TYPE (node)) - { - case D_STRUCT_IF: - { - rdot sif = RDOT_lhs_TT (node); - rdot ses = RDOT_rhs_TT (node); - - dot_pass_dataFlowBlock_ (RDOT_rhs_TT (sif), decls); - if (ses != NULL_DOT) - dot_pass_dataFlowBlock_ (RDOT_lhs_TT (ses), decls); - } - break; - - case D_STRUCT_WHILE: - dot_pass_dataFlowBlock_ (RDOT_rhs_TT (node), decls); - break; - - case D_STRUCT_LOOP: - dot_pass_dataFlowBlock_ (RDOT_lhs_TT (node), decls); - break; - - case C_BREAK_STMT: - case C_CONT_STMT: - break; - - default: - error ("Unhandled data flow in block on [%s]\n", RDOT_OPCODE_STR (node)); - break; - } - } - } -} - -static -void dot_pass_dataFlowBlock (rdot suite) -{ - std::vector block_decls; - dot_pass_dataFlowBlock_ (suite, &block_decls); - - // now we have all defined block declarations now need to get all - // references in their use if they have an undefined type. - std::vector::iterator it; - for (it = block_decls.begin (); it != block_decls.end (); ++it) - { - rdot decl = *it; - gcc_assert (RDOT_TYPE (decl) == D_VAR_DECL); - rdot idecl = RDOT_lhs_TT (decl); - const char * ident = RDOT_IDENTIFIER_POINTER (idecl); - if (RDOT_TYPE (RDOT_rhs_TT (decl)) == RTYPE_INFER) - { - std::vector * refs = dot_pass_getReferences (decl, suite); - if (refs->size () == 0) - { - error ("Unable to infer type of [%s] it looks to " - "be unused in this scope", ident); - continue; - } - RDOT_rhs_TT (decl) = dot_pass_inferTheType (refs, ident); - if (RDOT_TYPE (RDOT_rhs_TT (decl)) == RTYPE_INFER) - error ("Compiler was unable to infer the type for [%s]", ident); - delete refs; - } - } -} - -static -void dot_pass_dataFlowFunction (rdot node) -{ - const char * method_id = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - rdot type = RDOT_FIELD2 (node); - - // rust does not infer function types empty types are default void - // and parameters are synatically required to be typed - dot_pass_dataFlow_pushCtx (); - - // fill up the parameters here - rdot params; - for (params = RDOT_lhs_TT (node); params != NULL_DOT; - params = RDOT_CHAIN (params)) - { - rdot pident = RDOT_lhs_TT (params); - rdot ptype = RDOT_rhs_TT (params); - - const char * cpid = RDOT_IDENTIFIER_POINTER (pident); - if (strcmp (cpid, "self") == 0) - { - gcc_assert (impl_master != NULL_DOT); - rdot stid = RDOT_lhs_TT (impl_master); - ptype = rdot_build_decl1 (RTYPE_USER_STRUCT, stid); - } - rdot vpdecl = rdot_build_varDecl (ptype, RDOT_qual (params), pident); - bool chk = dot_pass_dataFlow_pushDecl (vpdecl, - RDOT_IDENTIFIER_POINTER (pident)); - gcc_assert (chk == false); - } - - rdot suite = RDOT_rhs_TT (node); - dot_pass_dataFlowBlock (suite); - - // now check the return type is correct - /* make sure its a valid type! */ - if (type != NULL) - { - bool verify = verifyType (type); - if (verify == false) - error ("unable to verify return type of %s [%s]\n", - method_id, RDOT_OPCODE_STR (type)); - else - { - std::vector retvals; - dot_pass_dataFlowBlock_retvals (suite, &retvals); - - if (retvals.size () == 0) - error ("Function [%s] does not seem to return anything!", method_id); - else - { - rdot retype = dot_pass_inferTheType (&retvals, method_id); - if (RDOT_TYPE (retype) == RTYPE_INFER) - error ("gcc rust was unable to verify the return type of [%s]", - method_id); - } - } - } - dot_pass_dataFlow_popCtx (); -} - -static -void dot_pass_dataFlowToplevel (rdot node) -{ - switch (RDOT_TYPE (node)) - { - case D_STRUCT_METHOD: - dot_pass_dataFlowFunction (node); - break; - - /* need to dataflow the layout to check the types eventually */ - case D_STRUCT_TYPE: - break; - - case D_STRUCT_IMPL: - { - // look up to make sure the impl name is available... - const char * implid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - rdot lookup = dot_pass_dataFlow_lookup (implid); - if (lookup == NULL_DOT) - error ("impl [%s] does not reference a type in scope", implid); - else - { - if (RDOT_TYPE (lookup) != D_STRUCT_TYPE) - error ("impl [%s] does not reference a struct points to [%s]", - implid, RDOT_OPCODE_STR (lookup)); - else - { - RDOT_FIELD (lookup) = node; - impl_master = lookup; - rdot next; - for (next = RDOT_rhs_TT (node); next != NULL_DOT; - next = RDOT_CHAIN (next)) - dot_pass_dataFlowFunction (next); - impl_master = NULL_DOT; - } - } - } - break; - - default: - error ("Unable to dataflow %s\n", RDOT_OPCODE_STR (node)); - break; - } -} - -vec * dot_pass_inferTypes (vec * decls) -{ - dot_pass_dataFlow_pushCtx (); - - rdot idtx = NULL_DOT; - size_t i; - for (i = 0; decls->iterate (i, &idtx); ++i) - { - rdot node = idtx; - switch (RDOT_TYPE (node)) - { - case D_STRUCT_METHOD: - { - const char * id = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - if (dot_pass_dataFlow_lookup (id)) - error ("Duplicate declaration against this function [%s]\n", id); - else - dot_pass_dataFlow_pushDecl (node, id); - } - break; - - case D_STRUCT_TYPE: - { - const char * id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - if (dot_pass_dataFlow_lookup (id)) - error ("Duplicate declaration against this type [%s]\n", id); - else - dot_pass_dataFlow_pushDecl (node, id); - } - break; - - case D_STRUCT_IMPL: - { - // look up to make sure the impl name is available... - const char * implid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - rdot lookup = dot_pass_dataFlow_lookup (implid); - if (lookup == NULL_DOT) - error ("impl [%s] does not reference a type in scope", implid); - else - { - if (RDOT_TYPE (lookup) != D_STRUCT_TYPE) - error ("impl [%s] does not reference a struct points to [%s]", - implid, RDOT_OPCODE_STR (lookup)); - else - RDOT_FIELD (lookup) = node; - } - } - break; - - default: - break; - } - } - - for (i = 0; decls->iterate (i, &idtx); ++i) - dot_pass_dataFlowToplevel (idtx); - - dot_pass_dataFlow_popCtx (); - return decls; -} diff --git a/gcc/rust/old/rdot-generic-compiler.cc b/gcc/rust/old/rdot-generic-compiler.cc deleted file mode 100644 index 13b09a4..0000000 --- a/gcc/rust/old/rdot-generic-compiler.cc +++ /dev/null @@ -1,1202 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -#define RUST_TMP "RUST_TMP" - -static std::vector *> context; - -static tree dot_pass_genFndecl_Basic (location_t, const char *, tree); -static tree dot_pass_lookupCTU (const char *); -static std::vector * dot_pass_popContext (void); -static void dot_pass_pushContext (void); -static void dot_pass_genMethodProto (rdot); -static void dot_pass_compileSuite (rdot, tree *); - -#define RDOT_ALLOCA_MODIFIERS_DO(_X, _Y) \ - if (RDOT_MEM_MODIFIER (_Y)) \ - do { \ - gcc_assert (_X != error_mark_node); \ - std::vector::reverse_iterator __rit; \ - for (__rit = RDOT_MEM_MODIFIER (_Y)->rbegin (); \ - __rit != RDOT_MEM_MODIFIER (_Y)->rend (); ++__rit) \ - { \ - switch (*__rit) \ - { \ - case ALLOC_HEAP: \ - _X = dot_pass_heapify (_X, TREE_TYPE (_X), \ - TYPE_SIZE_UNIT (TREE_TYPE (_X))); \ - break; \ - case ALLOC_REF: \ - _X = build_fold_addr_expr (_X); \ - break; \ - case ALLOC_DEREF: \ - { \ - _X = build_fold_indirect_ref_loc (RDOT_LOCATION (_Y), \ - _X); \ - TREE_THIS_NOTRAP (_X) = 1; \ - } \ - break; \ - } \ - } \ - } while (0) - -/* NOTE: this isn't global in the sense of the generated code, - This just makes it easier for expression compilation to access - the return decl */ -static tree global_retDecl; -static tree * current_function_block; -static bool global_retDecl_; -static tree __impl_type_decl = error_mark_node; -static std::vector __loopContexts; -#define dot_pass_rustToGccType(_x, _y) dot_pass_rustToGccType__ (_x, _y, false, NULL) - -static -char * dot_pass_demangleImpl (const char * val) -{ - // has form of type.method_name - size_t i; - size_t last_dot = 0; - for (i = 0; i < strlen (val); ++i) - { - if (val [i] == '.') - last_dot = i; - } - size_t bsize = (strlen (val) - last_dot) * sizeof (char); - char * buffer = (char *) xmalloc (bsize); - memset (buffer, 0, bsize); - strncpy (buffer, val + last_dot + 1, strlen (val) - last_dot); - - return buffer; -} - -static -char * dot_pass_mangle (const char * val) -{ - // just for now pre-append __rust_[id] will do ok for now - const char * stuff = "__rust_"; - size_t blen = (strlen (stuff) + strlen (val) + 1) * sizeof (char); - char * retval = (char *) xmalloc (blen); - memset (retval, 0, blen); - snprintf (retval, blen, "%s%s", stuff, val); - return retval; -} - -static -tree dot_pass_rustToGccType__ (rdot type, bool consty, bool rset, tree * record) -{ - tree retval = error_mark_node; - switch (RDOT_TYPE (type)) - { - case RTYPE_INT: - retval = integer_type_node; - break; - - case D_STRUCT_TYPE: - case D_STRUCT_INIT: - case RTYPE_USER_STRUCT: - { - const char * id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (type)); - retval = dot_pass_lookupCTU (id); - if (rset) - *record = retval; - - if (retval == error_mark_node) - error ("Unable to find struct type [%s]\n", id); - } - break; - - default: - error ("Unable to figure out gcc type for [%s]\n", - RDOT_OPCODE_STR (type)); - break; - } - if (RDOT_MEM_MODIFIER (type)) - { - std::vector::reverse_iterator rit; - for (rit = RDOT_MEM_MODIFIER (type)->rbegin (); - rit != RDOT_MEM_MODIFIER (type)->rend (); ++rit) - { - switch (*rit) - { - case ALLOC_REF: - case ALLOC_HEAP: - retval = build_pointer_type (retval); - break; - default: - fatal_error ("cannot figure out modifier applied to type [%i]", *rit); - break; - } - } - } - if (consty) - retval = build_qualified_type (retval, TYPE_QUAL_CONST); - return retval; -} - -static -tree dot_pass_genFndecl_Basic (location_t loc, const char * ident, tree fntype) -{ - tree fndecl = build_decl (loc, FUNCTION_DECL, - get_identifier (ident), fntype); - TREE_STATIC (fndecl) = 0; - TREE_USED (fndecl) = 1; - TREE_PUBLIC (fndecl) = 1; - - tree argslist = NULL_TREE; - DECL_ARGUMENTS (fndecl) = argslist; - - tree resdecl = build_decl (BUILTINS_LOCATION, RESULT_DECL, - NULL_TREE, TREE_TYPE (fntype)); - DECL_CONTEXT (resdecl) = fndecl; - DECL_ARTIFICIAL (resdecl) = true; - DECL_IGNORED_P (resdecl) = true; - DECL_RESULT (fndecl) = resdecl; - - if (DECL_STRUCT_FUNCTION (fndecl) == NULL) - push_struct_function (fndecl); - else - push_cfun (DECL_STRUCT_FUNCTION (fndecl)); - return fndecl; -} - -static -tree dot_pass_generateCString (const char * str) -{ - tree index_type = build_index_type (size_int (strlen (str))); - tree const_char_type = build_qualified_type (char_type_node, TYPE_QUAL_CONST); - tree string_type = build_array_type (const_char_type, index_type); - string_type = build_variant_type_copy (string_type); - - TYPE_STRING_FLAG (string_type) = 1; - tree string_val = build_string (strlen (str), str); - TREE_TYPE (string_val) = string_type; - - return string_val; -} - -static -tree dot_pass_lookupCTU (const char * id) -{ - tree retval = error_mark_node; - - std::vector *>::reverse_iterator it; - for (it = context.rbegin (); it != context.rend (); ++it) - { - std::map * ctx = *it; - if (ctx->count (std::string (id)) > 0) - { - retval = ctx->at (std::string (id)); - break; - } - } - - return retval; -} - -static -void dot_pass_pushDecl (const char * id, tree decl) -{ - tree test = dot_pass_lookupCTU (id); - if (test == error_mark_node) - { - std::map * ctx = context.back (); - (*ctx) [std::string (id)] = decl; - } - else - error ("duplicate declaration of [%s]\n", id); -} - -static tree -dot_pass_rust_RR_alloc (tree size) -{ - tree fntype = build_function_type_list (ptr_type_node, - size_type_node, - NULL_TREE); - tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, - get_identifier ("__rust_heap_alloc"), - fntype); - tree restype = TREE_TYPE (fndecl); - tree resdecl = build_decl (BUILTINS_LOCATION, RESULT_DECL, NULL_TREE, - restype); - DECL_CONTEXT (resdecl) = fndecl; - DECL_RESULT (fndecl) = resdecl; - DECL_EXTERNAL (fndecl) = 1; - TREE_PUBLIC (fndecl) = 1; - return build_call_expr (fndecl, 1, size); -} - -static tree -dot_pass_heap_alloc (tree size, tree type) -{ - tree ptype = build_pointer_type (type); - tree heap_tmp = build_decl (UNKNOWN_LOCATION, VAR_DECL, - create_tmp_var_name (RUST_TMP), - ptype); - dot_pass_pushDecl (IDENTIFIER_POINTER (DECL_NAME (heap_tmp)), heap_tmp); - append_to_statement_list (fold_build2 (MODIFY_EXPR, ptype, heap_tmp, - dot_pass_rust_RR_alloc (size)), - current_function_block); - return heap_tmp; -} - -static tree -dot_pass_heapify (tree value, tree type, tree size) -{ - tree alloc = dot_pass_heap_alloc (size, type); - tree gmemcpy = builtin_decl_implicit (BUILT_IN_MEMCPY); - vec * args; - vec_alloc (args, 0); - vec_safe_push (args, alloc); - vec_safe_push (args, build_fold_addr_expr (value)); - vec_safe_push (args, size); - append_to_statement_list (build_call_expr_loc_vec (UNKNOWN_LOCATION, gmemcpy, args), - current_function_block); - return alloc; -} - -static -tree dot_pass_genScalar (rdot decl) -{ - tree retval = error_mark_node; - gcc_assert (RDOT_TYPE (decl) == D_PRIMITIVE); - gcc_assert (RDOT_lhs_T (decl) == D_TD_COM); - - switch (RDOT_lhs_TC (decl).T) - { - case D_T_INTEGER: - retval = build_int_cst (integer_type_node, RDOT_lhs_TC (decl).o.integer); - break; - - default: - fatal_error ("invalid scalar type %s!\n", RDOT_CODE_STR (RDOT_lhs_TC (decl).T)); - break; - } - return retval; -} - -static -tree dot_pass_genifyCall (tree mfndecl, vec * arguments) -{ - tree retval = error_mark_node; - if (TREE_CODE (mfndecl) == FUNCTION_DECL) - { - // size_t len = arguments->length (); - // size_t lparms = 0; - // tree types = TYPE_ARG_TYPES (mfndecl); - - /* really need to check the calling types and number of arguments */ - retval = build_call_expr_loc_vec (UNKNOWN_LOCATION, mfndecl, arguments); - } - else - error ("trying to call a function which isn't callable [%s]", - IDENTIFIER_POINTER (mfndecl)); - return retval; -} - -static -tree dot_pass_lowerExpr (rdot dot, tree * block) -{ - tree retval = error_mark_node; - switch (RDOT_TYPE (dot)) - { - case D_PRIMITIVE: - { - retval = dot_pass_genScalar (dot); - RDOT_ALLOCA_MODIFIERS_DO (retval, dot); - } - break; - - case D_IDENTIFIER: - { - const char * id = RDOT_IDENTIFIER_POINTER (dot); - retval = dot_pass_lookupCTU (id); - if (retval == error_mark_node) - fatal_error ("no such id [%s] in scope", id); - RDOT_ALLOCA_MODIFIERS_DO (retval, dot); - } - break; - - case D_STRUCT_INIT: - { - // need to go fetch the type and build the constructor... - size_t count = 0; - tree root_type = error_mark_node; - dot_pass_rustToGccType__ (dot, false, true, &root_type); - gcc_assert (root_type != error_mark_node); - tree fields = TYPE_FIELDS (root_type); - - tree fnext; - for (fnext = fields; fnext != NULL_TREE; fnext = DECL_CHAIN (fnext)) - count++; - fnext = error_mark_node; - - vec *init; - vec_alloc (init, count + 1); - - /* - FIXME this is all very buggy: - eg: - struct test { - x : int - y : int - } - - initilize with test { x: 1, x: 1} will pass but it should fail - needs more validation at dataflow level and here - */ - tree rid = create_tmp_var_name (RUST_TMP); - retval = build_decl (RDOT_LOCATION (dot), VAR_DECL, rid, root_type); - dot_pass_pushDecl (IDENTIFIER_POINTER (rid), retval); - - constructor_elt empty = {NULL, NULL}; - rdot next; - size_t valid = 0; - for (next = RDOT_rhs_TT (dot); next != NULL_DOT; next = RDOT_CHAIN (next)) - { - constructor_elt* elt = init->quick_push (empty); - gcc_assert (RDOT_TYPE (next) == D_STRUCT_PARAM); - bool found = false; - for (fnext = fields; fnext != NULL_TREE; fnext = DECL_CHAIN (fnext)) - { - const char * pid = IDENTIFIER_POINTER (DECL_NAME (fnext)); - const char * sid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - if (strcmp (pid, sid) == 0) - { - found = true; - break; - } - } - if (!found) - { - error ("Unable to find field [%s] in struct [%s]", - IDENTIFIER_POINTER (TYPE_NAME (root_type)), - RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next))); - break; - } - - elt->index = fnext; - elt->value = fold_convert (TREE_TYPE (fnext), - dot_pass_lowerExpr (RDOT_rhs_TT (next), - block)); - valid++; - } - if (valid == count) - { - tree cons = build_constructor (root_type, init); - append_to_statement_list (fold_build2_loc (RDOT_LOCATION (dot), INIT_EXPR, - root_type, retval, cons), block); - } - else - { - fatal_error ("Cannot initilize struct required [%lu] fields got [%lu]", - valid, count); - // TODO better diagnostic make a map of the initilized so - // we can display the un initilized to the user - } - RDOT_ALLOCA_MODIFIERS_DO (retval, dot); - } - break; - - case D_CALL_EXPR: - { - const char * fnid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (dot)); - rdot ptr; - vec * arguments; - vec_alloc (arguments, 0); - for (ptr = RDOT_rhs_TT (dot); ptr != NULL_DOT; - ptr = RDOT_CHAIN (ptr)) - vec_safe_push (arguments, dot_pass_lowerExpr (ptr, block)); - /* lookup the function prototype */ - tree lookup = dot_pass_lookupCTU (fnid); - if (lookup != error_mark_node) - retval = dot_pass_genifyCall (lookup, arguments); - else - { - fatal_error ("Unable to find callable %s\n", fnid); - retval = error_mark_node; - } - RDOT_ALLOCA_MODIFIERS_DO (retval, dot); - } - break; - - case D_ATTRIB_REF: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree lookup = dot_pass_lowerExpr (lhs, block); - switch (RDOT_TYPE (rhs)) - { - case D_CALL_EXPR: - { - rdot crid = RDOT_lhs_TT (rhs); - const char * rlookup = RDOT_IDENTIFIER_POINTER (crid); - tree tid = TYPE_NAME (TREE_TYPE (lookup)); - const char * ctid = IDENTIFIER_POINTER (tid); - - tree type_decl = dot_pass_lookupCTU (ctid); - // just to be sure but we will have already error'd at this point.. - gcc_assert (type_decl != error_mark_node); - - tree mths = TYPE_METHODS (type_decl); - tree next; - for (next = mths; next != NULL_TREE; next = DECL_CHAIN (next)) - { - const char * mid = IDENTIFIER_POINTER (DECL_NAME (next)); - char * demangle = dot_pass_demangleImpl (mid); - if (strcmp (rlookup, demangle) == 0) - { - vec * cargs; - vec_alloc (cargs, 0); - vec_safe_push (cargs, lookup); - - rdot pnext; - for (pnext = RDOT_rhs_TT (rhs); pnext != NULL_DOT; - pnext = RDOT_CHAIN (pnext)) - vec_safe_push (cargs, dot_pass_lowerExpr (pnext, block)); - - retval = dot_pass_genifyCall (next, cargs); - break; - } - } - } - break; - - case D_IDENTIFIER: - { - const char * rlookup = RDOT_IDENTIFIER_POINTER (rhs); - tree fields = TYPE_FIELDS (TREE_TYPE (lookup)); - tree next; - for (next = fields; next != NULL_TREE; next = DECL_CHAIN (next)) - { - const char * fid = IDENTIFIER_POINTER (DECL_NAME (next)); - if (strcmp (rlookup, fid) == 0) - { - /* no idea why we need build3 here but build2 fails... */ - retval = build3 (COMPONENT_REF, TREE_TYPE (next), - lookup, next, NULL_TREE); - break; - } - } - } - break; - - default: - fatal_error ("Really don't know what happened here!\n"); - break; - } - } - break; - - case D_MODIFY_EXPR: - { - tree assignment = dot_pass_lowerExpr (RDOT_rhs_TT (dot), block); - tree decl = dot_pass_lowerExpr (RDOT_lhs_TT (dot), block); - retval = build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, assignment); - } - break; - - case D_ADD_EXPR: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree xlhs = dot_pass_lowerExpr (lhs, block); - tree xrhs = dot_pass_lowerExpr (rhs, block); - - retval = build2 (PLUS_EXPR, TREE_TYPE (xlhs), - xlhs, xrhs); - } - break; - - case D_MINUS_EXPR: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree xlhs = dot_pass_lowerExpr (lhs, block); - tree xrhs = dot_pass_lowerExpr (rhs, block); - - retval = build2 (MINUS_EXPR, TREE_TYPE (xlhs), - xlhs, xrhs); - } - break; - - case D_MULT_EXPR: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree xlhs = dot_pass_lowerExpr (lhs, block); - tree xrhs = dot_pass_lowerExpr (rhs, block); - - retval = build2 (MULT_EXPR, TREE_TYPE (xlhs), - xlhs, xrhs); - } - break; - - case D_LESS_EQ_EXPR: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree xlhs = dot_pass_lowerExpr (lhs, block); - tree xrhs = dot_pass_lowerExpr (rhs, block); - - retval = build2 (LE_EXPR, TREE_TYPE (xlhs), - xlhs, xrhs); - } - break; - - case D_EQ_EQ_EXPR: - { - rdot lhs = RDOT_lhs_TT (dot); - rdot rhs = RDOT_rhs_TT (dot); - - tree xlhs = dot_pass_lowerExpr (lhs, block); - tree xrhs = dot_pass_lowerExpr (rhs, block); - - retval = build2 (EQ_EXPR, TREE_TYPE (xlhs), - xlhs, xrhs); - } - break; - - case D_VAR_DECL: - { - const char * varID = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (dot)); - bool consty = RDOT_qual (dot); - tree gcc_type = dot_pass_rustToGccType (RDOT_rhs_TT (dot), consty); - tree decl = build_decl (RDOT_LOCATION (dot), - VAR_DECL, get_identifier (varID), - gcc_type); - if (dot_pass_lookupCTU (varID) == error_mark_node) - dot_pass_pushDecl (varID, decl); - retval = decl; - } - break; - - case D_ACC_EXPR: - { - rdot impl = RDOT_lhs_TT (dot); - char * implid = RDOT_IDENTIFIER_POINTER (impl); - printf ("implid = %s\n", implid); - } - break; - - default: - error ("unhandled binary operation type [%s]!\n", RDOT_OPCODE_STR (dot)); - break; - } - - if (DOT_RETVAL (dot)) - { - if (global_retDecl != error_mark_node) - { - tree retass = fold_build2_loc (RDOT_LOCATION (dot), - MODIFY_EXPR, TREE_TYPE (global_retDecl), - global_retDecl, retval); - append_to_statement_list (retass, block); - global_retDecl_ = true; - retval = global_retDecl; - } - } - - return retval; -} - -static -void dot_pass_compileCond (rdot node, tree * block) -{ - rdot ifblock = RDOT_lhs_TT (node); - rdot elseblock = RDOT_rhs_TT (node); - - tree endif_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("ENDIF"), - void_type_node); - tree endif_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, endif_label_decl); - DECL_CONTEXT (endif_label_decl) = current_function_decl; - - tree else_label_expr = error_mark_node; - tree else_label_decl = error_mark_node; - if (elseblock != NULL_DOT) - { - else_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("ELSE"), - void_type_node); - else_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, else_label_decl); - DECL_CONTEXT (else_label_decl) = current_function_decl; - } - else - { - else_label_expr = endif_label_expr; - else_label_decl = endif_label_decl; - } - - tree cond = dot_pass_lowerExpr (RDOT_lhs_TT (ifblock), block); - tree conditional = build3_loc (RDOT_LOCATION (node), COND_EXPR, void_type_node, - cond, - NULL_TREE, - build1 (GOTO_EXPR, void_type_node, else_label_decl)); - - append_to_statement_list (conditional, block); - dot_pass_compileSuite (RDOT_rhs_TT (ifblock), block); - append_to_statement_list (build1 (GOTO_EXPR, void_type_node, endif_label_decl), - block); - if (elseblock) - { - append_to_statement_list (else_label_expr, block); - dot_pass_compileSuite (RDOT_lhs_TT (elseblock), block); - append_to_statement_list (endif_label_expr, block); - } - else - append_to_statement_list (endif_label_expr, block); -} - -static -void dot_pass_compileBreak (rdot node, tree * block) -{ - size_t lts = __loopContexts.size (); - if (lts > 0) - append_to_statement_list (fold_build1_loc (RDOT_LOCATION (node), GOTO_EXPR, - void_type_node, - __loopContexts.back ()), - block); - else - error ("break outside of loop context"); -} - -static -void dot_pass_compileLoop (rdot node, tree * block) -{ - tree start_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("START"), - void_type_node); - tree start_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, start_label_decl); - DECL_CONTEXT (start_label_decl) = current_function_decl; - - tree end_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("END"), - void_type_node); - tree end_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, end_label_decl); - DECL_CONTEXT (end_label_decl) = current_function_decl; - __loopContexts.push_back (end_label_decl); - - /* -- -- -- */ - append_to_statement_list (start_label_expr, block); - - dot_pass_compileSuite (RDOT_lhs_TT (node), block); - append_to_statement_list (build1 (GOTO_EXPR, void_type_node, start_label_decl), block); - append_to_statement_list (end_label_expr, block); - - __loopContexts.pop_back (); - -} - -static -void dot_pass_compileWhile (rdot node, tree * block) -{ - rdot condition = RDOT_lhs_TT (node); - rdot suite = RDOT_rhs_TT (node); - - tree start_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("START"), - void_type_node); - tree start_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, start_label_decl); - DECL_CONTEXT (start_label_decl) = current_function_decl; - - tree end_label_decl = build_decl (BUILTINS_LOCATION, LABEL_DECL, - create_tmp_var_name ("END"), - void_type_node); - tree end_label_expr = fold_build1_loc (BUILTINS_LOCATION, LABEL_EXPR, - void_type_node, end_label_decl); - DECL_CONTEXT (end_label_decl) = current_function_decl; - __loopContexts.push_back (end_label_decl); - - /* -- -- -- */ - append_to_statement_list (start_label_expr, block); - - tree cond = dot_pass_lowerExpr (condition, block); - tree conditional = build3_loc (RDOT_LOCATION (node), COND_EXPR, void_type_node, - cond, NULL_TREE, - build1 (GOTO_EXPR, void_type_node, end_label_decl)); - append_to_statement_list (conditional, block); - dot_pass_compileSuite (suite, block); - append_to_statement_list (build1 (GOTO_EXPR, void_type_node, start_label_decl), block); - append_to_statement_list (end_label_expr, block); - - __loopContexts.pop_back (); -} - -static -void dot_pass_compileSuite (rdot suite, tree * block) -{ - rdot node; - for (node = suite; node != NULL_DOT; node = RDOT_CHAIN (node)) - { - if (RDOT_T_FIELD (node) == D_D_EXPR) - append_to_statement_list (dot_pass_lowerExpr (node, block), block); - else - { - switch (RDOT_TYPE (node)) - { - case D_STRUCT_IF: - dot_pass_compileCond (node, block); - break; - - case D_STRUCT_WHILE: - dot_pass_compileWhile (node, block); - break; - - case D_STRUCT_LOOP: - dot_pass_compileLoop (node, block); - break; - - case C_BREAK_STMT: - dot_pass_compileBreak (node, block); - break; - - default: - error ("Unhandled statement [%s]\n", RDOT_OPCODE_STR (node)); - break; - } - } - } -} - -static -void dot_pass_genMethodProto (rdot node) -{ - const char * method_id = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - if (dot_pass_lookupCTU (method_id) != error_mark_node) - { - error ("Duplicate declaration of function [%s]\n", method_id); - return; - } - tree rtype = void_type_node; - if (RDOT_FIELD2 (node)) - rtype = dot_pass_rustToGccType (RDOT_FIELD2 (node), false); - - rdot parameters = RDOT_lhs_TT (node); - tree fntype = error_mark_node; - if (parameters != NULL_DOT) - { - size_t nparams = 0; - rdot prm; - for (prm = parameters; prm != NULL_DOT; prm = RDOT_CHAIN (prm)) - nparams++; - - tree * gccparams = XALLOCAVEC (tree, nparams); - size_t i = 0; - for (prm = parameters; prm != NULL_DOT; prm = RDOT_CHAIN (prm)) - { - bool mut = false; - if (RDOT_qual (prm)) - mut = true; - gccparams [i] = dot_pass_rustToGccType (RDOT_rhs_TT (prm), mut); - i++; - } - fntype = build_function_type_array (rtype, nparams, gccparams); - } - else - fntype = build_function_type_list (rtype, NULL_TREE); - - tree fndecl = dot_pass_genFndecl_Basic (RDOT_LOCATION (node), method_id, fntype); - SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier (dot_pass_mangle (method_id))); - dot_pass_pushDecl (method_id, fndecl); -} - -static -tree dot_pass_genifyTopFndecl (rdot node) -{ - const char * method_id; - if (__impl_type_decl != error_mark_node) - { - char * mid = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - tree spfx = TYPE_NAME (__impl_type_decl); - const char *pfx = IDENTIFIER_POINTER (spfx); - - size_t len = strlen (mid) + strlen (pfx) + 2; - size_t bsize = len * sizeof (char); - char * buffer = (char *) alloca (bsize); - gcc_assert (buffer); - memset (buffer, 0, bsize); - - snprintf (buffer, bsize, "%s.%s", pfx, mid); - method_id = buffer; - } - else - method_id = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - - tree rtype = void_type_node; - if (RDOT_FIELD2 (node)) - rtype = dot_pass_rustToGccType (RDOT_FIELD2 (node), false); - - rdot parameters = RDOT_lhs_TT (node); - tree fntype = error_mark_node; - if (parameters != NULL_DOT) - { - size_t nparams = 0; - rdot prm; - for (prm = parameters; prm != NULL_DOT; prm = RDOT_CHAIN (prm)) - nparams++; - - tree * gccparams = XALLOCAVEC (tree, nparams); - size_t i = 0; - for (prm = parameters; prm != NULL_DOT; prm = RDOT_CHAIN (prm)) - { - bool mut = false; - if (RDOT_qual (prm)) - mut = true; - - const char * pid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (prm)); - if (strcmp (pid, "self") == 0) - { - fatal_error ("unhandled self argument!"); - } - else - gccparams [i] = dot_pass_rustToGccType (RDOT_rhs_TT (prm), mut); - i++; - } - fntype = build_function_type_array (rtype, nparams, gccparams); - } - else - fntype = build_function_type_list (rtype, NULL_TREE); - - tree fndecl = dot_pass_genFndecl_Basic (RDOT_LOCATION (node), method_id, fntype); - SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier (dot_pass_mangle (method_id))); - dot_pass_pushContext (); - - rdot rdot_params = RDOT_lhs_TT (node); - if (rdot_params != NULL_DOT) - { - tree argslist = NULL_TREE; - rdot next; - for (next = rdot_params; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - const char * pid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - if (dot_pass_lookupCTU (pid) != error_mark_node) - error ("paramater [%s] is already declared", pid); - - tree ptype = error_mark_node; - if (strcmp (pid, "self") == 0) - { - fatal_error ("unhandled self param!"); - } - else - ptype = dot_pass_rustToGccType (RDOT_rhs_TT (next), false); - - tree param = build_decl (RDOT_LOCATION (node), PARM_DECL, - get_identifier (pid), ptype); - DECL_CONTEXT (param) = fndecl; - DECL_ARG_TYPE (param) = ptype; - TREE_READONLY (param) = true; - TREE_USED (param) = true; - argslist = chainon (argslist, param); - - dot_pass_pushDecl (pid, param); - } - DECL_ARGUMENTS (fndecl) = argslist; - } - - current_function_decl = fndecl; - tree block = alloc_stmt_list (); - current_function_block = █ - - global_retDecl_ = false; - if (rtype == void_type_node) - global_retDecl = error_mark_node; - else - global_retDecl = DECL_RESULT (fndecl); - - // compile the block... - dot_pass_compileSuite (RDOT_rhs_TT (node), &block); - - // make sure it returns something!!! - if (rtype != void_type_node) - { - if (global_retDecl_ == false) - { - error ("Function [%s] doesn't seem to return anything!!\n", method_id); - return error_mark_node; - } - tree returnVal = build1 (RETURN_EXPR, rtype, global_retDecl); - append_to_statement_list (returnVal, &block); - } - - tree bind = NULL_TREE; - tree declare_vars = DECL_RESULT (fndecl); - - tree head = declare_vars; - std::vector * decl_vars = dot_pass_popContext (); - std::vector::iterator it; - for (it = decl_vars->begin (); it != decl_vars->end (); ++it) - { - if (TREE_CODE (*it) != PARM_DECL) - { - DECL_CHAIN (head) = *it; - head = *it; - } - } - delete decl_vars; - - tree bl = make_node (BLOCK); - BLOCK_SUPERCONTEXT (bl) = fndecl; - DECL_INITIAL (fndecl) = bl; - BLOCK_VARS(bl) = declare_vars; - TREE_USED (bl) = true; - - bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (bl), - NULL_TREE, bl); - TREE_SIDE_EFFECTS (bind) = 1; - /* Finalize the main function */ - BIND_EXPR_BODY (bind) = block; - block = bind; - DECL_SAVED_TREE (fndecl) = block; - - gimplify_function_tree (fndecl); - cgraph_finalize_function (fndecl, false); - - pop_cfun (); - - // reset them - global_retDecl = error_mark_node; - global_retDecl_ = false; - - return fndecl; -} - -static -tree dot_pass_genifyStruct (rdot node) -{ - rdot layout = RDOT_rhs_TT (node); - tree userStruct = make_node (RECORD_TYPE); - - bool first = true; - tree head_chain = NULL_TREE; - tree curr = head_chain; - - rdot next; - for (next = layout; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - gcc_assert (RDOT_TYPE (next) == D_PARAMETER); - tree name = get_identifier (RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next))); - tree type = dot_pass_rustToGccType (RDOT_rhs_TT (next), false); - tree field = build_decl (RDOT_LOCATION (node), - FIELD_DECL, name, type); - DECL_CONTEXT (field) = userStruct; - if (first == true) - { - head_chain = curr = field; - first = false; - } - else - { - DECL_CHAIN (curr) = field; - curr = field; - } - } - - TYPE_FIELDS (userStruct) = head_chain; - layout_type (userStruct); - - const char * struct_id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - tree type_decl = build_decl (RDOT_LOCATION (node), TYPE_DECL, - get_identifier (struct_id), userStruct); - TYPE_NAME (userStruct) = get_identifier (struct_id); - grs_preserve_from_gc (type_decl); - rest_of_decl_compilation (type_decl, 1, 0); - dot_pass_pushDecl (struct_id, userStruct); - return type_decl; -} - -static -std::vector * dot_pass_genifyImplBlock (rdot node) -{ - std::vector * retval = new std::vector; - // look up the struct type to set TYPE_METHODS on it... - const char * implid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - tree type_decl = dot_pass_lookupCTU (implid); - if (type_decl == error_mark_node) - error ("type [%s] does not exist for impl block", implid); - else - { - __impl_type_decl = type_decl; - rdot decl; - tree fndecl_chain = error_mark_node, curr = error_mark_node; - bool first = true; - for (decl = RDOT_rhs_TT (node); decl != NULL_DOT; decl = RDOT_CHAIN (decl)) - { - tree fndecl = dot_pass_genifyTopFndecl (decl); - retval->push_back (fndecl); - if (first == true) - { - fndecl_chain = fndecl; - curr = fndecl_chain; - first = false; - } - else - { - DECL_CHAIN (curr) = fndecl; - curr = fndecl; - } - } - TYPE_METHODS (__impl_type_decl) = fndecl_chain; - __impl_type_decl = error_mark_node; - } - return retval; -} - -static -std::vector * dot_pass_genifyTopNode (rdot node) -{ - std::vector * retval = NULL; - switch (RDOT_TYPE (node)) - { - case D_STRUCT_METHOD: - { - retval = new std::vector; - retval->push_back (dot_pass_genifyTopFndecl (node)); - } - break; - - // nothing to do here... - case D_STRUCT_TYPE: - case D_STRUCT_IMPL: - break; - - default: - error ("Unhandled Toplevel declaration [%s]\n", RDOT_OPCODE_STR (node)); - break; - } - return retval; -} - -static -void dot_pass_setupContext (void) -{ - std::map * lgrs = new std::map(); - rs_fill_runtime_decls (lgrs); - context.push_back (lgrs); -} - -static -void dot_pass_pushContext (void) -{ - std::map * nctx = new std::map; - context.push_back (nctx); -} - -static -std::vector * dot_pass_popContext (void) -{ - std::vector * retval = new std::vector; - if (context.size () > 0) - { - std::map * popd = context.back (); - context.pop_back (); - - std::map::iterator it; - for (it = popd->begin (); it != popd->end (); ++it) - retval->push_back (it->second); - - delete popd; - } - return retval; -} - -vec * dot_pass_Genericify (vec * decls) -{ - vec * retval; - vec_alloc (retval, 0); - - dot_pass_setupContext (); - dot_pass_pushContext (); - - size_t i; - rdot idtx = NULL_DOT; - - /* fill up the prototypes now ... */ - for (i = 0; decls->iterate (i, &idtx); ++i) - { - rdot node = idtx; - switch (RDOT_TYPE (node)) - { - case D_STRUCT_METHOD: - dot_pass_genMethodProto (node); - break; - - case D_STRUCT_TYPE: - { - tree gen = dot_pass_genifyStruct (node); - vec_safe_push (retval, gen); - } - break; - - default: - break; - } - } - - if (seen_error ()) - goto exit; - - for (i = 0; decls->iterate (i, &idtx); ++i) - { - rdot node = idtx; - switch (RDOT_TYPE (node)) - { - case D_STRUCT_IMPL: - { - std::vector * gdecls = dot_pass_genifyImplBlock (node); - std::vector::iterator it; - for (it = gdecls->begin (); it != gdecls->end (); ++it) - vec_safe_push (retval, *it); - delete gdecls; - } - break; - - default: - break; - } - } - - if (seen_error ()) - goto exit; - - __impl_type_decl = error_mark_node; - for (i = 0; decls->iterate (i, &idtx); ++i) - { - std::vector * gdecls = dot_pass_genifyTopNode (idtx); - if (gdecls != NULL) - { - std::vector::iterator it; - for (it = gdecls->begin (); it != gdecls->end (); ++it) - vec_safe_push (retval, *it); - delete gdecls; - } - } - - exit: - dot_pass_popContext (); - return retval; -} diff --git a/gcc/rust/old/rdot-impl.cc b/gcc/rust/old/rdot-impl.cc deleted file mode 100644 index be4421b..0000000 --- a/gcc/rust/old/rdot-impl.cc +++ /dev/null @@ -1,267 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -static bool initilized = false; - -static const char * opcodeStrings [] = { - /* [D_IDENTIFIER] */ "identifier", - /* [D_T_INTEGER] */ "literal_integer", - /* [D_T_FLOAT] */ "literal_float", - /* [D_T_STRING] */ "literal_string", - /* [D_T_LIST] */ "liteal_list", - /* [D_VAR_DECL] */ "var_decl", - /* [D_MODIFY_EXPR] */ "modify_expr", - /* [D_MULT_EXPR] */ "multiply_expr", - /* [D_DIVD_EXPR] */ "divide_expr", - /* [D_ADD_EXPR] */ "plus_expr", - /* [D_MINUS_EXPR] */ "minus_expr", - /* [D_EQ_EQ_EXPR] */ "equivilant_expr", - /* [D_LESS_EXPR] */ "less_than_expr", - /* [D_LESS_EQ_EXPR] */ "less_eq_expr", - /* [D_GREATER_EXPR] */ "greater_expr", - /* [D_GREATER_EQ_EXPR] */ "greater_eq_expr", - /* [D_NOT_EQ_EXPR] */ "not_equal_expr", - /* [D_CALL_EXPR] */ "call_expr", - /* [D_ATTRIB_EXPR] */ "attribute_reference", - /* [D_ACC_EXPR] */ "accessor_reference", - /* [D_STRUCT_METHOD] */ "struct_method", - /* [D_STRUCT_WHILE] */ "struct_while", - /* [D_STRUCT_LOOP] */ "struct_loop", - /* [D_D_EXPR] */ "enc_expression", - /* [D_TD_COM] */ "TD_COM", - /* [D_TD_DOT] */ "TD_DOT", - /* [D_TD_NULL] */ "TD_NULL", - /* [D_PRIMITIVE] */ "primitive", - /* [D_STRUCT_IF] */ "struct_if", - /* [D_STRUCT_ELIF] */ "struct_elif", - /* [D_STRUCT_ELSE] */ "struct_else", - /* [D_STRUCT_CONDITIONAL] */ "struct_conditional", - /* [RTYPE_BOOL] */ "type_bool", - /* [RTYPE_INT] */ "type_int", - /* [RTYPE_FLOAT] */ "type_float", - /* [RTYPE_UINT] */ "type_uint", - /* [RTYPE_INFER] */ "type_infer", - /* [D_PARAMETER] */ "parameter", - /* [D_STRUCT_TYPE] */ "struct_definition", - /* [D_STRUCT_PARAM] */ "struct_init_param", - /* [D_STRUCT_INIT] */ "struct_initilization", - /* [RTYPE_USER_STRUCT] */ "user_struct_type", - /* [D_STRUCT_ENUM] */ "struct_enum", - /* [D_STRUCT_IMPL] */ "impl_block", - /* [D_BOOLEAN] */ "d_boolean", - /* [D_T_BOOL] */ "d_t_bool", - /* [C_BREAK_STMT] */ "break_stmt", - /* [C_CONT_STMT] */ "continue_stmt", - /* [C_RETURN_STMT] */ "return_stmt", -}; - -const char * -rdot_getOpString_T (const opcode_t o) -{ - return opcodeStrings [o]; -} - -const char * -rdot_getOpString (const rdot dot) -{ - return rdot_getOpString_T (RDOT_TYPE (dot)); -} - -void rdot_init (void) -{ - if (initilized) - return; - //... probably should get rid of this function ... - initilized = true; -} - -rdot rdot_build_varDecl (rdot type, bool final, rdot id) -{ - rdot decl = rdot_build_decl2 (D_VAR_DECL, id, type); - RDOT_qual (decl) = final; - return decl; -} - -rdot rdot_alloc (void) -{ - rdot retval = (struct grs_tree_dot *) - xmalloc (sizeof (struct grs_tree_dot)); - gcc_assert (retval); - memset (retval, 0, sizeof (struct grs_tree_dot)); - RDOT_LOCATION (retval) = UNKNOWN_LOCATION; - return retval; -} - -rdot rdot_build_decl1 (opcode_t o, rdot t1) -{ - rdot decl = RDOT_alloc; - - RDOT_TYPE(decl) = o; - RDOT_T_FIELD(decl) = D_TD_NULL; - RDOT_FIELD(decl) = NULL_DOT; - - decl->opaT = D_TD_DOT; - decl->opa.t = t1; - decl->opbT = D_TD_NULL; - - RDOT_CHAIN(decl) = NULL_DOT; - - return decl; -} - -rdot rdot_build_decl2 (opcode_t o, rdot t1, rdot t2) -{ - rdot decl = RDOT_alloc; - - RDOT_TYPE (decl) = o; - if ((o == D_VAR_DECL) - || (o == D_MODIFY_EXPR) - || (o == D_ADD_EXPR) - || (o == D_MINUS_EXPR) - || (o == D_MULT_EXPR) - || (o == D_DIVD_EXPR) - || (o == D_CALL_EXPR) - || (o == D_EQ_EQ_EXPR) - || (o == D_LESS_EXPR) - || (o == D_LESS_EQ_EXPR) - || (o == D_GREATER_EXPR) - || (o == D_GREATER_EQ_EXPR) - || (o == D_NOT_EQ_EXPR) - || (o == D_ATTRIB_REF) - || (o == D_ACC_EXPR) - || (o == D_STRUCT_INIT) - ) - RDOT_T_FIELD(decl) = D_D_EXPR; - else - RDOT_T_FIELD(decl) = D_TD_NULL; - - RDOT_FIELD (decl) = NULL_DOT; - - decl->opaT = D_TD_DOT; - decl->opa.t = t1; - decl->opbT = D_TD_DOT; - decl->opb.t = t2; - - RDOT_CHAIN(decl) = NULL_DOT; - - return decl; -} - -rdot rdot_build_fndecl (rdot ident, bool pub, rdot params, rdot rtype, rdot suite) -{ - rdot decl = RDOT_alloc; - - RDOT_TYPE (decl) = D_STRUCT_METHOD; - RDOT_T_FIELD (decl) = D_TD_NULL; - - RDOT_FIELD (decl) = ident; - RDOT_FIELD2 (decl) = rtype; - DOT_RETVAL (decl) = pub; - - decl->opaT = D_TD_DOT; - decl->opa.t = params; - decl->opbT = D_TD_DOT; - decl->opb.t = suite; - - RDOT_CHAIN(decl) = NULL_DOT; - - return decl; -} - -rdot rdot_build_integer (const int i) -{ - rdot decl = RDOT_alloc; - RDOT_TYPE(decl) = D_PRIMITIVE; - - RDOT_FIELD(decl) = NULL_DOT; - RDOT_T_FIELD(decl) = D_D_EXPR; - - decl->opaT = D_TD_COM; - decl->opa.tc.T = D_T_INTEGER; - decl->opa.tc.o.integer = i; - - return decl; -} - -rdot rdot_build_float (const float f) -{ - rdot decl = RDOT_alloc; - RDOT_TYPE(decl) = D_PRIMITIVE; - - RDOT_FIELD(decl) = NULL_DOT; - RDOT_T_FIELD(decl) = D_D_EXPR; - - decl->opaT = D_TD_COM; - decl->opa.tc.T = D_T_FLOAT; - decl->opa.tc.o.ffloat = f; - - return decl; -} - -rdot rdot_build_string (const char * s) -{ - rdot decl = RDOT_alloc; - RDOT_TYPE (decl) = D_PRIMITIVE; - - RDOT_FIELD (decl) = NULL_DOT; - RDOT_T_FIELD (decl) = D_D_EXPR; - - decl->opaT = D_TD_COM; - decl->opa.tc.T = D_T_STRING; - decl->opa.tc.o.string = xstrdup (s); - - return decl; -} - -rdot rdot_build_identifier (const char * s) -{ - rdot decl = RDOT_alloc; - - RDOT_TYPE(decl) = D_IDENTIFIER; - RDOT_FIELD(decl) = NULL_DOT; - RDOT_T_FIELD(decl) = D_D_EXPR; - - decl->opaT = D_TD_COM; - decl->opa.tc.T = D_T_STRING; - decl->opa.tc.o.string = xstrdup (s); - - decl->opbT = D_TD_NULL; - - RDOT_CHAIN(decl) = NULL_DOT; - - return decl; -} - -rdot rdot_build_bool (bool val) -{ - rdot decl = RDOT_alloc; - - RDOT_TYPE(decl) = D_BOOLEAN; - RDOT_FIELD(decl) = NULL_DOT; - RDOT_T_FIELD(decl) = D_D_EXPR; - - decl->opaT = D_TD_COM; - decl->opa.tc.T = D_T_BOOL; - decl->opa.tc.o.boolean = val; - - decl->opbT = D_TD_NULL; - - RDOT_CHAIN(decl) = NULL_DOT; - - return decl; -} diff --git a/gcc/rust/old/rdot-impl.h b/gcc/rust/old/rdot-impl.h deleted file mode 100644 index 8f7d71d1..0000000 --- a/gcc/rust/old/rdot-impl.h +++ /dev/null @@ -1,166 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#ifndef __GCC_RDOT_IMPL_H__ -#define __GCC_RDOT_IMPL_H__ - -typedef enum { - D_IDENTIFIER = 0, - D_T_INTEGER, - D_T_FLOAT, - D_T_STRING, - D_T_LIST, - - D_VAR_DECL, - D_MODIFY_EXPR, - D_MULT_EXPR, - D_DIVD_EXPR, - D_ADD_EXPR, - D_MINUS_EXPR, - - D_EQ_EQ_EXPR, - D_LESS_EXPR, - D_LESS_EQ_EXPR, - D_GREATER_EXPR, - D_GREATER_EQ_EXPR, - D_NOT_EQ_EXPR, - - D_CALL_EXPR, - D_ATTRIB_REF, - D_ACC_EXPR, - - D_STRUCT_METHOD, - D_STRUCT_WHILE, - D_STRUCT_LOOP, - - D_D_EXPR, - D_TD_COM, - D_TD_DOT, - D_TD_NULL, - - D_PRIMITIVE, - - D_STRUCT_IF, - D_STRUCT_ELIF, - D_STRUCT_ELSE, - D_STRUCT_CONDITIONAL, - - RTYPE_BOOL, - RTYPE_INT, - RTYPE_FLOAT, - RTYPE_UINT, - RTYPE_INFER, - - D_PARAMETER, - D_STRUCT_TYPE, - D_STRUCT_PARAM, - D_STRUCT_INIT, - - RTYPE_USER_STRUCT, - - D_STRUCT_ENUM, - D_STRUCT_IMPL, - - D_BOOLEAN, - D_T_BOOL, - - C_BREAK_STMT, - C_CONT_STMT, - C_RETURN_STMT -} opcode_t ; - -typedef enum { - ALLOC_HEAP, - ALLOC_REF, - ALLOC_DEREF -} ALLOCA_; - -typedef struct grs_rdot_tree_common { - opcode_t T; - union { - int integer; - float ffloat; - unsigned char c; - char * string; - bool boolean; - } o; -} rdot_tree_common ; - -typedef struct GTY(()) grs_tree_dot { - opcode_t T, FT, opaT, opbT; - bool retval, qual; - std::vector alloca_modifier; - location_t loc; - struct grs_tree_dot * field1; - struct grs_tree_dot * field2; - union { - rdot_tree_common tc; - struct grs_tree_dot * t; - } opa; - union { - rdot_tree_common tc; - struct grs_tree_dot * t; - } opb; - struct grs_tree_dot * next; -} * rdot; - -#define NULL_DOT ((rdot) 0) -#define RDOT_alloc rdot_alloc () -#define RDOT_TYPE(x_) x_->T -#define RDOT_LOCATION(x_) x_->loc -#define RDOT_T_FIELD(x_) x_->FT -#define RDOT_CHAIN(x_) x_->next -#define RDOT_FIELD(x_) x_->field1 -#define RDOT_FIELD2(x_) x_->field2 -#define RDOT_lhs_T(x_) x_->opaT -#define RDOT_rhs_T(x_) x_->opbT -#define RDOT_lhs_TT(x_) x_->opa.t -#define RDOT_rhs_TT(x_) x_->opb.t -#define RDOT_lhs_TC(x_) x_->opa.tc -#define RDOT_rhs_TC(x_) x_->opb.tc -#define RDOT_qual(x_) x_->qual -#define DOT_RETVAL(x_) x_->retval -#define RDOT_MEM_MODIFIER(x_) (&(x_->alloca_modifier)) -#define RDOT_IDENTIFIER_POINTER(x_) RDOT_lhs_TC (x_).o.string -#define RDOT_BOOLEAN_VAL(x_) RDOT_lhs_TC (x_).o.boolean -#define RDOT_CODE_STR(x_) rdot_getOpString_T (x_) -#define RDOT_OPCODE_STR(x_) rdot_getOpString (x_) - -// destination is cleared before copy -// copy a vector (source, destination) -#define RDOT_MMEM_COPY(x_, y_) \ - do { \ - y_->clear (); \ - std::vector::iterator __it; \ - for (__it = x_->begin (); __it != x_->end (); ++__it) \ - y_->push_back (*__it); \ - } while (0) - -extern rdot rdot_alloc (void); -extern void rdot_init (void); -extern rdot rdot_build_decl1 (opcode_t, rdot); -extern rdot rdot_build_decl2 (opcode_t, rdot, rdot); -extern rdot rdot_build_fndecl (rdot, bool, rdot, rdot, rdot); -extern rdot rdot_build_float (const float); -extern rdot rdot_build_integer (const int); -extern rdot rdot_build_string (const char *); -extern rdot rdot_build_identifier (const char *); -extern rdot rdot_build_bool (bool); -extern rdot rdot_build_varDecl (rdot, bool, rdot); -extern const char * rdot_getOpString (const rdot); -extern const char * rdot_getOpString_T (const opcode_t); - -#endif //__GCC_RDOT_IMPL_H__ diff --git a/gcc/rust/old/rdot-pretty-print.cc b/gcc/rust/old/rdot-pretty-print.cc deleted file mode 100644 index 51330e3..0000000 --- a/gcc/rust/old/rdot-pretty-print.cc +++ /dev/null @@ -1,664 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -static bool _no_infer = false; -static bool first = true; - -#define RDOT_PREFIX_PRE ".pre-rdot" -#define RDOT_PREFIX_POST ".pst-rdot" - -static const char * typeStrings [] = { - "bool", - "int", - "float", - "unsigned_int", - "__infer_me", - "__user_struct", - "void" -}; - -static char * -typeStringNode (const rdot node) -{ - char buffer [128]; - size_t offset = 0; - if (RDOT_MEM_MODIFIER (node)) - { - std::vector::iterator it; - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it ) - { - switch (*it) - { - case ALLOC_HEAP: - { - buffer [offset] = '~'; - offset++; - } - break; - case ALLOC_REF: - { - buffer [offset] = '&'; - offset++; - } - break; - case ALLOC_DEREF: - { - buffer [offset] = '*'; - offset++; - } - break; - } - } - } - if (node != NULL_DOT) - { - switch (RDOT_TYPE (node)) - { - case RTYPE_BOOL: - strcpy (buffer+offset, typeStrings [0]); - break; - - case RTYPE_INT: - strcpy (buffer+offset, typeStrings [1]); - break; - - case RTYPE_FLOAT: - strcpy (buffer+offset, typeStrings [2]); - break; - - case RTYPE_UINT: - strcpy (buffer+offset, typeStrings [3]); - break; - - case RTYPE_INFER: - { - if (_no_infer) - fatal_error ("gcc-rust has failed to infer a type and cannot continue"); - else - strcpy (buffer+offset, typeStrings [4]); - } - break; - - case RTYPE_USER_STRUCT: - strcpy (buffer+offset, RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node))); - break; - - default: - fatal_error ("unhandled type [%s]", RDOT_OPCODE_STR (node)); - break; - } - } - return xstrdup (buffer); -} - -static void dot_pass_dump_node (FILE *, rdot, size_t); -static void dot_pass_dump_method (FILE *, rdot, size_t); -static void dot_pass_dump_struct (FILE *, rdot, size_t); - -static void dot_pass_dumpPrimitive (FILE *, rdot); -static void dot_pass_dumpExprNode (FILE *, rdot); -static void dot_pass_dump_expr (FILE *, rdot); - -static -void dot_pass_dump_struct (FILE * fd, rdot node, size_t indents) -{ - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - - rdot ident = RDOT_lhs_TT (node); - rdot layout = RDOT_rhs_TT (node); - - fprintf (fd, "struct %s {\n", RDOT_IDENTIFIER_POINTER (ident)); - rdot next; - for (next = layout; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - gcc_assert (RDOT_TYPE (next) = D_PARAMETER); - const char * id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - const char * typestr = typeStringNode (RDOT_rhs_TT (next)); - - for (i = 0; i < (indents + 1); ++i) - fprintf (fd, " "); - fprintf (fd, "%s %s;\n", typestr, id); - } - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}\n"); -} - -static -void dot_pass_dump_method (FILE * fd, rdot node, size_t indents) -{ - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - - const char * method_id = RDOT_IDENTIFIER_POINTER (RDOT_FIELD (node)); - char * rtype = NULL; - if (RDOT_FIELD2 (node)) - rtype = typeStringNode (RDOT_FIELD2 (node)); - else - rtype = xstrdup ("void"); - rdot parameters = RDOT_lhs_TT (node); - - if (DOT_RETVAL (node)) - fprintf (fd, "pub fn %s ( ", method_id); - else - fprintf (fd, "fn %s ( ", method_id); - - if (parameters == NULL_DOT) - fprintf (fd, "void"); - else - { - rdot next; - for (next = parameters; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - gcc_assert (RDOT_TYPE (next) = D_PARAMETER); - bool iself = false; - bool muta = RDOT_qual (next); - const char * id = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - - if (strcmp (id, "self") == 0) - iself = true; - - const char *smuta; - if (muta) { - smuta = "mut"; - } - else { - smuta = "final"; - } - - if (iself) - fprintf (fd, "[%s] _self_", smuta); - else - { - const char * typestr = typeStringNode (RDOT_rhs_TT (next)); - fprintf (fd, "[%s] %s:%s", smuta, typestr, id); - } - if (RDOT_CHAIN (next) != NULL_DOT) - fprintf (fd, ", "); - } - } - fprintf (fd, " ) -> %s {\n", rtype); - free (rtype); - - rdot suite; - for (suite = RDOT_rhs_TT (node); suite != NULL_DOT; suite = RDOT_CHAIN (suite)) - { - dot_pass_dump_node (fd, suite, indents + 1); - fprintf (fd, "\n"); - } - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}\n"); -} - -static -void dot_pass_dumpPrimitive (FILE * fd, rdot node) -{ - /* Handle other primitive literal types here ... */ - switch (RDOT_lhs_TC (node).T) - { - case D_T_INTEGER: - fprintf (fd, "%i", RDOT_lhs_TC (node).o.integer); - break; - - case D_T_FLOAT: - fprintf (fd, "%f", RDOT_lhs_TC (node).o.ffloat); - break; - - case D_T_STRING: - fprintf (fd, "\"%s\"", RDOT_lhs_TC (node).o.string); - break; - - default: - fatal_error ("Unable to dump primitive [%s]", - rdot_getOpString_T (RDOT_lhs_TC (node).T)); - break; - } -} - -static -void dot_pass_dumpExprNode (FILE * fd, rdot node) -{ - if (RDOT_MEM_MODIFIER (node)) - { - std::vector::iterator it; - for (it = RDOT_MEM_MODIFIER (node)->begin (); - it != RDOT_MEM_MODIFIER (node)->end (); ++it ) - { - switch (*it) - { - case ALLOC_DEREF: - fprintf (fd, "*"); - break; - case ALLOC_HEAP: - fprintf (fd, "~"); - break; - case ALLOC_REF: - fprintf (fd, "&"); - break; - } - } - } - switch (RDOT_TYPE (node)) - { - case D_PRIMITIVE: - dot_pass_dumpPrimitive (fd, node); - break; - - case D_IDENTIFIER: - fprintf (fd, "%s", RDOT_IDENTIFIER_POINTER (node)); - break; - - case D_BOOLEAN: - { - bool val = RDOT_BOOLEAN_VAL (node); - if (val) - fprintf (fd, "true"); - else - fprintf (fd, "false"); - } - break; - - case D_CALL_EXPR: - { - rdot id = RDOT_lhs_TT (node); - dot_pass_dump_expr (fd, id); - fprintf (fd, " ("); - - rdot p; - for (p = RDOT_rhs_TT (node); p != NULL_DOT; p = RDOT_CHAIN (p)) - { - dot_pass_dump_expr (fd, p); - if (RDOT_CHAIN (p) != NULL_DOT) - fprintf (fd, ", "); - } - fprintf (fd, ")"); - } - break; - - case D_VAR_DECL: - { - const char * mut; - if (RDOT_qual (node)) - mut = "_final_"; - else - mut = "_mut_"; - - fprintf (fd, "let [%s] ", mut); - dot_pass_dumpExprNode (fd, RDOT_lhs_TT (node)); - fprintf (fd, " -> [%s]", typeStringNode (RDOT_rhs_TT (node))); - } - break; - - case D_STRUCT_INIT: - { - rdot ident = RDOT_lhs_TT (node); - rdot init = RDOT_rhs_TT (node); - - fprintf (fd, "%s { ", RDOT_IDENTIFIER_POINTER (ident)); - rdot next; - for (next = init; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - gcc_assert (RDOT_TYPE (next) == D_STRUCT_PARAM); - const char * name = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - - fprintf (fd, "%s:(", name); - dot_pass_dump_expr (fd, RDOT_rhs_TT (next)); - fprintf (fd, ")"); - if (RDOT_CHAIN (next) != NULL_DOT) - fprintf (fd, ", "); - } - fprintf (fd, " }"); - } - break; - - default: - error ("unhandled dumpExprNode [%s]\n", RDOT_OPCODE_STR (node)); - break; - } -} - -static -void dot_pass_dump_expr (FILE * fd, rdot node) -{ - if (DOT_RETVAL (node)) { - fprintf (fd, "[_rust_retval]: "); - } - - switch (RDOT_TYPE (node)) - { - case D_PRIMITIVE: - case D_IDENTIFIER: - case D_CALL_EXPR: - case D_BOOLEAN: - case D_VAR_DECL: - case D_STRUCT_INIT: - dot_pass_dumpExprNode (fd, node); - break; - - default: - { - /* print expr tree ... */ - rdot lhs = RDOT_lhs_TT (node); - rdot rhs = RDOT_rhs_TT (node); - - dot_pass_dump_expr (fd, lhs); - switch (RDOT_TYPE (node)) - { - case D_MODIFY_EXPR: - fprintf (fd, " = "); - break; - - case D_ADD_EXPR: - fprintf (fd, " + "); - break; - - case D_MINUS_EXPR: - fprintf (fd, " - "); - break; - - case D_MULT_EXPR: - fprintf (fd, " * "); - break; - - case D_LESS_EXPR: - fprintf (fd, " < "); - break; - - case D_LESS_EQ_EXPR: - fprintf (fd, " <= "); - break; - - case D_GREATER_EXPR: - fprintf (fd, " > "); - break; - - case D_GREATER_EQ_EXPR: - fprintf (fd, " >= "); - break; - - case D_EQ_EQ_EXPR: - fprintf (fd, " == "); - break; - - case D_NOT_EQ_EXPR: - fprintf (fd, " != "); - break; - - case D_ATTRIB_REF: - fprintf (fd, "."); - break; - - case D_ACC_EXPR: - fprintf (fd, "::"); - break; - - default: - fatal_error ("unhandled dump [%s]!\n", RDOT_OPCODE_STR (node)); - break; - } - dot_pass_dump_expr (fd, rhs); - } - break; - } -} - -static -void dot_pass_dump_enum (FILE * fd, rdot node, size_t indents) -{ - rdot enum_id = RDOT_lhs_TT (node); - rdot enum_layout = RDOT_rhs_TT (node); - - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - const char * id = RDOT_IDENTIFIER_POINTER (enum_id); - fprintf (fd, "enum %s {\n", id); - - indents++; - rdot next; - for (next = enum_layout; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - const char *enumit = RDOT_IDENTIFIER_POINTER (next); - fprintf (fd, "[%s],\n", enumit); - } - indents--; - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}\n"); -} - -static -void dot_pass_dump_cond (FILE * fd, rdot node, size_t indents) -{ - size_t i; - rdot ifb = RDOT_lhs_TT (node); - rdot elb = RDOT_rhs_TT (node); - - gcc_assert (RDOT_TYPE (ifb) == D_STRUCT_IF); - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - - fprintf (fd, "if ("); - dot_pass_dump_expr (fd, RDOT_lhs_TT (ifb)); - fprintf (fd, ") {\n"); - - rdot next; - for (next = RDOT_rhs_TT (ifb) ; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - dot_pass_dump_node (fd, next, indents + 1); - fprintf (fd, "\n"); - } - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}"); - - if (elb != NULL_DOT) - { - fprintf (fd, " else {\n"); - for (next = RDOT_lhs_TT (elb); next != NULL_DOT; next = RDOT_CHAIN (next)) - { - dot_pass_dump_node (fd, next, indents + 1); - fprintf (fd, "\n"); - } - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}\n"); - } -} - -static -void dot_pass_dump_break (FILE * fd, const rdot node, size_t indents) -{ - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "break;"); -} - -static -void dot_pass_dump_loop (FILE * fd, const rdot node, size_t indents) -{ - const rdot suite = RDOT_lhs_TT (node); - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "loop {\n"); - - rdot next; - for (next = suite; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - dot_pass_dump_node (fd, next, indents + 1); - fprintf (fd, "\n"); - } - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}\n"); -} - -static -void dot_pass_dump_while (FILE * fd, const rdot node, size_t indents) -{ - size_t i; - rdot expr = RDOT_lhs_TT (node); - rdot suite = RDOT_rhs_TT (node); - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "while ("); - dot_pass_dump_expr (fd, expr); - fprintf (fd, ") {\n"); - - rdot next; - for (next = suite; next != NULL_DOT; next = RDOT_CHAIN (next)) - { - dot_pass_dump_node (fd, next, indents + 1); - fprintf (fd, "\n"); - } - - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - fprintf (fd, "}"); -} - -static -void dot_pass_dump_impl (FILE * fd, rdot node, size_t indents) -{ - const char * implid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (node)); - fprintf (fd, "impl %s {\n", implid); - - rdot next; - for (next = RDOT_rhs_TT (node); next != NULL_DOT; next = RDOT_CHAIN (next)) - { - dot_pass_dump_node (fd, next, indents + 1); - fprintf (fd, "\n"); - } - - fprintf (fd, "}\n"); -} - -static -void dot_pass_dump_node (FILE * fd, rdot node, size_t indents) -{ - if (RDOT_T_FIELD (node) == D_D_EXPR) - { - size_t i; - for (i = 0; i < indents; ++i) - fprintf (fd, " "); - dot_pass_dump_expr (fd, node); - fprintf (fd, ";"); - } - else - { - switch (RDOT_TYPE (node)) - { - case D_PRIMITIVE: - dot_pass_dump_expr (fd, node); - break; - - case D_STRUCT_IMPL: - dot_pass_dump_impl (fd, node, indents); - break; - - case D_STRUCT_METHOD: - dot_pass_dump_method (fd, node, indents); - break; - - case D_STRUCT_TYPE: - dot_pass_dump_struct (fd, node, indents); - break; - - case D_STRUCT_ENUM: - dot_pass_dump_enum (fd, node, indents); - break; - - case D_STRUCT_IF: - dot_pass_dump_cond (fd, node, indents); - break; - - case D_STRUCT_WHILE: - dot_pass_dump_while (fd, node, indents); - break; - - case D_STRUCT_LOOP: - dot_pass_dump_loop (fd, node, indents); - break; - - case C_BREAK_STMT: - dot_pass_dump_break (fd, node, indents); - break; - - default: - error ("unhandled node [%s]\n", RDOT_OPCODE_STR (node)); - break; - } - } -} - -vec * dot_pass_PrettyPrint (vec * decls) -{ - if (GRS_OPT_dump_dot) - { - size_t bsize = 128; - char * outfile = (char *) alloca (bsize); - gcc_assert (outfile); - memset (outfile, 0, bsize); - - strncpy (outfile, GRS_current_infile, strlen (GRS_current_infile)); - if (first == true) - { - strncat (outfile, RDOT_PREFIX_PRE, sizeof (RDOT_PREFIX_PRE)); - first = false; - } - else - { - strncat (outfile, RDOT_PREFIX_POST, sizeof (RDOT_PREFIX_POST)); - _no_infer = true; - } - - FILE * fd = fopen (outfile, "w"); - if (!fd) - { - error ("Unable to open %s for write\n", outfile); - goto exit; - } - - rdot idtx = NULL_DOT; - size_t i; - for (i = 0; decls->iterate (i, &idtx); ++i) - { - dot_pass_dump_node (fd, idtx, 0); - fprintf (fd, "\n"); - } - - fclose (fd); - } - exit: - return decls; -} diff --git a/gcc/rust/old/rs-lang.c b/gcc/rust/old/rs-lang.c deleted file mode 100644 index 9245847..0000000 --- a/gcc/rust/old/rs-lang.c +++ /dev/null @@ -1,326 +0,0 @@ -// rs-lang.cc - frontend interface or something -// NOTE: should be mentioned in gtfiles in config-lang.in -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . -*/ -#include "rust.h" - -// May not need this? -char* GRS_current_infname; -char* GRS_current_infile; - -/* Language-dependent contents of a type. GTY() mark used for garbage collector. */ -struct GTY(()) lang_type { - char dummy; -}; - -/* Language-dependent contents of a decl. */ -struct GTY(()) lang_decl { - char dummy; -}; - -/* Language-dependent contents of an identifier. This must include a - tree_identifier. -*/ -struct GTY(()) lang_identifier { - struct tree_identifier common; -}; - -/* The resulting tree type. */ -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " - "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) - lang_tree_node { - union tree_node GTY((tag("0"), - desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; -}; - -/* We don't use language_function. */ -struct GTY(()) language_function { - int dummy; -}; - -/* Language hooks. */ - -/* Initial lang hook called (possibly), used for initialisation. - * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, and - * build_common_builtin_nodes, as well as set global variable void_list_node. */ -static bool grs_langhook_init(void) { - /* Something to do with this: - This allows the code in d-builtins.cc to not have to worry about - converting (C signed char *) to (D char *) for string arguments of - built-in functions. The parameter (signed_char = false) specifies - whether char is signed. */ - build_common_tree_nodes(false); - - // Creates a new TREE_LIST node with purpose NULL_TREE and value void_type_node - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - // Builds built-ins for middle-end after all front-end built-ins are already instantiated - build_common_builtin_nodes(); - - mpfr_set_default_prec(128); - using_eh_for_cleanups(); - - rdot_init(); - return true; -} - -/* Initialize before parsing options. */ -static void grs_langhook_init_options_struct(struct gcc_options* opts) { - /* Go says that signed overflow is precisely defined. */ - opts->x_flag_wrapv = 1; - - /* We default to using strict aliasing, since Go pointers are safe. - This is turned off for code that imports the "unsafe" package, - because using unsafe.pointer violates C style aliasing - requirements. */ - opts->x_flag_strict_aliasing = 1; - - /* Default to avoiding range issues for complex multiply and - divide. */ - opts->x_flag_complex_method = 2; - - /* The builtin math functions should not set errno. */ - opts->x_flag_errno_math = 0; - opts->frontend_set_flag_errno_math = true; - - /* We turn on stack splitting if we can. */ - if (targetm_common.supports_split_stack(false, opts)) - opts->x_flag_split_stack = 1; - - /* Exceptions are used to handle recovering from panics. */ - opts->x_flag_exceptions = 1; - opts->x_flag_non_call_exceptions = 1; -} - -/* Handle grs specific options. Return 0 if we didn't do anything. */ -static bool grs_langhook_handle_option(size_t scode, const char* arg ATTRIBUTE_UNUSED, - int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED, location_t l ATTRIBUTE_UNUSED, - const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - enum opt_code code = (enum opt_code)scode; - int retval = 1; - - switch (code) { - /* ignore options for now... */ - - default: - break; - } - - return retval; -} - -/* Run after parsing options. */ -static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { - if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT) - flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD; - - /* Returning false means that the backend should be used. */ - return false; -} - -/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and - * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. - * This function must create a complete parse tree in a global var, and then return. - * - * Some consider this the "start of compilation". */ -static void grs_langhook_parse_file(void) { - size_t idx; - - // loop through all files in in_fnames array - for (idx = 0; idx < num_in_fnames; ++idx) { - const char* in = in_fnames[idx]; - GRS_current_infname = xstrdup(in); - GRS_current_infile = basename(GRS_current_infname); - - // parse file. seems to call flex-generated lexer, which then calls bison-generated parser - grs_do_compile(in); - // seems very coupled to old gccrs' lexer - e.g. rustc lexer handles parsing outside of the lexer - // note that apparently bison generates the "yyparse" automatically - perhaps the rs-parser.cc was actually generated using bison - } -} - -static tree grs_langhook_type_for_mode(enum machine_mode mode, int unsignedp) { - if (mode == TYPE_MODE(float_type_node)) - return float_type_node; - - if (mode == TYPE_MODE(double_type_node)) - return double_type_node; - - // More code about other type_nodes here? intQI, intHI, intSI, intDI, intTI? - // Don't know what they mean, but one site has them here in a similar fashion of selections - - if (mode == TYPE_MODE(integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - - if (mode == TYPE_MODE(long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - - if (COMPLEX_MODE_P(mode)) { - if (mode == TYPE_MODE(complex_float_type_node)) - return complex_float_type_node; - if (mode == TYPE_MODE(complex_double_type_node)) - return complex_double_type_node; - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) - return complex_integer_type_node; - } - /* gcc_unreachable */ - return NULL; -} - -static tree grs_langhook_type_for_size(unsigned int bits ATTRIBUTE_UNUSED, - int unsignedp ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL_TREE; -} - -/* Record a builtin function. We just ignore builtin functions. */ -static tree grs_langhook_builtin_function(tree decl ATTRIBUTE_UNUSED) { - return decl; -} - -static bool grs_langhook_global_bindings_p(void) { - return current_function_decl == NULL_TREE; -} - -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL; -} - -static tree grs_langhook_getdecls(void) { - gcc_unreachable(); - return NULL; -} - -/* Write out globals. */ -static void grs_langhook_write_globals(void) { - // pass off to middle end function basically. - dot_pass_WriteGlobals(); -} - -static unsigned int grs_langhook_option_lang_mask(void) { - return CL_Rust; -} - -/* Return a decl for the exception personality function. The function - itself is implemented in libgo/runtime/go-unwind.c. */ -static tree grs_langhook_eh_personality(void) { - static tree personality_decl; - if (personality_decl == NULL_TREE) { - personality_decl = build_personality_function("gccrs"); - grs_preserve_from_gc(personality_decl); - } - return personality_decl; -} - -static int -grs_langhook_gimplify_expr(tree* expr_p ATTRIBUTE_UNUSED, - gimple_seq* pre_p ATTRIBUTE_UNUSED, - gimple_seq* post_p ATTRIBUTE_UNUSED) { - if (TREE_CODE(*expr_p) == CALL_EXPR && CALL_EXPR_STATIC_CHAIN(*expr_p) != NULL_TREE) - gimplify_expr(&CALL_EXPR_STATIC_CHAIN(*expr_p), pre_p, post_p, is_gimple_val, fb_rvalue); - /* Often useful to use debug_tree here to see whats going on because - ever gimplication calls this. */ - // debug_tree (*expr_p) - return GS_UNHANDLED; -} - -/* Functions called directly by the generic backend. */ -tree convert(tree type, tree expr) { - if (type == error_mark_node || expr == error_mark_node || TREE_TYPE(expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE(expr)) - return expr; - - if (TYPE_MAIN_VARIANT(type) == TYPE_MAIN_VARIANT(TREE_TYPE(expr))) - return fold_convert(type, expr); - - switch (TREE_CODE(type)) { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert(type, expr); - case INTEGER_TYPE: - return fold(convert_to_integer(type, expr)); - case POINTER_TYPE: - return fold(convert_to_pointer(type, expr)); - case REAL_TYPE: - return fold(convert_to_real(type, expr)); - case COMPLEX_TYPE: - return fold(convert_to_complex(type, expr)); - default: - break; - } - - gcc_unreachable(); -} - -static GTY(()) tree grs_gc_root; -void grs_preserve_from_gc(tree t) { - grs_gc_root = tree_cons(NULL_TREE, t, grs_gc_root); -} - -/* The language hooks data structure. This is the main interface between the GCC front-end - * and the GCC middle-end/back-end. A list of language hooks could be found in - * /langhooks.h - */ -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -#undef LANG_HOOKS_OPTION_LANG_MASK -#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -#undef LANG_HOOKS_HANDLE_OPTION -#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -#undef LANG_HOOKS_WRITE_GLOBALS -#undef LANG_HOOKS_GIMPLIFY_EXPR -#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT grs_langhook_init -#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask -#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct -#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option -#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -/* Main lang-hook, apparently. Finds input file names in global vars in_fnames and num_in_fnames - * From this, frontend can take over and do actual parsing and initial compilation. - * This hook must create a complete parse tree in a global var, and then return. */ -#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl -#define LANG_HOOKS_GETDECLS grs_langhook_getdecls -#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals -#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr -#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality - -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -// These are for GCC's garbage collector to work properly or something -#include "gt-rust-rs-lang.h" -#include "gtype-rust.h" \ No newline at end of file diff --git a/gcc/rust/old/rs-lexer.l b/gcc/rust/old/rs-lexer.l deleted file mode 100644 index b45f931..0000000 --- a/gcc/rust/old/rs-lexer.l +++ /dev/null @@ -1,161 +0,0 @@ -%{ - /* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 3, or (at your option) any later - version. - - GCC is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" -#include "y.rs.h" - -extern int yydebug; -extern int yyparse (void); -%} - -DIGIT [0-9] -ID [_a-zA-Z][a-zA_Z0-9_$]* -QSTRING \"[^\"\n]*[\"\n] - -%x comment -%option yylineno noyywrap nounput 8bit never-interactive -%% - -"/*" { BEGIN (comment); } -[^*\n]* { /* eat it up flex you be le hungry maybe? */ } -"*"+[^*/\n]* { /* eat up boyo */ } -\n { ++yylineno; } -"*"+"/" { BEGIN (INITIAL); } - -as { return AS; } -pub { return PUB; } -break { return BREAK; } -return { return RETURN; } -continue { return CONTINUE; } -do { return DO; } -fn { return DEFUN; } -let { return LET; } -mut { return MUT; } -while { return WHILE; } -loop { return LOOP; } -static { return STATIC; } -struct { return STRUCT; } -if { return IF; } -"else if" { return ELIF; } -else { return ELSE; } -impl { return IMPL; } -self { return SELF; } -bool { return TYPE_BOOL; } -int { return TYPE_INT; } -float { return TYPE_FLOAT; } -uint { return TYPE_UINT; } -enum { return ENUM; } -match { return MATCH; } -true { return XTRUE; } -false { return XFALSE; } -trait { return TRAIT; } -for { return FOR; } -\[ { return '['; } -\] { return ']'; } -\( { return '('; } -\) { return ')'; } -\{ { return '{'; } -\} { return '}'; } -"->" { return RTYPE; } -"=>" { return GOES; } -";" { return ';'; } -"," { return ','; } -"." { return '.'; } -":" { return ':'; } -"::" { return ACC; } -"=" { return '='; } -"+" { return '+'; } -"-" { return '-'; } -"/" { return '/'; } -"*" { return '*'; } -"|" { return '|'; } -"~" { return '~'; } -"&" { return '&'; } -"==" { return EQUAL_EQUAL; } -"!=" { return NOT_EQUAL; } -"<" { return '<'; } -"<=" { return LESS_EQUAL; } -">" { return '>'; } -">=" { return GREATER_EQUAL; } - -\/\/.* ; /* // style comment */ - -{QSTRING} { - yylval.string = xstrdup (yytext + 1); - if (yylval.string [yyleng - 2] != '\"') - error ("Un-termintated character string!\n"); - else - yylval.string [yyleng - 2] = '\0'; - return STRING; -} - -{DIGIT}+ { - mpfr_t x; - mpfr_init2 (x, 32); - if (mpfr_set_str (x, yytext, 10, GMP_RNDU)) - { - fatal_error ("error initilizing integer value <%s>!\n", yytext); - } - yylval.integer = mpfr_get_si (x, GMP_RNDU); - mpfr_clear (x); - return INTEGER; -} - -{DIGIT}+"."{DIGIT}+ { - mpfr_t x; - mpfr_init2 (x, 32); - if (mpfr_set_str (x, yytext, 10, GMP_RNDU)) - { - fatal_error ("error initilizing float value <%s>!\n", yytext); - } - yylval.ffloat = mpfr_get_flt (x, GMP_RNDU); - mpfr_clear (x); - return FLOAT; -} - -{ID} { - yylval.string = xstrdup (yytext); - return IDENTIFIER; -} - -. { } -\n { } - -%% - -bool grs_do_compile (const char * in) -{ - bool retval = true; - FILE * fd = fopen (in, "rb"); - if (fd) - { - yyin = fd; - // yydebug = 1; - linemap_add (line_table, LC_ENTER, 0, in, 0); - retval = yyparse (); - fclose (fd); - linemap_add (line_table, LC_LEAVE, 0, NULL, 0); - yylex_destroy (); - } - else - { - fprintf (stderr, "error opening file %s\n", in); - retval = false; - } - return retval; -} - diff --git a/gcc/rust/old/rs-parser.cc b/gcc/rust/old/rs-parser.cc deleted file mode 100644 index c3c8c2c..0000000 --- a/gcc/rust/old/rs-parser.cc +++ /dev/null @@ -1,838 +0,0 @@ -#include "rust.h" -#include "y.rs.h" - -yystype yylval; -static int sym; -static int __yyerror; -extern int yylineno; - -static void yyerror (const char *, ...); -extern int yylex (void); -static bool __yyaccept__ (int, bool); -static bool yyexpect (int); - -#ifdef _DEBUG -# define yylex_() \ - yylex (); \ - do { \ - char *__token = yytoken_string (sym); \ - printf ("[%i:%s]\n", sym, __token); \ - free (__token); \ - } while (0) -#else -# define yylex_() yylex () -#endif - -static std::vector * alloca_modifiers (void); - -static rdot type (void); -static rdot target (void); -static rdot suite (void); -static rdot else_block (void); -static rdot elif_block (void); -static rdot if_block (void); -static rdot struct_conditional (void); -static rdot primary (void); -static rdot factor1 (void); -static rdot factor2 (void); -static rdot expression (void); - -static vec * symStack; -static const char * token_strings [] = { - "impl", - "as", - "break", - "continue", - "do", - "fn", - "let", - "mut", - "loop", - "static", - "->", - "bool", - "int", - "uint", - "float", - "::", - "enum", - "==", - "!=", - "<", - ">", - "<=", - ">=", - "struct", - "while", - "if", - "else", - "self", - "match", - "=>", - "true", - "false", - "string_literal", - "identifier", - "integer", - "pub", - "for", - "trait", - "else if", - "float", - "unknown" -}; - -static char * -yytoken_string (int token) -{ - char retval [128]; - memset (retval, 0, 128); - if (token >= 258 && token <= 298) - strncpy (retval, token_strings [token-258-1], 128); - else - retval [0] = (char) token; - return xstrdup (retval); -} - -#define yyaccept(_X) __yyaccept__ (_X, true) -#define yyaccept_(_X) __yyaccept__ (_X, false) -static -bool __yyaccept__ (int s, bool forward) -{ - if (sym == s) - { - if (forward) - { - sym = yylex_ (); - } - return true; - } - return false; -} - -static -bool yyexpect (int s) -{ - bool retval = false; - if (yyaccept (s) == true) - retval = true; - else - { - char * e1 = yytoken_string (s); - char * e2 = yytoken_string (sym); - yyerror ("expected [%s] got [%s]", e1, e2); - free (e1); - free (e2); - } - return retval; -} - -/* Also realy need to make use of location_t and gcc diagnostics .. */ -/* this is really hacky but its ok for now really need to fix this though */ -static void __attribute__ ((format (printf, 1, 2))) -yyerror (const char * fmt, ...) -{ - __yyerror += 1; - char * buffer = (char *) alloca (512); - memset (buffer, 0, 512); - - va_list vl; - va_start (vl, fmt); - vsprintf (buffer, fmt, vl); - va_end (vl); - - char * buffer_message = (char *) alloca (512); - memset (buffer_message, 0, 512); - snprintf (buffer_message, 512, "syntax error at %i: [%s]", yylineno, buffer); - - fatal_error ("%s", buffer_message); -} - -std::vector * alloca_modifiers (void) -{ - std::vector * allocas = new std::vector; - while (sym == '~' || sym == '&' || sym == '*') - { - ALLOCA_ mod; - switch (sym) - { - case '~': - mod = ALLOC_HEAP; - break; - case '&': - mod = ALLOC_REF; - break; - case '*': - mod = ALLOC_DEREF; - break; - default: - break; - } - yyexpect (sym); - allocas->push_back (mod); - } - return allocas; -} - -rdot type (void) -{ - std::vector * mem = alloca_modifiers (); - rdot retval = NULL_DOT; - if (yyaccept (TYPE_INT)) - retval = rdot_build_decl1 (RTYPE_INT, NULL_DOT); - else if (yyaccept (TYPE_UINT)) - retval = rdot_build_decl1 (RTYPE_UINT, NULL_DOT); - else if (yyaccept (TYPE_FLOAT)) - retval = rdot_build_decl1 (RTYPE_FLOAT, NULL_DOT); - else if (yyaccept (TYPE_BOOL)) - retval = rdot_build_decl1 (RTYPE_BOOL, NULL_DOT); - else if (yyaccept (IDENTIFIER)) - { - char * sid = yylval.string; - retval = rdot_build_decl1 (RTYPE_USER_STRUCT, - rdot_build_identifier (sid)); - free (sid); - } - else - yyerror ("expected a type got [%s]", yytoken_string (sym)); - - RDOT_MMEM_COPY (mem, RDOT_MEM_MODIFIER (retval)); - delete mem; - - return retval; -} - -rdot target (void) -{ - yyexpect (LET); - bool qual = true; - if (yyaccept (MUT)) - qual = false; - - yyexpect (IDENTIFIER); - char * tid = yylval.string; - - rdot ltype = NULL_DOT; - if (yyaccept (':')) - ltype = type (); - if (ltype == NULL_DOT) - ltype = rdot_build_decl1 (RTYPE_INFER, NULL_DOT); - - rdot retval = rdot_build_varDecl (ltype, qual, - rdot_build_identifier (tid)); - free (tid); - return retval; -} - -void argument_list_ (rdot head) -{ - if (yyaccept_ (')')) - return; - - rdot p = expression (); - if (head == NULL_DOT) - vec_safe_push (symStack, p); - else - RDOT_CHAIN (head) = p; - - if (yyaccept (',')) - argument_list_ (p); -} - -rdot argument_list () -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - argument_list_ (NULL_DOT); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -rdot struct_elem () -{ - yyexpect (IDENTIFIER); - char * selem = yylval.string; - yyexpect (':'); - rdot expr = expression (); - rdot retval = rdot_build_decl2 (D_STRUCT_PARAM, - rdot_build_identifier (selem), - expr); - free (selem); - return retval; -} - -void struct_init_list_ (rdot head) -{ - if (yyaccept_ ('}')) - return; - rdot e = struct_elem (); - if (head == NULL_DOT) - vec_safe_push (symStack, e); - else - RDOT_CHAIN (head) = e; - if (yyaccept (',')) - struct_init_list_ (e); -} - -rdot struct_init_list (void) -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - struct_init_list_ (NULL_DOT); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -rdot primary (void) -{ - rdot retval = NULL_DOT; - std::vector * mem = alloca_modifiers (); - if (yyaccept (IDENTIFIER)) - { - // maybe call... - char * pid = yylval.string; - if (yyaccept_ ('(')) - { - yyexpect ('('); - rdot alist = argument_list (); - yyexpect (')'); - retval = rdot_build_decl2 (D_CALL_EXPR, - rdot_build_identifier (pid), - alist); - } - // struct init - else if (yyaccept_ ('{')) - { - yyexpect ('{'); - rdot sls = struct_init_list (); - yyexpect ('}'); - retval = rdot_build_decl2 (D_STRUCT_INIT, - rdot_build_identifier (pid), - sls); - } - // just a simple identifier... - else - retval = rdot_build_identifier (pid); - free (pid); - } - else if (yyaccept (INTEGER)) - retval = rdot_build_integer (yylval.integer); - else if (yyaccept (FLOAT)) - retval = rdot_build_float (yylval.ffloat); - else if (yyaccept (STRING)) - retval = rdot_build_string (yylval.string); - else if (yyaccept (XFALSE)) - retval = rdot_build_bool (false); - else if (yyaccept (XTRUE)) - retval = rdot_build_bool (true); - else - yyerror ("expected a primary got [%s]", yytoken_string (sym)); - - RDOT_MMEM_COPY (mem, RDOT_MEM_MODIFIER (retval)); - delete mem; - return retval; -} - -rdot factor1 (void) -{ - rdot retval = NULL_DOT; - if (yyaccept (IDENTIFIER)) - { - char * pid = yylval.string; - if (yyaccept ('=')) - { - rdot rhs = expression (); - retval = rdot_build_decl2 (D_MODIFY_EXPR, rdot_build_identifier (pid), rhs); - } - else if (yyaccept_ ('(')) - { - yyexpect ('('); - rdot alist = argument_list (); - yyexpect (')'); - retval = rdot_build_decl2 (D_CALL_EXPR, - rdot_build_identifier (pid), - alist); - } - // struct init - else if (yyaccept_ ('{')) - { - yyexpect ('{'); - rdot sls = struct_init_list (); - yyexpect ('}'); - retval = rdot_build_decl2 (D_STRUCT_INIT, - rdot_build_identifier (pid), - sls); - } - else if (yyaccept_ (ACC)) - { - yyexpect (ACC); - rdot node = factor1 (); - retval = rdot_build_decl2 (D_ACC_EXPR, rdot_build_identifier (pid), node); - } - else - { - retval = rdot_build_identifier (yylval.string); - if (yyaccept ('.')) - { - rdot rhs = factor2 (); - retval = rdot_build_decl2 (D_ATTRIB_REF, retval, rhs); - } - } - free (pid); - } - else - retval = factor2 (); - return retval; -} - -rdot factor2 (void) -{ - rdot retval = NULL_DOT; - if (yyaccept ('(')) - { - retval = expression (); - yyexpect (')'); - } - else - { - retval = primary (); - if (RDOT_TYPE (retval) == D_IDENTIFIER - || RDOT_TYPE (retval) == D_CALL_EXPR) - { - if (yyaccept ('.')) - { - rdot rhs = factor2 (); - retval = rdot_build_decl2 (D_ATTRIB_REF, retval, rhs); - } - } - } - return retval; -} - -opcode_t symToDeclType (int sym) -{ - opcode_t retval = D_D_EXPR; - switch (sym) - { - case '=': - retval = D_MODIFY_EXPR; - break; - - case '+': - retval = D_ADD_EXPR; - break; - - case '-': - retval = D_MINUS_EXPR; - break; - - case '*': - retval = D_MULT_EXPR; - break; - - case '/': - retval = D_DIVD_EXPR; - break; - - case '.': - retval = D_ATTRIB_REF; - break; - - case EQUAL_EQUAL: - retval = D_EQ_EQ_EXPR; - break; - - case NOT_EQUAL: - retval = D_NOT_EQ_EXPR; - break; - - case '<': - retval = D_LESS_EXPR; - break; - - case LESS_EQUAL: - retval = D_LESS_EQ_EXPR; - break; - - case '>': - retval = D_GREATER_EXPR; - break; - - case GREATER_EQUAL: - retval = D_GREATER_EQ_EXPR; - break; - - default: - yyerror ("invalid symbol [%i:%s]", - sym, yytoken_string (sym)); - break; - } - return retval; -} - -rdot expression (void) -{ - bool head = false; - rdot retval = factor1 (); - rdot next = NULL_DOT; - while (sym == '+' || sym == '-' || - sym == '*' || sym == '/' || - sym == '<' || sym == '>' || - sym == EQUAL_EQUAL || sym == NOT_EQUAL || - sym == LESS_EQUAL || sym == GREATER_EQUAL) - { - opcode_t o = symToDeclType (sym); - yyexpect (sym); - rdot rhs = factor2 (); - if (head == false) - { - retval = next = rdot_build_decl2 (o, retval, rhs); - head = true; - } - else - { - rdot prev = RDOT_rhs_TT (next); - rdot rhs_expr = rdot_build_decl2 (o, prev, rhs); - RDOT_rhs_TT (next) = rhs_expr; - next = rhs_expr; - } - } - return retval; -} - -rdot statement () -{ - rdot retval = NULL_DOT; - if (yyaccept_ (BREAK)) - { - yyexpect (BREAK); - retval = rdot_build_decl1 (C_BREAK_STMT, NULL_DOT); - } - else if (yyaccept_ (CONTINUE)) - { - yyexpect (CONTINUE); - retval = rdot_build_decl1 (C_CONT_STMT, NULL_DOT); - } - else if (yyaccept_ (RETURN)) - { - yyexpect (RETURN); - retval = rdot_build_decl1 (C_RETURN_STMT, expression ()); - } - else if (yyaccept_ (LET)) - { - // simple vardecl [let x;] - rdot tg = target (); - if (yyaccept ('=')) - { - retval = rdot_build_decl2 (D_MODIFY_EXPR, - tg, expression ()); - } - else - retval = tg; - } - else - retval = expression (); - return retval; -} - -rdot struct_while_loop () -{ - yyexpect (WHILE); - rdot expr = expression (); - yyexpect ('{'); - rdot sb = suite (); - yyexpect ('}'); - return rdot_build_decl2 (D_STRUCT_WHILE, expr, sb); -} - -rdot struct_loop () -{ - yyexpect (LOOP); - yyexpect ('{'); - rdot sb = suite (); - yyexpect ('}'); - return rdot_build_decl1 (D_STRUCT_LOOP, sb); -} - -rdot if_block (void) -{ - yyexpect (IF); - rdot expr = expression (); - yyexpect ('{'); - rdot sb = suite (); - yyexpect ('}'); - return rdot_build_decl2 (D_STRUCT_IF, expr, sb); -} - -rdot elif_block (void) -{ - yyexpect (ELIF); - rdot expr = expression (); - yyexpect ('{'); - rdot sb = suite (); - yyexpect ('}'); - return rdot_build_decl2 (D_STRUCT_IF, expr, sb); -} - -rdot else_block (void) -{ - yyexpect (ELSE); - yyexpect ('{'); - rdot block = suite (); - yyexpect ('}'); - return rdot_build_decl1 (D_STRUCT_ELSE, block); -} - -rdot struct_conditional () -{ - rdot iblock = if_block (); - rdot eblock = NULL_DOT; - rdot elblock = NULL_DOT; - rdot curr = NULL_DOT; - rdot prev = NULL_DOT; - while (yyaccept_ (ELIF)) - { - curr = elif_block (); - if (elblock == NULL_DOT) - elblock = prev = curr; - else - { - RDOT_CHAIN (prev) = curr; - prev = curr; - } - } - if (yyaccept_ (ELSE)) - eblock = else_block (); - rdot retval = rdot_build_decl2 (D_STRUCT_IF, iblock, eblock); - RDOT_FIELD (retval)= elblock; - return retval; -} - -void statement_list (rdot head) -{ - if (yyaccept_ ('}')) - return; - - rdot st = NULL_DOT; - if (yyaccept_ (LOOP)) - st = struct_loop (); - else if (yyaccept_ (WHILE)) - st = struct_while_loop (); - else if (yyaccept_ (IF)) - st = struct_conditional (); - else - { - st = statement (); - if (!yyaccept (';')) - DOT_RETVAL (st) = true; - } - gcc_assert (st != NULL_DOT); - if (head == NULL_DOT) - vec_safe_push (symStack, st); - else - RDOT_CHAIN (head) = st; - statement_list (st); -} - -rdot suite () -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - statement_list (NULL); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -rdot param (void) -{ - yyexpect (IDENTIFIER); - char * pid = yylval.string; - yyexpect (':'); - rdot pit = type (); - rdot retval = rdot_build_decl2 (D_PARAMETER, - rdot_build_identifier (pid), - pit); - free (pid); - return retval; -} - -void param_list_ (rdot head) -{ - if (yyaccept_ (')')) - return; - - rdot p = param (); - if (head == NULL_DOT) - vec_safe_push (symStack, p); - else - RDOT_CHAIN (head) = p; - - if (yyaccept (',')) - param_list_ (p); -} - -rdot param_list () -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - param_list_ (NULL_DOT); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -/* fndecl := [pub] fn IDENTIFIER ([param_list]) [-> type] { stmt_list } */ -rdot fndecl () -{ - bool pub = false; - if (yyaccept (PUB)) - pub = true; - yyexpect (DEFUN); - yyexpect (IDENTIFIER); - char * fid = yylval.string; - yyexpect ('('); - rdot plist = param_list (); - yyexpect (')'); - rdot rtype = NULL_DOT; - if (yyaccept (RTYPE)) - rtype = type (); - yyexpect ('{'); - rdot block = suite (); - yyexpect ('}'); - rdot retval = rdot_build_fndecl (rdot_build_identifier (fid), - pub, plist, rtype, block); - free (fid); - return retval; -} - -void struct_layout_ (rdot head) -{ - if (yyaccept_ ('}')) - return; - - rdot p = param (); - if (head == NULL_DOT) - vec_safe_push (symStack, p); - else - RDOT_CHAIN (head) = p; - - if (yyaccept (',')) - struct_layout_ (p); -} - -rdot struct_layout () -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - struct_layout_ (NULL_DOT); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -rdot struct_decl () -{ - yyexpect (STRUCT); - yyexpect (IDENTIFIER); - char * sid = yylval.string; - - yyexpect ('{'); - rdot layout = struct_layout (); - yyexpect ('}'); - rdot retval = rdot_build_decl2 (D_STRUCT_TYPE, - rdot_build_identifier (sid), - layout); - free (sid); - return retval; -} - -void fndecl_block_ (rdot head) -{ - if (yyaccept_ ('}')) - return; - - rdot f = fndecl (); - if (head == NULL_DOT) - vec_safe_push (symStack, f); - else - RDOT_CHAIN (head) = f; - - fndecl_block_ (f); -} - -rdot fndecl_block (void) -{ - rdot retval = NULL_DOT; - size_t prev = symStack->length (); - fndecl_block_ (NULL_DOT); - size_t next = symStack->length (); - - if (next > prev) - retval = symStack->pop (); - return retval; -} - -rdot impl_block () -{ - rdot retval = NULL_DOT; - yyexpect (IMPL); - yyexpect (IDENTIFIER); - char * iid = yylval.string; - rdot rid = rdot_build_identifier (iid); - free (iid); - if (yyaccept (FOR)) - yyexpect (IDENTIFIER); - yyexpect ('{'); - rdot fb = fndecl_block (); - yyexpect ('}'); - retval = rdot_build_decl2 (D_STRUCT_IMPL, rid, fb); - return retval; -} - -/* - decl := fndecl | structdecl | impldecl | enumdecl -*/ -void decl (void) -{ - rdot rdecl = NULL_DOT; - if (yyaccept_ (STRUCT)) - rdecl = struct_decl (); - else if (yyaccept_ (IMPL)) - rdecl = impl_block (); - else - rdecl = fndecl (); - if (rdecl != NULL_DOT) - dot_pass_pushDecl (rdecl); -} - -int yyparse (void) -{ - // kick things off with the first token - __yyerror = 0; - sym = yylex_ (); - - vec_alloc (symStack, 0); - vec_safe_push (symStack, NULL_DOT); - - while (sym != 0) - decl (); - - if (symStack->length() > 1) - yyerror ("some unpoped symbols on the parse stack!"); - - vec_free (symStack); - return __yyerror; -} diff --git a/gcc/rust/old/rs-pass-manager.cc b/gcc/rust/old/rs-pass-manager.cc deleted file mode 100644 index 9ffac6e..0000000 --- a/gcc/rust/old/rs-pass-manager.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 3, or (at your option) any later - version. - - GCC is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -tree cstring_type_node; -static bool empty = true; -#define MAYBE_BOMB_OUT \ - do \ - if (seen_error ()) return; \ - while (0); - -static vec * rust_decls; -typedef vec * (*dot_pass)(vec *); -static dot_pass dot_pass_mngr[] = - { - &dot_pass_PrettyPrint, /* pretty print if -fdump-dot pre and post infereance */ - &dot_pass_inferTypes, /* This ensures there are no longer any D_MAYBE_TYPES */ - &dot_pass_PrettyPrint, - NULL /* sentinal */ - }; - -/* Pushes each decl from the parser onto the current translation unit */ -void dot_pass_pushDecl (rdot decl) -{ - if (empty) - empty = false; - - if (RDOT_TYPE (decl) == D_STRUCT_TYPE) - { - // look for duplicate fields - std::map layout; - rdot next; - for (next = RDOT_rhs_TT (decl); next != NULL_DOT; - next = RDOT_CHAIN (next)) - { - const char * pid = RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (next)); - if (layout.count (pid) > 0) - error ("structure [%s] already contains element [%s]", - RDOT_IDENTIFIER_POINTER (RDOT_lhs_TT (decl)), pid); - else - layout [pid] = true; - } - } - vec_safe_push (rust_decls, decl); -} - -/* Function to run over the pass manager hooks and - generate the generic code to pass to gcc middle-end -*/ -void dot_pass_WriteGlobals (void) -{ - // if the rdot translation unit is empty there is nothing to compile.. - if (empty == true) - return; - - tree cptr = build_pointer_type (char_type_node); - cstring_type_node = build_qualified_type (cptr, TYPE_QUAL_CONST); - - dot_pass *p = NULL; - vec * dot_decls = rust_decls; - - /* walk the passes */ - for (p = dot_pass_mngr; *p != NULL; ++p) - { - MAYBE_BOMB_OUT; - dot_decls = (*p)(dot_decls); - } - - /* check errors */ - MAYBE_BOMB_OUT; - - /* lower the decls from DOT -> GENERIC */ - vec * globals = dot_pass_Genericify (dot_decls); - - int global_vec_len = vec_safe_length (globals); - tree * global_vec = new tree[global_vec_len]; - tree itx = NULL_TREE; - int idx, idy = 0; - /* - Lets make sure to dump the Translation Unit this isn't that - useful to read over but can help to make sure certain tree's - are being generated... - - We also fill up the vector of tree's to be passed to the middle-end - */ - FILE * tu_stream = dump_begin (TDI_tu, NULL); - for (idx = 0; vec_safe_iterate (globals, idx, &itx); ++idx) - { - if (tu_stream) - dump_node (itx, 0, tu_stream); - global_vec [idy] = itx; - idy++; - } - if (tu_stream) - dump_end(TDI_tu, tu_stream); - - /* Passing control to GCC middle-end */ - wrapup_global_declarations (global_vec, global_vec_len); - finalize_compilation_unit (); - check_global_declarations (global_vec, global_vec_len); - emit_debug_global_declarations (global_vec, global_vec_len); - - delete [] global_vec; -} diff --git a/gcc/rust/old/rs-runtime-hooks.cc b/gcc/rust/old/rs-runtime-hooks.cc deleted file mode 100644 index 7e7c868..0000000 --- a/gcc/rust/old/rs-runtime-hooks.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - . */ - -#include "rust.h" - -#define nitems(_a) (sizeof (_a)) / sizeof ((_a)[0]) -#define LANG_HOOK(name_) "__GRUST_"name_, name_ - -struct rust_runtime { - const char * mangled_name; - const char * rust_symbol; - const size_t nargs; - const tree ** paramater_types; -}; - -static struct rust_runtime hooks [] = { - /* sentinal */ - { NULL, NULL, 0, NULL } -}; - -void rs_fill_runtime_decls (std::map * dict) -{ - struct rust_runtime * hk; - for (hk = hooks; hk->mangled_name != NULL; ++hk) - { - tree * args = XALLOCAVEC (tree, hk->nargs); - size_t i; - for (i = 0; i < hk->nargs; ++i) - args[i] = *(hk->paramater_types [i]); - - tree fntype = build_function_type_array (void_type_node, hk->nargs, args); - tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, - get_identifier (hk->mangled_name), fntype); - tree restype = TREE_TYPE (fndecl); - tree resdecl = build_decl (BUILTINS_LOCATION, RESULT_DECL, - NULL_TREE, restype); - DECL_CONTEXT (resdecl) = fndecl; - DECL_RESULT (fndecl) = resdecl; - DECL_EXTERNAL (fndecl) = 1; - TREE_PUBLIC (fndecl) = 1; - - (*dict)[std::string (hk->rust_symbol)] = fndecl; - } -} diff --git a/gcc/rust/old/rsspec.cc b/gcc/rust/old/rsspec.cc deleted file mode 100644 index c5dde9b..0000000 --- a/gcc/rust/old/rsspec.cc +++ /dev/null @@ -1,401 +0,0 @@ -/* This file is part of GCC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "gcc.h" -#include "opts.h" - -#include "tm.h" -#include "intl.h" - -#ifndef MATH_LIBRARY -# define MATH_LIBRARY "m" -#endif - -#ifndef RUST_LIBRARY -# define RUST_LIBRARY "grust" -#endif - -/* The original argument list and related info is copied here. */ -static unsigned int grs_xargc; -static const struct cl_decoded_option *grs_x_decoded_options; -static void append_arg (const struct cl_decoded_option *); - -/* The new argument list will be built here. */ -static unsigned int grs_newargc; -static struct cl_decoded_option *grs_new_decoded_options; - -/* Return whether strings S1 and S2 are both NULL or both the same - string. */ - -static bool -strings_same (const char *s1, const char *s2) -{ - return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0); -} - -/* Return whether decoded option structures OPT1 and OPT2 are the - same. */ - -static bool -options_same (const struct cl_decoded_option *opt1, - const struct cl_decoded_option *opt2) -{ - return (opt1->opt_index == opt2->opt_index - && strings_same (opt1->arg, opt2->arg) - && strings_same (opt1->orig_option_with_args_text, - opt2->orig_option_with_args_text) - && strings_same (opt1->canonical_option[0], - opt2->canonical_option[0]) - && strings_same (opt1->canonical_option[1], - opt2->canonical_option[1]) - && strings_same (opt1->canonical_option[2], - opt2->canonical_option[2]) - && strings_same (opt1->canonical_option[3], - opt2->canonical_option[3]) - && (opt1->canonical_option_num_elements - == opt2->canonical_option_num_elements) - && opt1->value == opt2->value - && opt1->errors == opt2->errors); -} - -/* Append another argument to the list being built. As long as it is - identical to the corresponding arg in the original list, just increment - the new arg count. Otherwise allocate a new list, etc. */ - -static void -append_arg (const struct cl_decoded_option *arg) -{ - static unsigned int newargsize; - -#if 0 - fprintf (stderr, "`%s'\n", arg); -#endif - - if (grs_new_decoded_options == grs_x_decoded_options - && grs_newargc < grs_xargc - && options_same (arg, &grs_x_decoded_options[grs_newargc])) - { - ++grs_newargc; - return; /* Nothing new here. */ - } - - if (grs_new_decoded_options == grs_x_decoded_options) - { /* Make new arglist. */ - unsigned int i; - - newargsize = (grs_xargc << 2) + 20; /* This should handle all. */ - grs_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); - - /* Copy what has been done so far. */ - for (i = 0; i < grs_newargc; ++i) - grs_new_decoded_options[i] = grs_x_decoded_options[i]; - } - - if (grs_newargc == newargsize) - fatal_error ("overflowed output arg list for %qs", - arg->orig_option_with_args_text); - - grs_new_decoded_options[grs_newargc++] = *arg; -} - -/* Append an option described by OPT_INDEX, ARG and VALUE to the list - being built. */ -static void -append_option (size_t opt_index, const char *arg, int value) -{ - struct cl_decoded_option decoded; - - generate_option (opt_index, arg, value, CL_DRIVER, &decoded); - append_arg (&decoded); -} - -/* Append a librust argument to the list being built. If - FORCE_STATIC, ensure the library is linked statically. */ - -static void -add_arg_libgrust (bool force_static ATTRIBUTE_UNUSED) -{ -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option (OPT_Wl_, "-Bstatic", 1); -#endif - append_option (OPT_l, RUST_LIBRARY, 1); -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option (OPT_Wl_, "-Bdynamic", 1); -#endif -} - -/* Modeled closely of gcc/fortran/gfortranspec.c */ - -void lang_specific_driver( struct cl_decoded_option **in_decoded_options, - unsigned int *in_decoded_options_count, - int *in_added_libraries ATTRIBUTE_UNUSED ) -{ - unsigned int i = 0; - unsigned int argc = *in_decoded_options_count; - struct cl_decoded_option *decoded_options = *in_decoded_options; - - int verbose = 0; - - /* This will be NULL if we encounter a situation where we should not - link in libf2c. */ - const char *library = RUST_LIBRARY; - - /* 0 => -xnone in effect. - 1 => -xfoo in effect. */ - int saw_speclang = 0; - - /* 0 => initial/reset state - 1 => last arg was -l - 2 => last two args were -l -lm. */ - int saw_library = 0; - - /* By default, we throw on the math library if we have one. */ - int need_math = (MATH_LIBRARY[0] != '\0'); - - /* Whether we should link a static libgrsthon. */ - int static_lib = 0; - - /* Whether we need to link statically. */ - int static_linking = 0; - - /* The number of input and output files in the incoming arg list. */ - int n_infiles = 0; - int n_outfiles = 0; - -#if 0 - fprintf (stderr, "Incoming:"); - for( i=0; i. */ - append_option (OPT_l, MATH_LIBRARY, 1); - - saw_library = 0; - - if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) - { - append_arg (&decoded_options[i]); /* "-" == Standard input. */ - continue; - } - - if (decoded_options[i].opt_index == OPT_x) - { - /* Track input language. */ - const char *lang = decoded_options[i].arg; - saw_speclang = (strcmp (lang, "none") != 0); - } - append_arg (&decoded_options[i]); - continue; - } - - /* A filename/library, not an option. */ - - if (saw_speclang) - saw_library = 0; /* -xfoo currently active. */ - else - { /* -lfoo or filename. */ - if (decoded_options[i].opt_index == OPT_l - && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0) - { - if (saw_library == 1) - saw_library = 2; /* -l -lm. */ - else - add_arg_libgrust (static_lib && !static_linking); - } - else if (decoded_options[i].opt_index == OPT_l - && strcmp (decoded_options[i].arg, RUST_LIBRARY) == 0) - { - saw_library = 1; /* -l. */ - add_arg_libgrust (static_lib && !static_linking); - continue; - } - else - { /* Other library, or filename. */ - if (saw_library == 1 && need_math) - append_option (OPT_l, MATH_LIBRARY, 1); - saw_library = 0; - } - } - append_arg (&decoded_options[i]); - } - - /* Append `-lrust -lm' as necessary. */ - - if (library) - { /* Doing a link and no -nostdlib. */ - if (saw_speclang) - append_option (OPT_x, "none", 1); - - switch (saw_library) - { - case 0: - add_arg_libgrust (static_lib && !static_linking); - /* Fall through. */ - case 1: - if (need_math) - append_option (OPT_l, MATH_LIBRARY, 1); - default: - break; - } - } - -#ifdef ENABLE_SHARED_LIBGCC - if (library) - { - unsigned int i; - - for (i = 1; i < grs_newargc; i++) - if (grs_new_decoded_options[i].opt_index == OPT_static_libgcc - || grs_new_decoded_options[i].opt_index == OPT_static) - break; - - if (i == grs_newargc) - append_option (OPT_shared_libgcc, NULL, 1); - } - -#endif - - if (verbose && grs_new_decoded_options != grs_x_decoded_options) - { - fprintf (stderr, _("Driving:")); - for (i = 0; i < grs_newargc; i++) - fprintf (stderr, " %s", - grs_new_decoded_options[i].orig_option_with_args_text); - fprintf (stderr, "\n"); - } - - *in_decoded_options_count = grs_newargc; - *in_decoded_options = grs_new_decoded_options; -} - -/* Called before linking. Returns 0 on success and -1 on failure. */ -int lang_specific_pre_link (void) -{ - return 0; -} - -/* Number of extra output files that lang_specific_pre_link may generate. */ -int lang_specific_extra_outfiles = 0; diff --git a/gcc/rust/old/rust.h b/gcc/rust/old/rust.h deleted file mode 100644 index 4a1a6d1..0000000 --- a/gcc/rust/old/rust.h +++ /dev/null @@ -1,99 +0,0 @@ -/* This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#ifndef __GCC_RUST_H__ -#define __GCC_RUST_H__ - -#include "config.h" - -// These must be included before the #poison declarations in system.h. -#include -#include -#include -#include -#include -#include - -#include "system.h" -#include "ansidecl.h" -#include "coretypes.h" -#include "opts.h" -#include "tree.h" -#include "tree-iterator.h" -#include "tree-pass.h" -#include "basic-block.h" -#include "gimple-expr.h" -#include "gimplify.h" -#include "stor-layout.h" -#include "toplev.h" -#include "debug.h" -#include "options.h" -#include "flags.h" -#include "convert.h" -#include "diagnostic.h" -#include "langhooks.h" -#include "langhooks-def.h" -#include "target.h" -#include "common/common-target.h" -#include "diagnostic-core.h" -#include "cgraph.h" -#include "varasm.h" -#include "stringpool.h" -#include "print-tree.h" -#include -#include -#include "input.h" - -#include -#include -/* rust include */ -#include "rdot-impl.h" - -#if !defined(YYLTYPE) -typedef struct grs_location { - int line; - int column; -} grs_location_t; -typedef grs_location_t YYLTYPE; -#define YYLTYPE YYLTYPE -#endif - -extern char * GRS_current_infile; -extern char * GRS_current_infname; - -/* important langhook prototypes */ -extern void grs_set_prefix (const char *); -extern void grs_preserve_from_gc (tree); -extern void grs_add_search_path (const char *); -extern void grs_parse_input_files (const char **, unsigned int); -extern tree grs_type_for_size (unsigned int, int); -extern tree grs_type_for_mode (enum machine_mode, int); - -extern bool grs_do_compile (const char *); - -/* rdot pass manager */ -extern tree cstring_type_node; - -extern vec * dot_pass_inferTypes (vec *); -extern vec * dot_pass_PrettyPrint (vec *); -extern vec * dot_pass_Genericify (vec *); -extern void dot_pass_pushDecl (rdot); -extern void dot_pass_WriteGlobals (void); - -/* hooks */ -extern void rs_fill_runtime_decls (std::map *); - -#endif //__GCC_RUST_H__ diff --git a/gcc/rust/old/y.rs.h b/gcc/rust/old/y.rs.h deleted file mode 100644 index d0246a2..0000000 --- a/gcc/rust/old/y.rs.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __Y_RS_H__ -#define __Y_RS_H__ - -enum yytokentype { - IMPL = 258, - AS = 259, - BREAK = 260, - CONTINUE = 261, - RETURN = 262, - DO = 263, - DEFUN = 264, - LET = 265, - MUT = 266, - LOOP = 267, - STATIC = 268, - RTYPE = 269, - TYPE_BOOL = 270, - TYPE_INT = 271, - TYPE_UINT = 272, - TYPE_FLOAT = 273, - ACC = 274, - ENUM = 275, - EQUAL_EQUAL = 276, - NOT_EQUAL = 277, - LESS = 278, - GREATER = 279, - LESS_EQUAL = 280, - GREATER_EQUAL = 281, - STRUCT = 282, - WHILE = 283, - IF = 284, - ELSE = 285, - SELF = 286, - MATCH = 287, - GOES = 288, - XTRUE = 289, - XFALSE = 290, - STRING = 291, - IDENTIFIER = 292, - INTEGER = 293, - PUB = 294, - FOR = 295, - TRAIT = 296, - ELIF = 297, - FLOAT = 298 -}; - -union yystype { - rdot symbol; - char * string; - int integer; - float ffloat; - bool boolean; -} ; - -extern yystype yylval; - -#endif //__Y_RS_H__ diff --git a/gcc/rust/operator.h b/gcc/rust/operator.h new file mode 100644 index 0000000..f3e0fd0 --- /dev/null +++ b/gcc/rust/operator.h @@ -0,0 +1,66 @@ +// operator.h -- Go frontend operators. -*- C++ -*- + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#ifndef GO_OPERATOR_H +#define GO_OPERATOR_H + +// The operators. + +enum Operator +{ + OPERATOR_INVALID, + OPERATOR_OROR, // || + OPERATOR_ANDAND, // && + OPERATOR_EQEQ, // == + OPERATOR_NOTEQ, // != + OPERATOR_LT, // < + OPERATOR_LE, // <= + OPERATOR_GT, // > + OPERATOR_GE, // >= + OPERATOR_PLUS, // + + OPERATOR_MINUS, // - + OPERATOR_OR, // | + OPERATOR_XOR, // ^ + OPERATOR_MULT, // * + OPERATOR_DIV, // / + OPERATOR_MOD, // % + OPERATOR_LSHIFT, // << + OPERATOR_RSHIFT, // >> + OPERATOR_AND, // & + OPERATOR_NOT, // ! + OPERATOR_BITCLEAR, // &^ + OPERATOR_CHANOP, // <- + + OPERATOR_EQ, // = + OPERATOR_PLUSEQ, // += + OPERATOR_MINUSEQ, // -= + OPERATOR_OREQ, // |= + OPERATOR_XOREQ, // ^= + OPERATOR_MULTEQ, // *= + OPERATOR_DIVEQ, // /= + OPERATOR_MODEQ, // %= + OPERATOR_LSHIFTEQ, // <<= + OPERATOR_RSHIFTEQ, // >>= + OPERATOR_ANDEQ, // &= + OPERATOR_BITCLEAREQ, // &^= + OPERATOR_PLUSPLUS, // ++ + OPERATOR_MINUSMINUS, // -- + + OPERATOR_COLON, // : + OPERATOR_COLONEQ, // := + OPERATOR_SEMICOLON, // ; + OPERATOR_DOT, // . + OPERATOR_ELLIPSIS, // ... + OPERATOR_COMMA, // , + OPERATOR_LPAREN, // ( + OPERATOR_RPAREN, // ) + OPERATOR_LCURLY, // { + OPERATOR_RCURLY, // } + OPERATOR_LSQUARE, // [ + OPERATOR_RSQUARE // ] +}; + +#endif // !defined(GO_OPERATOR_H) diff --git a/gcc/rust/parse/rust-parse-includes.h b/gcc/rust/parse/rust-parse-includes.h new file mode 100644 index 0000000..ad7b920 --- /dev/null +++ b/gcc/rust/parse/rust-parse-includes.h @@ -0,0 +1,27 @@ +#ifndef RUST_PARSE_INCLUDES_H +#define RUST_PARSE_INCLUDES_H +/* basically, this is just to stop gcc includes in rust-parse.cc from getting out of order due to + * formatter, which I can not figure out how to modify to not do this. */ +// HACK: remove for final or near-final compiler where I don't have to use auto formatter anymore + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "tree-iterator.h" +#include "input.h" +#include "diagnostic.h" +#include "stringpool.h" +#include "cgraph.h" +#include "gimplify.h" +#include "gimple-expr.h" +#include "convert.h" +#include "print-tree.h" +#include "stor-layout.h" +#include "fold-const.h" +/* order: config, system, coretypes, target, tree, tree-iterator, input, diagnostic, stringpool, + * cgraph, gimplify, gimple-expr, convert, print-tree, stor-layout, fold-const */ +// probably don't need all these + +#endif \ No newline at end of file diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc new file mode 100644 index 0000000..1eac8a1 --- /dev/null +++ b/gcc/rust/parse/rust-parse.cc @@ -0,0 +1,13001 @@ +#include "rust-parse.h" + +// instead of gcc includes specified here. Thanks clang-format. +#include "rust-parse-includes.h" + +#include // for std::find + +namespace Rust { + // Left binding powers of operations. + enum binding_powers { + // Highest priority + LBP_HIGHEST = 100, + + LBP_PATH = 95, + + LBP_METHOD_CALL = 90, + + LBP_FIELD_EXPR = 85, + + // LBP_DOT = 80, /* method call and field expr have different precedence now */ + + LBP_FUNCTION_CALL = 80, + LBP_ARRAY_REF = LBP_FUNCTION_CALL, + + LBP_QUESTION_MARK = 75, // unary postfix - counts as left + + LBP_UNARY_PLUS = 70, // Used only when the null denotation is + + LBP_UNARY_MINUS = LBP_UNARY_PLUS, // Used only when the null denotation is - + LBP_UNARY_ASTERISK = LBP_UNARY_PLUS, // deref operator - unary prefix + LBP_UNARY_EXCLAM = LBP_UNARY_PLUS, + LBP_UNARY_AMP = LBP_UNARY_PLUS, + LBP_UNARY_AMP_MUT = LBP_UNARY_PLUS, + + LBP_AS = 65, + + LBP_MUL = 60, + LBP_DIV = LBP_MUL, + LBP_MOD = LBP_MUL, + + LBP_PLUS = 55, + LBP_MINUS = LBP_PLUS, + + LBP_L_SHIFT = 50, + LBP_R_SHIFT = LBP_L_SHIFT, + + LBP_AMP = 45, + + LBP_CARET = 40, + + LBP_PIPE = 35, + + LBP_EQUAL = 30, + LBP_NOT_EQUAL = LBP_EQUAL, + LBP_SMALLER_THAN = LBP_EQUAL, + LBP_SMALLER_EQUAL = LBP_EQUAL, + LBP_GREATER_THAN = LBP_EQUAL, + LBP_GREATER_EQUAL = LBP_EQUAL, + + LBP_LOGICAL_AND = 25, + + LBP_LOGICAL_OR = 20, + + LBP_DOT_DOT = 15, + LBP_DOT_DOT_EQ = LBP_DOT_DOT, + + // TODO: note all these assig operators are RIGHT associative! + LBP_ASSIG = 10, + LBP_PLUS_ASSIG = LBP_ASSIG, + LBP_MINUS_ASSIG = LBP_ASSIG, + LBP_MULT_ASSIG = LBP_ASSIG, + LBP_DIV_ASSIG = LBP_ASSIG, + LBP_MOD_ASSIG = LBP_ASSIG, + LBP_AMP_ASSIG = LBP_ASSIG, + LBP_PIPE_ASSIG = LBP_ASSIG, + LBP_CARET_ASSIG = LBP_ASSIG, + LBP_L_SHIFT_ASSIG = LBP_ASSIG, + LBP_R_SHIFT_ASSIG = LBP_ASSIG, + + // return, break, and closures as lowest priority? + LBP_RETURN = 5, + LBP_BREAK = LBP_RETURN, + LBP_CLOSURE = LBP_RETURN, // unary prefix operators + +#if 0 + // rust precedences + PREC_CLOSURE = -40, // used for closures + PREC_JUMP = -30, // used for break, continue, return, and yield + PREC_RANGE = -10, // used for range (although weird comment in rustc about this) + PREC_BINOP = FROM_ASSOC_OP, + // used for binary operators mentioned below - also cast, colon (type), assign, assign_op + PREC_PREFIX = 50, // used for box, address_of, let, unary (again, weird comment on let) + PREC_POSTFIX = 60, // used for await, call, method call, field, index, try, inline asm, macro invocation + PREC_PAREN = 99, // used for array, repeat, tuple, literal, path, paren, if, while, for, 'loop', match, block, try block, async, struct + PREC_FORCE_PAREN = 100, +#endif + + // lowest priority + LBP_LOWEST = 0 + }; + + // Checks if Tree has a string type (tree code pointer_type and tree variant char node). + bool is_string_type(Tree type) { + // assert node represents a type + gcc_assert(TYPE_P(type.get_tree())); + + // ensure main variant of pointee is char_type_node (i.e. type is char*) + return type.get_tree_code() == POINTER_TYPE + && TYPE_MAIN_VARIANT(TREE_TYPE(type.get_tree())) == char_type_node; + } + + // Checks if Tree has array type. + bool is_array_type(Tree type) { + gcc_assert(TYPE_P(type.get_tree())); + return type.get_tree_code() == ARRAY_TYPE; + } + + // Checks if Tree has record type. + bool is_record_type(Tree type) { + gcc_assert(TYPE_P(type.get_tree())); + return type.get_tree_code() == RECORD_TYPE; + } + + // Returns whether the token can start a type (i.e. there is a valid type beginning with the + // token). + bool can_tok_start_type(TokenId id) { + switch (id) { + case EXCLAM: + case LEFT_SQUARE: + case LEFT_ANGLE: + case UNDERSCORE: + case ASTERISK: + case AMP: + case LIFETIME: + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: + case LEFT_PAREN: + case FOR: + case ASYNC: + case CONST: + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + case IMPL: + case DYN: + case QUESTION_MARK: + return true; + default: + return false; + } + } + + /* Returns whether the token id is (or is likely to be) a right angle bracket. i.e. '>', '>>', + * '>=' and '>>=' tokens. */ + bool is_right_angle_tok(TokenId id) { + switch (id) { + case RIGHT_ANGLE: + case RIGHT_SHIFT: + case GREATER_OR_EQUAL: + case RIGHT_SHIFT_EQ: + return true; + default: + return false; + } + } + + // HACK-y special handling for skipping a right angle token at the end of generic arguments. + bool Parser::skip_generics_right_angle() { + // HACK: special handling for right shift '>>', greater or equal '>=', and right shift assig + // '>>=' + const_TokenPtr tok = lexer.peek_token(); + switch (tok->get_id()) { + case RIGHT_ANGLE: + // this is good - skip token + lexer.skip_token(); + return true; + case RIGHT_SHIFT: { + /* shit. preferred HACK would be to replace this token in stream with '>', but may not + * be possible at this point. */ + // FIXME: ensure locations aren't messed up + TokenPtr right_angle = Token::make(RIGHT_ANGLE, tok->get_locus() + 1); + lexer.replace_current_token(right_angle); + return true; + } + case GREATER_OR_EQUAL: { + // another HACK - replace with equal (as assignment intended, probably) + /* FIXME: is this even required? how many people wouldn't leave a space? - apparently + * rustc has this feature */ + // FIXME: ensure locations aren't messed up + TokenPtr equal = Token::make(EQUAL, tok->get_locus() + 1); + lexer.replace_current_token(equal); + return true; + } + case RIGHT_SHIFT_EQ: { + // another HACK - replace with greater or equal + // FIXME: again, is this really required? rustc has the feature, though + // FIXME: ensure locations aren't messed up + TokenPtr greater_equal = Token::make(GREATER_OR_EQUAL, tok->get_locus() + 1); + lexer.replace_current_token(greater_equal); + return true; + } + default: + error_at(tok->get_locus(), "expected '>' at end of generic argument - found '%s'", + tok->get_token_description()); + return false; + } + } + + /* Gets left binding power for specified token. + * Not suitable for use at the moment or possibly ever because binding power cannot be purely + * determined from operator token with Rust grammar - e.g. method call and field access have + * different left binding powers but the same operator token. */ + int Parser::left_binding_power(const_TokenPtr token) { + // HACK: called with "peek_token()", so lookahead is "peek_token(1)" + switch (token->get_id()) { + /* TODO: issue here - distinguish between method calls and field access somehow? + Also would have to distinguish between paths and function calls (:: operator), + maybe more stuff. */ + /* Current plan for tackling LBP - don't do it based on token, use lookahead. + * Or alternatively, only use Pratt parsing for OperatorExpr and handle other + * expressions without it. rustc only considers arithmetic, logical/relational, 'as', + * '?=', ranges, colons, and assignment to have operator precedence and associativity + * rules applicable. It then has + * a separate "ExprPrecedence" that also includes binary operators. */ + + // TODO: handle operator overloading - have a function replace the operator? + + /*case DOT: + return LBP_DOT;*/ + + case SCOPE_RESOLUTION: + fprintf(stderr, "possible error - looked up LBP of scope resolution operator. should " + "be handled elsewhere. \n"); + return LBP_PATH; + + /* Resolved by lookahead HACK that should work with current code. If next token is + * identifier and token after that isn't parenthesised expression list, it is a field + * reference. */ + case DOT: + if (lexer.peek_token(1)->get_id() == IDENTIFIER + && lexer.peek_token(2)->get_id() != LEFT_PAREN) { + return LBP_FIELD_EXPR; + } + return LBP_METHOD_CALL; + + case LEFT_PAREN: + return LBP_FUNCTION_CALL; + + case LEFT_SQUARE: + return LBP_ARRAY_REF; + + // postfix question mark (i.e. error propagation expression) + case QUESTION_MARK: + return LBP_QUESTION_MARK; + + case AS: + return LBP_AS; + + case ASTERISK: + return LBP_MUL; + case DIV: + return LBP_DIV; + case PERCENT: + return LBP_MOD; + + case PLUS: + return LBP_PLUS; + case MINUS: + return LBP_MINUS; + + case LEFT_SHIFT: + return LBP_L_SHIFT; + case RIGHT_SHIFT: + return LBP_R_SHIFT; + + // binary & operator + case AMP: + return LBP_AMP; + + // binary ^ operator + case CARET: + return LBP_CARET; + + // binary | operator + case PIPE: + return LBP_PIPE; + + case EQUAL_EQUAL: + return LBP_EQUAL; + case NOT_EQUAL: + return LBP_NOT_EQUAL; + case RIGHT_ANGLE: + return LBP_GREATER_THAN; + case GREATER_OR_EQUAL: + return LBP_GREATER_EQUAL; + case LEFT_ANGLE: + return LBP_SMALLER_THAN; + case LESS_OR_EQUAL: + return LBP_SMALLER_EQUAL; + + case LOGICAL_AND: + return LBP_LOGICAL_AND; + + case OR: + return LBP_LOGICAL_OR; + + case DOT_DOT: + return LBP_DOT_DOT; + + case DOT_DOT_EQ: + return LBP_DOT_DOT_EQ; + + case EQUAL: + return LBP_ASSIG; + case PLUS_EQ: + return LBP_PLUS_ASSIG; + case MINUS_EQ: + return LBP_MINUS_ASSIG; + case ASTERISK_EQ: + return LBP_MULT_ASSIG; + case DIV_EQ: + return LBP_DIV_ASSIG; + case PERCENT_EQ: + return LBP_MOD_ASSIG; + case AMP_EQ: + return LBP_AMP_ASSIG; + case CARET_EQ: + return LBP_CARET_ASSIG; + case LEFT_SHIFT_EQ: + return LBP_L_SHIFT_ASSIG; + case RIGHT_SHIFT_EQ: + return LBP_R_SHIFT_ASSIG; + + // HACK: float literal due to lexer misidentifying a dot then an integer as a float + case FLOAT_LITERAL: + return LBP_FIELD_EXPR; + // field expr is same as tuple expr in precedence, i imagine + + // anything that can't appear in an infix position is given lowest priority + default: + return LBP_LOWEST; + } + } + + TreeStmtList& Parser::get_current_stmt_list() { + return stack_stmt_list.back(); + } + + // Parse statements until done (EOF) and append to current stmt list. + void Parser::parse_statement_seq(bool (Parser::*done)()) { + // Parse statements until done and append to the current stmt list + /*while (!(this->*done)()) { + // get stmt tree for parsed statement + Tree stmt = parse_statement(); + // append each stmt tree to current stmt list + get_current_stmt_list().append(stmt); + }*/ + } + + // Parse "items" until done (EOF) and append to current something list. Seems to be method taken + // rather than statements in rust. + /*void Parser::parse_item_seq(bool (Parser::*done)()) { + // Parse statements until done and append to the current stmt list + // TODO: fix + while (!(this->*done)()) { + // get stmt tree for parsed statement + Tree item = parse_item(); + // append each stmt tree to current stmt list + get_current_stmt_list().append(stmt); + } + }*/ + + // Returns true when current token is EOF. + bool Parser::done_end_of_file() { + const_TokenPtr t = lexer.peek_token(); + return (t->get_id() == END_OF_FILE); + } + + // Entry point - parse entire program (in file) from here. + void Parser::parse_program() { + // should be only able to parse decls at this point (scope)? + + // TODO: convert to a crate-based approach? parse_crate()? + parse_crate(); + + // TODO: structural changes - strongly-typed AST instead of Trees? + + // TODO: how much of this is fake main function vs actually required for any function? + // Built type of main "int (int, char**)" + tree main_fndecl_type_param[] + = { integer_type_node, build_pointer_type(build_pointer_type(char_type_node)) }; + tree main_fndecl_type + = build_function_type_array(integer_type_node, 2, main_fndecl_type_param); + // Create function declaration "int main(int, char**)" + main_fndecl = build_fn_decl("main", main_fndecl_type); + + // Enter top-level scope. + enter_scope(); + // program -> statement* + parse_statement_seq(&Parser::done_end_of_file); + // Append "return 0;" + tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); + // create decl_context of resdecl for main function (local variable of main function) + DECL_CONTEXT(resdecl) = main_fndecl; + DECL_RESULT(main_fndecl) = resdecl; + tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), + build_int_cst_type(integer_type_node, 0)); + tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); + + get_current_stmt_list().append(return_stmt); + + // Leave top-level scope, get its binding expression and its main block + TreeSymbolMapping main_tree_scope = leave_scope(); + Tree main_block = main_tree_scope.block; + + // Finish/finalise main function + BLOCK_SUPERCONTEXT(main_block.get_tree()) = main_fndecl; + DECL_INITIAL(main_fndecl) = main_block.get_tree(); + DECL_SAVED_TREE(main_fndecl) = main_tree_scope.bind_expr.get_tree(); + + // Main function is not external + DECL_EXTERNAL(main_fndecl) = 0; + // Preserve main function + DECL_PRESERVE_P(main_fndecl) = 1; + + // Convert from GENERIC to GIMPLE + gimplify_function_tree(main_fndecl); + + // Insert it into the graph (queue for compilation?) + cgraph_node::finalize_function(main_fndecl, true); + + main_fndecl = NULL_TREE; + } + + // Parses a crate (compilation unit) - entry point + AST::Crate Parser::parse_crate() { + /* TODO: determine if has utf8bom and shebang. Currently, they are eliminated by the lexing + * phase. + * Neither are useful for the compiler anyway, so maybe a better idea would be to eliminate + * the has_utf8bom and has_shebang variables from the crate data structure. */ + bool has_utf8bom = false; + bool has_shebang = false; + + // parse inner attributes + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse items + ::std::vector< ::std::unique_ptr > items; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != END_OF_FILE) { + ::std::unique_ptr item = parse_item(false); + if (item == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse item in crate"); + items = ::std::vector< ::std::unique_ptr >(); + break; + } + + items.push_back(::std::move(item)); + + t = lexer.peek_token(); + } + + return AST::Crate(::std::move(items), ::std::move(inner_attrs), has_utf8bom, has_shebang); + } + + // Parse a contiguous block of inner attributes. + ::std::vector Parser::parse_inner_attributes() { + ::std::vector inner_attributes; + + while (lexer.peek_token()->get_id() == HASH) { + AST::Attribute inner_attr = parse_inner_attribute(); + + // Ensure only valid inner attributes are added to the inner_attributes list + if (!inner_attr.is_empty()) { + inner_attributes.push_back(::std::move(inner_attr)); + } else { + /* If no more valid inner attributes, break out of loop (only contiguous inner + * attributes parsed). */ + break; + } + } + + return inner_attributes; + } + + // Parse a single inner attribute. + AST::Attribute Parser::parse_inner_attribute() { + if (lexer.peek_token()->get_id() != HASH) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + if (lexer.peek_token()->get_id() != EXCLAM) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + if (lexer.peek_token()->get_id() != LEFT_SQUARE) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + AST::Attribute actual_attribute = parse_attribute_body(); + + if (lexer.peek_token()->get_id() != RIGHT_SQUARE) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + return actual_attribute; + } + + // Parses the body of an attribute (inner or outer). + AST::Attribute Parser::parse_attribute_body() { + location_t locus = lexer.peek_token()->get_locus(); + + AST::SimplePath attr_path = parse_simple_path(); + // ensure path is valid to parse attribute input + if (attr_path.is_empty()) { + error_at(lexer.peek_token()->get_locus(), "empty simple path in attribute"); + + // Skip past potential further info in attribute (i.e. attr_input) + skip_after_end_attribute(); + return AST::Attribute::create_empty(); + } + + ::std::unique_ptr attr_input = parse_attr_input(); + // AttrInput is allowed to be null, so no checks here + + return AST::Attribute(::std::move(attr_path), ::std::move(attr_input), locus); + } + + // Parses a SimplePath AST node + AST::SimplePath Parser::parse_simple_path() { + bool has_opening_scope_resolution = false; + location_t locus = UNKNOWN_LOCATION; + + // Checks for opening scope resolution (i.e. global scope fully-qualified path) + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { + has_opening_scope_resolution = true; + + locus = lexer.peek_token()->get_locus(); + + lexer.skip_token(); + } + + // Parse single required simple path segment + AST::SimplePathSegment segment = parse_simple_path_segment(); + + // get location if not gotten already + if (locus == UNKNOWN_LOCATION) { + locus = segment.get_locus(); + } + + ::std::vector segments; + + // Return empty vector if first, actually required segment is an error + if (segment.is_error()) { + return AST::SimplePath::create_empty(); + } + + segments.push_back(segment); + + // Parse all other simple path segments + while (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { + // Skip scope resolution operator + lexer.skip_token(); + + AST::SimplePathSegment new_segment = parse_simple_path_segment(); + + // Return path as currently constructed if segment in error state. + if (new_segment.is_error()) { + break; + } + segments.push_back(new_segment); + } + + // DEBUG: check for any empty segments + for (const auto& seg : segments) { + if (seg.is_error()) { + fprintf(stderr, + "when parsing simple path, somehow empty path segment was not filtered out. Path " + "begins with '%s' \n", + segments.at(0).as_string().c_str()); + } + } + + return AST::SimplePath(::std::move(segments), has_opening_scope_resolution, locus); + } + + // Parses a single SimplePathSegment (does not handle the scope resolution operators) + AST::SimplePathSegment Parser::parse_simple_path_segment() { + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + lexer.skip_token(); + + return AST::SimplePathSegment(t->get_str(), t->get_locus()); + case SUPER: + lexer.skip_token(); + + return AST::SimplePathSegment(::std::string("super"), t->get_locus()); + case SELF: + lexer.skip_token(); + + return AST::SimplePathSegment(::std::string("self"), t->get_locus()); + case CRATE: + lexer.skip_token(); + + return AST::SimplePathSegment(::std::string("crate"), t->get_locus()); + case DOLLAR_SIGN: + if (lexer.peek_token(1)->get_id() == CRATE) { + lexer.skip_token(1); + + return AST::SimplePathSegment(::std::string("$crate"), t->get_locus()); + } + gcc_fallthrough(); + default: + // do nothing but inactivates warning from gcc when compiling + // could put the error_at thing here but fallthrough (from failing $crate condition) + // isn't completely obvious if it is. + + // test prevent error + return AST::SimplePathSegment::create_error(); + } + gcc_unreachable(); + /*error_at( + t->get_locus(), "invalid token '%s' in simple path segment", t->get_token_description());*/ + // this is not necessarily an error, e.g. end of path + // return AST::SimplePathSegment::create_error(); + } + + // Parses a PathIdentSegment - an identifier segment of a non-SimplePath path. + AST::PathIdentSegment Parser::parse_path_ident_segment() { + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + lexer.skip_token(); + + return AST::PathIdentSegment(t->get_str()); + case SUPER: + lexer.skip_token(); + + return AST::PathIdentSegment(::std::string("super")); + case SELF: + lexer.skip_token(); + + return AST::PathIdentSegment(::std::string("self")); + case SELF_ALIAS: + lexer.skip_token(); + + return AST::PathIdentSegment(::std::string("Self")); + case CRATE: + lexer.skip_token(); + + return AST::PathIdentSegment(::std::string("crate")); + case DOLLAR_SIGN: + if (lexer.peek_token(1)->get_id() == CRATE) { + lexer.skip_token(1); + + return AST::PathIdentSegment(::std::string("$crate")); + } + gcc_fallthrough(); + default: + // do nothing but inactivates warning from gcc when compiling + // could put the error_at thing here but fallthrough (from failing $crate condition) + // isn't completely obvious if it is. + + // test prevent error + return AST::PathIdentSegment::create_error(); + } + gcc_unreachable(); + // not necessarily an error + } + + // Parses an AttrInput AST node (polymorphic, as AttrInput is abstract) + ::std::unique_ptr Parser::parse_attr_input() { + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: + case LEFT_SQUARE: + case LEFT_CURLY: { + // must be a delimited token tree, so parse that + ::std::unique_ptr input_tree( + new AST::DelimTokenTree(parse_delim_token_tree())); + + // TODO: potential checks on DelimTokenTree before returning + + return input_tree; + } + case EQUAL: { + // = LiteralExpr + lexer.skip_token(); + + t = lexer.peek_token(); + + // Ensure token is a "literal expression" (literally only a literal token of any type) + if (!t->is_literal()) { + error_at(t->get_locus(), + "unknown token '%s' in attribute body - literal expected", + t->get_token_description()); + skip_after_end_attribute(); + return NULL; + } + + AST::Literal::LitType lit_type = AST::Literal::STRING; + // Crappy mapping of token type to literal type + switch (t->get_id()) { + case INT_LITERAL: + lit_type = AST::Literal::INT; + break; + case FLOAT_LITERAL: + lit_type = AST::Literal::FLOAT; + break; + case CHAR_LITERAL: + lit_type = AST::Literal::CHAR; + break; + case BYTE_CHAR_LITERAL: + lit_type = AST::Literal::BYTE; + break; + case BYTE_STRING_LITERAL: + lit_type = AST::Literal::BYTE_STRING; + break; + case STRING_LITERAL: + default: + lit_type = AST::Literal::STRING; + break; // TODO: raw string? don't eliminate it from lexer? + } + + // create actual LiteralExpr + AST::LiteralExpr lit_expr(t->get_str(), lit_type, t->get_locus()); + + ::std::unique_ptr attr_input_lit( + new AST::AttrInputLiteral(::std::move(lit_expr))); + + // do checks or whatever? none required, really + + // FIXME: shouldn't a skip token be required here? + + return attr_input_lit; + } break; + case RIGHT_SQUARE: + // means AttrInput is missing, which is allowed + return NULL; + default: + error_at(t->get_locus(), + "unknown token '%s' in attribute body - attribute input or none expected", + t->get_token_description()); + skip_after_end_attribute(); + return NULL; + } + gcc_unreachable(); + // TODO: find out how to stop gcc error on "no return value" + } + + /* Returns true if the token id matches the delimiter type. Note that this only operates for + * END delimiter tokens. */ + inline bool token_id_matches_delims(TokenId token_id, AST::DelimType delim_type) { + return ((token_id == RIGHT_PAREN && delim_type == AST::PARENS) + || (token_id == RIGHT_SQUARE && delim_type == AST::SQUARE) + || (token_id == RIGHT_CURLY && delim_type == AST::CURLY)); + } + + /* Returns true if the likely result of parsing the next few tokens is a path. Not guaranteed, + * though, especially in the case of syntax errors. */ + inline bool is_likely_path_next(TokenId next_token_id) { + switch (next_token_id) { + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + // maybe - maybe do extra check. But then requires another TokenId. + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: + return true; + default: + return false; + } + } + + // Parses a delimited token tree + AST::DelimTokenTree Parser::parse_delim_token_tree() { + // DEBUG + fprintf(stderr, "new delim token tree parsing begun\n"); + + const_TokenPtr t = lexer.peek_token(); + lexer.skip_token(); + location_t initial_loc = t->get_locus(); + + // save delim type to ensure it is reused later + AST::DelimType delim_type = AST::PARENS; + + // Map tokens to DelimType + switch (t->get_id()) { + case LEFT_PAREN: + delim_type = AST::PARENS; + break; + case LEFT_SQUARE: + delim_type = AST::SQUARE; + break; + case LEFT_CURLY: + delim_type = AST::CURLY; + break; + default: + error_at(t->get_locus(), + "unexpected token '%s' - expecting delimiters (for a delimited token tree)", + t->get_token_description()); + return AST::DelimTokenTree::create_empty(); + } + + // parse actual token tree vector - 0 or more + ::std::vector< ::std::unique_ptr > token_trees_in_tree; + + // repeat loop until finding the matching delimiter + t = lexer.peek_token(); + while (!token_id_matches_delims(t->get_id(), delim_type)) { + ::std::unique_ptr tok_tree = parse_token_tree(); + + if (tok_tree == NULL) { + // TODO: is this error handling appropriate? + error_at(t->get_locus(), + "failed to parse token tree in delimited token tree - found '%s'", + t->get_token_description()); + return AST::DelimTokenTree::create_empty(); + } + + token_trees_in_tree.push_back(::std::move(tok_tree)); + + // lexer.skip_token(); + t = lexer.peek_token(); + } + + AST::DelimTokenTree token_tree(delim_type, ::std::move(token_trees_in_tree), initial_loc); + + // parse end delimiters + t = lexer.peek_token(); + + if (token_id_matches_delims(t->get_id(), delim_type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + // DEBUG + fprintf(stderr, + "finished parsing new delim token tree - peeked token is now '%s' while t is '%s'\n", + lexer.peek_token()->get_token_description(), t->get_token_description()); + + return token_tree; + } else { + // tokens don't match opening delimiters, so produce error + error_at(t->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a delimited token tree)", + t->get_token_description(), + (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); + + /* return empty token tree despite possibly parsing valid token tree - TODO is this a + * good idea? */ + return AST::DelimTokenTree::create_empty(); + } + } + + /* Parses a TokenTree syntactical production. This is either a delimited token tree or a + * non-delimiter token. */ + ::std::unique_ptr Parser::parse_token_tree() { + const_TokenPtr t = lexer.peek_token(); + + switch (t->get_id()) { + case LEFT_PAREN: + case LEFT_SQUARE: + case LEFT_CURLY: + // Parse delimited token tree + // TODO: use move rather than copy constructor + return ::std::unique_ptr( + new AST::DelimTokenTree(parse_delim_token_tree())); + case RIGHT_PAREN: + case RIGHT_SQUARE: + case RIGHT_CURLY: + // error - should not be called when this a token + error_at(t->get_locus(), + "unexpected closing delimiter '%s' - token tree requires either paired delimiters " + "or non-delimiter tokens", + t->get_token_description()); + lexer.skip_token(); + return NULL; + default: + // parse token itself as TokenTree + lexer.skip_token(); + // TODO: fix that token constructor, possibly with c++11 features + return ::std::unique_ptr(new AST::Token(t)); + } + } + + /* Parses a sequence of items within a module or the implicit top-level module in a crate. Note: + * this is not currently used as parsing an item sequence individually is pretty simple and allows + * for better error diagnostics and detection. */ + ::std::vector< ::std::unique_ptr > Parser::parse_items() { + ::std::vector< ::std::unique_ptr > items; + + // TODO: replace with do-while loop? + // infinite loop to save on comparisons (may be a tight loop) - breaks when next item is null + while (true) { + ::std::unique_ptr item = parse_item(false); + + if (item != NULL) { + items.push_back(::std::move(item)); + } else { + break; + } + } + + return items; + } + + // Parses a single item + ::std::unique_ptr Parser::parse_item(bool called_from_statement) { + // has a "called_from_statement" parameter for better error message handling + + // parse outer attributes for item + ::std::vector outer_attrs = parse_outer_attributes(); + + // TODO: decide how to deal with VisItem vs MacroItem dichotomy + // best current solution: catch all keywords that would imply a VisItem in a switch and have + // MacroItem as a last resort + + const_TokenPtr t = lexer.peek_token(); + + switch (t->get_id()) { + case END_OF_FILE: + // not necessarily an error + return NULL; + case PUB: + case MOD: + case EXTERN_TOK: + case USE: + case FN_TOK: + case TYPE: + case STRUCT_TOK: + case ENUM_TOK: + case CONST: + case STATIC_TOK: + case TRAIT: + case IMPL: + /* TODO: implement union keyword but not really because of context-dependence + * crappy hack way to parse a union written below to separate it from the good code. */ + // case UNION: + case UNSAFE: // maybe - unsafe traits are a thing + // if any of these (should be all possible VisItem prefixes), parse a VisItem + return parse_vis_item(::std::move(outer_attrs)); + break; + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + // almost certainly macro invocation semi + return parse_macro_item(::std::move(outer_attrs)); + break; + // crappy hack to do union "keyword" + case IDENTIFIER: + // TODO: ensure std::string and literal comparison works + if (t->get_str() == "union") { + return parse_vis_item(::std::move(outer_attrs)); + // or should this go straight to parsing union? + } else if (t->get_str() == "macro_rules") { + // macro_rules! macro item + return parse_macro_item(::std::move(outer_attrs)); + } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION + || lexer.peek_token(1)->get_id() == EXCLAM) { + // path (probably) or macro invocation, so probably a macro invocation semi + return parse_macro_item(::std::move(outer_attrs)); + } + gcc_fallthrough(); + // TODO: find out how to disable gcc "implicit fallthrough" warning + default: + // otherwise unrecognised + // return parse_macro_item(::std::move(outer_attrs)); + error_at(t->get_locus(), "unrecognised token '%s' for start of %s", + t->get_token_description(), called_from_statement ? "statement" : "item"); + // skip somewhere? + return NULL; + break; + } + } + + // Parses a contiguous block of outer attributes. + ::std::vector Parser::parse_outer_attributes() { + ::std::vector outer_attributes; + + while (lexer.peek_token()->get_id() == HASH) { + AST::Attribute outer_attr = parse_outer_attribute(); + + // Ensure only valid outer attributes are added to the outer_attributes list + if (!outer_attr.is_empty()) { + outer_attributes.push_back(::std::move(outer_attr)); + } else { + /* If no more valid outer attributes, break out of loop (only contiguous outer + * attributes parsed). */ + break; + } + } + + return outer_attributes; + + // TODO: this shares basically all code with parse_inner_attributes except function call + // find way of making it more modular? + } + + // Parse a single outer attribute. + AST::Attribute Parser::parse_outer_attribute() { + /* OuterAttribute -> '#' '[' Attr ']' */ + + if (lexer.peek_token()->get_id() != HASH) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + TokenId id = lexer.peek_token()->get_id(); + if (id != LEFT_SQUARE) { + if (id == EXCLAM) { + // this is inner attribute syntax, so throw error + error_at(lexer.peek_token()->get_locus(), + "token '!' found, indicating inner attribute definition. Inner attributes are not " + "possible at this location."); + } // TODO: are there any cases where this wouldn't be an error? + return AST::Attribute::create_empty(); + } + + lexer.skip_token(); + + AST::Attribute actual_attribute = parse_attribute_body(); + + if (lexer.peek_token()->get_id() != RIGHT_SQUARE) + return AST::Attribute::create_empty(); + + lexer.skip_token(); + + return actual_attribute; + } + + // Parses a VisItem (item that can have non-default visibility). + ::std::unique_ptr Parser::parse_vis_item( + ::std::vector outer_attrs) { + // parse visibility, which may or may not exist + AST::Visibility vis = parse_visibility(); + + // select VisItem to create depending on keyword + const_TokenPtr t = lexer.peek_token(); + + switch (t->get_id()) { + case MOD: + return parse_module(::std::move(vis), ::std::move(outer_attrs)); + case EXTERN_TOK: + // lookahead to resolve syntactical production + t = lexer.peek_token(1); + + switch (t->get_id()) { + case CRATE: + return parse_extern_crate(::std::move(vis), ::std::move(outer_attrs)); + case FN_TOK: // extern function + return parse_function(::std::move(vis), ::std::move(outer_attrs)); + case LEFT_CURLY: // extern block + return parse_extern_block(::std::move(vis), ::std::move(outer_attrs)); + case STRING_LITERAL: // for specifying extern ABI + // could be extern block or extern function, so more lookahead + t = lexer.peek_token(2); + + switch (t->get_id()) { + case FN_TOK: + return parse_function(::std::move(vis), ::std::move(outer_attrs)); + case LEFT_CURLY: + return parse_extern_block(::std::move(vis), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of extern production", + t->get_token_description()); + lexer.skip_token(2); // TODO: is this right thing to do? + return NULL; + } + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of extern production", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + case USE: + return parse_use_decl(::std::move(vis), ::std::move(outer_attrs)); + case FN_TOK: + return parse_function(::std::move(vis), ::std::move(outer_attrs)); + case TYPE: + return parse_type_alias(::std::move(vis), ::std::move(outer_attrs)); + case STRUCT_TOK: + return parse_struct(::std::move(vis), ::std::move(outer_attrs)); + case ENUM_TOK: + return parse_enum(::std::move(vis), ::std::move(outer_attrs)); + // TODO: implement union keyword but not really because of context-dependence + // case UNION: + // crappy hack to do union "keyword" + case IDENTIFIER: + // TODO: ensure std::string and literal comparison works + if (t->get_str() == "union") { + return parse_union(::std::move(vis), ::std::move(outer_attrs)); + // or should item switch go straight to parsing union? + } else { + break; + } + case CONST: + // lookahead to resolve syntactical production + t = lexer.peek_token(1); + + switch (t->get_id()) { + case IDENTIFIER: + case UNDERSCORE: + return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_function(::std::move(vis), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of const production", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + case STATIC_TOK: + return parse_static_item(::std::move(vis), ::std::move(outer_attrs)); + case TRAIT: + return parse_trait(::std::move(vis), ::std::move(outer_attrs)); + case IMPL: + return parse_impl(::std::move(vis), ::std::move(outer_attrs)); + case UNSAFE: // unsafe traits, unsafe functions, unsafe impls (trait impls), + // lookahead to resolve syntactical production + t = lexer.peek_token(1); + + switch (t->get_id()) { + case TRAIT: + return parse_trait(::std::move(vis), ::std::move(outer_attrs)); + case EXTERN_TOK: + case FN_TOK: + return parse_function(::std::move(vis), ::std::move(outer_attrs)); + case IMPL: + return parse_impl(::std::move(vis), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of unsafe production", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + default: + // otherwise vis item clearly doesn't exist, which is not an error + // has a catch-all post-switch return to allow other breaks to occur + break; + } + return NULL; + } + + // Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition). + ::std::unique_ptr Parser::parse_macro_item( + ::std::vector outer_attrs) { + const_TokenPtr t = lexer.peek_token(); + + /* dodgy way of detecting macro due to weird context-dependence thing. probably can be + * improved */ + // TODO: ensure that string compare works properly + if (t->get_id() == IDENTIFIER && t->get_str() == ::std::string("macro_rules")) { + return parse_macro_rules_def(::std::move(outer_attrs)); + } else { + // DEBUG: TODO: remove + fprintf(stderr, "DEBUG - parse_macro_item called and token is not macro_rules"); + if (t->get_id() == IDENTIFIER) { + fprintf(stderr, + "just add to last error: token is not macro_rules and is instead '%s'", + t->get_str().c_str()); + } else { + fprintf(stderr, + "just add to last error: token is not macro_rules and is not an identifier either " + "- it is '%s'", + t->get_token_description()); + } + + return parse_macro_invocation_semi(::std::move(outer_attrs)); + } + } + + // Parses a macro rules definition syntax extension whatever thing. + ::std::unique_ptr Parser::parse_macro_rules_def( + ::std::vector outer_attrs) { + // ensure that first token is identifier saying "macro_rules" + const_TokenPtr t = lexer.peek_token(); + if (t->get_id() != IDENTIFIER || t->get_str() != "macro_rules") { + error_at(t->get_locus(), "macro rules definition does not start with 'macro_rules'"); + // skip after somewhere? + return NULL; + } + lexer.skip_token(); + location_t macro_locus = t->get_locus(); + + if (!skip_token(EXCLAM)) { + // skip after somewhere? + return NULL; + } + + // parse macro name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + return NULL; + } + Identifier rule_name = ident_tok->get_str(); + + // DEBUG + fprintf(stderr, "in macro rules def, about to parse parens.\n"); + + // save delim type to ensure it is reused later + AST::DelimType delim_type = AST::PARENS; + + // Map tokens to DelimType + t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: + delim_type = AST::PARENS; + break; + case LEFT_SQUARE: + delim_type = AST::SQUARE; + break; + case LEFT_CURLY: + delim_type = AST::CURLY; + break; + default: + error_at(t->get_locus(), + "unexpected token '%s' - expecting delimiters (for a macro rules definition)", + t->get_token_description()); + return NULL; + } + lexer.skip_token(); + + // parse actual macro rules + ::std::vector macro_rules; + + // must be at least one macro rule, so parse it + AST::MacroRule initial_rule = parse_macro_rule(); + if (initial_rule.is_error()) { + error_at(lexer.peek_token()->get_locus(), + "required first macro rule in macro rules definition could not be parsed"); + // skip after somewhere? + return NULL; + } + macro_rules.push_back(::std::move(initial_rule)); + + // DEBUG + fprintf(stderr, "successfully pushed back initial macro rule\n"); + + t = lexer.peek_token(); + // parse macro rules + while (t->get_id() == SEMICOLON) { + // skip semicolon + lexer.skip_token(); + + // don't parse if end of macro rules + if (token_id_matches_delims(lexer.peek_token()->get_id(), delim_type)) { + // DEBUG + fprintf(stderr, "broke out of parsing macro rules loop due to finding delim\n"); + + break; + } + + // try to parse next rule + AST::MacroRule rule = parse_macro_rule(); + if (rule.is_error()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse macro rule in macro rules definition"); + return NULL; + } + + macro_rules.push_back(::std::move(rule)); + + // DEBUG + fprintf(stderr, "successfully pushed back another macro rule\n"); + + t = lexer.peek_token(); + } + + // parse end delimiters + t = lexer.peek_token(); + if (token_id_matches_delims(t->get_id(), delim_type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + if (delim_type != AST::CURLY) { + // skip semicolon at end of non-curly macro definitions + if (!skip_token(SEMICOLON)) { + // as this is the end, allow recovery (probably) - may change + return ::std::unique_ptr( + new AST::MacroRulesDefinition(::std::move(rule_name), delim_type, + ::std::move(macro_rules), ::std::move(outer_attrs), macro_locus)); + } + } + + return ::std::unique_ptr( + new AST::MacroRulesDefinition(::std::move(rule_name), delim_type, + ::std::move(macro_rules), ::std::move(outer_attrs), macro_locus)); + } else { + // tokens don't match opening delimiters, so produce error + error_at(t->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a macro rules " + "definition)", + t->get_token_description(), + (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); + + /* return empty macro definiton despite possibly parsing mostly valid one - TODO is this + * a good idea? */ + return NULL; + } + } + + // Parses a semi-coloned (except for full block) macro invocation item. + ::std::unique_ptr Parser::parse_macro_invocation_semi( + ::std::vector outer_attrs) { + location_t macro_locus = lexer.peek_token()->get_locus(); + AST::SimplePath path = parse_simple_path(); + + if (!skip_token(EXCLAM)) { + // skip after somewhere? + return NULL; + } + + // save delim type to ensure it is reused later + AST::DelimType delim_type = AST::PARENS; + + // Map tokens to DelimType + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: + delim_type = AST::PARENS; + break; + case LEFT_SQUARE: + delim_type = AST::SQUARE; + break; + case LEFT_CURLY: + delim_type = AST::CURLY; + break; + default: + error_at(t->get_locus(), + "unexpected token '%s' - expecting delimiters (for a macro invocation semi body)", + t->get_token_description()); + return NULL; + } + lexer.skip_token(); + + // parse actual token trees + ::std::vector< ::std::unique_ptr > token_trees; + + t = lexer.peek_token(); + // parse token trees until the initial delimiter token is found again + while (!token_id_matches_delims(t->get_id(), delim_type)) { + ::std::unique_ptr tree = parse_token_tree(); + + if (tree == NULL) { + error_at(t->get_locus(), + "failed to parse token tree for macro invocation semi - found '%s'", + t->get_token_description()); + return NULL; + } + + token_trees.push_back(::std::move(tree)); + + t = lexer.peek_token(); + } + + // parse end delimiters + t = lexer.peek_token(); + if (token_id_matches_delims(t->get_id(), delim_type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + if (delim_type != AST::CURLY) { + // skip semicolon at end of non-curly macro invocation semis + if (!skip_token(SEMICOLON)) { + // as this is the end, allow recovery (probably) - may change + return ::std::unique_ptr( + new AST::MacroInvocationSemi(::std::move(path), delim_type, + ::std::move(token_trees), ::std::move(outer_attrs), macro_locus)); + } + } + + // DEBUG: + fprintf(stderr, "skipped token is '%s', next token (current peek) is '%s'\n", + t->get_token_description(), lexer.peek_token()->get_token_description()); + + return ::std::unique_ptr( + new AST::MacroInvocationSemi(::std::move(path), delim_type, ::std::move(token_trees), + ::std::move(outer_attrs), macro_locus)); + } else { + // tokens don't match opening delimiters, so produce error + error_at(t->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a macro invocation " + "semi)", + t->get_token_description(), + (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); + + /* return empty macro invocation despite possibly parsing mostly valid one - TODO is this + * a good idea? */ + return NULL; + } + } + + // Parses a non-semicoloned macro invocation (i.e. as pattern or expression). + ::std::unique_ptr Parser::parse_macro_invocation( + ::std::vector outer_attrs) { + // parse macro path + AST::SimplePath macro_path = parse_simple_path(); + if (macro_path.is_empty()) { + error_at(lexer.peek_token()->get_locus(), "failed to parse macro invocation path"); + // skip? + return NULL; + } + + if (!skip_token(EXCLAM)) { + // skip after somewhere? + return NULL; + } + + // parse internal delim token tree + AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree(); + + location_t macro_locus = macro_path.get_locus(); + + return ::std::unique_ptr( + new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), + ::std::move(outer_attrs), macro_locus)); + } + + // Parses a macro rule definition - does not parse semicolons. + AST::MacroRule Parser::parse_macro_rule() { + // DEBUG + fprintf(stderr, "begun parsing macro rule\n"); + + // parse macro matcher + AST::MacroMatcher matcher = parse_macro_matcher(); + + // DEBUG + fprintf(stderr, "managed to get past parsing macro matcher\n"); + + if (matcher.is_error()) { + return AST::MacroRule::create_error(); + } + + // DEBUG + fprintf(stderr, "successfully parsed macro matcher\n"); + + if (!skip_token(MATCH_ARROW)) { + // skip after somewhere? + return AST::MacroRule::create_error(); + } + + // DEBUG + fprintf(stderr, "successfully skipped match arrow\n"); + + // parse transcriber (this is just a delim token tree) + AST::DelimTokenTree transcribe_tree = parse_delim_token_tree(); + + // DEBUG + fprintf(stderr, "successfully parsed transcribe tree\n"); + + AST::MacroTranscriber transcriber(::std::move(transcribe_tree)); + + // DEBUG + fprintf(stderr, "successfully parsed macro transcriber - returning macro rule\n"); + + return AST::MacroRule(::std::move(matcher), ::std::move(transcriber)); + } + + // Parses a macro matcher (part of a macro rule definition). + AST::MacroMatcher Parser::parse_macro_matcher() { + // save delim type to ensure it is reused later + AST::DelimType delim_type = AST::PARENS; + + // DEBUG + fprintf(stderr, "begun parsing macro matcher\n"); + + // Map tokens to DelimType + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: + delim_type = AST::PARENS; + break; + case LEFT_SQUARE: + delim_type = AST::SQUARE; + break; + case LEFT_CURLY: + delim_type = AST::CURLY; + break; + default: + error_at(t->get_locus(), + "unexpected token '%s' - expecting delimiters (for a macro matcher)", + t->get_token_description()); + return AST::MacroMatcher::create_error(); + } + lexer.skip_token(); + + // parse actual macro matches + ::std::vector< ::std::unique_ptr > matches; + + t = lexer.peek_token(); + // parse token trees until the initial delimiter token is found again + while (!token_id_matches_delims(t->get_id(), delim_type)) { + ::std::unique_ptr match = parse_macro_match(); + + if (match == NULL) { + error_at(t->get_locus(), "failed to parse macro match for macro matcher - found '%s'", + t->get_token_description()); + return AST::MacroMatcher::create_error(); + } + + matches.push_back(::std::move(match)); + + // DEBUG + fprintf(stderr, "pushed back a match in macro matcher\n"); + + t = lexer.peek_token(); + } + + // parse end delimiters + t = lexer.peek_token(); + if (token_id_matches_delims(t->get_id(), delim_type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + return AST::MacroMatcher(delim_type, ::std::move(matches)); + } else { + // tokens don't match opening delimiters, so produce error + error_at(t->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a macro matcher)", + t->get_token_description(), + (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); + + /* return error macro matcher despite possibly parsing mostly correct one? TODO is this + * the best idea? */ + return AST::MacroMatcher::create_error(); + } + } + + // Parses a macro match (syntax match inside a matcher in a macro rule). + ::std::unique_ptr Parser::parse_macro_match() { + // branch based on token available + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: + case LEFT_SQUARE: + case LEFT_CURLY: { + // must be macro matcher as delimited + AST::MacroMatcher matcher = parse_macro_matcher(); + if (matcher.is_error()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse macro matcher in macro match"); + return NULL; + } + return ::std::unique_ptr( + new AST::MacroMatcher(::std::move(matcher))); + } + case DOLLAR_SIGN: { + // have to do more lookahead to determine if fragment or repetition + const_TokenPtr t2 = lexer.peek_token(1); + switch (t2->get_id()) { + case IDENTIFIER: + // macro fragment + return parse_macro_match_fragment(); + case LEFT_PAREN: + // macro repetition + return parse_macro_match_repetition(); + default: + // error: unrecognised + error_at(t2->get_locus(), + "unrecognised token combination '$%s' at start of macro match - did you " + "mean '$identifier' or '$('?", + t2->get_token_description()); + // skip somewhere? + return NULL; + } + } + case RIGHT_PAREN: + case RIGHT_SQUARE: + case RIGHT_CURLY: + // not allowed + error_at(t->get_locus(), + "closing delimiters like '%s' are not allowed at the start of a macro match", + t->get_token_description()); + // skip somewhere? + return NULL; + default: + // just the token + lexer.skip_token(); + return ::std::unique_ptr(new AST::Token(t)); + } + } + + // Parses a fragment macro match. + ::std::unique_ptr Parser::parse_macro_match_fragment() { + skip_token(DOLLAR_SIGN); + + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + error_at(lexer.peek_token()->get_locus(), "missing identifier in macro match fragment"); + return NULL; + } + Identifier ident = ident_tok->get_str(); + + if (!skip_token(COLON)) { + // skip after somewhere? + return NULL; + } + + // get MacroFragSpec for macro + const_TokenPtr t = expect_token(IDENTIFIER); + AST::MacroFragSpec frag = AST::get_frag_spec_from_str(t->get_str()); + if (frag == AST::INVALID) { + error_at(t->get_locus(), "invalid fragment specifier '%s' in fragment macro match", + t->get_str().c_str()); + return NULL; + } + + return ::std::unique_ptr( + new AST::MacroMatchFragment(::std::move(ident), frag)); + } + + // Parses a repetition macro match. + ::std::unique_ptr Parser::parse_macro_match_repetition() { + skip_token(DOLLAR_SIGN); + skip_token(LEFT_PAREN); + + ::std::vector< ::std::unique_ptr > matches; + + // parse required first macro match + ::std::unique_ptr initial_match = parse_macro_match(); + if (initial_match == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse required first macro match in macro match repetition"); + // skip after somewhere? + return NULL; + } + matches.push_back(::std::move(initial_match)); + + // parse optional later macro matches + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + ::std::unique_ptr match = parse_macro_match(); + + if (match == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse macro match in macro match repetition"); + return NULL; + } + + matches.push_back(::std::move(match)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + // skip after somewhere? + return NULL; + } + + t = lexer.peek_token(); + // see if separator token exists + ::std::unique_ptr separator = NULL; + switch (t->get_id()) { + // repetition operators + case ASTERISK: + case PLUS: + case QUESTION_MARK: + // delimiters + case LEFT_PAREN: + case LEFT_CURLY: + case LEFT_SQUARE: + case RIGHT_PAREN: + case RIGHT_CURLY: + case RIGHT_SQUARE: + // separator does not exist, so still null and don't skip token + break; + default: + // separator does exist + separator = ::std::unique_ptr(new AST::Token(t)); + lexer.skip_token(); + break; + } + + // parse repetition operator + t = lexer.peek_token(); + AST::MacroMatchRepetition::MacroRepOp op = AST::MacroMatchRepetition::ASTERISK; + switch (t->get_id()) { + case ASTERISK: + op = AST::MacroMatchRepetition::ASTERISK; + lexer.skip_token(); + break; + case PLUS: + op = AST::MacroMatchRepetition::PLUS; + lexer.skip_token(); + break; + case QUESTION_MARK: + op = AST::MacroMatchRepetition::QUESTION_MARK; + lexer.skip_token(); + break; + default: + error_at(t->get_locus(), + "expected macro repetition operator ('*', '+', or '?') in macro match - found '%s'", + t->get_token_description()); + // skip after somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::MacroMatchRepetition(::std::move(matches), op, ::std::move(separator))); + } + + // Parses a visibility syntactical production (i.e. creating a non-default visibility) + AST::Visibility Parser::parse_visibility() { + // check for no visibility + if (lexer.peek_token()->get_id() != PUB) { + return AST::Visibility::create_error(); + } + + lexer.skip_token(); + + // create simple pub visibility if no parentheses + if (lexer.peek_token()->get_id() != LEFT_PAREN) { + return AST::Visibility::create_public(); + // or whatever + } + + lexer.skip_token(); + + const_TokenPtr t = lexer.peek_token(); + + switch (t->get_id()) { + case CRATE: + lexer.skip_token(); + + skip_token(RIGHT_PAREN); + + return AST::Visibility::create_crate(); + case SELF: + lexer.skip_token(); + + skip_token(RIGHT_PAREN); + + return AST::Visibility::create_self(); + case SUPER: + lexer.skip_token(); + + skip_token(RIGHT_PAREN); + + return AST::Visibility::create_super(); + case IN: { + lexer.skip_token(); + + // parse the "in" path as well + AST::SimplePath path = parse_simple_path(); + if (path.is_empty()) { + error_at( + lexer.peek_token()->get_locus(), "missing path in pub(in path) visibility"); + // skip after somewhere? + return AST::Visibility::create_error(); + } + + skip_token(RIGHT_PAREN); + + return AST::Visibility::create_in_path(::std::move(path)); + } + default: + error_at( + t->get_locus(), "unexpected token '%s' in visibility", t->get_token_description()); + lexer.skip_token(); + return AST::Visibility::create_error(); + } + } + + // Parses a module - either a bodied module or a module defined in another file. + ::std::unique_ptr Parser::parse_module( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(MOD); + + const_TokenPtr module_name = expect_token(IDENTIFIER); + if (module_name == NULL) { + return NULL; + } + Identifier name = module_name->get_str(); + + const_TokenPtr t = lexer.peek_token(); + + switch (t->get_id()) { + case SEMICOLON: + lexer.skip_token(); + + return ::std::unique_ptr(new AST::ModuleNoBody(::std::move(name), + ::std::move(vis), ::std::move(outer_attrs), locus)); // module name? + case LEFT_CURLY: { + lexer.skip_token(); + + // parse inner attributes + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse items + ::std::vector< ::std::unique_ptr > items; + const_TokenPtr tok = lexer.peek_token(); + while (tok->get_id() != RIGHT_CURLY) { + ::std::unique_ptr item = parse_item(false); + if (item == NULL) { + error_at(tok->get_locus(), "failed to parse item in module"); + return NULL; + } + + items.push_back(::std::move(item)); + + tok = lexer.peek_token(); + } + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::ModuleBodied(::std::move(name), + locus, ::std::move(items), ::std::move(vis), ::std::move(inner_attrs), + ::std::move(outer_attrs))); // module name? + } + default: + error_at(t->get_locus(), + "unexpected token '%s' in module declaration/definition item", + t->get_token_description()); + lexer.skip_token(); + return NULL; + } + } + + // Parses an extern crate declaration (dependency on external crate) + ::std::unique_ptr Parser::parse_extern_crate( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + if (!skip_token(EXTERN_TOK)) { + skip_after_semicolon(); + return NULL; + } + + if (!skip_token(CRATE)) { + skip_after_semicolon(); + return NULL; + } + + /* parse crate reference name - this has its own syntactical rule in reference but seems + * to not be used elsewhere, so i'm putting it here */ + const_TokenPtr crate_name_tok = lexer.peek_token(); + ::std::string crate_name; + + switch (crate_name_tok->get_id()) { + case IDENTIFIER: + crate_name = crate_name_tok->get_str(); + lexer.skip_token(); + break; + case SELF: + crate_name = ::std::string("self"); + lexer.skip_token(); + break; + default: + error_at(crate_name_tok->get_locus(), + "expecting crate name (identifier or 'self'), found '%s'", + crate_name_tok->get_token_description()); + skip_after_semicolon(); + return NULL; + } + + // don't parse as clause if it doesn't exist + if (lexer.peek_token()->get_id() == SEMICOLON) { + lexer.skip_token(); + + return ::std::unique_ptr(new AST::ExternCrate( + ::std::move(crate_name), ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + /* parse as clause - this also has its own syntactical rule in reference and also seems to + * not be used elsewhere, so including here again. */ + if (!skip_token(AS)) { + skip_after_semicolon(); + return NULL; + } + + const_TokenPtr as_name_tok = lexer.peek_token(); + ::std::string as_name; + + switch (as_name_tok->get_id()) { + case IDENTIFIER: + as_name = as_name_tok->get_str(); + lexer.skip_token(); + break; + case UNDERSCORE: + as_name = ::std::string("_"); + lexer.skip_token(); + break; + default: + error_at(as_name_tok->get_locus(), + "expecting as clause name (identifier or '_'), found '%s'", + as_name_tok->get_token_description()); + skip_after_semicolon(); + return NULL; + } + + if (!skip_token(SEMICOLON)) { + skip_after_semicolon(); + return NULL; + } + + return ::std::unique_ptr(new AST::ExternCrate(::std::move(crate_name), + ::std::move(vis), ::std::move(outer_attrs), locus, ::std::move(as_name))); + } + + // Parses a use declaration. + ::std::unique_ptr Parser::parse_use_decl( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + if (!skip_token(USE)) { + skip_after_semicolon(); + return NULL; + } + + // parse use tree, which is required + ::std::unique_ptr use_tree = parse_use_tree(); + if (use_tree == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse use tree in use declaration"); + skip_after_semicolon(); + return NULL; + } + + if (!skip_token(SEMICOLON)) { + skip_after_semicolon(); + return NULL; + } + + return ::std::unique_ptr(new AST::UseDeclaration( + ::std::move(use_tree), ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // Parses a use tree (which can be recursive and is actually a base class). + ::std::unique_ptr Parser::parse_use_tree() { + /* potential syntax definitions in attempt to get algorithm: + * Glob: + * <- SimplePath :: * + * <- :: * + * <- * + * Nested tree thing: + * <- SimplePath :: { COMPLICATED_INNER_TREE_THING } + * <- :: COMPLICATED_INNER_TREE_THING } + * <- { COMPLICATED_INNER_TREE_THING } + * Rebind thing: + * <- SimplePath as IDENTIFIER + * <- SimplePath as _ + * <- SimplePath + */ + + /* current plan of attack: try to parse SimplePath first - if fails, one of top two + * then try parse :: - if fails, one of top two. Next is deciding character for top two. */ + + // Thus, parsing smaller parts of use tree may require feeding into function via parameters + // (or could handle all in this single function because other use tree types aren't + // recognised) as separate in the spec + + // TODO: I think this function is too complex, probably should split it + + location_t locus = lexer.peek_token()->get_locus(); + + // bool has_path = false; + AST::SimplePath path = parse_simple_path(); + + if (path.is_empty()) { + // has no path, so must be glob or nested tree UseTree type + + /* due to implementation issues, parsing simple path removes any trailing scope + * resolutions (or any, actually, if the use tree has no path given), so we'll just + * assume that there's one there. */ + // Check anyway, but optional. + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { + lexer.skip_token(); + } + /* Note that this implementation issue also makes it impossible to determine at the + * moment whether the tree has GLOBAL or NO_PATH path type. */ + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case ASTERISK: + // glob UseTree type + lexer.skip_token(); + + // TODO: find way to determine whether GLOBAL or NO_PATH path type - placeholder + return ::std::unique_ptr(new AST::UseTreeGlob( + AST::UseTreeGlob::NO_PATH, AST::SimplePath::create_empty(), locus)); + case LEFT_CURLY: { + // nested tree UseTree type + lexer.skip_token(); + + ::std::vector< ::std::unique_ptr > use_trees; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr use_tree = parse_use_tree(); + if (use_tree == NULL) { + break; + } + + use_trees.push_back(::std::move(use_tree)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // skip end curly delimiter + if (!skip_token(RIGHT_CURLY)) { + // skip after somewhere? + return NULL; + } + + // TODO: find way to determine whether GLOBAL or NO_PATH path type - placeholder + return ::std::unique_ptr( + new AST::UseTreeList(AST::UseTreeList::NO_PATH, AST::SimplePath::create_empty(), + ::std::move(use_trees), locus)); + } + case AS: + // this is not allowed + error_at(t->get_locus(), + "use declaration with rebind 'as' requires a valid simple path - none found."); + skip_after_semicolon(); + return NULL; + default: + error_at(t->get_locus(), + "unexpected token '%s' in use tree with no valid simple path (i.e. list or " + "glob use tree)", + t->get_token_description()); + skip_after_semicolon(); + return NULL; + } + } else { + /* Due to aforementioned implementation issues, the trailing :: token is consumed by the + * path, so it can not be used as a disambiguator. */ + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case ASTERISK: + // glob UseTree type + lexer.skip_token(); + + return ::std::unique_ptr(new AST::UseTreeGlob( + AST::UseTreeGlob::PATH_PREFIXED, ::std::move(path), locus)); + case LEFT_CURLY: { + // nested tree UseTree type + lexer.skip_token(); + + ::std::vector< ::std::unique_ptr > use_trees; + + // TODO: think of better control structure + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr use_tree = parse_use_tree(); + if (use_tree == NULL) { + break; + } + + use_trees.push_back(::std::move(use_tree)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // skip end curly delimiter + if (!skip_token(RIGHT_CURLY)) { + // skip after somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::UseTreeList(AST::UseTreeList::PATH_PREFIXED, ::std::move(path), + std::move(use_trees), locus)); + } + case AS: { + // rebind UseTree type + lexer.skip_token(); + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + // skip lexer token + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::UseTreeRebind(AST::UseTreeRebind::IDENTIFIER, + ::std::move(path), locus, t->get_str())); + case UNDERSCORE: + // skip lexer token + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::UseTreeRebind(AST::UseTreeRebind::WILDCARD, ::std::move(path), + locus, ::std::string("_"))); + default: + error_at(t->get_locus(), + "unexpected token '%s' in use tree with as clause - expected " + "identifier or '_'", + t->get_token_description()); + skip_after_semicolon(); + return NULL; + } + } + case SEMICOLON: + // rebind UseTree type without rebinding - path only + + // don't skip semicolon - handled in parse_use_tree + // lexer.skip_token(); + + return ::std::unique_ptr( + new AST::UseTreeRebind(AST::UseTreeRebind::NONE, ::std::move(path), locus)); + case COMMA: + case RIGHT_CURLY: + // this may occur in recursive calls - assume it is ok and ignore it + return ::std::unique_ptr( + new AST::UseTreeRebind(AST::UseTreeRebind::NONE, ::std::move(path), locus)); + default: + error_at(t->get_locus(), "unexpected token '%s' in use tree with valid path", + t->get_token_description()); + // skip_after_semicolon(); + return NULL; + } + } + } + + // Parses a function (not a method). + ::std::unique_ptr Parser::parse_function( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + // Get qualifiers for function if they exist + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + skip_token(FN_TOK); + + // Save function name token + const_TokenPtr function_name_tok = expect_token(IDENTIFIER); + if (function_name_tok == NULL) { + skip_after_next_block(); + return NULL; + } + Identifier function_name = function_name_tok->get_str(); + + // parse generic params - if exist + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + if (!skip_token(LEFT_PAREN)) { + error_at(lexer.peek_token()->get_locus(), + "function declaration missing opening parentheses before parameter list"); + skip_after_next_block(); + return NULL; + } + + // parse function parameters (only if next token isn't right paren) + ::std::vector function_params; + if (lexer.peek_token()->get_id() != RIGHT_PAREN) { + function_params = parse_function_params(); + } + + if (!skip_token(RIGHT_PAREN)) { + error_at(lexer.peek_token()->get_locus(), + "function declaration missing closing parentheses after parameter list"); + skip_after_next_block(); + return NULL; + } + + // parse function return type - if exists + ::std::unique_ptr return_type = parse_function_return_type(); + + // parse where clause - if exists + AST::WhereClause where_clause = parse_where_clause(); + + // parse block expression + ::std::unique_ptr block_expr = parse_block_expr(); + + return ::std::unique_ptr(new AST::Function(::std::move(function_name), + ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), + ::std::move(return_type), ::std::move(where_clause), ::std::move(block_expr), + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // Parses function or method qualifiers (i.e. const, unsafe, and extern). + AST::FunctionQualifiers Parser::parse_function_qualifiers() { + AST::FunctionQualifiers::AsyncConstStatus const_status = AST::FunctionQualifiers::NONE; + // bool has_const = false; + bool has_unsafe = false; + bool has_extern = false; + ::std::string abi; + + // Check in order of const, unsafe, then extern + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case CONST: + lexer.skip_token(); + const_status = AST::FunctionQualifiers::CONST; + break; + case ASYNC: + lexer.skip_token(); + const_status = AST::FunctionQualifiers::ASYNC; + break; + default: + // const status is still none + break; + } + + if (lexer.peek_token()->get_id() == UNSAFE) { + lexer.skip_token(); + has_unsafe = true; + } + + if (lexer.peek_token()->get_id() == EXTERN_TOK) { + lexer.skip_token(); + has_extern = true; + + // detect optional abi name + const_TokenPtr next_tok = lexer.peek_token(); + if (next_tok->get_id() == STRING_LITERAL) { + lexer.skip_token(); + abi = next_tok->get_str(); + } + } + + return AST::FunctionQualifiers(const_status, has_unsafe, has_extern, ::std::move(abi)); + } + + // Parses generic (lifetime or type) params inside angle brackets (optional). + ::std::vector< ::std::unique_ptr > Parser::parse_generic_params_in_angles() { + if (lexer.peek_token()->get_id() != LEFT_ANGLE) { + // seems to be no generic params, so exit with empty vector + return ::std::vector< ::std::unique_ptr >(); + } + lexer.skip_token(); + + // DEBUG: + fprintf(stderr, "skipped left angle in generic param\n"); + + ::std::vector< ::std::unique_ptr > generic_params = parse_generic_params(); + + // DEBUG: + fprintf(stderr, "finished parsing actual generic params (i.e. inside angles)\n"); + + if (!skip_generics_right_angle()) { + // DEBUG + fprintf(stderr, "failed to skip generics right angle - returning empty generic params\n"); + + return ::std::vector< ::std::unique_ptr >(); + } + + return generic_params; + } + + /* Parse generic (lifetime or type) params NOT INSIDE ANGLE BRACKETS!!! Almost always + * parse_generic_params_in_angles is what is wanted. */ + ::std::vector< ::std::unique_ptr > Parser::parse_generic_params() { + ::std::vector< ::std::unique_ptr > generic_params; + + // can't parse lifetime and type params separately due to lookahead issues + // thus, parse them all here + + // DEBUG + fprintf(stderr, "starting to parse generic params (inside angle brackets)\n"); + + // HACK: used to retain attribute data if a lifetime param is tentatively parsed but it turns + // out to be type param + AST::Attribute parsed_outer_attr = AST::Attribute::create_empty(); + + // HACK: generic params always in angle brackets with current syntax, so have that as end char + const_TokenPtr t = lexer.peek_token(); + // parse lifetime params + while (!is_right_angle_tok(t->get_id())) { + // HACK: reimpl of lifetime param parsing + AST::Attribute outer_attr = parse_outer_attribute(); + + // move attribute outward if type param + if (lexer.peek_token()->get_id() != LIFETIME) { + parsed_outer_attr = ::std::move(outer_attr); + + // DEBUG + fprintf(stderr, "broke from parsing lifetime params as next token isn't lifetime - " + "saved attribute\n"); + + break; + } + + location_t locus = lexer.peek_token()->get_locus(); + AST::Lifetime lifetime = parse_lifetime(); + + // DEBUG + fprintf(stderr, "parsed lifetime in lifetime params\n"); + + // parse optional bounds + ::std::vector lifetime_bounds; + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + // parse required bounds + lifetime_bounds = parse_lifetime_bounds(); + } + + ::std::unique_ptr param(new AST::LifetimeParam( + ::std::move(lifetime), locus, ::std::move(lifetime_bounds), ::std::move(outer_attr))); + generic_params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // parse type params (reimpl required for first one but not others) + if (!is_right_angle_tok(lexer.peek_token()->get_id()) && !parsed_outer_attr.is_empty()) { + // DEBUG + fprintf(stderr, "as parsed outer attr isn't empty, started parsing type param reimpl\n"); + + // reimpl as type param definitely exists + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse identifier in type param in generic params"); + return ::std::vector< ::std::unique_ptr >(); + } + Identifier ident = ident_tok->get_str(); + + // parse optional bounds + ::std::vector< ::std::unique_ptr > type_param_bounds; + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + + // parse optional type param bounds + type_param_bounds = parse_type_param_bounds(); + } + + // parse optional type + ::std::unique_ptr type = NULL; + if (lexer.peek_token()->get_id() == EQUAL) { + lexer.skip_token(); + + // parse required type + type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_id(), + "failed to parse type in type param in generic params"); + return ::std::vector< ::std::unique_ptr >(); + } + } + + ::std::unique_ptr param( + new AST::TypeParam(::std::move(ident), ident_tok->get_locus(), + ::std::move(type_param_bounds), ::std::move(type), ::std::move(parsed_outer_attr))); + generic_params.push_back(::std::move(param)); + + // handle comma + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + } + + // DEBUG + fprintf(stderr, "about to start parsing normally-parsed type params in generic params\n"); + + // parse rest of type params - reimpl due to right angle tokens + t = lexer.peek_token(); + while (!is_right_angle_tok(t->get_id())) { + ::std::unique_ptr type_param = parse_type_param(); + + if (type_param == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse type param in generic params"); + return ::std::vector< ::std::unique_ptr >(); + } + + // DEBUG + fprintf(stderr, "successfully parsed type param\n"); + + generic_params.push_back(::std::move(type_param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip commas, including trailing commas + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // old code + /* + // parse lifetime params (optional), allowed to end with a trailing comma + ::std::vector< ::std::unique_ptr > lifetime_params + = parse_lifetime_params(); + if (!lifetime_params.empty()) { + // C++11 code: + generic_params.insert(generic_params.end(), + ::std::make_move_iterator(lifetime_params.begin()), + ::std::make_move_iterator(lifetime_params.end())); + } + + // parse type params (optional) + ::std::vector< ::std::unique_ptr > type_params = parse_type_params(); + if (!type_params.empty()) { + // C++11 code: + generic_params.insert(generic_params.end(), + ::std::make_move_iterator(type_params.begin()), + ::std::make_move_iterator(type_params.end())); + }*/ + + return generic_params; + } + + // Parses lifetime generic parameters (pointers). Will also consume any trailing comma. + ::std::vector< ::std::unique_ptr > Parser::parse_lifetime_params() { + ::std::vector< ::std::unique_ptr > lifetime_params; + + // TODO: think of better control structure than infinite loop with break on failure? + while (true) { + AST::LifetimeParam lifetime_param = parse_lifetime_param(); + + if (lifetime_param.is_error()) { + // break if fails to parse + break; + } + + lifetime_params.push_back( + ::std::unique_ptr(new AST::LifetimeParam(lifetime_param))); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip commas, including trailing commas + lexer.skip_token(); + } + + return lifetime_params; + } + + /* Parses lifetime generic parameters (objects). Will also consume any trailing comma. + * TODO: is this best solution? implements most of the same algorithm. */ + ::std::vector Parser::parse_lifetime_params_objs() { + ::std::vector lifetime_params; + + // TODO: think of better control structure than infinite loop with break on failure? + while (true) { + AST::LifetimeParam lifetime_param = parse_lifetime_param(); + + if (lifetime_param.is_error()) { + // break if fails to parse + break; + } + + lifetime_params.push_back(lifetime_param); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip commas, including trailing commas + lexer.skip_token(); + } + + return lifetime_params; + } + + /* Parses a single lifetime generic parameter (not including comma). */ + AST::LifetimeParam Parser::parse_lifetime_param() { + // parse outer attribute, which is optional and may not exist + AST::Attribute outer_attr = parse_outer_attribute(); + + // save lifetime token - required + const_TokenPtr lifetime_tok = lexer.peek_token(); + if (lifetime_tok->get_id() != LIFETIME) { + // if lifetime is missing, must not be a lifetime param, so return null + return AST::LifetimeParam::create_error(); + } + // TODO: does this always create a named lifetime? or can a different type be made? + AST::Lifetime lifetime( + AST::Lifetime::NAMED, lifetime_tok->get_str(), lifetime_tok->get_locus()); + + // parse lifetime bounds, if it exists + ::std::vector lifetime_bounds; + if (lexer.peek_token()->get_id() == COLON) { + // parse lifetime bounds + lifetime_bounds = parse_lifetime_bounds(); + } + + return AST::LifetimeParam(::std::move(lifetime), lifetime_tok->get_locus(), + ::std::move(lifetime_bounds), ::std::move(outer_attr)); + } + + // Parses type generic parameters. Will also consume any trailing comma. + ::std::vector< ::std::unique_ptr > Parser::parse_type_params() { + ::std::vector< ::std::unique_ptr > type_params; + + // TODO: think of better control structure than infinite loop with break on failure? + while (true) { + ::std::unique_ptr type_param = parse_type_param(); + + if (type_param == NULL) { + // break if fails to parse + break; + } + + type_params.push_back(::std::move(type_param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip commas, including trailing commas + lexer.skip_token(); + } + + return type_params; + // TODO: this shares most code with parse_lifetime_params - good place to use template? + } + + // Parses a single type (generic) parameter, not including commas. May change to return value. + ::std::unique_ptr Parser::parse_type_param() { + // parse outer attribute, which is optional and may not exist + AST::Attribute outer_attr = parse_outer_attribute(); + + const_TokenPtr identifier_tok = lexer.peek_token(); + if (identifier_tok->get_id() != IDENTIFIER) { + // return null as type param can't exist without this required identifier + return NULL; + } + // TODO: create identifier from identifier token + Identifier ident = identifier_tok->get_str(); + lexer.skip_token(); + + // parse type param bounds (if they exist) + ::std::vector< ::std::unique_ptr > type_param_bounds; + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + + // parse type param bounds, which may or may not exist + type_param_bounds = parse_type_param_bounds(); + } + + // parse type (if it exists) + ::std::unique_ptr type = NULL; + if (lexer.peek_token()->get_id() == EQUAL) { + lexer.skip_token(); + + // parse type (now required) + type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse type in type param"); + return NULL; + } + } + + return ::std::unique_ptr( + new AST::TypeParam(::std::move(ident), identifier_tok->get_locus(), + ::std::move(type_param_bounds), ::std::move(type), ::std::move(outer_attr))); + } + + // Parses regular (i.e. non-generic) parameters in functions or methods. + ::std::vector Parser::parse_function_params() { + ::std::vector params; + + // HACK: return early if RIGHT_PAREN is found + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + return params; + } + + AST::FunctionParam initial_param = parse_function_param(); + + // Return empty parameter list if no parameter there + if (initial_param.is_error()) { + return params; + } + + params.push_back(::std::move(initial_param)); + + // maybe think of a better control structure here - do-while with an initial error state? + // basically, loop through parameter list until can't find any more params + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + // skip comma if applies + lexer.skip_token(); + + /* HACK: break if next token is a right (closing) paren - this is not strictly true via + * grammar rule but seems to be true in practice (i.e. with trailing comma). */ + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // now, as right paren would break, function param is required + AST::FunctionParam param = parse_function_param(); + if (param.is_error()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse function param (in function params)"); + // skip somewhere? + return ::std::vector(); + } + + params.push_back(::std::move(param)); + + t = lexer.peek_token(); + } + + return params; + } + + /* Parses a single regular (i.e. non-generic) parameter in a function or method, i.e. the + * "name: type" bit. Also handles it not existing. */ + AST::FunctionParam Parser::parse_function_param() { + location_t locus = lexer.peek_token()->get_locus(); + ::std::unique_ptr param_pattern = parse_pattern(); + + // create error function param if it doesn't exist + if (param_pattern == NULL) { + // skip after something + return AST::FunctionParam::create_error(); + } + + if (!skip_token(COLON)) { + // skip after something + return AST::FunctionParam::create_error(); + } + + ::std::unique_ptr param_type = parse_type(); + if (param_type == NULL) { + // skip? + return AST::FunctionParam::create_error(); + } + + return AST::FunctionParam(::std::move(param_pattern), ::std::move(param_type), locus); + } + + /* Parses a function or method return type syntactical construction. Also handles a function + * return type not existing. */ + ::std::unique_ptr Parser::parse_function_return_type() { + if (lexer.peek_token()->get_id() != RETURN_TYPE) { + return NULL; + } + // skip return type, as it now obviously exists + lexer.skip_token(); + + ::std::unique_ptr type = parse_type(); + + return type; + } + + /* Parses a "where clause" (in a function, struct, method, etc.). Also handles a where clause + * not existing, in which it will return WhereClause::create_empty(), which can be checked via + * WhereClause::is_empty(). */ + AST::WhereClause Parser::parse_where_clause() { + const_TokenPtr where_tok = lexer.peek_token(); + if (where_tok->get_id() != WHERE) { + // where clause doesn't exist, so create empty one + return AST::WhereClause::create_empty(); + } + + lexer.skip_token(); + + // parse where clause items - this is not a separate rule in the reference so won't be here + ::std::vector< ::std::unique_ptr > where_clause_items; + + // HACK: where clauses end with a right curly or semicolon or equals in all uses currently + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != LEFT_CURLY && t->get_id() != SEMICOLON && t->get_id() != EQUAL) { + ::std::unique_ptr where_clause_item = parse_where_clause_item(); + + if (where_clause_item == NULL) { + error_at(t->get_locus(), "failed to parse where clause item"); + return AST::WhereClause::create_empty(); + } + + where_clause_items.push_back(::std::move(where_clause_item)); + + // also skip comma if it exists + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + return AST::WhereClause(::std::move(where_clause_items)); + } + + // Parses a where clause item (lifetime or type bound). Does not parse any commas. + ::std::unique_ptr Parser::parse_where_clause_item() { + // shitty cheat way of determining lifetime or type bound - test for lifetime + const_TokenPtr t = lexer.peek_token(); + + if (t->get_id() == LIFETIME) { + return parse_lifetime_where_clause_item(); + } else { + return parse_type_bound_where_clause_item(); + } + } + + // Parses a lifetime where clause item. + ::std::unique_ptr Parser::parse_lifetime_where_clause_item() { + AST::Lifetime lifetime = parse_lifetime(); + if (lifetime.is_error()) { + // TODO: error here? + return NULL; + } + + if (!skip_token(COLON)) { + // TODO: skip after somewhere + return NULL; + } + + ::std::vector lifetime_bounds = parse_lifetime_bounds(); + + return ::std::unique_ptr( + new AST::LifetimeWhereClauseItem(::std::move(lifetime), ::std::move(lifetime_bounds))); + } + + // Parses a type bound where clause item. + ::std::unique_ptr Parser::parse_type_bound_where_clause_item() { + // parse for lifetimes, if it exists + ::std::vector for_lifetimes; + if (lexer.peek_token()->get_id() == FOR) { + for_lifetimes = parse_for_lifetimes(); + } + + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + return NULL; + } + + if (!skip_token(COLON)) { + // TODO: skip after somewhere + return NULL; + } + + // parse type param bounds if they exist + ::std::vector< ::std::unique_ptr > type_param_bounds + = parse_type_param_bounds(); + + return ::std::unique_ptr(new AST::TypeBoundWhereClauseItem( + ::std::move(for_lifetimes), ::std::move(type), ::std::move(type_param_bounds))); + } + + // Parses a for lifetimes clause, including the for keyword and angle brackets. + ::std::vector Parser::parse_for_lifetimes() { + ::std::vector params; + + if (!skip_token(FOR)) { + // skip after somewhere? + return params; + } + + if (!skip_token(LEFT_ANGLE)) { + // skip after somewhere? + return params; + } + + params = parse_lifetime_params_objs(); + + if (!skip_generics_right_angle()) { + // skip after somewhere? + return params; + } + + return params; + } + + // Parses type parameter bounds in where clause or generic arguments. + ::std::vector< ::std::unique_ptr > Parser::parse_type_param_bounds() { + ::std::vector< ::std::unique_ptr > type_param_bounds; + + ::std::unique_ptr initial_bound = parse_type_param_bound(); + + // quick exit if null + if (initial_bound == NULL) { + // error? type param bounds must have at least one term, but are bounds optional? + return type_param_bounds; + } + + type_param_bounds.push_back(::std::move(initial_bound)); + + // TODO think of better control structure than infinite loop + while (true) { + // Quick exit for no more bounds + if (lexer.peek_token()->get_id() != PLUS) { + return type_param_bounds; + } + lexer.skip_token(); + + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + // not an error: bound is allowed to be null as trailing plus is allowed + return type_param_bounds; + } + + type_param_bounds.push_back(::std::move(bound)); + } + + return type_param_bounds; + } + + /* Parses a single type parameter bound in a where clause or generic argument. Does not parse + * the '+' between arguments. */ + ::std::unique_ptr Parser::parse_type_param_bound() { + // shitty cheat way of determining lifetime or trait bound - test for lifetime + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LIFETIME: + return ::std::unique_ptr(new AST::Lifetime(parse_lifetime())); + case LEFT_PAREN: + case QUESTION_MARK: + case FOR: + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case DOLLAR_SIGN: + return parse_trait_bound(); + default: + // don't error - assume this is fine TODO + return NULL; + } + } + + // Parses a trait bound type param bound. + ::std::unique_ptr Parser::parse_trait_bound() { + bool has_parens = false; + bool has_question_mark = false; + + location_t locus = lexer.peek_token()->get_locus(); + + // handle trait bound being in parentheses + if (lexer.peek_token()->get_id() == LEFT_PAREN) { + has_parens = true; + lexer.skip_token(); + } + + // handle having question mark (optional) + if (lexer.peek_token()->get_id() == QUESTION_MARK) { + has_question_mark = true; + lexer.skip_token(); + } + + // parse for lifetimes, if it exists (although empty for lifetimes is ok to handle this) + ::std::vector for_lifetimes; + if (lexer.peek_token()->get_id() == FOR) { + for_lifetimes = parse_for_lifetimes(); + } + + // handle TypePath + AST::TypePath type_path = parse_type_path(); + + // handle closing parentheses + if (has_parens) { + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + } + + return ::std::unique_ptr(new AST::TraitBound( + ::std::move(type_path), locus, has_parens, has_question_mark, ::std::move(for_lifetimes))); + } + + // Parses lifetime bounds. + ::std::vector Parser::parse_lifetime_bounds() { + ::std::vector lifetime_bounds; + + // TODO: think of better control structure + while (true) { + AST::Lifetime lifetime = parse_lifetime(); + + // quick exit for parsing failure + if (lifetime.is_error()) { + return lifetime_bounds; + } + + lifetime_bounds.push_back(::std::move(lifetime)); + + // plus is maybe required - spec defines it poorly, so assuming not required + if (lexer.peek_token()->get_id() != PLUS) { + return lifetime_bounds; + } + + lexer.skip_token(); + } + + return lifetime_bounds; + } + + // Parses a lifetime token (named, 'static, or '_). Also handles lifetime not existing. + AST::Lifetime Parser::parse_lifetime() { + const_TokenPtr lifetime_tok = lexer.peek_token(); + location_t locus = lifetime_tok->get_locus(); + // create error lifetime if doesn't exist + if (lifetime_tok->get_id() != LIFETIME) { + return AST::Lifetime::error(); + } + lexer.skip_token(); + + ::std::string lifetime_ident = lifetime_tok->get_str(); + + if (lifetime_ident == "'static") { + return AST::Lifetime(AST::Lifetime::STATIC, "", locus); + } else if (lifetime_ident == "'_") { + return AST::Lifetime(AST::Lifetime::WILDCARD, "", locus); + } else { + return AST::Lifetime(AST::Lifetime::NAMED, ::std::move(lifetime_ident), locus); + } + } + + // Parses a "type alias" (typedef) item. + ::std::unique_ptr Parser::parse_type_alias( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(TYPE); + + // TODO: use this token for identifier when finished that + const_TokenPtr alias_name_tok = expect_token(IDENTIFIER); + if (alias_name_tok == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse identifier in type alias"); + skip_after_semicolon(); + return NULL; + } + Identifier alias_name = alias_name_tok->get_str(); + + // parse generic params, which may not exist + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // parse where clause, which may not exist + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(EQUAL)) { + skip_after_semicolon(); + return NULL; + } + + ::std::unique_ptr type_to_alias = parse_type(); + + if (!skip_token(SEMICOLON)) { + // should be skipping past this, not the next line + return NULL; + } + + return ::std::unique_ptr(new AST::TypeAlias(::std::move(alias_name), + ::std::move(generic_params), ::std::move(where_clause), ::std::move(type_to_alias), + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // Parse a struct item AST node. + ::std::unique_ptr Parser::parse_struct( + AST::Visibility vis, ::std::vector outer_attrs) { + /* TODO: determine best way to parse the proper struct vs tuple struct - share most of + * initial constructs so lookahead might be impossible, and if not probably too expensive. + * Best way is probably unified parsing for the initial parts and then pass them in as params + * to more derived functions. Alternatively, just parse everything in this one function - + * do this if function not too long. */ + + /* Proper struct <- 'struct' IDENTIFIER generic_params? where_clause? ( '{' struct_fields? '}' + * | ';' ) */ + /* Tuple struct <- 'struct' IDENTIFIER generic_params? '(' tuple_fields? ')' + * where_clause? ';' */ + location_t locus = lexer.peek_token()->get_locus(); + skip_token(STRUCT_TOK); + + // parse struct name + const_TokenPtr name_tok = expect_token(IDENTIFIER); + if (name_tok == NULL) { + error_at( + lexer.peek_token()->get_locus(), "could not parse struct or tuple struct identifier"); + // skip after somewhere? + return NULL; + } + Identifier struct_name = name_tok->get_str(); + + // parse generic params, which may or may not exist + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // branch on next token - determines whether proper struct or tuple struct + if (lexer.peek_token()->get_id() == LEFT_PAREN) { + // tuple struct + + // skip left parenthesis + lexer.skip_token(); + + // parse tuple fields + ::std::vector tuple_fields = parse_tuple_fields(); + + // tuple parameters must have closing parenthesis + if (!skip_token(RIGHT_PAREN)) { + skip_after_semicolon(); + return NULL; + } + + // parse where clause, which is optional + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(SEMICOLON)) { + // can't skip after semicolon because it's meant to be here + return NULL; + } + + return ::std::unique_ptr(new AST::TupleStruct(::std::move(tuple_fields), + ::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // assume it is a proper struct being parsed and continue outside of switch - label only here + // to suppress warning + + // parse where clause, which is optional + AST::WhereClause where_clause = parse_where_clause(); + + // branch on next token - determines whether struct is a unit struct + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_CURLY: { + // struct with body + + // skip curly bracket + lexer.skip_token(); + + // parse struct fields, if any + ::std::vector struct_fields = parse_struct_fields(); + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::StructStruct(::std::move(struct_fields), ::std::move(struct_name), + ::std::move(generic_params), ::std::move(where_clause), false, ::std::move(vis), + ::std::move(outer_attrs), locus)); + } + case SEMICOLON: + // unit struct declaration + + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::StructStruct(::std::move(struct_name), ::std::move(generic_params), + ::std::move(where_clause), ::std::move(vis), ::std::move(outer_attrs), locus)); + default: + error_at(t->get_locus(), "unexpected token '%s' in struct declaration", + t->get_token_description()); + // skip somewhere? + return NULL; + } + } + + // Parses struct fields in struct declarations. + ::std::vector Parser::parse_struct_fields() { + ::std::vector fields; + + AST::StructField initial_field = parse_struct_field(); + + // Return empty field list if no field there + if (initial_field.is_error()) { + return fields; + } + + fields.push_back(::std::move(initial_field)); + + // maybe think of a better control structure here - do-while with an initial error state? + // basically, loop through field list until can't find any more params + while (true) { + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + + // skip comma if applies + lexer.skip_token(); + + AST::StructField field = parse_struct_field(); + + if (!field.is_error()) { + fields.push_back(::std::move(field)); + } else { + // this would occur with a trailing comma, which is allowed + break; + } + } + + return fields; + + // TODO: this shares basically all code with function params and tuple fields - templates? + } + + // Parses a single struct field (in a struct definition). Does not parse commas. + AST::StructField Parser::parse_struct_field() { + // parse outer attributes, if they exist + ::std::vector outer_attrs = parse_outer_attributes(); + + // parse visibility, if it exists + AST::Visibility vis = parse_visibility(); + + // parse field name + const_TokenPtr field_name_tok = lexer.peek_token(); + if (field_name_tok->get_id() != IDENTIFIER) { + // if not identifier, assumes there is no struct field and exits - not necessarily error + return AST::StructField::create_error(); + } + Identifier field_name = field_name_tok->get_str(); + lexer.skip_token(); + + if (!skip_token(COLON)) { + // skip after somewhere? + return AST::StructField::create_error(); + } + + // parse field type - this is required + ::std::unique_ptr field_type = parse_type(); + if (field_type == NULL) { + error_at( + lexer.peek_token()->get_locus(), "could not parse type in struct field definition"); + // skip after somewhere + return AST::StructField::create_error(); + } + + return AST::StructField(::std::move(field_name), ::std::move(field_type), ::std::move(vis), + ::std::move(outer_attrs)); + } + + // Parses tuple fields in tuple/tuple struct declarations. + ::std::vector Parser::parse_tuple_fields() { + ::std::vector fields; + + AST::TupleField initial_field = parse_tuple_field(); + + // Return empty field list if no field there + if (initial_field.is_error()) { + return fields; + } + + fields.push_back(::std::move(initial_field)); + + // maybe think of a better control structure here - do-while with an initial error state? + // basically, loop through field list until can't find any more params + // HACK: all current syntax uses of tuple fields have them ending with a right paren token + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + // skip comma if applies - e.g. trailing comma + lexer.skip_token(); + + // break out due to right paren if it exists + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + AST::TupleField field = parse_tuple_field(); + if (field.is_error()) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse tuple field in tuple fields"); + return ::std::vector(); + } + + fields.push_back(::std::move(field)); + + t = lexer.peek_token(); + } + + return fields; + + // TODO: this shares basically all code with function params and struct fields - templates? + } + + // Parses a single tuple struct field in a tuple struct definition. Does not parse commas. + AST::TupleField Parser::parse_tuple_field() { + // parse outer attributes if they exist + ::std::vector outer_attrs = parse_outer_attributes(); + + // parse visibility if it exists + AST::Visibility vis = parse_visibility(); + + // parse type, which is required + ::std::unique_ptr field_type = parse_type(); + if (field_type == NULL) { + // error if null + error_at(lexer.peek_token()->get_locus(), "could not parse type in tuple struct field"); + // skip after something + return AST::TupleField::create_error(); + } + + return AST::TupleField(::std::move(field_type), ::std::move(vis), ::std::move(outer_attrs)); + } + + // Parses a Rust "enum" tagged union item definition. + ::std::unique_ptr Parser::parse_enum( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(ENUM_TOK); + + // parse enum name + const_TokenPtr enum_name_tok = expect_token(IDENTIFIER); + Identifier enum_name = enum_name_tok->get_str(); + + // parse generic params (of enum container, not enum variants) if they exist + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // parse where clause if it exists + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(LEFT_CURLY)) { + skip_after_end_block(); + return NULL; + } + + // parse actual enum variant definitions + ::std::vector< ::std::unique_ptr > enum_items = parse_enum_items(); + + if (!skip_token(RIGHT_CURLY)) { + skip_after_end_block(); + return NULL; + } + + return ::std::unique_ptr( + new AST::Enum(::std::move(enum_name), ::std::move(vis), ::std::move(generic_params), + ::std::move(where_clause), ::std::move(enum_items), ::std::move(outer_attrs), locus)); + } + + // Parses the enum variants inside an enum definiton. + ::std::vector< ::std::unique_ptr > Parser::parse_enum_items() { + ::std::vector< ::std::unique_ptr > items; + + ::std::unique_ptr initial_item = parse_enum_item(); + + // Return empty item list if no field there + if (initial_item == NULL) { + return items; + } + + items.push_back(::std::move(initial_item)); + + // maybe think of a better control structure here - do-while with an initial error state? + // basically, loop through item list until can't find any more params + while (true) { + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + + // skip comma if applies + lexer.skip_token(); + + ::std::unique_ptr item = parse_enum_item(); + + if (item != NULL) { + items.push_back(::std::move(item)); + } else { + // this would occur with a trailing comma, which is allowed + break; + } + } + + // TODO: does this need move? + return items; + + // TODO: shares virtually all code with function params, tuple and struct fields - templates? + } + + // Parses a single enum variant item in an enum definition. Does not parse commas. + ::std::unique_ptr Parser::parse_enum_item() { + // parse outer attributes if they exist + ::std::vector outer_attrs = parse_outer_attributes(); + + // parse name for enum item, which is required + const_TokenPtr item_name_tok = lexer.peek_token(); + if (item_name_tok->get_id() != IDENTIFIER) { + // this may not be an error but it means there is no enum item here + return NULL; + } + lexer.skip_token(); + Identifier item_name = item_name_tok->get_str(); + + // branch based on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_PAREN: { + // tuple enum item + lexer.skip_token(); + + ::std::vector tuple_fields = parse_tuple_fields(); + + if (!skip_token(RIGHT_PAREN)) { + // skip after somewhere + return NULL; + } + + return ::std::unique_ptr( + new AST::EnumItemTuple(::std::move(item_name), ::std::move(tuple_fields), + ::std::move(outer_attrs), item_name_tok->get_locus())); + } + case LEFT_CURLY: { + // struct enum item + lexer.skip_token(); + + ::std::vector struct_fields = parse_struct_fields(); + + if (!skip_token(RIGHT_CURLY)) { + // skip after somewhere + return NULL; + } + + return ::std::unique_ptr( + new AST::EnumItemStruct(::std::move(item_name), ::std::move(struct_fields), + ::std::move(outer_attrs), item_name_tok->get_locus())); + } + case EQUAL: { + // discriminant enum item + lexer.skip_token(); + + ::std::unique_ptr discriminant_expr = parse_expr(); + + return ::std::unique_ptr(new AST::EnumItemDiscriminant( + ::std::move(item_name), ::std::move(discriminant_expr), ::std::move(outer_attrs), + item_name_tok->get_locus())); + } + default: + // regular enum with just an identifier + return ::std::unique_ptr(new AST::EnumItem( + ::std::move(item_name), ::std::move(outer_attrs), item_name_tok->get_locus())); + } + } + + // Parses a C-style (and C-compat) untagged union declaration. + ::std::unique_ptr Parser::parse_union( + AST::Visibility vis, ::std::vector outer_attrs) { + // hack - "weak keyword" by finding identifier called "union" (lookahead in item switch) + location_t locus = lexer.peek_token()->get_locus(); + // skip union "identifier" + skip_token(IDENTIFIER); + + // parse actual union name + const_TokenPtr union_name_tok = expect_token(IDENTIFIER); + if (union_name_tok == NULL) { + skip_after_next_block(); + return NULL; + } + Identifier union_name = union_name_tok->get_str(); + + // parse optional generic parameters + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // parse optional where clause + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(LEFT_CURLY)) { + skip_after_end_block(); + return NULL; + } + + // parse union inner items as "struct fields" because hey, syntax reuse. Spec said so. + ::std::vector union_fields = parse_struct_fields(); + + if (!skip_token(RIGHT_CURLY)) { + // skip after somewhere + return NULL; + } + + return ::std::unique_ptr( + new AST::Union(::std::move(union_name), ::std::move(vis), ::std::move(generic_params), + ::std::move(where_clause), ::std::move(union_fields), ::std::move(outer_attrs), locus)); + } + + // Parses a "constant item" (compile-time constant to maybe "inline" throughout the program). + ::std::unique_ptr Parser::parse_const_item( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(CONST); + + // get constant identifier - this is either a proper identifier or the _ wildcard + const_TokenPtr ident_tok = lexer.peek_token(); + // make default identifier the underscore wildcard one + ::std::string ident("_"); + switch (ident_tok->get_id()) { + case IDENTIFIER: + ident = ident_tok->get_str(); + lexer.skip_token(); + break; + case UNDERSCORE: + // do nothing - identifier is already "_" + lexer.skip_token(); + break; + default: + error_at(ident_tok->get_locus(), + "expected item name (identifier or '_') in constant item declaration - found '%s'", + ident_tok->get_token_description()); + skip_after_semicolon(); + return NULL; + } + + if (!skip_token(COLON)) { + skip_after_semicolon(); + return NULL; + } + + // parse constant type (required) + ::std::unique_ptr type = parse_type(); + + if (!skip_token(EQUAL)) { + skip_after_semicolon(); + return NULL; + } + + // parse constant expression (required) + ::std::unique_ptr expr = parse_expr(); + + if (!skip_token(SEMICOLON)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::ConstantItem(::std::move(ident), + ::std::move(vis), ::std::move(type), ::std::move(expr), ::std::move(outer_attrs), locus)); + } + + // Parses a "static item" (static storage item, with 'static lifetime). + ::std::unique_ptr Parser::parse_static_item( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(STATIC_TOK); + + // determine whether static item is mutable + bool is_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + is_mut = true; + lexer.skip_token(); + } + + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + if (!skip_token(COLON)) { + skip_after_semicolon(); + return NULL; + } + + // parse static item type (required) + ::std::unique_ptr type = parse_type(); + + if (!skip_token(EQUAL)) { + skip_after_semicolon(); + return NULL; + } + + // parse static item expression (required) + ::std::unique_ptr expr = parse_expr(); + + if (!skip_token(SEMICOLON)) { + // skip after somewhere + return NULL; + } + + return ::std::unique_ptr(new AST::StaticItem(::std::move(ident), is_mut, + ::std::move(type), ::std::move(expr), ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // Parses a trait definition item, including unsafe ones. + ::std::unique_ptr Parser::parse_trait( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + bool is_unsafe = false; + if (lexer.peek_token()->get_id() == UNSAFE) { + is_unsafe = true; + lexer.skip_token(); + } + + skip_token(TRAIT); + + // parse trait name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + // parse generic parameters (if they exist) + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // create placeholder type param bounds in case they don't exist + ::std::vector< ::std::unique_ptr > type_param_bounds; + + // parse type param bounds (if they exist) + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + + // TODO: does this need move? + type_param_bounds = parse_type_param_bounds(); + } + + // parse where clause (if it exists) + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(LEFT_CURLY)) { + skip_after_end_block(); + return NULL; + } + + // parse trait items + ::std::vector< ::std::unique_ptr > trait_items; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr trait_item = parse_trait_item(); + + if (trait_item == NULL) { + // TODO: this is probably an error as next character should equal RIGHT_CURLY + break; + } + + trait_items.push_back(::std::move(trait_item)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_CURLY)) { + // skip after something + return NULL; + } + + return ::std::unique_ptr(new AST::Trait(::std::move(ident), is_unsafe, + ::std::move(generic_params), ::std::move(type_param_bounds), ::std::move(where_clause), + ::std::move(trait_items), ::std::move(vis), ::std::move(outer_attrs), locus)); + } + + // Parses a trait item used inside traits (not trait, the Item). + ::std::unique_ptr Parser::parse_trait_item() { + // parse outer attributes (if they exist) + ::std::vector outer_attrs = parse_outer_attributes(); + + // lookahead to determine what type of trait item to parse + const_TokenPtr tok = lexer.peek_token(); + switch (tok->get_id()) { + case TYPE: + return parse_trait_type(::std::move(outer_attrs)); + case CONST: + // disambiguate with function qualifier + if (lexer.peek_token(1)->get_id() == IDENTIFIER) { + return parse_trait_const(::std::move(outer_attrs)); + } + // else, fallthrough to function + // TODO: find out how to disable gcc "implicit fallthrough" error + gcc_fallthrough(); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: { + /* function and method can't be disambiguated by lookahead alone (without a lot of + * work and waste), so either make a "parse_trait_function_or_method" or parse here + * mostly and pass in most parameters (or if short enough, parse whole thing here). */ + // parse function and method here + + // parse function or method qualifiers + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + skip_token(FN_TOK); + + // parse function or method name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + // parse generic params + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + if (!skip_token(LEFT_PAREN)) { + // skip after somewhere? + return NULL; + } + + // now for function vs method disambiguation - method has opening "self" param + AST::SelfParam self_param = parse_self_param(); + // FIXME: ensure that self param doesn't accidently consume tokens for a function + bool is_method = false; + if (!self_param.is_error()) { + is_method = true; + + // skip comma so function and method regular params can be parsed in same way + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + } + + // parse trait function params + ::std::vector function_params = parse_function_params(); + + if (!skip_token(RIGHT_PAREN)) { + // skip after somewhere? + return NULL; + } + + // parse return type (optional) + ::std::unique_ptr return_type = parse_function_return_type(); + + // parse where clause (optional) + AST::WhereClause where_clause = parse_where_clause(); + + // parse semicolon or function definition (in block) + const_TokenPtr t = lexer.peek_token(); + ::std::unique_ptr definition = NULL; + switch (t->get_id()) { + case SEMICOLON: + lexer.skip_token(); + // definition is already NULL, so don't need to change it + break; + case LEFT_CURLY: + definition = parse_block_expr(); + // FIXME: are these outer attributes meant to be passed into the block? + break; + default: + error_at(t->get_locus(), + "expected ';' or definiton at the end of trait %s definition - found '%s' " + "instead", + is_method ? "method" : "function", t->get_token_description()); + // skip? + return NULL; + } + + // do actual if instead of ternary for return value optimisation + if (is_method) { + AST::TraitMethodDecl method_decl(::std::move(ident), ::std::move(qualifiers), + ::std::move(generic_params), ::std::move(self_param), + ::std::move(function_params), ::std::move(return_type), + ::std::move(where_clause)); + + // TODO: does this (method_decl) need move? + return ::std::unique_ptr( + new AST::TraitItemMethod(::std::move(method_decl), ::std::move(definition), + ::std::move(outer_attrs), tok->get_locus())); + } else { + AST::TraitFunctionDecl function_decl(::std::move(ident), ::std::move(qualifiers), + ::std::move(generic_params), ::std::move(function_params), + ::std::move(return_type), ::std::move(where_clause)); + + return ::std::unique_ptr( + new AST::TraitItemFunc(::std::move(function_decl), ::std::move(definition), + ::std::move(outer_attrs), tok->get_locus())); + } + } + default: { + // TODO: try and parse macro invocation semi - if fails, maybe error. + ::std::unique_ptr macro_invoc + = parse_macro_invocation_semi(outer_attrs); + + if (macro_invoc == NULL) { + // TODO: error? + return NULL; + } else { + return macro_invoc; + } + // FIXME: macro invocations can only start with certain tokens. be more picky with + // these? + } + } + } + + // Parse a typedef trait item. + ::std::unique_ptr Parser::parse_trait_type( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(TYPE); + + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + bool has_colon = false; + ::std::vector< ::std::unique_ptr > bounds; + + // parse optional colon + if (lexer.peek_token()->get_id() == COLON) { + has_colon = true; + lexer.skip_token(); + + // parse optional type param bounds + bounds = parse_type_param_bounds(); + } + + if (!skip_token(SEMICOLON)) { + // skip? + return NULL; + } + + return ::std::unique_ptr(new AST::TraitItemType( + ::std::move(ident), ::std::move(bounds), ::std::move(outer_attrs), locus)); + } + + // Parses a constant trait item. + ::std::unique_ptr Parser::parse_trait_const( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(CONST); + + // parse constant item name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + if (!skip_token(COLON)) { + skip_after_semicolon(); + return NULL; + } + + // parse constant trait item type + ::std::unique_ptr type = parse_type(); + + // parse constant trait body expression, if it exists + ::std::unique_ptr const_body = NULL; + if (lexer.peek_token()->get_id() == EQUAL) { + lexer.skip_token(); + + // expression must exist, so parse it + const_body = parse_expr(); + } + + if (!skip_token(SEMICOLON)) { + // skip after something? + return NULL; + } + + return ::std::unique_ptr(new AST::TraitItemConst(::std::move(ident), + ::std::move(type), ::std::move(const_body), ::std::move(outer_attrs), locus)); + } + + // Parses a struct "impl" item (both inherent impl and trait impl can be parsed here), + ::std::unique_ptr Parser::parse_impl( + AST::Visibility vis, ::std::vector outer_attrs) { + /* Note that only trait impls are allowed to be unsafe. So if unsafe, it must be a trait + * impl. However, this isn't enough for full disambiguation, so don't branch here. */ + location_t locus = lexer.peek_token()->get_locus(); + bool is_unsafe = false; + if (lexer.peek_token()->get_id() == UNSAFE) { + lexer.skip_token(); + is_unsafe = true; + } + + if (!skip_token(IMPL)) { + skip_after_next_block(); + return NULL; + } + + // parse generic params (shared by trait and inherent impls) + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // Again, trait impl-only feature, but optional one, so can be used for branching yet. + bool has_exclam = false; + if (lexer.peek_token()->get_id() == EXCLAM) { + lexer.skip_token(); + has_exclam = true; + } + + /* FIXME: code that doesn't look shit for TypePath. Also, make sure this doesn't parse too + * much and not work. */ + AST::TypePath type_path = parse_type_path(); + if (type_path.is_error() || lexer.peek_token()->get_id() != FOR) { + // cannot parse type path (or not for token next, at least), so must be inherent impl + + // hacky conversion of TypePath stack object to Type pointer + ::std::unique_ptr type = NULL; + if (!type_path.is_error()) { + // TODO: would move work here? + type = ::std::unique_ptr(new AST::TypePath(type_path)); + } else { + type = parse_type(); + } + // Type is required, so error if null + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse type in inherent impl"); + skip_after_next_block(); + return NULL; + } + + // parse optional where clause + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(LEFT_CURLY)) { + // TODO: does this still skip properly? + skip_after_end_block(); + return NULL; + } + + // parse inner attributes (optional) + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse inherent impl items + ::std::vector< ::std::unique_ptr > impl_items; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr impl_item = parse_inherent_impl_item(); + + if (impl_item == NULL) { + // TODO: this is probably an error as next character should equal RIGHT_CURLY + fprintf(stderr, + "impl item is null and next char wasn't RIGHT_CURLY - probably an error"); + break; + } + + impl_items.push_back(::std::move(impl_item)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere + return NULL; + } + + // DEBUG + fprintf(stderr, "successfully parsed inherent impl\n"); + + return ::std::unique_ptr(new AST::InherentImpl(::std::move(impl_items), + ::std::move(generic_params), ::std::move(type), ::std::move(where_clause), + ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else { + // type path must both be valid and next token is for, so trait impl + if (!skip_token(FOR)) { + skip_after_next_block(); + return NULL; + } + + // parse type + ::std::unique_ptr type = parse_type(); + // ensure type is included as it is required + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse type in trait impl"); + skip_after_next_block(); + return NULL; + } + + // parse optional where clause + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(LEFT_CURLY)) { + // TODO: does this still skip properly? + skip_after_end_block(); + return NULL; + } + + // parse inner attributes (optional) + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse trait impl items + ::std::vector< ::std::unique_ptr > impl_items; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr impl_item = parse_trait_impl_item(); + + if (impl_item == NULL) { + // DEBUG + fprintf( + stderr, "break out of parsing trait impl items (due to parse giving null)\n"); + + // TODO: this is probably an error as next character should equal RIGHT_CURLY + break; + } + + impl_items.push_back(::std::move(impl_item)); + + t = lexer.peek_token(); + + // DEBUG + fprintf(stderr, "successfully parsed a trait impl item\n"); + } + // DEBUG + fprintf(stderr, "successfully finished trait impl items\n"); + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere + return NULL; + } + + // DEBUG + fprintf(stderr, "successfully parsed trait impl\n"); + + return ::std::unique_ptr(new AST::TraitImpl(::std::move(type_path), + is_unsafe, has_exclam, ::std::move(impl_items), ::std::move(generic_params), + ::std::move(type), ::std::move(where_clause), ::std::move(vis), + ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + } + + // Parses a single inherent impl item (item inside an inherent impl block). + ::std::unique_ptr Parser::parse_inherent_impl_item() { + // parse outer attributes (if they exist) + ::std::vector outer_attrs = parse_outer_attributes(); + + // TODO: cleanup - currently an unreadable mess + + // branch on next token: + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + // these seem to be SimplePath tokens, so this is a macro invocation semi + return parse_macro_invocation_semi(::std::move(outer_attrs)); + case PUB: { + // visibility, so not a macro invocation semi - must be constant, function, or method + AST::Visibility vis = parse_visibility(); + + // TODO: is a recursive call to parse_inherent_impl_item better? + switch (lexer.peek_token()->get_id()) { + case EXTERN_TOK: + case UNSAFE: + case FN_TOK: + // function or method + return parse_inherent_impl_function_or_method( + ::std::move(vis), ::std::move(outer_attrs)); + case CONST: + // lookahead to resolve production - could be function/method or const item + t = lexer.peek_token(1); + + switch (t->get_id()) { + case IDENTIFIER: + case UNDERSCORE: + return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_inherent_impl_function_or_method( + ::std::move(vis), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of const item in inherent impl", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + default: + error_at(t->get_locus(), "unrecognised token '%s' for item in inherent impl", + t->get_token_description()); + // skip? + return NULL; + } + } + case EXTERN_TOK: + case UNSAFE: + case FN_TOK: + // function or method + return parse_inherent_impl_function_or_method( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + case CONST: + // lookahead to resolve production - could be function/method or const item + t = lexer.peek_token(1); + + switch (t->get_id()) { + case IDENTIFIER: + case UNDERSCORE: + return parse_const_item( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_inherent_impl_function_or_method( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of const item in inherent impl", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + gcc_unreachable(); + default: + error_at(t->get_locus(), "unrecognised token '%s' for item in inherent impl", + t->get_token_description()); + // skip? + return NULL; + } + } + + /* For internal use only by parse_inherent_impl_item() - splits giant method into smaller ones + * and prevents duplication of logic. Strictly, this parses a function or method item inside an + * inherent impl item block. */ + // TODO: make this a templated function with "return type" as type param - InherentImplItem is this + // specialisation of the template while TraitImplItem will be the other. + ::std::unique_ptr Parser::parse_inherent_impl_function_or_method( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + // parse function or method qualifiers + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + skip_token(FN_TOK); + + // parse function or method name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + // parse generic params + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + if (!skip_token(LEFT_PAREN)) { + // skip after somewhere? + return NULL; + } + + // now for function vs method disambiguation - method has opening "self" param + AST::SelfParam self_param = parse_self_param(); + // FIXME: ensure that self param doesn't accidently consume tokens for a function + // one idea is to lookahead up to 4 tokens to see whether self is one of them + bool is_method = false; + if (!self_param.is_error()) { + is_method = true; + + // skip comma so function and method regular params can be parsed in same way + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + } + + // parse trait function params + ::std::vector function_params = parse_function_params(); + + if (!skip_token(RIGHT_PAREN)) { + skip_after_end_block(); + return NULL; + } + + // parse return type (optional) + ::std::unique_ptr return_type = parse_function_return_type(); + + // parse where clause (optional) + AST::WhereClause where_clause = parse_where_clause(); + + // parse function definition (in block) - semicolon not allowed + if (lexer.peek_token()->get_id() == SEMICOLON) { + error_at(lexer.peek_token()->get_locus(), + "%s declaration in inherent impl not allowed - must have a definition", + is_method ? "method" : "function"); + lexer.skip_token(); + return NULL; + } + ::std::unique_ptr body = parse_block_expr(); + if (body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse definition in inherent impl %s definition", + is_method ? "method" : "function"); + skip_after_end_block(); + return NULL; + } + + // do actual if instead of ternary for return value optimisation + if (is_method) { + return ::std::unique_ptr(new AST::Method(::std::move(ident), + ::std::move(qualifiers), ::std::move(generic_params), ::std::move(self_param), + ::std::move(function_params), ::std::move(return_type), ::std::move(where_clause), + ::std::move(body), ::std::move(vis), ::std::move(outer_attrs), locus)); + } else { + return ::std::unique_ptr(new AST::Function(::std::move(ident), + ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), + ::std::move(return_type), ::std::move(where_clause), ::std::move(body), + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + } + + // Parses a single trait impl item (item inside a trait impl block). + ::std::unique_ptr Parser::parse_trait_impl_item() { + // parse outer attributes (if they exist) + ::std::vector outer_attrs = parse_outer_attributes(); + + // TODO: clean this function up, it is basically unreadable hacks + + // branch on next token: + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + // these seem to be SimplePath tokens, so this is a macro invocation semi + return parse_macro_invocation_semi(::std::move(outer_attrs)); + case TYPE: + return parse_type_alias(AST::Visibility::create_error(), ::std::move(outer_attrs)); + case PUB: { + // visibility, so not a macro invocation semi - must be constant, function, or method + AST::Visibility vis = parse_visibility(); + + // TODO: is a recursive call to parse_trait_impl_item better? + switch (lexer.peek_token()->get_id()) { + case TYPE: + return parse_type_alias(::std::move(vis), ::std::move(outer_attrs)); + case EXTERN_TOK: + case UNSAFE: + case FN_TOK: + // function or method + return parse_trait_impl_function_or_method( + ::std::move(vis), ::std::move(outer_attrs)); + case CONST: + // lookahead to resolve production - could be function/method or const item + t = lexer.peek_token(1); + + switch (t->get_id()) { + case IDENTIFIER: + case UNDERSCORE: + return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_trait_impl_function_or_method( + ::std::move(vis), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of const item in trait impl", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + default: + error_at(t->get_locus(), "unrecognised token '%s' for item in trait impl", + t->get_token_description()); + // skip? + return NULL; + } + } + case EXTERN_TOK: + case UNSAFE: + case FN_TOK: + // function or method + return parse_trait_impl_function_or_method( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + case CONST: + // lookahead to resolve production - could be function/method or const item + t = lexer.peek_token(1); + + switch (t->get_id()) { + case IDENTIFIER: + case UNDERSCORE: + return parse_const_item( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_trait_impl_function_or_method( + AST::Visibility::create_error(), ::std::move(outer_attrs)); + default: + error_at(t->get_locus(), + "unexpected token '%s' in some sort of const item in trait impl", + t->get_token_description()); + lexer.skip_token(1); // TODO: is this right thing to do? + return NULL; + } + gcc_unreachable(); + default: + error_at(t->get_locus(), "unrecognised token '%s' for item in trait impl", + t->get_token_description()); + // skip? + return NULL; + } + } + + /* For internal use only by parse_trait_impl_item() - splits giant method into smaller ones + * and prevents duplication of logic. Strictly, this parses a function or method item inside a + * trait impl item block. */ + ::std::unique_ptr Parser::parse_trait_impl_function_or_method( + AST::Visibility vis, ::std::vector outer_attrs) { + // this shares virtually all logic with parse_inherent_impl_function_or_method - template? + location_t locus = lexer.peek_token()->get_locus(); + + // parse function or method qualifiers + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + skip_token(FN_TOK); + + // parse function or method name + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + return NULL; + } + Identifier ident = ident_tok->get_str(); + + // DEBUG: + fprintf(stderr, "about to start parsing generic params in trait impl function or method\n"); + + // parse generic params + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + // DEBUG: + fprintf(stderr, "finished parsing generic params in trait impl function or method\n"); + + if (!skip_token(LEFT_PAREN)) { + // skip after somewhere? + return NULL; + } + + // now for function vs method disambiguation - method has opening "self" param + AST::SelfParam self_param = parse_self_param(); + // FIXME: ensure that self param doesn't accidently consume tokens for a function + bool is_method = false; + if (!self_param.is_error()) { + is_method = true; + + // skip comma so function and method regular params can be parsed in same way + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + + // DEBUG + fprintf(stderr, "successfully parsed self param in method trait impl item\n"); + } + + // DEBUG + fprintf(stderr, "started to parse function params in function or method trait impl item\n"); + + // parse trait function params (only if next token isn't right paren) + ::std::vector function_params; + if (lexer.peek_token()->get_id() != RIGHT_PAREN) { + function_params = parse_function_params(); + + if (function_params.empty()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse function params in trait impl %s definition", + is_method ? "method" : "function"); + skip_after_next_block(); + return NULL; + } + } + + // FIXME: segfault occurs during parsing of function params + + // DEBUG + fprintf( + stderr, "successfully parsed function params in function or method trait impl item\n"); + + if (!skip_token(RIGHT_PAREN)) { + skip_after_next_block(); + return NULL; + } + + // parse return type (optional) + ::std::unique_ptr return_type = parse_function_return_type(); + + // DEBUG + fprintf(stderr, "successfully parsed return type in function or method trait impl item\n"); + + // parse where clause (optional) + AST::WhereClause where_clause = parse_where_clause(); + + // DEBUG + fprintf(stderr, "successfully parsed where clause in function or method trait impl item\n"); + + // parse function definition (in block) - semicolon not allowed + if (lexer.peek_token()->get_id() == SEMICOLON) { + error_at(lexer.peek_token()->get_locus(), + "%s declaration in trait impl not allowed - must have a definition", + is_method ? "method" : "function"); + lexer.skip_token(); + return NULL; + } + ::std::unique_ptr body = parse_block_expr(); + if (body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse definition in trait impl %s definition", + is_method ? "method" : "function"); + skip_after_end_block(); + return NULL; + } + + // do actual if instead of ternary for return value optimisation + if (is_method) { + return ::std::unique_ptr(new AST::Method(::std::move(ident), + ::std::move(qualifiers), ::std::move(generic_params), ::std::move(self_param), + ::std::move(function_params), ::std::move(return_type), ::std::move(where_clause), + ::std::move(body), ::std::move(vis), ::std::move(outer_attrs), locus)); + } else { + return ::std::unique_ptr(new AST::Function(::std::move(ident), + ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), + ::std::move(return_type), ::std::move(where_clause), ::std::move(body), + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + } + + // Parses an extern block of declarations. + ::std::unique_ptr Parser::parse_extern_block( + AST::Visibility vis, ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(EXTERN_TOK); + + // detect optional abi name + ::std::string abi; + const_TokenPtr next_tok = lexer.peek_token(); + if (next_tok->get_id() == STRING_LITERAL) { + lexer.skip_token(); + abi = next_tok->get_str(); + } + + if (!skip_token(LEFT_CURLY)) { + skip_after_end_block(); + return NULL; + } + + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse declarations inside extern block + ::std::vector< ::std::unique_ptr > extern_items; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ::std::unique_ptr extern_item = parse_external_item(); + + if (extern_item == NULL) { + error_at(t->get_locus(), + "failed to parse external item despite not reaching end of extern block"); + return NULL; + } + + extern_items.push_back(::std::move(extern_item)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere + return NULL; + } + + return ::std::unique_ptr( + new AST::ExternBlock(::std::move(abi), ::std::move(extern_items), ::std::move(vis), + ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + + // Parses a single extern block item (static or function declaration). + ::std::unique_ptr Parser::parse_external_item() { + // parse optional outer attributes + ::std::vector outer_attrs = parse_outer_attributes(); + + location_t locus = lexer.peek_token()->get_locus(); + + // parse optional visibility + AST::Visibility vis = parse_visibility(); + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case STATIC_TOK: { + // parse extern static item + lexer.skip_token(); + + // parse mut (optional) + bool has_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + lexer.skip_token(); + has_mut = true; + } + + // parse identifier + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + skip_after_semicolon(); + return NULL; + } + Identifier ident = ident_tok->get_str(); + + if (!skip_token(COLON)) { + skip_after_semicolon(); + return NULL; + } + + // parse type (required) + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse type in external static item"); + skip_after_semicolon(); + return NULL; + } + + if (!skip_token(SEMICOLON)) { + // skip after somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ExternalStaticItem(::std::move(ident), ::std::move(type), has_mut, + ::std::move(vis), ::std::move(outer_attrs), locus)); + } + case FN_TOK: { + // parse extern function declaration item + // skip function token + lexer.skip_token(); + + // parse identifier + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + skip_after_semicolon(); + return NULL; + } + Identifier ident = ident_tok->get_str(); + + // parse (optional) generic params + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + if (!skip_token(LEFT_PAREN)) { + skip_after_semicolon(); + return NULL; + } + + // parse parameters + ::std::vector function_params; + bool is_variadic = false; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + AST::NamedFunctionParam param = parse_named_function_param(); + + if (param.is_error()) { + // is this an error? probably + error_at(t->get_locus(), + "could not parse named function parameter in external function"); + skip_after_semicolon(); + return NULL; + } + + function_params.push_back(::std::move(param)); + + t = lexer.peek_token(); + if (t->get_id() != COMMA) { + if (t->get_id() != RIGHT_PAREN) { + error_at(t->get_locus(), + "expected comma or right parentheses in named function parameters, " + "found '%s'", + t->get_token_description()); + } else { + // end of loop + break; + } + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + + // parse variadic ... if it exists + if (t->get_id() == ELLIPSIS && lexer.peek_token(1)->get_id() == RIGHT_PAREN) { + lexer.skip_token(); + + is_variadic = true; + + t = lexer.peek_token(); + } + } + + if (!skip_token(RIGHT_PAREN)) { + skip_after_semicolon(); + return NULL; + } + + // parse (optional) return type + ::std::unique_ptr return_type = parse_function_return_type(); + + // parse (optional) where clause + AST::WhereClause where_clause = parse_where_clause(); + + if (!skip_token(SEMICOLON)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ExternalFunctionItem(::std::move(ident), ::std::move(generic_params), + ::std::move(return_type), ::std::move(where_clause), ::std::move(function_params), + is_variadic, ::std::move(vis), ::std::move(outer_attrs), locus)); + } + default: + // error + error_at(t->get_locus(), "unrecognised token '%s' in extern block item declaration", + t->get_token_description()); + skip_after_semicolon(); + return NULL; + } + } + + // Parses an extern block function param (with "pattern" being _ or an identifier). + AST::NamedFunctionParam Parser::parse_named_function_param() { + // parse identifier/_ + Identifier name; + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + name = t->get_str(); + lexer.skip_token(); + break; + case UNDERSCORE: + name = "_"; + lexer.skip_token(); + break; + default: + // this is not a function param, but not necessarily an error + return AST::NamedFunctionParam::create_error(); + } + + if (!skip_token(COLON)) { + // skip after somewhere? + return AST::NamedFunctionParam::create_error(); + } + + // parse (required) type + ::std::unique_ptr param_type = parse_type(); + if (param_type == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse param type in extern block function declaration"); + skip_after_semicolon(); + return AST::NamedFunctionParam::create_error(); + } + + return AST::NamedFunctionParam(::std::move(name), ::std::move(param_type)); + } + + // Parses a statement (will further disambiguate any statement). + ::std::unique_ptr Parser::parse_stmt() { + // quick exit for empty statement + const_TokenPtr t = lexer.peek_token(); + if (t->get_id() == SEMICOLON) { + lexer.skip_token(); + return ::std::unique_ptr(new AST::EmptyStmt(t->get_locus())); + } + + // parse outer attributes + ::std::vector outer_attrs = parse_outer_attributes(); + + // parsing this will be annoying because of the many different possibilities + /* best may be just to copy paste in parse_item switch, and failing that try to parse outer + * attributes, and then pass them in to either a let statement or (fallback) expression + * statement. */ + // FIXME: think of a way to do this without such a large switch? + t = lexer.peek_token(); + switch (t->get_id()) { + case LET: + // let statement + return parse_let_stmt(::std::move(outer_attrs)); + case PUB: + case MOD: + case EXTERN_TOK: + case USE: + case FN_TOK: + case TYPE: + case STRUCT_TOK: + case ENUM_TOK: + case CONST: + case STATIC_TOK: + case TRAIT: + case IMPL: + /* TODO: implement union keyword but not really because of context-dependence + * crappy hack way to parse a union written below to separate it from the good code. */ + // case UNION: + case UNSAFE: // maybe - unsafe traits are a thing + // if any of these (should be all possible VisItem prefixes), parse a VisItem + // can't parse item because would require reparsing outer attributes + return parse_vis_item(::std::move(outer_attrs)); + break; + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + // almost certainly macro invocation semi + return parse_macro_item(::std::move(outer_attrs)); + break; + // crappy hack to do union "keyword" + case IDENTIFIER: + // TODO: ensure std::string and literal comparison works + if (t->get_str() == "union") { + return parse_vis_item(::std::move(outer_attrs)); + // or should this go straight to parsing union? + } else if (t->get_str() == "macro_rules") { + // macro_rules! macro item + return parse_macro_item(::std::move(outer_attrs)); + } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION + || lexer.peek_token(1)->get_id() == EXCLAM) { + // FIXME: ensure doesn't take any expressions by mistake + // path (probably) or macro invocation, so probably a macro invocation semi + return parse_macro_item(::std::move(outer_attrs)); + } + gcc_fallthrough(); + // TODO: find out how to disable gcc "implicit fallthrough" warning + default: + // fallback: expression statement + return parse_expr_stmt(::std::move(outer_attrs)); + break; + } + } + + // Parses a let statement. + ::std::unique_ptr Parser::parse_let_stmt( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(LET); + + // parse pattern (required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in let statement"); + skip_after_semicolon(); + return NULL; + } + + // parse type declaration (optional) + ::std::unique_ptr type = NULL; + if (lexer.peek_token()->get_id() == COLON) { + // must have a type declaration + lexer.skip_token(); + + type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse type in let statement"); + skip_after_semicolon(); + return NULL; + } + } + + // parse expression to set variable to (optional) + ::std::unique_ptr expr = NULL; + if (lexer.peek_token()->get_id() == EQUAL) { + // must have an expression + lexer.skip_token(); + + expr = parse_expr(); + if (expr == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse expression in let statement"); + skip_after_semicolon(); + return NULL; + } + } + + if (!skip_token(SEMICOLON)) { + // skip after somewhere + return NULL; + // TODO: how wise is it to ditch a mostly-valid let statement just because a semicolon is + // missing? + } + + return ::std::unique_ptr(new AST::LetStmt(::std::move(pattern), + ::std::move(expr), ::std::move(type), ::std::move(outer_attrs), locus)); + } + + // Parses a type path. + AST::TypePath Parser::parse_type_path() { + bool has_opening_scope_resolution = false; + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { + has_opening_scope_resolution = true; + lexer.skip_token(); + } + + // create segment vector + ::std::vector< ::std::unique_ptr > segments; + + // parse required initial segment + ::std::unique_ptr initial_segment = parse_type_path_segment(); + if (initial_segment == NULL) { + // skip after somewhere? + // don't necessarily throw error but yeah + return AST::TypePath::create_error(); + } + segments.push_back(::std::move(initial_segment)); + + // parse optional segments (as long as scope resolution operator exists) + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == SCOPE_RESOLUTION) { + // skip scope resolution operator + lexer.skip_token(); + + // parse the actual segment - it is an error if it doesn't exist now + ::std::unique_ptr segment = parse_type_path_segment(); + if (segment == NULL) { + // skip after somewhere? + error_at(t->get_locus(), "could not parse type path segment"); + return AST::TypePath::create_error(); + } + + segments.push_back(::std::move(segment)); + + t = lexer.peek_token(); + } + + return AST::TypePath(::std::move(segments), has_opening_scope_resolution); + } + + // Parses the generic arguments in each path segment. + AST::GenericArgs Parser::parse_path_generic_args() { + if (!skip_token(LEFT_ANGLE)) { + // skip after somewhere? + return AST::GenericArgs::create_empty(); + } + + // try to parse lifetimes first + ::std::vector lifetime_args; + + const_TokenPtr t = lexer.peek_token(); + location_t locus = t->get_locus(); + const_TokenPtr t2 = lexer.peek_token(1); + while ( + t->get_id() == LIFETIME && (t2->get_id() == COMMA || !is_right_angle_tok(t2->get_id()))) { + AST::Lifetime lifetime = parse_lifetime(); + if (lifetime.is_error()) { + // not necessarily an error + break; + } + + lifetime_args.push_back(::std::move(lifetime)); + + // if next token isn't comma, then it must be end of list + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + t2 = lexer.peek_token(1); + } + + // try to parse types second + ::std::vector< ::std::unique_ptr > type_args; + + // TODO: think of better control structure + t = lexer.peek_token(); + while (!is_right_angle_tok(t->get_id())) { + // ensure not binding being parsed as type accidently + if (t->get_id() == IDENTIFIER && lexer.peek_token(1)->get_id() == EQUAL) { + break; + } + + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + // not necessarily an error + break; + } + + type_args.push_back(::std::move(type)); + + // if next token isn't comma, then it must be end of list + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // try to parse bindings third + ::std::vector binding_args; + + // TODO: think of better control structure + t = lexer.peek_token(); + while (!is_right_angle_tok(t->get_id())) { + AST::GenericArgsBinding binding = parse_generic_args_binding(); + if (binding.is_error()) { + // not necessarily an error + break; + } + + binding_args.push_back(::std::move(binding)); + + // if next token isn't comma, then it must be end of list + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // skip any trailing commas + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + + if (!skip_generics_right_angle()) { + return AST::GenericArgs::create_empty(); + } + + return AST::GenericArgs( + ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args), locus); + } + + // Parses a binding in a generic args path segment. + AST::GenericArgsBinding Parser::parse_generic_args_binding() { + const_TokenPtr ident_tok = lexer.peek_token(); + if (ident_tok->get_id() != IDENTIFIER) { + // allow non error-inducing use + // skip somewhere? + return AST::GenericArgsBinding::create_error(); + } + lexer.skip_token(); + Identifier ident = ident_tok->get_str(); + + if (!skip_token(EQUAL)) { + // skip after somewhere? + return AST::GenericArgsBinding::create_error(); + } + + // parse type (required) + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + // skip somewhere? + return AST::GenericArgsBinding::create_error(); + } + + return AST::GenericArgsBinding(::std::move(ident), ::std::move(type), ident_tok->get_locus()); + } + + /* Parses a single type path segment (not including opening scope resolution, but includes any + * internal ones). Includes generic args or type path functions too. */ + ::std::unique_ptr Parser::parse_type_path_segment() { + location_t locus = lexer.peek_token()->get_locus(); + // parse ident segment part + AST::PathIdentSegment ident_segment = parse_path_ident_segment(); + if (ident_segment.is_error()) { + // not necessarily an error + return NULL; + } + + // lookahead to determine if variants exist - only consume scope resolution then + bool has_separating_scope_resolution = false; + const_TokenPtr next = lexer.peek_token(1); + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION + && (next->get_id() == LEFT_ANGLE || next->get_id() == LEFT_PAREN)) { + has_separating_scope_resolution = true; + lexer.skip_token(); + } + + // branch into variants on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_ANGLE: { + // parse generic args + AST::GenericArgs generic_args = parse_path_generic_args(); + + return ::std::unique_ptr( + new AST::TypePathSegmentGeneric(::std::move(ident_segment), + has_separating_scope_resolution, ::std::move(generic_args), locus)); + } + case LEFT_PAREN: { + // parse type path function + AST::TypePathFunction type_path_function = parse_type_path_function(); + + if (type_path_function.is_error()) { + // skip after somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::TypePathSegmentFunction(::std::move(ident_segment), + has_separating_scope_resolution, ::std::move(type_path_function), locus)); + } + default: + // neither of them + return ::std::unique_ptr(new AST::TypePathSegment( + ::std::move(ident_segment), has_separating_scope_resolution, locus)); + } + gcc_unreachable(); + } + + // Parses a function call representation inside a type path. + AST::TypePathFunction Parser::parse_type_path_function() { + if (!skip_token(LEFT_PAREN)) { + // skip somewhere? + return AST::TypePathFunction::create_error(); + } + + // parse function inputs + ::std::vector< ::std::unique_ptr > inputs; + + // TODO: think of better control structure + while (true) { + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + // not necessarily an error + break; + } + + inputs.push_back(::std::move(type)); + + // skip commas, including trailing commas + if (lexer.peek_token()->get_id() != COMMA) { + break; + } else { + lexer.skip_token(); + } + } + + if (!skip_token(RIGHT_PAREN)) { + // skip somewhere? + return AST::TypePathFunction::create_error(); + } + + // parse optional return type + ::std::unique_ptr return_type = parse_function_return_type(); + + return AST::TypePathFunction(::std::move(inputs), ::std::move(return_type)); + } + + // Parses a path inside an expression that allows generic arguments. + AST::PathInExpression Parser::parse_path_in_expression() { + location_t locus = UNKNOWN_LOCATION; + bool has_opening_scope_resolution = false; + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { + has_opening_scope_resolution = true; + + locus = lexer.peek_token()->get_locus(); + + lexer.skip_token(); + } + + // create segment vector + ::std::vector segments; + + if (locus == UNKNOWN_LOCATION) { + locus = lexer.peek_token()->get_locus(); + } + + // parse required initial segment + AST::PathExprSegment initial_segment = parse_path_expr_segment(); + if (initial_segment.is_error()) { + // skip after somewhere? + // don't necessarily throw error but yeah + return AST::PathInExpression::create_error(); + } + segments.push_back(::std::move(initial_segment)); + + // parse optional segments (as long as scope resolution operator exists) + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == SCOPE_RESOLUTION) { + // skip scope resolution operator + lexer.skip_token(); + + // parse the actual segment - it is an error if it doesn't exist now + AST::PathExprSegment segment = parse_path_expr_segment(); + if (segment.is_error()) { + // skip after somewhere? + error_at(t->get_locus(), "could not parse path expression segment"); + return AST::PathInExpression::create_error(); + } + + segments.push_back(::std::move(segment)); + + t = lexer.peek_token(); + } + + return AST::PathInExpression(::std::move(segments), locus, has_opening_scope_resolution, + ::std::vector()); + } + + // Parses a single path in expression path segment (including generic arguments). + AST::PathExprSegment Parser::parse_path_expr_segment() { + location_t locus = lexer.peek_token()->get_locus(); + // parse ident segment + AST::PathIdentSegment ident = parse_path_ident_segment(); + if (ident.is_error()) { + // not necessarily an error? + return AST::PathExprSegment::create_error(); + } + + // parse generic args (and turbofish), if they exist + /* use lookahead to determine if they actually exist (don't want to accidently parse over + * next ident segment) */ + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION + && lexer.peek_token(1)->get_id() == LEFT_ANGLE) { + // skip scope resolution + lexer.skip_token(); + + AST::GenericArgs generic_args = parse_path_generic_args(); + + return AST::PathExprSegment(::std::move(ident), locus, ::std::move(generic_args)); + } + + // return a generic parameter-less expr segment if not found + return AST::PathExprSegment(::std::move(ident), locus); + } + + // Parses a fully qualified path in expression (i.e. a pattern). FIXME does not parse outer attrs. + AST::QualifiedPathInExpression Parser::parse_qualified_path_in_expression(bool pratt_parse) { + /* Note: the Rust grammar is defined in such a way that it is impossible to determine whether + * a prospective qualified path is a QualifiedPathInExpression or QualifiedPathInType in all + * cases by the rules themselves (the only possible difference is a TypePathSegment with + * function, and lookahead to find this is too difficult). However, as this is a pattern and + * QualifiedPathInType is a type, I believe it that their construction will not be confused + * (due to rules regarding patterns vs types). + * As such, this function will not attempt to minimise errors created by their confusion. */ + + // parse the qualified path type (required) + AST::QualifiedPathType qual_path_type = parse_qualified_path_type(pratt_parse); + if (qual_path_type.is_error()) { + // TODO: should this create a parse error? + return AST::QualifiedPathInExpression::create_error(); + } + location_t locus = qual_path_type.get_locus(); + + // parse path segments + ::std::vector segments; + + // parse initial required segment + if (!expect_token(SCOPE_RESOLUTION)) { + // skip after somewhere? + + return AST::QualifiedPathInExpression::create_error(); + } + AST::PathExprSegment initial_segment = parse_path_expr_segment(); + if (initial_segment.is_error()) { + // skip after somewhere? + error_at(lexer.peek_token()->get_locus(), + "required initial path expression segment in " + "qualified path in expression could not be parsed"); + return AST::QualifiedPathInExpression::create_error(); + } + segments.push_back(::std::move(initial_segment)); + + // parse optional segments (as long as scope resolution operator exists) + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == SCOPE_RESOLUTION) { + // skip scope resolution operator + lexer.skip_token(); + + // parse the actual segment - it is an error if it doesn't exist now + AST::PathExprSegment segment = parse_path_expr_segment(); + if (segment.is_error()) { + // skip after somewhere? + error_at(t->get_locus(), + "could not parse path expression segment in qualified path in expression"); + return AST::QualifiedPathInExpression::create_error(); + } + + segments.push_back(::std::move(segment)); + + t = lexer.peek_token(); + } + + // FIXME: outer attr parsing + return AST::QualifiedPathInExpression( + ::std::move(qual_path_type), ::std::move(segments), locus, ::std::vector()); + } + + // Parses the type syntactical construction at the start of a qualified path. + AST::QualifiedPathType Parser::parse_qualified_path_type(bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + // TODO: should this actually be error? is there anywhere where this could be valid? + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + if (!skip_token(LEFT_ANGLE)) { + // skip after somewhere? + return AST::QualifiedPathType::create_error(); + } + } else { + // move back by 1 if pratt parsing due to skipping '<' + locus = lexer.peek_token()->get_locus() - 1; + } + + // parse type (required) + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse type in qualified path type"); + // skip somewhere? + return AST::QualifiedPathType::create_error(); + } + + // parse optional as clause + AST::TypePath as_type_path = AST::TypePath::create_error(); + if (lexer.peek_token()->get_id() == AS) { + lexer.skip_token(); + + // parse type path, which is required now + as_type_path = parse_type_path(); + if (as_type_path.is_error()) { + error_at(lexer.peek_token()->get_locus(), + "could not parse type path in as clause in qualified path type"); + // skip somewhere? + return AST::QualifiedPathType::create_error(); + } + } + + // NOTE: should actually be a right-angle token, so skip_generics_right_angle shouldn't be + // required + if (!skip_token(RIGHT_ANGLE)) { + // skip after somewhere? + return AST::QualifiedPathType::create_error(); + } + + return AST::QualifiedPathType(::std::move(type), locus, ::std::move(as_type_path)); + } + + // Parses a fully qualified path in type (i.e. a type). + AST::QualifiedPathInType Parser::parse_qualified_path_in_type() { + location_t locus = lexer.peek_token()->get_locus(); + // parse the qualified path type (required) + AST::QualifiedPathType qual_path_type = parse_qualified_path_type(); + if (qual_path_type.is_error()) { + // TODO: should this create a parse error? + return AST::QualifiedPathInType::create_error(); + } + + // parse path segments + ::std::vector< ::std::unique_ptr > segments; + + // parse initial required segment + if (!expect_token(SCOPE_RESOLUTION)) { + // skip after somewhere? + + return AST::QualifiedPathInType::create_error(); + } + ::std::unique_ptr initial_segment = parse_type_path_segment(); + if (initial_segment == NULL) { + // skip after somewhere? + error_at(lexer.peek_token()->get_locus(), + "required initial type path segment in qualified path in type could not be parsed"); + return AST::QualifiedPathInType::create_error(); + } + segments.push_back(::std::move(initial_segment)); + + // parse optional segments (as long as scope resolution operator exists) + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == SCOPE_RESOLUTION) { + // skip scope resolution operator + lexer.skip_token(); + + // parse the actual segment - it is an error if it doesn't exist now + ::std::unique_ptr segment = parse_type_path_segment(); + if (segment == NULL) { + // skip after somewhere? + error_at( + t->get_locus(), "could not parse type path segment in qualified path in type"); + return AST::QualifiedPathInType::create_error(); + } + + segments.push_back(::std::move(segment)); + + t = lexer.peek_token(); + } + + return AST::QualifiedPathInType(::std::move(qual_path_type), ::std::move(segments), locus); + } + + // Parses a self param. Also handles self param not existing. + AST::SelfParam Parser::parse_self_param() { + bool has_reference = false; + AST::Lifetime lifetime = AST::Lifetime::error(); + + location_t locus = lexer.peek_token()->get_locus(); + + // test if self is a reference parameter + if (lexer.peek_token()->get_id() == AMP) { + has_reference = true; + lexer.skip_token(); + + // now test whether it has a lifetime + if (lexer.peek_token()->get_id() == LIFETIME) { + lifetime = parse_lifetime(); + + // something went wrong somehow + if (lifetime.is_error()) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse lifetime in self param"); + // skip after somewhere? + return AST::SelfParam::create_error(); + } + } + } + + // test for mut + bool has_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + has_mut = true; + lexer.skip_token(); + } + + // skip self token + const_TokenPtr self_tok = lexer.peek_token(); + if (self_tok->get_id() != SELF) { + // skip after somewhere? + return AST::SelfParam::create_error(); + } + lexer.skip_token(); + + // parse optional type + ::std::unique_ptr type = NULL; + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + + // type is now required + type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "could not parse type in self param"); + // skip after somewhere? + return AST::SelfParam::create_error(); + } + } + + // ensure that cannot have both type and reference + if (type != NULL && has_reference) { + error_at(lexer.peek_token()->get_locus(), + "cannot have both a reference and a type specified in a self param"); + // skip after somewhere? + return AST::SelfParam::create_error(); + } + + if (has_reference) { + return AST::SelfParam(::std::move(lifetime), has_mut, locus); + } else { + // note that type may be NULL here and that's fine + return AST::SelfParam(::std::move(type), has_mut, locus); + } + } + + /* Parses a method. Note that this function is probably useless because using lookahead to + * determine whether a function is a method is a PITA (maybe not even doable), so most places + * probably parse a "function or method" and then resolve it into whatever it is afterward. As + * such, this is only here for algorithmically defining the grammar rule. */ + AST::Method Parser::parse_method() { + location_t locus = lexer.peek_token()->get_locus(); + // Note: as a result of the above, this will not attempt to disambiguate a function + // parse qualifiers + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + skip_token(FN_TOK); + + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + skip_after_next_block(); + return AST::Method::create_error(); + } + Identifier method_name = ident_tok->get_str(); + + // parse generic params - if exist + ::std::vector< ::std::unique_ptr > generic_params + = parse_generic_params_in_angles(); + + if (!skip_token(LEFT_PAREN)) { + error_at(lexer.peek_token()->get_locus(), + "method missing opening parentheses before parameter list"); + skip_after_next_block(); + return AST::Method::create_error(); + } + + // parse self param + AST::SelfParam self_param = parse_self_param(); + if (self_param.is_error()) { + error_at(lexer.peek_token()->get_locus(), "could not parse self param in method"); + skip_after_next_block(); + return AST::Method::create_error(); + } + + // skip comma if it exists + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + + // parse function parameters + ::std::vector function_params = parse_function_params(); + + if (!skip_token(RIGHT_PAREN)) { + error_at(lexer.peek_token()->get_locus(), + "method declaration missing closing parentheses after parameter list"); + skip_after_next_block(); + return AST::Method::create_error(); + } + + // parse function return type - if exists + ::std::unique_ptr return_type = parse_function_return_type(); + + // parse where clause - if exists + AST::WhereClause where_clause = parse_where_clause(); + + // parse block expression + ::std::unique_ptr block_expr = parse_block_expr(); + if (block_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), "method declaration missing block expression"); + skip_after_end_block(); + return AST::Method::create_error(); + } + + // does not parse visibility, but this method isn't used, so doesn't matter + return AST::Method(::std::move(method_name), ::std::move(qualifiers), + ::std::move(generic_params), ::std::move(self_param), ::std::move(function_params), + ::std::move(return_type), ::std::move(where_clause), ::std::move(block_expr), + AST::Visibility::create_error(), ::std::vector(), locus); + } + + // Parses an expression statement (disambiguates to expression with or without block statement). + ::std::unique_ptr Parser::parse_expr_stmt( + ::std::vector outer_attrs) { + /* potential thoughts - define new virtual method "has_block()" on expr. parse expr and then + * determine whether semicolon is needed as a result of this method. + * but then this would require dynamic_cast, which is not allowed. */ + + /* okay new thought - big switch to disambiguate exprs with blocks - either block expr, + * async block expr, unsafe block expr, loop expr, if expr, if let expr, or match expr. So + * all others are exprs without block. */ + /* new thought: possible initial tokens: 'loop', 'while', 'for', lifetime (and then ':' and + * then loop), 'if', 'match', '{', 'async', 'unsafe' (and then '{')). This seems to have no + * ambiguity. */ + + const_TokenPtr t = lexer.peek_token(); + /* TODO: should the switch just directly call the individual parse methods rather than adding + * another layer of indirection with parse_expr_stmt_with_block()? */ + switch (t->get_id()) { + case LOOP: + case WHILE: + case FOR: + case IF: + case MATCH_TOK: + case LEFT_CURLY: + case ASYNC: + // expression with block + return parse_expr_stmt_with_block(::std::move(outer_attrs)); + case LIFETIME: { + /* FIXME: are there any expressions without blocks that can have lifetime as their + * first token? Or is loop expr the only one? */ + // safe side for now: + if (lexer.peek_token(1)->get_id() == COLON && lexer.peek_token(2)->get_id() == LOOP) { + return parse_expr_stmt_with_block(::std::move(outer_attrs)); + } else { + return parse_expr_stmt_without_block(::std::move(outer_attrs)); + } + } + case UNSAFE: { + /* FIXME: are there any expressions without blocks that can have unsafe as their + * first token? Or is unsafe the only one? */ + // safe side for now + if (lexer.peek_token(1)->get_id() == LEFT_CURLY) { + return parse_expr_stmt_with_block(::std::move(outer_attrs)); + } else { + return parse_expr_stmt_without_block(::std::move(outer_attrs)); + } + } + default: + // not a parse expr with block, so must be expr without block + /* TODO: if possible, be more selective about possible expr without block initial + * tokens in order to prevent more syntactical errors at parse time. */ + return parse_expr_stmt_without_block(::std::move(outer_attrs)); + } + } + + // Parses a expression statement containing an expression with block. Disambiguates internally. + ::std::unique_ptr Parser::parse_expr_stmt_with_block( + ::std::vector outer_attrs) { + ::std::unique_ptr expr_parsed = NULL; + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IF: + // if or if let, so more lookahead to find out + if (lexer.peek_token(1)->get_id() == LET) { + // if let expr + expr_parsed = parse_if_let_expr(::std::move(outer_attrs)); + break; + } else { + // if expr + expr_parsed = parse_if_expr(::std::move(outer_attrs)); + break; + } + case LOOP: + // infinite loop + expr_parsed = parse_loop_expr(::std::move(outer_attrs)); + break; + case FOR: + // "for" iterator loop + expr_parsed = parse_for_loop_expr(::std::move(outer_attrs)); + break; + case WHILE: { + // while or while let, so more lookahead to find out + if (lexer.peek_token()->get_id() == LET) { + // while let loop expr + expr_parsed = parse_while_let_loop_expr(::std::move(outer_attrs)); + break; + } else { + // while loop expr + expr_parsed = parse_while_loop_expr(::std::move(outer_attrs)); + break; + } + } + case MATCH_TOK: + // match expression + expr_parsed = parse_match_expr(::std::move(outer_attrs)); + break; + case LEFT_CURLY: + // block expression + expr_parsed = parse_block_expr(::std::move(outer_attrs)); + break; + case ASYNC: + // async block expression + expr_parsed = parse_async_block_expr(::std::move(outer_attrs)); + break; + case UNSAFE: + // unsafe block expression + expr_parsed = parse_unsafe_block_expr(::std::move(outer_attrs)); + break; + case LIFETIME: + // some kind of loop expr (with loop label) + expr_parsed = parse_labelled_loop_expr(::std::move(outer_attrs)); + break; + default: + error_at(t->get_locus(), + "could not recognise expr beginning with '%s' as an expr with block in parsing " + "expr statement.", + t->get_token_description()); + skip_after_next_block(); + return NULL; + } + + // ensure expr parsed exists + if (expr_parsed == NULL) { + error_at(t->get_locus(), "failed to parse expr with block in parsing expr statement"); + skip_after_end_block(); + return NULL; + } + + // return expr stmt created from expr + return ::std::unique_ptr( + new AST::ExprStmtWithBlock(::std::move(expr_parsed), t->get_locus())); + } + + // Parses an expression statement containing an expression without block. Disambiguates further. + ::std::unique_ptr Parser::parse_expr_stmt_without_block( + ::std::vector outer_attrs) { + // TODO: maybe move more logic for expr without block in here for better error handling + + // try to parse expr without block + /*AST::ExprWithoutBlock* expr = NULL; + expr = parse_expr_without_block(::std::move(outer_attrs));*/ + // HACK: parse expression instead of expression without block, due to Pratt parsing issues + ::std::unique_ptr expr = NULL; + location_t locus = lexer.peek_token()->get_locus(); + expr = parse_expr(::std::move(outer_attrs)); + if (expr == NULL) { + // expr is required, error + error_at(lexer.peek_token()->get_locus(), + "failed to parse expr without block in expr statement"); + skip_after_semicolon(); + return NULL; + } + + // skip semicolon at end that is required + if (!skip_token(SEMICOLON)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ExprStmtWithoutBlock(::std::move(expr), locus)); + } + + // Parses an expression without a block associated with it (further disambiguates). + ::std::unique_ptr Parser::parse_expr_without_block( + ::std::vector outer_attrs) { + /* Notes on types of expr without block: + * - literal expr tokens that are literals + * - path expr path_in_expr or qual_path_in_expr + * - operator expr many different types + * unary: + * borrow expr ( '&' | '&&' ) 'mut'? expr + * dereference expr '*' expr + * error propagation expr '?' + * negation '-' expr + * not '!' expr + * binary: all start with expr + * - grouped/paren expr '(' inner_attributes expr ')' + * - array expr '[' inner_attributes array_elems? ']' + * - await expr expr '.' 'await' + * - (array/slice) index expr expr '[' expr ']' + * - tuple expr '(' inner_attributes tuple_elems? ')' + * note that a single elem tuple is distinguished from a grouped expr by a trailing + * comma, i.e. a grouped expr is preferred over a tuple expr + * - tuple index expr expr '.' tuple_index + * - struct expr path_in_expr (and optional other stuff) + * - enum variant expr path_in_expr (and optional other stuff) + * this means that there is no syntactic difference between an enum variant and a struct + * - only name resolution can tell the difference. Thus, maybe rework AST to take this + * into account ("struct or enum" nodes?) + * - (function) call expr expr '(' call_params? ')' + * - method call expr expr '.' path_expr_segment '(' call_params? ')' + * - field expr expr '.' identifier + * note that method call expr is preferred, i.e. field expr must not be followed by + * parenthesised expression sequence. + * - closure expr 'move'? ( '||' | '|' closure_params? '|' ) ( expr | '->' + * type_no_bounds block_expr ) + * - continue expr 'continue' labelled_lifetime? + * - break expr 'break' labelled_lifetime? expr? + * - range expr many different types but all involve '..' or '..=' + * - return expr 'return' as 1st tok + * - macro invocation identifier then :: or identifier then ! (simple_path '!') + * + * any that have rules beginning with 'expr' should probably be pratt-parsed, with parsing + * type to use determined by token AND lookahead. */ + + // ok well at least can do easy ones + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case RETURN_TOK: + // return expr + return parse_return_expr(::std::move(outer_attrs)); + case BREAK: + // break expr + return parse_break_expr(::std::move(outer_attrs)); + case CONTINUE: + // continue expr + return parse_continue_expr(::std::move(outer_attrs)); + case MOVE: + // closure expr (though not all closure exprs require this) + return parse_closure_expr(::std::move(outer_attrs)); + case LEFT_SQUARE: + // array expr (creation, not index) + return parse_array_expr(::std::move(outer_attrs)); + case LEFT_PAREN: + /* either grouped expr or tuple expr - depends on whether there is a comma inside the + * parentheses - if so, tuple expr, otherwise, grouped expr. */ + return parse_grouped_or_tuple_expr(::std::move(outer_attrs)); + default: { + // HACK: piggyback on pratt parsed expr and abuse polymorphism to essentially downcast + + // DEBUG + fprintf(stderr, "about to parse expr (in expr without block method)\n"); + + ::std::unique_ptr expr = parse_expr(::std::move(outer_attrs)); + + // DEBUG + fprintf(stderr, "successfully parsed expr (in expr without block method)\n"); + + if (expr == NULL) { + error_at(t->get_locus(), "failed to parse expression for expression without " + "block (pratt-parsed expression is null)"); + return NULL; + } + + ::std::unique_ptr expr_without_block( + expr->as_expr_without_block()); + // THIS IS THE CAUSE OF THE SEGFAULT + + // DEBUG + fprintf(stderr, "expr to expr without block conversion didn't error\n"); + + if (expr_without_block != NULL) { + + // DEBUG + fprintf( + stderr, "expr to expr without block conversion was successful; returning\n"); + + return expr_without_block; + } else { + error_at(t->get_locus(), "converted expr without block is null"); + return NULL; + } + } + } + } + + // Parses a block expression, including the curly braces at start and end. + ::std::unique_ptr Parser::parse_block_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + if (!skip_token(LEFT_CURLY)) { + skip_after_end_block(); + return NULL; + } + } else { + locus = lexer.peek_token()->get_locus() - 1; + } + + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse statements and expression + ::std::vector< ::std::unique_ptr > stmts; + ::std::unique_ptr expr = NULL; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY) { + ExprOrStmt expr_or_stmt = parse_stmt_or_expr_without_block(); + if (expr_or_stmt.is_error()) { + error_at(t->get_locus(), + "failed to parse statement or expression without block in block expression"); + return NULL; + } + + if (expr_or_stmt.stmt != NULL) { + // FIXME: determine if this move works + stmts.push_back(::std::move(expr_or_stmt.stmt)); + } else { + // assign to expression and end parsing inside + expr = ::std::move(expr_or_stmt.expr); + break; + } + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_CURLY)) { + error_at(t->get_locus(), "error may be from having an expression (as opposed to " + "statement) in the body of the function but not last"); + skip_after_end_block(); + return NULL; + } + + // ensure that there is at least either a statement or an expr + /*if (stmts.empty() && expr == NULL) { + error_at(lexer.peek_token()->get_id(), + "block expression requires statements or an expression without block - found neither"); + skip_after_end_block(); + return NULL; + }*/ + // grammar allows for empty block expressions + + return ::std::unique_ptr(new AST::BlockExpr(::std::move(stmts), + ::std::move(expr), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + + // Parses a "grouped" expression (expression in parentheses), used to control precedence. + ::std::unique_ptr Parser::parse_grouped_expr( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(LEFT_PAREN); + + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse required expr inside parentheses + ::std::unique_ptr expr_in_parens = parse_expr(); + if (expr_in_parens == NULL) { + // skip after somewhere? + // error? + return NULL; + } + + if (!skip_token(RIGHT_PAREN)) { + // skip after somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::GroupedExpr( + ::std::move(expr_in_parens), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + + // Parses a closure expression (closure definition). + ::std::unique_ptr Parser::parse_closure_expr( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + // detect optional "move" + bool has_move = false; + if (lexer.peek_token()->get_id() == MOVE) { + lexer.skip_token(); + has_move = true; + } + + // handle parameter list + ::std::vector params; + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case OR: + // skip token, no parameters + lexer.skip_token(); + break; + case PIPE: + // actually may have parameters + lexer.skip_token(); + + while (t->get_id() != PIPE) { + AST::ClosureParam param = parse_closure_param(); + if (param.is_error()) { + // TODO is this really an error? + error_at(t->get_locus(), "could not parse closure param"); + break; + } + params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + // not an error but means param list is done + break; + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + } + break; + default: + error_at(t->get_locus(), + "unexpected token '%s' in closure expression - expected '|' or '||'", + t->get_token_description()); + // skip somewhere? + return NULL; + } + + // again branch based on next token + t = lexer.peek_token(); + if (t->get_id() == RETURN_TYPE) { + // must be return type closure with block expr + + // skip "return type" token + lexer.skip_token(); + + // parse actual type, which is required + ::std::unique_ptr type = parse_type_no_bounds(); + if (type == NULL) { + // error + error_at(t->get_locus(), "failed to parse type for closure"); + // skip somewhere? + return NULL; + } + + // parse block expr, which is required + ::std::unique_ptr block = parse_block_expr(); + if (block == NULL) { + // error + error_at(lexer.peek_token()->get_locus(), "failed to parse block expr in closure"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ClosureExprInnerTyped(::std::move(type), ::std::move(block), + ::std::move(params), locus, has_move, ::std::move(outer_attrs))); + } else { + // must be expr-only closure + + // parse expr, which is required + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(t->get_locus(), "failed to parse expression in closure"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::ClosureExprInner( + ::std::move(expr), ::std::move(params), locus, has_move, ::std::move(outer_attrs))); + } + } + + // Parses a literal token (to literal expression). + ::std::unique_ptr Parser::parse_literal_expr( + ::std::vector outer_attrs) { + // TODO: change if literal representation in lexer changes + + ::std::string literal_value; + AST::Literal::LitType type = AST::Literal::STRING; + + // branch based on token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case CHAR_LITERAL: + type = AST::Literal::CHAR; + literal_value = t->get_str(); + lexer.skip_token(); + break; + case STRING_LITERAL: + type = AST::Literal::STRING; + literal_value = t->get_str(); + lexer.skip_token(); + break; + // case RAW_STRING_LITERAL: + // put here if lexer changes to have these + case BYTE_CHAR_LITERAL: + type = AST::Literal::BYTE; + literal_value = t->get_str(); + lexer.skip_token(); + break; + case BYTE_STRING_LITERAL: + type = AST::Literal::BYTE_STRING; + literal_value = t->get_str(); + lexer.skip_token(); + break; + // case RAW_BYTE_STRING_LITERAL: + case INT_LITERAL: + type = AST::Literal::INT; + literal_value = t->get_str(); + lexer.skip_token(); + break; + case FLOAT_LITERAL: + type = AST::Literal::FLOAT; + literal_value = t->get_str(); + lexer.skip_token(); + break; + // case BOOL_LITERAL + // use true and false keywords rather than "bool literal" Rust terminology + case TRUE_LITERAL: + type = AST::Literal::BOOL; + literal_value = ::std::string("true"); + lexer.skip_token(); + break; + case FALSE_LITERAL: + type = AST::Literal::BOOL; + literal_value = ::std::string("false"); + lexer.skip_token(); + break; + default: + // error - cannot be a literal expr + error_at(t->get_locus(), "unexpected token '%s' when parsing literal expression", + t->get_token_description()); + // skip? + return NULL; + } + + // create literal based on stuff in switch + return ::std::unique_ptr(new AST::LiteralExpr( + ::std::move(literal_value), ::std::move(type), t->get_locus(), ::std::move(outer_attrs))); + } + + // Parses a return expression (including any expression to return). + ::std::unique_ptr Parser::parse_return_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(RETURN_TOK); + } else { + // minus 7 chars for 6 in return and a space + // or just TODO: pass in location data + locus = lexer.peek_token()->get_locus() - 7; + } + + // parse expression to return, if it exists + ::std::unique_ptr returned_expr = parse_expr(); + // FIXME: ensure this doesn't ruin the middle of any expressions or anything + + return ::std::unique_ptr( + new AST::ReturnExpr(locus, ::std::move(returned_expr), ::std::move(outer_attrs))); + } + + // Parses a break expression (including any label to break to AND any return expression). + ::std::unique_ptr Parser::parse_break_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(BREAK); + } else { + // minus 6 chars for 5 in return and a space + // or just TODO: pass in location data + locus = lexer.peek_token()->get_locus() - 6; + } + + // parse label (lifetime) if it exists - create dummy first + AST::Lifetime label = AST::Lifetime::error(); + if (lexer.peek_token()->get_id() == LIFETIME) { + label = parse_lifetime(); + } + + // parse break return expression if it exists + ::std::unique_ptr return_expr = parse_expr(); + + return ::std::unique_ptr(new AST::BreakExpr( + locus, ::std::move(label), ::std::move(return_expr), ::std::move(outer_attrs))); + } + + // Parses a continue expression (including any label to continue from). + ::std::unique_ptr Parser::parse_continue_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(CONTINUE); + } else { + // minus 9 chars for 8 in return and a space + // or just TODO: pass in location data + locus = lexer.peek_token()->get_locus() - 9; + } + + // parse label (lifetime) if it exists - create dummy first + AST::Lifetime label = AST::Lifetime::error(); + if (lexer.peek_token()->get_id() == LIFETIME) { + label = parse_lifetime(); + } + + return ::std::unique_ptr( + new AST::ContinueExpr(locus, ::std::move(label), ::std::move(outer_attrs))); + } + + // Parses a loop label used in loop expressions. + AST::LoopLabel Parser::parse_loop_label() { + // parse lifetime - if doesn't exist, assume no label + const_TokenPtr t = lexer.peek_token(); + if (t->get_id() != LIFETIME) { + // not necessarily an error + return AST::LoopLabel::error(); + } + // FIXME: check for named lifetime requirement here? or check in semantic analysis phase? + AST::Lifetime label = parse_lifetime(); + + if (!skip_token(COLON)) { + // skip somewhere? + return AST::LoopLabel::error(); + } + + return AST::LoopLabel(::std::move(label), t->get_locus()); + } + + /* Parses an if expression of any kind, including with else, else if, else if let, and neither. + * Note that any outer attributes will be ignored because if expressions don't support them. */ + ::std::unique_ptr Parser::parse_if_expr( + ::std::vector outer_attrs ATTRIBUTE_UNUSED) { + // TODO: make having outer attributes an error? + + location_t locus = lexer.peek_token()->get_locus(); + skip_token(IF); + + // detect accidental if let + if (lexer.peek_token()->get_id() == LET) { + error_at(lexer.peek_token()->get_locus(), + "if let expression probably exists, but is being parsed as an if expression. This may " + "be a parser error."); + // skip somewhere? + return NULL; + } + + // parse required condition expr - HACK to prevent struct expr from being parsed + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr condition + = parse_expr(::std::vector(), no_struct_expr); + if (condition == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse condition expression in if expression"); + // skip somewhere? + return NULL; + } + + // parse required block expr + ::std::unique_ptr if_body = parse_block_expr(); + if (if_body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse if body block expression in if expression"); + // skip somewhere? + return NULL; + } + + // branch to parse end or else (and then else, else if, or else if let) + if (lexer.peek_token()->get_id() != ELSE) { + // single selection - end of if expression + return ::std::unique_ptr( + new AST::IfExpr(::std::move(condition), ::std::move(if_body), locus)); + } else { + // double or multiple selection - branch on end, else if, or else if let + + // skip "else" + lexer.skip_token(); + + // branch on whether next token is '{' or 'if' + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_CURLY: { + // double selection - else + // parse else block expr (required) + ::std::unique_ptr else_body = parse_block_expr(); + if (else_body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse else body block expression in if expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::IfExprConseqElse( + ::std::move(condition), ::std::move(if_body), ::std::move(else_body), locus)); + } + case IF: { + // multiple selection - else if or else if let + // branch on whether next token is 'let' or not + if (lexer.peek_token(1)->get_id() == LET) { + // parse if let expr (required) + ::std::unique_ptr if_let_expr = parse_if_let_expr(); + if (if_let_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse (else) if let expression after if expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::IfExprConseqIfLet(::std::move(condition), ::std::move(if_body), + ::std::move(if_let_expr), locus)); + } else { + // parse if expr (required) + ::std::unique_ptr if_expr = parse_if_expr(); + if (if_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse (else) if expression after if expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::IfExprConseqIf( + ::std::move(condition), ::std::move(if_body), ::std::move(if_expr), locus)); + } + } + default: + // error - invalid token + error_at(t->get_locus(), "unexpected token '%s' after else in if expression", + t->get_token_description()); + // skip somewhere? + return NULL; + } + } + } + + /* Parses an if let expression of any kind, including with else, else if, else if let, and none. + * Note that any outer attributes will be ignored as if let expressions don't support them. */ + ::std::unique_ptr Parser::parse_if_let_expr( + ::std::vector outer_attrs ATTRIBUTE_UNUSED) { + // TODO: make having outer attributes an error? + + location_t locus = lexer.peek_token()->get_locus(); + skip_token(IF); + + // detect accidental if expr parsed as if let expr + if (lexer.peek_token()->get_id() != LET) { + error_at(lexer.peek_token()->get_locus(), + "if expression probably exists, but is being parsed as an if let expression. This may " + "be a parser error."); + // skip somewhere? + return NULL; + } + lexer.skip_token(); + + // parse match arm patterns (which are required) + ::std::vector< ::std::unique_ptr > match_arm_patterns + = parse_match_arm_patterns(EQUAL); + if (match_arm_patterns.empty()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse any match arm patterns in if let expression"); + // skip somewhere? + return NULL; + } + + if (!skip_token(EQUAL)) { + // skip somewhere? + return NULL; + } + + // parse expression (required) - HACK to prevent struct expr being parsed + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr scrutinee_expr + = parse_expr(::std::vector(), no_struct_expr); + if (scrutinee_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse scrutinee expression in if let expression"); + // skip somewhere? + return NULL; + } + /* TODO: check for expression not being a struct expression or lazy boolean expression here? + * or actually probably in semantic analysis. */ + + // parse block expression (required) + ::std::unique_ptr if_let_body = parse_block_expr(); + if (if_let_body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse if let body block expression in if let expression"); + // skip somewhere? + return NULL; + } + + // branch to parse end or else (and then else, else if, or else if let) + if (lexer.peek_token()->get_id() != ELSE) { + // single selection - end of if let expression + return ::std::unique_ptr( + new AST::IfLetExpr(::std::move(match_arm_patterns), ::std::move(scrutinee_expr), + ::std::move(if_let_body), locus)); + } else { + // double or multiple selection - branch on end, else if, or else if let + + // skip "else" + lexer.skip_token(); + + // branch on whether next token is '{' or 'if' + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LEFT_CURLY: { + // double selection - else + // parse else block expr (required) + ::std::unique_ptr else_body = parse_block_expr(); + if (else_body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse else body block expression in if let expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::IfLetExprConseqElse( + ::std::move(match_arm_patterns), ::std::move(scrutinee_expr), + ::std::move(if_let_body), ::std::move(else_body), locus)); + } + case IF: { + // multiple selection - else if or else if let + // branch on whether next token is 'let' or not + if (lexer.peek_token(1)->get_id() == LET) { + // parse if let expr (required) + ::std::unique_ptr if_let_expr = parse_if_let_expr(); + if (if_let_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse (else) if let expression after if let expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::IfLetExprConseqIfLet(::std::move(match_arm_patterns), + ::std::move(scrutinee_expr), ::std::move(if_let_body), + ::std::move(if_let_expr), locus)); + } else { + // parse if expr (required) + ::std::unique_ptr if_expr = parse_if_expr(); + if (if_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse (else) if expression after if let expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::IfLetExprConseqIf( + ::std::move(match_arm_patterns), ::std::move(scrutinee_expr), + ::std::move(if_let_body), ::std::move(if_expr), locus)); + } + } + default: + // error - invalid token + error_at(t->get_locus(), "unexpected token '%s' after else in if let expression", + t->get_token_description()); + // skip somewhere? + return NULL; + } + } + } + + // TODO: possibly decide on different method of handling label (i.e. not parameter) + + /* Parses a "loop" infinite loop expression. Label is not parsed and should be parsed via + * parse_labelled_loop_expr, which would call this. */ + ::std::unique_ptr Parser::parse_loop_expr( + ::std::vector outer_attrs, AST::LoopLabel label) { + location_t locus = UNKNOWN_LOCATION; + if (label.is_error()) { + locus = lexer.peek_token()->get_locus(); + } else { + locus = label.get_locus(); + } + skip_token(LOOP); + + // parse loop body, which is required + ::std::unique_ptr loop_body = parse_block_expr(); + if (loop_body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse loop body in (infinite) loop expression"); + return NULL; + } + + return ::std::unique_ptr(new AST::LoopExpr( + ::std::move(loop_body), locus, ::std::move(label), ::std::move(outer_attrs))); + } + + /* Parses a "while" loop expression. Label is not parsed and should be parsed via + * parse_labelled_loop_expr, which would call this. */ + ::std::unique_ptr Parser::parse_while_loop_expr( + ::std::vector outer_attrs, AST::LoopLabel label) { + location_t locus = UNKNOWN_LOCATION; + if (label.is_error()) { + locus = lexer.peek_token()->get_locus(); + } else { + locus = label.get_locus(); + } + skip_token(WHILE); + + // ensure it isn't a while let loop + if (lexer.peek_token()->get_id() == LET) { + error_at(lexer.peek_token()->get_locus(), + "appears to be while let loop but is being parsed by " + "while loop - this may be a compiler issue"); + // skip somewhere? + return NULL; + } + + // parse loop predicate (required) with HACK to prevent struct expr parsing + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr predicate + = parse_expr(::std::vector(), no_struct_expr); + if (predicate == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse predicate expression in while loop"); + // skip somewhere? + return NULL; + } + // TODO: check that it isn't struct expression here? actually, probably in semantic analysis + + // parse loop body (required) + ::std::unique_ptr body = parse_block_expr(); + if (body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse loop body block expression in while loop"); + // skip somewhere + return NULL; + } + + return ::std::unique_ptr(new AST::WhileLoopExpr(::std::move(predicate), + ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); + } + + /* Parses a "while let" loop expression. Label is not parsed and should be parsed via + * parse_labelled_loop_expr, which would call this. */ + ::std::unique_ptr Parser::parse_while_let_loop_expr( + ::std::vector outer_attrs, AST::LoopLabel label) { + location_t locus = UNKNOWN_LOCATION; + if (label.is_error()) { + locus = lexer.peek_token()->get_locus(); + } else { + locus = label.get_locus(); + } + skip_token(WHILE); + + // check for possible accidental recognition of a while loop as a while let loop + if (lexer.peek_token()->get_id() != LET) { + error_at(lexer.peek_token()->get_locus(), + "appears to be a while loop but is being parsed by " + "while let loop - this may be a compiler issue"); + // skip somewhere + return NULL; + } + // as this token is definitely let now, save the computation of comparison + lexer.skip_token(); + + // parse predicate patterns + ::std::vector< ::std::unique_ptr > predicate_patterns + = parse_match_arm_patterns(EQUAL); + // TODO: have to ensure that there is at least 1 pattern? + + if (!skip_token(EQUAL)) { + // skip somewhere? + return NULL; + } + + // parse predicate expression, which is required (and HACK to prevent struct expr) + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr predicate_expr + = parse_expr(::std::vector(), no_struct_expr); + if (predicate_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse predicate expression in while let loop"); + // skip somewhere? + return NULL; + } + // TODO: ensure that struct expression is not parsed? Actually, probably in semantic analysis. + + // parse loop body, which is required + ::std::unique_ptr body = parse_block_expr(); + if (body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse block expr (loop body) of while let loop"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::WhileLetLoopExpr(::std::move(predicate_patterns), ::std::move(predicate_expr), + ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); + } + + /* Parses a "for" iterative loop. Label is not parsed and should be parsed via + * parse_labelled_loop_expr, which would call this. */ + ::std::unique_ptr Parser::parse_for_loop_expr( + ::std::vector outer_attrs, AST::LoopLabel label) { + location_t locus = UNKNOWN_LOCATION; + if (label.is_error()) { + locus = lexer.peek_token()->get_locus(); + } else { + locus = label.get_locus(); + } + skip_token(FOR); + + // parse pattern, which is required + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse iterator pattern in for loop"); + // skip somewhere? + return NULL; + } + + if (!skip_token(IN)) { + // skip somewhere? + return NULL; + } + + // parse iterator expression, which is required - also HACK to prevent struct expr + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr expr + = parse_expr(::std::vector(), no_struct_expr); + if (expr == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse iterator expression in for loop"); + // skip somewhere? + return NULL; + } + // TODO: check to ensure this isn't struct expr? Or in semantic analysis. + + // parse loop body, which is required + ::std::unique_ptr body = parse_block_expr(); + if (body == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse loop body block expression in for loop"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::ForLoopExpr(::std::move(pattern), + ::std::move(expr), ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); + } + + // Parses a loop expression with label (any kind of loop - disambiguates). + ::std::unique_ptr Parser::parse_labelled_loop_expr( + ::std::vector outer_attrs) { + // TODO: decide whether it should not work if there is no label, or parse it with no label + // at the moment, I will make it not work with no label because that's the implication. + + if (lexer.peek_token()->get_id() != LIFETIME) { + error_at(lexer.peek_token()->get_locus(), + "expected lifetime in labelled loop expr (to parse loop label) - found '%s'", + lexer.peek_token()->get_token_description()); + // skip? + return NULL; + } + + // parse loop label (required) + AST::LoopLabel label = parse_loop_label(); + if (label.is_error()) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse loop label in labelled loop expr"); + // skip? + return NULL; + } + + // branch on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case LOOP: + return parse_loop_expr(::std::move(outer_attrs), ::std::move(label)); + case FOR: + return parse_for_loop_expr(::std::move(outer_attrs), ::std::move(label)); + case WHILE: + // further disambiguate into while vs while let + if (lexer.peek_token(1)->get_id() == LET) { + return parse_while_let_loop_expr(::std::move(outer_attrs), ::std::move(label)); + } else { + return parse_while_loop_expr(::std::move(outer_attrs), ::std::move(label)); + } + default: + // error + error_at(t->get_locus(), "unexpected token '%s' when parsing labelled loop", + t->get_token_description()); + // skip? + return NULL; + } + } + + // Parses a match expression. + ::std::unique_ptr Parser::parse_match_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(MATCH_TOK); + } else { + // TODO: probably just pass in location data as param + // get current pos then move back 6 - 5 for match, 1 for space + locus = lexer.peek_token()->get_locus() - 6; + } + + // parse scrutinee expression, which is required (and HACK to prevent struct expr) + ParseRestrictions no_struct_expr; + no_struct_expr.can_be_struct_expr = false; + ::std::unique_ptr scrutinee + = parse_expr(::std::vector(), no_struct_expr); + if (scrutinee == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse scrutinee expression in match expression"); + // skip somewhere? + return NULL; + } + // TODO: check for scrutinee expr not being struct expr? or do so in semantic analysis + + if (!skip_token(LEFT_CURLY)) { + // skip somewhere? + return NULL; + } + + // parse inner attributes (if they exist) + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse match arms (if they exist) + ::std::vector< ::std::unique_ptr > match_arms; + + // DEBUG + fprintf(stderr, "about to start loop to start parsing match cases\n"); + + // FIXME: absolute worst control structure ever + // parse match cases + while (true) { + // parse match arm itself, which is required + AST::MatchArm arm = parse_match_arm(); + if (arm.is_error()) { + // DEBUG + fprintf(stderr, "broke loop on invalid match arm\n"); + + // not necessarily an error + break; + } + + // DEBUG + fprintf(stderr, "parsed valid match arm\n"); + + if (!skip_token(MATCH_ARROW)) { + // skip after somewhere? + // TODO is returning here a good idea? or is break better? + return NULL; + } + + // DEBUG + fprintf(stderr, "skipped match arrow\n"); + + // branch on next token - if '{', block expr, otherwise just expr + if (lexer.peek_token()->get_id() == LEFT_CURLY) { + // block expr + ::std::unique_ptr block_expr = parse_block_expr(); + if (block_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse block expr in match arm in match expr"); + // skip somewhere + return NULL; + } + + // create match case block expr and add to cases + ::std::unique_ptr match_case_block( + new AST::MatchCaseBlockExpr(::std::move(arm), ::std::move(block_expr))); + match_arms.push_back(::std::move(match_case_block)); + + // skip optional comma + if (lexer.peek_token()->get_id() == COMMA) { + lexer.skip_token(); + } + } else { + // regular expr + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse expr in match arm in match expr"); + // skip somewhere? + return NULL; + } + + // construct match case expr and add to cases + ::std::unique_ptr match_case_expr( + new AST::MatchCaseExpr(::std::move(arm), ::std::move(expr))); + match_arms.push_back(::std::move(match_case_expr)); + + // skip REQUIRED comma - if no comma, break + if (lexer.peek_token()->get_id() != COMMA) { + // if no comma, must be end of cases + break; + } + lexer.skip_token(); + } + } + + if (!skip_token(RIGHT_CURLY)) { + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::MatchExpr(::std::move(scrutinee), + ::std::move(match_arms), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + + // Parses the "pattern" part of the match arm (the 'case x:' equivalent). + AST::MatchArm Parser::parse_match_arm() { + // parse optional outer attributes + ::std::vector outer_attrs = parse_outer_attributes(); + + // DEBUG + fprintf(stderr, "about to start parsing match arm patterns\n"); + + // break early if find right curly + if (lexer.peek_token()->get_id() == RIGHT_CURLY) { + // not an error + return AST::MatchArm::create_error(); + } + + // parse match arm patterns - at least 1 is required + ::std::vector< ::std::unique_ptr > match_arm_patterns + = parse_match_arm_patterns(RIGHT_CURLY); + if (match_arm_patterns.empty()) { + error_at(lexer.peek_token()->get_locus(), "failed to parse any patterns in match arm"); + // skip somewhere? + return AST::MatchArm::create_error(); + } + + // DEBUG + fprintf(stderr, "successfully parsed match arm patterns\n"); + + // parse match arm guard expr if it exists + ::std::unique_ptr guard_expr = NULL; + if (lexer.peek_token()->get_id() == IF) { + lexer.skip_token(); + + guard_expr = parse_expr(); + if (guard_expr == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse guard expression in match arm"); + // skip somewhere? + return AST::MatchArm::create_error(); + } + } + + // DEBUG + fprintf(stderr, "successfully parsed match arm\n"); + + return AST::MatchArm( + ::std::move(match_arm_patterns), ::std::move(guard_expr), ::std::move(outer_attrs)); + } + + /* Parses the patterns used in a match arm. End token id is the id of the token that would exist + * after the patterns are done (e.g. '}' for match expr, '=' for if let and while let). */ + ::std::vector< ::std::unique_ptr > Parser::parse_match_arm_patterns( + TokenId end_token_id) { + // skip optional leading '|' + bool has_leading_pipe = false; + if (lexer.peek_token()->get_id() == PIPE) { + has_leading_pipe = true; + lexer.skip_token(); + } + // TODO: do I even need to store the result of this? can't be used. + // If semantically different, I need a wrapped "match arm patterns" object for this. + + ::std::vector< ::std::unique_ptr > patterns; + + // quick break out if end_token_id + if (lexer.peek_token()->get_id() == end_token_id) { + return patterns; + } + + // parse required pattern - if doesn't exist, return empty + ::std::unique_ptr initial_pattern = parse_pattern(); + if (initial_pattern == NULL) { + // FIXME: should this be an error? + return patterns; + } + patterns.push_back(::std::move(initial_pattern)); + + // DEBUG + fprintf(stderr, "successfully parsed initial match arm pattern\n"); + + // parse new patterns as long as next char is '|' + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == PIPE) { + // skip pipe token + lexer.skip_token(); + + // break if hit end token id + if (lexer.peek_token()->get_id() == end_token_id) { + break; + } + + // parse pattern + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + // this is an error + error_at( + lexer.peek_token()->get_locus(), "failed to parse pattern in match arm patterns"); + // skip somewhere? + return ::std::vector< ::std::unique_ptr >(); + } + + patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + return patterns; + } + + // Parses an async block expression. + ::std::unique_ptr Parser::parse_async_block_expr( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(ASYNC); + + // detect optional move token + bool has_move = false; + if (lexer.peek_token()->get_id() == MOVE) { + lexer.skip_token(); + has_move = true; + } + + // parse block expression (required) + ::std::unique_ptr block_expr = parse_block_expr(); + if (block_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse block expression of async block expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::AsyncBlockExpr( + ::std::move(block_expr), has_move, ::std::move(outer_attrs), locus)); + } + + // Parses an unsafe block expression. + ::std::unique_ptr Parser::parse_unsafe_block_expr( + ::std::vector outer_attrs) { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(UNSAFE); + + // parse block expression (required) + ::std::unique_ptr block_expr = parse_block_expr(); + if (block_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse block expression of unsafe block expression"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::UnsafeBlockExpr(::std::move(block_expr), ::std::move(outer_attrs), locus)); + } + + // Parses an array definition expression. + ::std::unique_ptr Parser::parse_array_expr( + ::std::vector outer_attrs, bool pratt_parse) { + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(LEFT_SQUARE); + } else { + locus = lexer.peek_token()->get_locus() - 1; + } + + // parse optional inner attributes + ::std::vector inner_attrs = parse_inner_attributes(); + + // parse the "array elements" section, which is optional + if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { + // no array elements + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::ArrayExpr(NULL, ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else { + // should have array elements + // parse initial expression, which is required for either + ::std::unique_ptr initial_expr = parse_expr(); + if (initial_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse expression in array expression " + "(even though arrayelems seems to be present)"); + // skip somewhere? + return NULL; + } + + if (lexer.peek_token()->get_id() == SEMICOLON) { + // copy array elems + lexer.skip_token(); + + // parse copy amount expression (required) + ::std::unique_ptr copy_amount = parse_expr(); + if (copy_amount == NULL) { + error_at(lexer.peek_token()->get_locus(), + "could not parse copy amount expression in array expression (arrayelems)"); + // skip somewhere? + return NULL; + } + + ::std::unique_ptr copied_array_elems( + new AST::ArrayElemsCopied(::std::move(initial_expr), ::std::move(copy_amount))); + return ::std::unique_ptr( + new AST::ArrayExpr(::std::move(copied_array_elems), ::std::move(inner_attrs), + ::std::move(outer_attrs), locus)); + } else if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { + // single-element array expression + ::std::vector< ::std::unique_ptr > exprs; + exprs.push_back(::std::move(initial_expr)); + + ::std::unique_ptr array_elems( + new AST::ArrayElemsValues(::std::move(exprs))); + return ::std::unique_ptr(new AST::ArrayExpr(::std::move(array_elems), + ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else if (lexer.peek_token()->get_id() == COMMA) { + // multi-element array expression (or trailing comma) + ::std::vector< ::std::unique_ptr > exprs; + exprs.push_back(::std::move(initial_expr)); + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // quick break if right square bracket + if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { + break; + } + + // parse expression (required) + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse element in array expression"); + // skip somewhere? + return NULL; + } + exprs.push_back(::std::move(expr)); + + t = lexer.peek_token(); + } + + skip_token(RIGHT_SQUARE); + + ::std::unique_ptr array_elems( + new AST::ArrayElemsValues(::std::move(exprs))); + return ::std::unique_ptr(new AST::ArrayExpr(::std::move(array_elems), + ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else { + // error + error_at(lexer.peek_token()->get_locus(), + "unexpected token '%s' in array expression (arrayelems)", + lexer.peek_token()->get_token_description()); + // skip somewhere? + return NULL; + } + } + } + + // Parses a single parameter used in a closure definition. + AST::ClosureParam Parser::parse_closure_param() { + // parse pattern (which is required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + // not necessarily an error + return AST::ClosureParam::create_error(); + } + + // parse optional type of param + ::std::unique_ptr type = NULL; + if (lexer.peek_token()->get_id() == COLON) { + lexer.skip_token(); + + // parse type, which is now required + type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_id(), "failed to parse type in closure parameter"); + // skip somewhere? + return AST::ClosureParam::create_error(); + } + } + + return AST::ClosureParam(::std::move(pattern), ::std::move(type)); + } + + // Parses a grouped or tuple expression (disambiguates). + ::std::unique_ptr Parser::parse_grouped_or_tuple_expr( + ::std::vector outer_attrs, bool pratt_parse) { + // adjustment to allow Pratt parsing to reuse function without copy-paste + location_t locus = UNKNOWN_LOCATION; + if (!pratt_parse) { + locus = lexer.peek_token()->get_locus(); + + skip_token(LEFT_PAREN); + } else { + locus = lexer.peek_token()->get_locus() - 1; + } + + // parse optional inner attributes + ::std::vector inner_attrs = parse_inner_attributes(); + + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + // must be empty tuple + lexer.skip_token(); + + // create tuple with empty tuple elems + return ::std::unique_ptr( + new AST::TupleExpr(::std::vector< ::std::unique_ptr >(), + ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } + + // parse first expression (required) + ::std::unique_ptr first_expr = parse_expr(); + if (first_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse expression in grouped or tuple expression"); + // skip after somewhere? + return NULL; + } + + // detect whether grouped expression with right parentheses as next token + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + // must be grouped expr + lexer.skip_token(); + + // create grouped expr + return ::std::unique_ptr(new AST::GroupedExpr( + ::std::move(first_expr), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else if (lexer.peek_token()->get_id() == COMMA) { + // tuple expr + ::std::vector< ::std::unique_ptr > exprs; + exprs.push_back(::std::move(first_expr)); + + // parse potential other tuple exprs + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break out if right paren + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // parse expr, which is now required + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse expr in tuple expr"); + // skip somewhere? + return NULL; + } + exprs.push_back(::std::move(expr)); + + t = lexer.peek_token(); + } + + // skip right paren + skip_token(RIGHT_PAREN); + + return ::std::unique_ptr(new AST::TupleExpr( + ::std::move(exprs), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); + } else { + // error + const_TokenPtr t = lexer.peek_token(); + error_at(t->get_locus(), + "unexpected token '%s' in grouped or tuple expression (parenthesised expression) - " + "expected ')' for grouped expr and ',' for tuple expr", + t->get_token_description()); + // skip somewhere? + return NULL; + } + } + + // Parses a type (will further disambiguate any type). + ::std::unique_ptr Parser::parse_type() { + /* rules for all types: + * NeverType: '!' + * SliceType: '[' Type ']' + * InferredType: '_' + * MacroInvocation: SimplePath '!' DelimTokenTree + * ParenthesisedType: '(' Type ')' + * ImplTraitType: 'impl' TypeParamBounds + * TypeParamBounds (not type) TypeParamBound ( '+' TypeParamBound )* '+'? + * TypeParamBound Lifetime | TraitBound + * ImplTraitTypeOneBound: 'impl' TraitBound + * TraitObjectType: 'dyn'? TypeParamBounds + * TraitObjectTypeOneBound: 'dyn'? TraitBound + * TraitBound '?'? ForLifetimes? TypePath | '(' '?'? ForLifetimes? TypePath ')' + * BareFunctionType: ForLifetimes? FunctionQualifiers 'fn' etc. + * ForLifetimes (not type) 'for' '<' LifetimeParams '>' + * FunctionQualifiers ( 'async' | 'const' )? 'unsafe'? ('extern' abi?)? + * QualifiedPathInType: '<' Type ( 'as' TypePath )? '>' ( '::' TypePathSegment )+ + * TypePath: '::'? TypePathSegment ( '::' TypePathSegment)* + * ArrayType: '[' Type ';' Expr ']' + * ReferenceType: '&' Lifetime? 'mut'? TypeNoBounds + * RawPointerType: '*' ( 'mut' | 'const' ) TypeNoBounds + * TupleType: '(' Type etc. - regular tuple stuff. Also regular tuple vs + * parenthesised precedence + * + * Disambiguate between macro and type path via type path being parsed, and then if '!' + * found, convert type path to simple path for macro. + * Usual disambiguation for tuple vs parenthesised. + * For ImplTraitType and TraitObjectType individual disambiguations, they seem more like + * "special cases", so probably just try to parse the more general ImplTraitType or + * TraitObjectType and return OneBound versions if they satisfy those criteria. */ + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: + // never type - can't be macro as no path beforehand + lexer.skip_token(); + return ::std::unique_ptr(new AST::NeverType(t->get_locus())); + case LEFT_SQUARE: + // slice type or array type - requires further disambiguation + return parse_slice_or_array_type(); + case LEFT_ANGLE: { + // qualified path in type + AST::QualifiedPathInType path = parse_qualified_path_in_type(); + if (path.is_error()) { + error_at(t->get_locus(), "failed to parse qualified path in type"); + return NULL; + } + return ::std::unique_ptr( + new AST::QualifiedPathInType(::std::move(path))); + } + case UNDERSCORE: + // inferred type + lexer.skip_token(); + return ::std::unique_ptr(new AST::InferredType(t->get_locus())); + case ASTERISK: + // raw pointer type + return parse_raw_pointer_type(); + case AMP: // does this also include AMP_AMP? + // reference type + return parse_reference_type(); + case LIFETIME: { + // probably a lifetime bound, so probably type param bounds in TraitObjectType + ::std::vector< ::std::unique_ptr > bounds + = parse_type_param_bounds(); + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), t->get_locus())); + } + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: { + // macro invocation or type path - requires further disambiguation. + /* for parsing path component of each rule, perhaps parse it as a typepath and + * attempt conversion to simplepath if a trailing '!' is found */ + /* Type path also includes TraitObjectTypeOneBound BUT if it starts with it, it is + * exactly the same as a TypePath syntactically, so this is a syntactical ambiguity. + * As such, the parser will parse it as a TypePath. + * This, however, does not prevent TraitObjectType from starting with a typepath. */ + + // parse path as type path + AST::TypePath path = parse_type_path(); + if (path.is_error()) { + error_at(t->get_locus(), "failed to parse path as first component of type"); + return NULL; + } + location_t locus = path.get_locus(); + + // branch on next token + t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: { + // macro invocation + // convert to simple path + AST::SimplePath macro_path = path.as_simple_path(); + if (macro_path.is_empty()) { + error_at(t->get_locus(), + "failed to parse simple path in macro invocation (for type)"); + return NULL; + } + + lexer.skip_token(); + + AST::DelimTokenTree tok_tree = parse_delim_token_tree(); + + return ::std::unique_ptr( + new AST::MacroInvocation(::std::move(macro_path), ::std::move(tok_tree), + ::std::vector(), locus)); + } + case PLUS: { + // type param bounds + ::std::vector< ::std::unique_ptr > bounds; + + // convert type path to trait bound + ::std::unique_ptr path_bound( + new AST::TraitBound(::std::move(path), locus, false, false)); + bounds.push_back(::std::move(path_bound)); + + // parse rest of bounds - FIXME: better way to find when to stop parsing + while (t->get_id() == PLUS) { + lexer.skip_token(); + + // parse bound if it exists - if not, assume end of sequence + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + break; + } + bounds.push_back(::std::move(bound)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), locus)); + } + default: + // assume that this is a type path and not an error + return ::std::unique_ptr(new AST::TypePath(::std::move(path))); + } + } + case LEFT_PAREN: + // tuple type or parenthesised type - requires further disambiguation (the usual) + // ok apparently can be a parenthesised TraitBound too, so could be + // TraitObjectTypeOneBound or TraitObjectType + return parse_paren_prefixed_type(); + case FOR: + // TraitObjectTypeOneBound or BareFunctionType + return parse_for_prefixed_type(); + case ASYNC: + case CONST: + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + // bare function type (with no for lifetimes) + return parse_bare_function_type(::std::vector()); + case IMPL: + lexer.skip_token(); + if (lexer.peek_token()->get_id() == LIFETIME) { + // cannot be one bound because lifetime prevents it from being traitbound + ::std::vector< ::std::unique_ptr > bounds + = parse_type_param_bounds(); + + return ::std::unique_ptr( + new AST::ImplTraitType(::std::move(bounds), t->get_locus())); + } else { + // should be trait bound, so parse trait bound + ::std::unique_ptr initial_bound = parse_trait_bound(); + if (initial_bound == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse ImplTraitType initial bound"); + return NULL; + } + + location_t locus = t->get_locus(); + + // short cut if next token isn't '+' + t = lexer.peek_token(); + if (t->get_id() != PLUS) { + // convert trait bound to value object + AST::TraitBound value_bound(*initial_bound); + + // DEBUG: removed as unique ptr, so should auto-delete + // delete initial_bound; + + return ::std::unique_ptr( + new AST::ImplTraitTypeOneBound(::std::move(value_bound), locus)); + } + + // parse additional type param bounds + ::std::vector< ::std::unique_ptr > bounds; + bounds.push_back(::std::move(initial_bound)); + while (t->get_id() == PLUS) { + lexer.skip_token(); + + // parse bound if it exists + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + // not an error as trailing plus may exist + break; + } + bounds.push_back(::std::move(bound)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr( + new AST::ImplTraitType(::std::move(bounds), locus)); + } + case DYN: + case QUESTION_MARK: { + // either TraitObjectType or TraitObjectTypeOneBound + bool has_dyn = false; + if (t->get_id() == DYN) { + lexer.skip_token(); + has_dyn = true; + } + + if (lexer.peek_token()->get_id() == LIFETIME) { + // cannot be one bound because lifetime prevents it from being traitbound + ::std::vector< ::std::unique_ptr > bounds + = parse_type_param_bounds(); + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), t->get_locus(), has_dyn)); + } else { + // should be trait bound, so parse trait bound + ::std::unique_ptr initial_bound = parse_trait_bound(); + if (initial_bound == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse TraitObjectType initial bound"); + return NULL; + } + + // short cut if next token isn't '+' + t = lexer.peek_token(); + if (t->get_id() != PLUS) { + // convert trait bound to value object + AST::TraitBound value_bound(*initial_bound); + + // DEBUG: removed as unique ptr, so should auto delete + // delete initial_bound; + + return ::std::unique_ptr( + new AST::TraitObjectTypeOneBound( + ::std::move(value_bound), t->get_locus(), has_dyn)); + } + + // parse additional type param bounds + ::std::vector< ::std::unique_ptr > bounds; + bounds.push_back(::std::move(initial_bound)); + while (t->get_id() == PLUS) { + lexer.skip_token(); + + // parse bound if it exists + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + // not an error as trailing plus may exist + break; + } + bounds.push_back(::std::move(bound)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), t->get_locus(), has_dyn)); + } + } + default: + error_at( + t->get_locus(), "unrecognised token '%s' in type", t->get_token_description()); + return NULL; + } + } + + /* Parses a type that has '(' as its first character. Returns a tuple type, parenthesised type, + * TraitObjectTypeOneBound, or TraitObjectType depending on following characters. */ + ::std::unique_ptr Parser::parse_paren_prefixed_type() { + /* NOTE: Syntactical ambiguity of a parenthesised trait bound is considered a trait bound, + * not a parenthesised type, so that it can still be used in type param bounds. */ + + /* NOTE: this implementation is really shit but I couldn't think of a better one. It requires + * essentially breaking polymorphism and downcasting via virtual method abuse, as it was + * copied from the rustc implementation (in which types are reified due to tagged union), + * after a more OOP attempt by me failed. */ + location_t left_delim_locus = lexer.peek_token()->get_locus(); + + // skip left delim + lexer.skip_token(); + // while next token isn't close delim, parse comma-separated types, saving whether trailing + // comma happens + const_TokenPtr t = lexer.peek_token(); + bool trailing_comma = true; + ::std::vector< ::std::unique_ptr > types; + + while (t->get_id() != RIGHT_PAREN) { + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + error_at(t->get_locus(), + "failed to parse type inside parentheses (probably tuple or parenthesised)"); + return NULL; + } + types.push_back(::std::move(type)); + + t = lexer.peek_token(); + if (t->get_id() != COMMA) { + trailing_comma = false; + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + // if only one type and no trailing comma, then not a tuple type + if (types.size() == 1 && !trailing_comma) { + // must be a TraitObjectType (with more than one bound) + if (lexer.peek_token()->get_id() == PLUS) { + // create type param bounds vector + ::std::vector< ::std::unique_ptr > bounds; + + // HACK: convert type to traitbound and add to bounds + AST::Type* released_ptr = types[0].release(); + AST::TraitBound* converted_bound = released_ptr->to_trait_bound(true); + delete released_ptr; + if (converted_bound == NULL) { + error_at(lexer.peek_token()->get_id(), + "failed to hackily converted parsed type to trait bound"); + return NULL; + } + bounds.push_back(::std::unique_ptr(converted_bound)); + // FIXME: possibly issues wrt memory here + + t = lexer.peek_token(); + while (t->get_id() == PLUS) { + lexer.skip_token(); + + // attempt to parse typeparambound + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + // not an error if null + break; + } + bounds.push_back(::std::move(bound)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), left_delim_locus)); + } else { + // release vector pointer + ::std::unique_ptr released_ptr(types[0].release()); + // HACK: attempt to convert to trait bound. if fails, parenthesised type + ::std::unique_ptr converted_bound( + released_ptr->to_trait_bound(true)); + if (converted_bound == NULL) { + // parenthesised type + return ::std::unique_ptr( + new AST::ParenthesisedType(::std::move(released_ptr), left_delim_locus)); + } else { + // trait object type (one bound) + + // DEBUG: removed as unique_ptr should auto-delete + // delete released_ptr; + + // get value semantics trait bound + AST::TraitBound value_bound(*converted_bound); + + // DEBUG: removed as unique ptr should auto-delete + // delete converted_bound; + + return ::std::unique_ptr( + new AST::TraitObjectTypeOneBound(value_bound, left_delim_locus)); + } + // FIXME: may be issues wrt memory here + } + } else { + return ::std::unique_ptr( + new AST::TupleType(::std::move(types), left_delim_locus)); + } + // TODO: ensure that this ensures that dynamic dispatch for traits is not lost somehow + } + + /* Parses a type that has 'for' as its first character. This means it has a "for lifetimes", so + * returns either a BareFunctionType, TraitObjectType, or TraitObjectTypeOneBound depending on + * following characters. */ + ::std::unique_ptr Parser::parse_for_prefixed_type() { + location_t for_locus = lexer.peek_token()->get_locus(); + // parse for lifetimes in type + ::std::vector for_lifetimes = parse_for_lifetimes(); + + // branch on next token - either function or a trait type + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case ASYNC: + case CONST: + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + return parse_bare_function_type(::std::move(for_lifetimes)); + case SCOPE_RESOLUTION: + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case DOLLAR_SIGN: { + // path, so trait type + + // parse type path to finish parsing trait bound + AST::TypePath path = parse_type_path(); + + t = lexer.peek_token(); + if (t->get_id() != PLUS) { + // must be one-bound trait type + // create trait bound value object + AST::TraitBound bound( + ::std::move(path), for_locus, false, false, ::std::move(for_lifetimes)); + + return ::std::unique_ptr( + new AST::TraitObjectTypeOneBound(::std::move(bound), for_locus)); + } + + // more than one bound trait type (or at least parsed as it - could be trailing '+') + // create trait bound pointer and bounds + ::std::unique_ptr initial_bound(new AST::TraitBound( + ::std::move(path), for_locus, false, false, ::std::move(for_lifetimes))); + ::std::vector< ::std::unique_ptr > bounds; + bounds.push_back(::std::move(initial_bound)); + + while (t->get_id() == PLUS) { + lexer.skip_token(); + + // parse type param bound if it exists + ::std::unique_ptr bound = parse_type_param_bound(); + if (bound == NULL) { + // not an error - e.g. trailing plus + return NULL; + } + bounds.push_back(::std::move(bound)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr( + new AST::TraitObjectType(::std::move(bounds), for_locus)); + } + default: + // error + error_at(t->get_locus(), + "unrecognised token '%s' in bare function type or trait object type or trait " + "object type one bound", + t->get_token_description()); + return NULL; + } + } + + // Parses a maybe named param used in bare function types. + AST::MaybeNamedParam Parser::parse_maybe_named_param() { + /* Basically guess that param is named if first token is identifier or underscore and + * second token is semicolon. This should probably have no exceptions. rustc uses + * backtracking to parse these, but at the time of writing gccrs has no backtracking + * capabilities. */ + const_TokenPtr current = lexer.peek_token(); + const_TokenPtr next = lexer.peek_token(1); + + Identifier name; + AST::MaybeNamedParam::ParamKind kind = AST::MaybeNamedParam::UNNAMED; + + if (current->get_id() == IDENTIFIER && next->get_id() == COLON) { + // named param + name = current->get_str(); + kind = AST::MaybeNamedParam::IDENTIFIER; + lexer.skip_token(1); + } else if (current->get_id() == UNDERSCORE && next->get_id() == COLON) { + // wildcard param + name = "_"; + kind = AST::MaybeNamedParam::WILDCARD; + lexer.skip_token(1); + } + + // parse type (required) + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse type in maybe named param"); + return AST::MaybeNamedParam::create_error(); + } + + return AST::MaybeNamedParam(::std::move(name), kind, ::std::move(type), current->get_locus()); + } + + /* Parses a bare function type (with the given for lifetimes for convenience - does not parse them + * itself). */ + ::std::unique_ptr Parser::parse_bare_function_type( + ::std::vector for_lifetimes) { + // TODO: pass in for lifetime location as param + location_t best_try_locus = lexer.peek_token()->get_locus(); + + AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); + + if (!skip_token(FN_TOK)) { + return NULL; + } + + if (!skip_token(LEFT_PAREN)) { + return NULL; + } + + // parse function params, if they exist + ::std::vector params; + bool is_variadic = false; + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + // handle ellipsis (only if next character is right paren) + if (t->get_id() == ELLIPSIS) { + if (lexer.peek_token(1)->get_id() == RIGHT_PAREN) { + lexer.skip_token(); + is_variadic = true; + break; + } else { + error_at(t->get_locus(), + "ellipsis (for variadic) can only go at end of bare function type"); + return NULL; + } + } + + // parse required param + AST::MaybeNamedParam param = parse_maybe_named_param(); + if (param.is_error()) { + error_at(t->get_locus(), "failed to parse maybe named param in bare function type"); + return NULL; + } + params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + // bare function return type, if exists + ::std::unique_ptr return_type = NULL; + if (lexer.peek_token()->get_id() == RETURN_TYPE) { + lexer.skip_token(); + + // parse required TypeNoBounds + return_type = parse_type_no_bounds(); + if (return_type == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse return type (type no bounds) in bare function type"); + return NULL; + } + } + + return ::std::unique_ptr( + new AST::BareFunctionType(::std::move(for_lifetimes), ::std::move(qualifiers), + ::std::move(params), is_variadic, ::std::move(return_type), best_try_locus)); + } + + // Parses a reference type (mutable or immutable, with given lifetime). + ::std::unique_ptr Parser::parse_reference_type() { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(AMP); + + // parse optional lifetime + AST::Lifetime lifetime = AST::Lifetime::error(); + if (lexer.peek_token()->get_id() == LIFETIME) { + lifetime = parse_lifetime(); + if (lifetime.is_error()) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse lifetime in reference type"); + return NULL; + } + } + + bool is_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + lexer.skip_token(); + is_mut = true; + } + + // parse type no bounds, which is required + ::std::unique_ptr type = parse_type_no_bounds(); + if (type == NULL) { + error_at( + lexer.peek_token()->get_id(), "failed to parse referenced type in reference type"); + return NULL; + } + + return ::std::unique_ptr( + new AST::ReferenceType(is_mut, ::std::move(type), locus, ::std::move(lifetime))); + } + + // Parses a raw (unsafe) pointer type. + ::std::unique_ptr Parser::parse_raw_pointer_type() { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(ASTERISK); + + AST::RawPointerType::PointerType kind = AST::RawPointerType::CONST; + + // branch on next token for pointer kind info + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case MUT: + kind = AST::RawPointerType::MUT; + lexer.skip_token(); + break; + case CONST: + kind = AST::RawPointerType::CONST; + lexer.skip_token(); + break; + default: + error_at(t->get_locus(), "unrecognised token '%s' in raw pointer type", + t->get_token_description()); + return NULL; + } + + // parse type no bounds (required) + ::std::unique_ptr type = parse_type_no_bounds(); + if (type == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse pointed type of raw pointer type"); + return NULL; + } + + return ::std::unique_ptr( + new AST::RawPointerType(kind, ::std::move(type), locus)); + } + + // Parses a slice or array type, depending on following arguments (as lookahead is not possible). + ::std::unique_ptr Parser::parse_slice_or_array_type() { + location_t locus = lexer.peek_token()->get_locus(); + skip_token(LEFT_SQUARE); + + // parse inner type (required) + ::std::unique_ptr inner_type = parse_type(); + if (inner_type == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse inner type in slice or array type"); + return NULL; + } + + // branch on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case RIGHT_SQUARE: + // slice type + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::SliceType(::std::move(inner_type), locus)); + case SEMICOLON: { + // array type + lexer.skip_token(); + + // parse required array size expression + ::std::unique_ptr size = parse_expr(); + if (size == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse size expression in array type"); + return NULL; + } + + if (!skip_token(RIGHT_SQUARE)) { + return NULL; + } + + return ::std::unique_ptr( + new AST::ArrayType(::std::move(inner_type), ::std::move(size), locus)); + } + default: + // error + error_at(t->get_locus(), + "unrecognised token '%s' in slice or array type after inner type", + t->get_token_description()); + return NULL; + } + } + + // Parses a type, taking into account type boundary disambiguation. + ::std::unique_ptr Parser::parse_type_no_bounds() { + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: + // never type - can't be macro as no path beforehand + lexer.skip_token(); + return ::std::unique_ptr(new AST::NeverType(t->get_locus())); + case LEFT_SQUARE: + // slice type or array type - requires further disambiguation + return parse_slice_or_array_type(); + case LEFT_ANGLE: { + // qualified path in type + AST::QualifiedPathInType path = parse_qualified_path_in_type(); + if (path.is_error()) { + error_at(t->get_locus(), "failed to parse qualified path in type"); + return NULL; + } + return ::std::unique_ptr( + new AST::QualifiedPathInType(::std::move(path))); + } + case UNDERSCORE: + // inferred type + lexer.skip_token(); + return ::std::unique_ptr(new AST::InferredType(t->get_locus())); + case ASTERISK: + // raw pointer type + return parse_raw_pointer_type(); + case AMP: // does this also include AMP_AMP? + // reference type + return parse_reference_type(); + case LIFETIME: { + // probably a lifetime bound, so probably type param bounds in TraitObjectType + // this is not allowed, but detection here for error message + error_at(t->get_locus(), "lifetime bounds (i.e. in type param bounds, in " + "TraitObjectType) are not allowed as TypeNoBounds"); + return NULL; + } + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: { + // macro invocation or type path - requires further disambiguation. + /* for parsing path component of each rule, perhaps parse it as a typepath and + * attempt conversion to simplepath if a trailing '!' is found */ + /* Type path also includes TraitObjectTypeOneBound BUT if it starts with it, it is + * exactly the same as a TypePath syntactically, so this is a syntactical ambiguity. + * As such, the parser will parse it as a TypePath. + * This, however, does not prevent TraitObjectType from starting with a typepath. */ + + // parse path as type path + AST::TypePath path = parse_type_path(); + if (path.is_error()) { + error_at( + t->get_locus(), "failed to parse path as first component of type no bounds"); + return NULL; + } + location_t locus = path.get_locus(); + + // branch on next token + t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: { + // macro invocation + // convert to simple path + AST::SimplePath macro_path = path.as_simple_path(); + if (macro_path.is_empty()) { + error_at(t->get_locus(), + "failed to parse simple path in macro invocation (for type)"); + return NULL; + } + + lexer.skip_token(); + + AST::DelimTokenTree tok_tree = parse_delim_token_tree(); + + return ::std::unique_ptr( + new AST::MacroInvocation(::std::move(macro_path), ::std::move(tok_tree), + ::std::vector(), locus)); + } + case PLUS: { + // type param bounds - not allowed, here for error message + error_at(t->get_locus(), + "type param bounds (in TraitObjectType) are not allowed as TypeNoBounds"); + return NULL; + } + default: + // assume that this is a type path and not an error + return ::std::unique_ptr(new AST::TypePath(::std::move(path))); + } + } + case LEFT_PAREN: + // tuple type or parenthesised type - requires further disambiguation (the usual) + // ok apparently can be a parenthesised TraitBound too, so could be + // TraitObjectTypeOneBound + return parse_paren_prefixed_type_no_bounds(); + case FOR: + case ASYNC: + case CONST: + case UNSAFE: + case EXTERN_TOK: + case FN_TOK: + // bare function type (with no for lifetimes) + return parse_bare_function_type(::std::vector()); + case IMPL: + lexer.skip_token(); + if (lexer.peek_token()->get_id() == LIFETIME) { + // cannot be one bound because lifetime prevents it from being traitbound + // not allowed as type no bounds, only here for error message + error_at(lexer.peek_token()->get_locus(), + "lifetime (probably lifetime bound, in type param bounds, in ImplTraitType) is " + "not allowed in TypeNoBounds"); + return NULL; + } else { + // should be trait bound, so parse trait bound + ::std::unique_ptr initial_bound = parse_trait_bound(); + if (initial_bound == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse ImplTraitTypeOneBound bound"); + return NULL; + } + + location_t locus = t->get_locus(); + + // ensure not a trait with multiple bounds + t = lexer.peek_token(); + if (t->get_id() == PLUS) { + error_at(t->get_locus(), "plus after trait bound means an ImplTraitType, " + "which is not allowed as a TypeNoBounds"); + return NULL; + } + + // convert trait bound to value object + AST::TraitBound value_bound(*initial_bound); + + // DEBUG: removed as unique ptr so should auto-delete + // delete initial_bound; + + return ::std::unique_ptr( + new AST::ImplTraitTypeOneBound(::std::move(value_bound), locus)); + } + case DYN: + case QUESTION_MARK: { + // either TraitObjectTypeOneBound + bool has_dyn = false; + if (t->get_id() == DYN) { + lexer.skip_token(); + has_dyn = true; + } + + if (lexer.peek_token()->get_id() == LIFETIME) { + // means that cannot be TraitObjectTypeOneBound - so here for error message + error_at(lexer.peek_token()->get_locus(), + "lifetime as bound in TraitObjectTypeOneBound " + "is not allowed, so cannot be TypeNoBounds"); + return NULL; + } + + // should be trait bound, so parse trait bound + ::std::unique_ptr initial_bound = parse_trait_bound(); + if (initial_bound == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse TraitObjectTypeOneBound initial bound"); + return NULL; + } + + location_t locus = t->get_locus(); + + // detect error with plus as next token + t = lexer.peek_token(); + if (t->get_id() == PLUS) { + error_at(t->get_locus(), "plus after trait bound means a TraitObjectType, " + "which is not allowed as a TypeNoBounds"); + return NULL; + } + + // convert trait bound to value object + AST::TraitBound value_bound(*initial_bound); + + // DEBUG: removed as unique ptr so should auto delete + // delete initial_bound; + + return ::std::unique_ptr( + new AST::TraitObjectTypeOneBound(::std::move(value_bound), locus, has_dyn)); + } + default: + error_at(t->get_locus(), "unrecognised token '%s' in type no bounds", + t->get_token_description()); + return NULL; + } + } + + // Parses a type no bounds beginning with '('. + ::std::unique_ptr Parser::parse_paren_prefixed_type_no_bounds() { + /* NOTE: this could probably be parsed without the HACK solution of parse_paren_prefixed_type, + * but I was lazy. So FIXME for future.*/ + + /* NOTE: again, syntactical ambiguity of a parenthesised trait bound is considered a trait + * bound, not a parenthesised type, so that it can still be used in type param bounds. */ + + location_t left_paren_locus = lexer.peek_token()->get_locus(); + + // skip left delim + lexer.skip_token(); + // while next token isn't close delim, parse comma-separated types, saving whether trailing + // comma happens + const_TokenPtr t = lexer.peek_token(); + bool trailing_comma = true; + ::std::vector< ::std::unique_ptr > types; + + while (t->get_id() != RIGHT_PAREN) { + ::std::unique_ptr type = parse_type(); + if (type == NULL) { + error_at(t->get_locus(), + "failed to parse type inside parentheses (probably tuple or parenthesised)"); + return NULL; + } + types.push_back(::std::move(type)); + + t = lexer.peek_token(); + if (t->get_id() != COMMA) { + trailing_comma = false; + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + // if only one type and no trailing comma, then not a tuple type + if (types.size() == 1 && !trailing_comma) { + // must be a TraitObjectType (with more than one bound) + if (lexer.peek_token()->get_id() == PLUS) { + // error - this is not allowed for type no bounds + error_at(lexer.peek_token()->get_id(), "plus (implying TraitObjectType as type param " + "bounds) is not allowed in type no bounds"); + return NULL; + } else { + // release vector pointer + ::std::unique_ptr released_ptr(types[0].release()); + // HACK: attempt to convert to trait bound. if fails, parenthesised type + ::std::unique_ptr converted_bound( + released_ptr->to_trait_bound(true)); + if (converted_bound == NULL) { + // parenthesised type + return ::std::unique_ptr( + new AST::ParenthesisedType(::std::move(released_ptr), left_paren_locus)); + } else { + // trait object type (one bound) + + // DEBUG: removed as unique_ptr should auto-delete + // delete released_ptr; + + // get value semantics trait bound + AST::TraitBound value_bound(*converted_bound); + + // DEBUG: removed as unique_ptr should auto-delete + // delete converted_bound; + + return ::std::unique_ptr( + new AST::TraitObjectTypeOneBound(value_bound, left_paren_locus)); + } + // FIXME: memory safety issues here + } + } else { + return ::std::unique_ptr( + new AST::TupleType(::std::move(types), left_paren_locus)); + } + // TODO: ensure that this ensures that dynamic dispatch for traits is not lost somehow + } + + /* Parses a literal pattern or range pattern. Assumes that literals passed in are valid range + * pattern bounds. Do not pass in paths in expressions, for instance. */ + ::std::unique_ptr Parser::parse_literal_or_range_pattern() { + const_TokenPtr range_lower = lexer.peek_token(); + AST::Literal::LitType type = AST::Literal::STRING; + bool has_minus = false; + + // get lit type + switch (range_lower->get_id()) { + case CHAR_LITERAL: + type = AST::Literal::CHAR; + lexer.skip_token(); + break; + case BYTE_CHAR_LITERAL: + type = AST::Literal::BYTE; + lexer.skip_token(); + break; + case INT_LITERAL: + type = AST::Literal::INT; + lexer.skip_token(); + break; + case FLOAT_LITERAL: + type = AST::Literal::FLOAT; + lexer.skip_token(); + break; + case MINUS: + // branch on next token + range_lower = lexer.peek_token(1); + switch (range_lower->get_id()) { + case INT_LITERAL: + type = AST::Literal::INT; + has_minus = true; + lexer.skip_token(1); + break; + case FLOAT_LITERAL: + type = AST::Literal::FLOAT; + has_minus = true; + lexer.skip_token(1); + break; + default: + error_at(range_lower->get_locus(), + "token type '%s' cannot be parsed as range pattern bound or literal after " + "minus " + "symbol", + range_lower->get_token_description()); + return NULL; + } + break; + default: + error_at(range_lower->get_locus(), + "token type '%s' cannot be parsed as range pattern bound", + range_lower->get_token_description()); + return NULL; + } + + const_TokenPtr next = lexer.peek_token(); + if (next->get_id() == DOT_DOT_EQ || next->get_id() == ELLIPSIS) { + // range pattern + lexer.skip_token(); + ::std::unique_ptr lower(new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), type), range_lower->get_locus(), has_minus)); + + ::std::unique_ptr upper = parse_range_pattern_bound(); + if (upper == NULL) { + error_at(next->get_locus(), "failed to parse range pattern bound in range pattern"); + return NULL; + } + + return ::std::unique_ptr(new AST::RangePattern( + ::std::move(lower), ::std::move(upper), range_lower->get_locus())); + } else { + // literal pattern + return ::std::unique_ptr(new AST::LiteralPattern( + range_lower->get_str(), type, range_lower->get_locus(), has_minus)); + } + } + + // Parses a range pattern bound (value only). + ::std::unique_ptr Parser::parse_range_pattern_bound() { + const_TokenPtr range_lower = lexer.peek_token(); + location_t range_lower_locus = range_lower->get_locus(); + + // get lit type + switch (range_lower->get_id()) { + case CHAR_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::CHAR), range_lower_locus)); + case BYTE_CHAR_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::BYTE), range_lower_locus)); + case INT_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::INT), range_lower_locus)); + case FLOAT_LITERAL: + lexer.skip_token(); + fprintf(stderr, "warning: used deprecated float range pattern bound"); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::FLOAT), range_lower_locus)); + case MINUS: + // branch on next token + range_lower = lexer.peek_token(1); + switch (range_lower->get_id()) { + case INT_LITERAL: + lexer.skip_token(1); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::INT), + range_lower_locus, true)); + case FLOAT_LITERAL: + lexer.skip_token(1); + fprintf(stderr, "warning: used deprecated float range pattern bound"); + return ::std::unique_ptr( + new AST::RangePatternBoundLiteral( + AST::Literal(range_lower->get_str(), AST::Literal::FLOAT), + range_lower_locus, true)); + default: + error_at(range_lower->get_locus(), + "token type '%s' cannot be parsed as range pattern bound after minus " + "symbol", + range_lower->get_token_description()); + return NULL; + } + case IDENTIFIER: + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case SCOPE_RESOLUTION: + case DOLLAR_SIGN: { + // path in expression + AST::PathInExpression path = parse_path_in_expression(); + if (path.is_error()) { + error_at(range_lower->get_locus(), + "failed to parse path in expression range pattern bound"); + return NULL; + } + return ::std::unique_ptr( + new AST::RangePatternBoundPath(::std::move(path))); + } + case LEFT_ANGLE: { + // qualified path in expression + AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(); + if (path.is_error()) { + error_at(range_lower->get_locus(), + "failed to parse qualified path in expression range pattern bound"); + return NULL; + } + return ::std::unique_ptr( + new AST::RangePatternBoundQualPath(::std::move(path))); + } + default: + error_at(range_lower->get_locus(), + "token type '%s' cannot be parsed as range pattern bound", + range_lower->get_token_description()); + return NULL; + } + } + + // Parses a pattern (will further disambiguate any pattern). + ::std::unique_ptr Parser::parse_pattern() { + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case TRUE_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::LiteralPattern("true", AST::Literal::BOOL, t->get_locus())); + case FALSE_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::LiteralPattern("false", AST::Literal::BOOL, t->get_locus())); + case CHAR_LITERAL: + case BYTE_CHAR_LITERAL: + case INT_LITERAL: + case FLOAT_LITERAL: + return parse_literal_or_range_pattern(); + case STRING_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::LiteralPattern(t->get_str(), AST::Literal::STRING, t->get_locus())); + case BYTE_STRING_LITERAL: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::LiteralPattern(t->get_str(), AST::Literal::BYTE_STRING, t->get_locus())); + // raw string and raw byte string literals too if they are readded to lexer + case MINUS: + if (lexer.peek_token(1)->get_id() == INT_LITERAL) { + return parse_literal_or_range_pattern(); + } else if (lexer.peek_token(1)->get_id() == FLOAT_LITERAL) { + return parse_literal_or_range_pattern(); + } else { + error_at(t->get_locus(), + "unexpected token '-' in pattern - did you forget an integer literal?"); + return NULL; + } + case UNDERSCORE: + lexer.skip_token(); + return ::std::unique_ptr( + new AST::WildcardPattern(t->get_locus())); + case REF: + case MUT: + return parse_identifier_pattern(); + case IDENTIFIER: + // if identifier with no scope resolution afterwards, identifier pattern. + // if scope resolution afterwards, path pattern (or range pattern or struct pattern or + // tuple struct pattern) or macro invocation + return parse_ident_leading_pattern(); + case AMP: + case LOGICAL_AND: + // reference pattern + return parse_reference_pattern(); + case LEFT_PAREN: + // tuple pattern or grouped pattern + return parse_grouped_or_tuple_pattern(); + case LEFT_SQUARE: + // slice pattern + return parse_slice_pattern(); + case LEFT_ANGLE: { + // qualified path in expression or qualified range pattern bound + AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(); + + if (lexer.peek_token()->get_id() == DOT_DOT_EQ + || lexer.peek_token()->get_id() == ELLIPSIS) { + // qualified range pattern bound, so parse rest of range pattern + bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; + lexer.skip_token(); + + ::std::unique_ptr lower_bound( + new AST::RangePatternBoundQualPath(::std::move(path))); + ::std::unique_ptr upper_bound + = parse_range_pattern_bound(); + + return ::std::unique_ptr( + new AST::RangePattern(::std::move(lower_bound), ::std::move(upper_bound), + t->get_locus(), has_ellipsis_syntax)); + } else { + // just qualified path in expression + return ::std::unique_ptr( + new AST::QualifiedPathInExpression(::std::move(path))); + } + } + case SUPER: + case SELF: + case SELF_ALIAS: + case CRATE: + case SCOPE_RESOLUTION: + case DOLLAR_SIGN: { + // path in expression or range pattern bound + AST::PathInExpression path = parse_path_in_expression(); + + const_TokenPtr next = lexer.peek_token(); + switch (next->get_id()) { + case DOT_DOT_EQ: + case ELLIPSIS: { + // qualified range pattern bound, so parse rest of range pattern + bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; + lexer.skip_token(); + + ::std::unique_ptr lower_bound( + new AST::RangePatternBoundPath(::std::move(path))); + ::std::unique_ptr upper_bound + = parse_range_pattern_bound(); + + return ::std::unique_ptr(new AST::RangePattern( + ::std::move(lower_bound), ::std::move(upper_bound), has_ellipsis_syntax)); + } + case EXCLAM: + return parse_macro_invocation_partial( + ::std::move(path), ::std::vector()); + case LEFT_PAREN: { + // tuple struct + lexer.skip_token(); + + // parse items + ::std::unique_ptr items = parse_tuple_struct_items(); + if (items == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse tuple struct items"); + return NULL; + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + return ::std::unique_ptr( + new AST::TupleStructPattern(::std::move(path), ::std::move(items))); + } + case LEFT_CURLY: { + // struct + lexer.skip_token(); + + // parse elements (optional) + AST::StructPatternElements elems = parse_struct_pattern_elems(); + + if (!skip_token(RIGHT_CURLY)) { + return NULL; + } + + return ::std::unique_ptr( + new AST::StructPattern(::std::move(path), ::std::move(elems))); + } + default: + // assume path in expression + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + } + default: + error_at( + t->get_locus(), "unexpected token '%s' in pattern", t->get_token_description()); + return NULL; + } + } + + // Parses a single or double reference pattern. + ::std::unique_ptr Parser::parse_reference_pattern() { + // parse double or single ref + bool is_double_ref = false; + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case AMP: + // still false + lexer.skip_token(); + break; + case LOGICAL_AND: + is_double_ref = true; + lexer.skip_token(); + break; + default: + error_at(t->get_locus(), "unexpected token '%s' in reference pattern", + t->get_token_description()); + return NULL; + } + + // parse mut (if it exists) + bool is_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + is_mut = true; + lexer.skip_token(); + } + + // parse pattern to get reference of (required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in reference pattern"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ReferencePattern(::std::move(pattern), is_mut, is_double_ref, t->get_locus())); + } + + /* Parses a grouped pattern or tuple pattern. Prefers grouped over tuple if only a single element + * with no commas. */ + ::std::unique_ptr Parser::parse_grouped_or_tuple_pattern() { + location_t paren_locus = lexer.peek_token()->get_locus(); + skip_token(LEFT_PAREN); + + // detect '..' token (ranged with no lower range) + if (lexer.peek_token()->get_id() == DOT_DOT) { + lexer.skip_token(); + + // parse new patterns while next token is a comma + ::std::vector< ::std::unique_ptr > patterns; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break if next token is ')' + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // parse pattern, which is required + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse pattern inside ranged tuple pattern"); + // skip somewhere? + return NULL; + } + patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + // skip somewhere? + return NULL; + } + + // create ranged tuple pattern items with only upper items + ::std::unique_ptr items(new AST::TuplePatternItemsRanged( + ::std::vector< ::std::unique_ptr >(), ::std::move(patterns))); + return ::std::unique_ptr( + new AST::TuplePattern(::std::move(items), paren_locus)); + } + + // parse initial pattern (required) + ::std::unique_ptr initial_pattern = parse_pattern(); + if (initial_pattern == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse pattern in grouped or tuple pattern"); + return NULL; + } + + // branch on whether next token is a comma or not + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case RIGHT_PAREN: + // grouped pattern + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::GroupedPattern(::std::move(initial_pattern), paren_locus)); + case COMMA: { + // tuple pattern + lexer.skip_token(); + + // create vector of patterns + ::std::vector< ::std::unique_ptr > patterns; + patterns.push_back(::std::move(initial_pattern)); + + t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN && t->get_id() != DOT_DOT) { + // parse pattern (required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(t->get_locus(), "failed to parse pattern in tuple pattern"); + return NULL; + } + patterns.push_back(::std::move(pattern)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + t = lexer.peek_token(); + if (t->get_id() == RIGHT_PAREN) { + // non-ranged tuple pattern + lexer.skip_token(); + + ::std::unique_ptr items( + new AST::TuplePatternItemsMultiple(::std::move(patterns))); + return ::std::unique_ptr( + new AST::TuplePattern(::std::move(items), paren_locus)); + } else if (t->get_id() == DOT_DOT) { + // ranged tuple pattern + lexer.skip_token(); + + // parse upper patterns + ::std::vector< ::std::unique_ptr > upper_patterns; + t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break if end + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // parse pattern (required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse pattern in tuple pattern"); + return NULL; + } + upper_patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + ::std::unique_ptr items( + new AST::TuplePatternItemsRanged( + ::std::move(patterns), ::std::move(upper_patterns))); + return ::std::unique_ptr( + new AST::TuplePattern(::std::move(items), paren_locus)); + } else { + // some kind of error + error_at(t->get_locus(), + "failed to parse tuple pattern (probably) or maybe grouped pattern"); + return NULL; + } + } + default: + // error + error_at(t->get_locus(), + "unrecognised token '%s' in grouped or tuple pattern after first pattern", + t->get_token_description()); + return NULL; + } + } + + // Parses a slice pattern that can match arrays or slices. Parses the square brackets too. + ::std::unique_ptr Parser::parse_slice_pattern() { + location_t square_locus = lexer.peek_token()->get_locus(); + skip_token(LEFT_SQUARE); + + // parse initial pattern (required) + ::std::unique_ptr initial_pattern = parse_pattern(); + if (initial_pattern == NULL) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse initial pattern in slice pattern"); + return NULL; + } + + ::std::vector< ::std::unique_ptr > patterns; + patterns.push_back(::std::move(initial_pattern)); + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break if end bracket + if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { + break; + } + + // parse pattern (required) + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in slice pattern"); + return NULL; + } + patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_SQUARE)) { + return NULL; + } + + return ::std::unique_ptr( + new AST::SlicePattern(::std::move(patterns), square_locus)); + } + + // Parses an identifier pattern (pattern that binds a value matched to a variable). + ::std::unique_ptr Parser::parse_identifier_pattern() { + location_t locus = lexer.peek_token()->get_locus(); + + bool has_ref = false; + if (lexer.peek_token()->get_id() == REF) { + has_ref = true; + lexer.skip_token(); + + // DEBUG + fprintf(stderr, "parsed ref in identifier pattern\n"); + } + + bool has_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + has_mut = true; + lexer.skip_token(); + } + + // parse identifier (required) + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + // skip somewhere? + return NULL; + } + Identifier ident = ident_tok->get_str(); + + // DEBUG + fprintf(stderr, "parsed identifier in identifier pattern\n"); + + // parse optional pattern binding thing + ::std::unique_ptr bind_pattern = NULL; + if (lexer.peek_token()->get_id() == PATTERN_BIND) { + lexer.skip_token(); + + // parse required pattern to bind + bind_pattern = parse_pattern(); + if (bind_pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse pattern to bind in identifier pattern\n"); + return NULL; + } + } + + // DEBUG + fprintf(stderr, "about to return identifier pattern\n"); + + return ::std::unique_ptr(new AST::IdentifierPattern( + ::std::move(ident), locus, has_ref, has_mut, ::std::move(bind_pattern))); + } + + /* Parses a pattern that opens with an identifier. This includes identifier patterns, path + * patterns (and derivatives such as struct patterns, tuple struct patterns, and macro + * invocations), and ranges. */ + ::std::unique_ptr Parser::parse_ident_leading_pattern() { + // ensure first token is actually identifier + const_TokenPtr initial_tok = lexer.peek_token(); + if (initial_tok->get_id() != IDENTIFIER) { + return NULL; + } + + // save initial identifier as it may be useful (but don't skip) + ::std::string initial_ident = initial_tok->get_str(); + + // parse next tokens as a PathInExpression + AST::PathInExpression path = parse_path_in_expression(); + + // branch on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: + return parse_macro_invocation_partial( + ::std::move(path), ::std::vector()); + case LEFT_PAREN: { + // tuple struct + lexer.skip_token(); + + // DEBUG + fprintf(stderr, "parsing tuple struct pattern\n"); + + // parse items + ::std::unique_ptr items = parse_tuple_struct_items(); + if (items == NULL) { + error_at(lexer.peek_token()->get_locus(), "failed to parse tuple struct items"); + return NULL; + } + + // DEBUG + fprintf(stderr, "successfully parsed tuple struct items\n"); + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + // DEBUG + fprintf(stderr, "successfully parsed tuple struct pattern\n"); + + return ::std::unique_ptr( + new AST::TupleStructPattern(::std::move(path), ::std::move(items))); + } + case LEFT_CURLY: { + // struct + lexer.skip_token(); + + // parse elements (optional) + AST::StructPatternElements elems = parse_struct_pattern_elems(); + + if (!skip_token(RIGHT_CURLY)) { + return NULL; + } + + // DEBUG + fprintf(stderr, "successfully parsed struct pattern\n"); + + return ::std::unique_ptr( + new AST::StructPattern(::std::move(path), ::std::move(elems))); + } + case DOT_DOT_EQ: + case ELLIPSIS: { + // range + bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; + + lexer.skip_token(); + + ::std::unique_ptr lower_bound( + new AST::RangePatternBoundPath(::std::move(path))); + ::std::unique_ptr upper_bound = parse_range_pattern_bound(); + + return ::std::unique_ptr(new AST::RangePattern( + ::std::move(lower_bound), ::std::move(upper_bound), has_ellipsis_syntax)); + } + case PATTERN_BIND: { + // only allow on single-segment paths + if (path.is_single_segment()) { + // identifier with pattern bind + lexer.skip_token(); + + ::std::unique_ptr bind_pattern = parse_pattern(); + if (bind_pattern == NULL) { + error_at( + t->get_locus(), "failed to parse pattern to bind to identifier pattern"); + return NULL; + } + return ::std::unique_ptr( + new AST::IdentifierPattern(::std::move(initial_ident), initial_tok->get_locus(), + false, false, ::std::move(bind_pattern))); + } + error_at(t->get_locus(), "failed to parse pattern bind to a path, not an identifier"); + return NULL; + } + default: + // assume identifier if single segment + if (path.is_single_segment()) { + return ::std::unique_ptr(new AST::IdentifierPattern( + ::std::move(initial_ident), initial_tok->get_locus())); + } + // return path otherwise + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + } + + // Parses tuple struct items if they exist. Does not parse parentheses. + ::std::unique_ptr Parser::parse_tuple_struct_items() { + ::std::vector< ::std::unique_ptr > lower_patterns; + + // DEBUG + fprintf(stderr, "started parsing tuple struct items\n"); + + // check for '..' at front + if (lexer.peek_token()->get_id() == DOT_DOT) { + // only parse upper patterns + lexer.skip_token(); + + // DEBUG + fprintf(stderr, "'..' at front in tuple struct items detected\n"); + + ::std::vector< ::std::unique_ptr > upper_patterns; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break if right paren + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // parse pattern, which is now required + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse pattern in tuple struct items"); + return NULL; + } + upper_patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + // DEBUG + fprintf(stderr, "finished parsing tuple struct items ranged (upper/none only)\n"); + + return ::std::unique_ptr(new AST::TupleStructItemsRange( + ::std::move(lower_patterns), ::std::move(upper_patterns))); + } + + // has at least some lower patterns + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN && t->get_id() != DOT_DOT) { + + // DEBUG + fprintf(stderr, "about to parse pattern in tuple struct items\n"); + + // parse pattern, which is required + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(t->get_locus(), "failed to parse pattern in tuple struct items"); + return NULL; + } + lower_patterns.push_back(::std::move(pattern)); + + // DEBUG + fprintf(stderr, "successfully parsed pattern in tuple struct items\n"); + + if (lexer.peek_token()->get_id() != COMMA) { + // DEBUG + fprintf(stderr, "broke out of parsing patterns in tuple struct items as no comma \n"); + + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // branch on next token + t = lexer.peek_token(); + switch (t->get_id()) { + case RIGHT_PAREN: + return ::std::unique_ptr( + new AST::TupleStructItemsNoRange(::std::move(lower_patterns))); + case DOT_DOT: { + // has an upper range that must be parsed separately + lexer.skip_token(); + + ::std::vector< ::std::unique_ptr > upper_patterns; + + t = lexer.peek_token(); + while (t->get_id() == COMMA) { + lexer.skip_token(); + + // break if next token is right paren + if (lexer.peek_token()->get_id() == RIGHT_PAREN) { + break; + } + + // parse pattern, which is required + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse pattern in tuple struct items"); + return NULL; + } + upper_patterns.push_back(::std::move(pattern)); + + t = lexer.peek_token(); + } + + return ::std::unique_ptr(new AST::TupleStructItemsRange( + ::std::move(lower_patterns), ::std::move(upper_patterns))); + } + default: + // error + error_at(t->get_locus(), "unexpected token '%s' in tuple struct items", + t->get_token_description()); + return NULL; + } + } + + // Parses struct pattern elements if they exist. + AST::StructPatternElements Parser::parse_struct_pattern_elems() { + ::std::vector< ::std::unique_ptr > fields; + + // try parsing struct pattern fields + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_CURLY && t->get_id() != DOT_DOT) { + ::std::unique_ptr field = parse_struct_pattern_field(); + if (field == NULL) { + // TODO: should this be an error? + // assuming that this means that it is a struct pattern etc instead + + // DEBUG + fprintf(stderr, "failed to parse struct pattern field - breaking from loop\n"); + + break; + } + + fields.push_back(::std::move(field)); + + // DEBUG + fprintf(stderr, "successfully pushed back a struct pattern field\n"); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // FIXME: this method of parsing prevents parsing any outer attributes on the .. + // also there seems to be no distinction between having etc and not having etc. + if (lexer.peek_token()->get_id() == DOT_DOT) { + lexer.skip_token(); + + // as no outer attributes + AST::StructPatternEtc etc = AST::StructPatternEtc::create_empty(); + + return AST::StructPatternElements(::std::move(fields), ::std::move(etc)); + } + + return AST::StructPatternElements(::std::move(fields)); + } + + // Parses a struct pattern field (tuple index/pattern, identifier/pattern, or identifier). + ::std::unique_ptr Parser::parse_struct_pattern_field() { + // parse outer attributes (if they exist) + ::std::vector outer_attrs = parse_outer_attributes(); + + // branch based on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case INT_LITERAL: { + // tuple index + ::std::string index_str = t->get_str(); + int index = atoi(index_str.c_str()); + + if (!skip_token(COLON)) { + return NULL; + } + + // parse required pattern + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at( + t->get_locus(), "failed to parse pattern in tuple index struct pattern field"); + return NULL; + } + + return ::std::unique_ptr( + new AST::StructPatternFieldTuplePat( + index, ::std::move(pattern), ::std::move(outer_attrs), t->get_locus())); + } + case IDENTIFIER: + // identifier-pattern OR only identifier + // branch on next token + switch (lexer.peek_token(1)->get_id()) { + case COLON: { + // identifier-pattern + Identifier ident = t->get_str(); + lexer.skip_token(); + + skip_token(COLON); + + // parse required pattern + ::std::unique_ptr pattern = parse_pattern(); + if (pattern == NULL) { + error_at( + t->get_locus(), "failed to parse pattern in struct pattern field"); + return NULL; + } + + return ::std::unique_ptr( + new AST::StructPatternFieldIdentPat(::std::move(ident), + ::std::move(pattern), ::std::move(outer_attrs), t->get_locus())); + } + case COMMA: + case RIGHT_CURLY: { + // identifier only + Identifier ident = t->get_str(); + lexer.skip_token(); + + return ::std::unique_ptr( + new AST::StructPatternFieldIdent(::std::move(ident), false, false, + ::std::move(outer_attrs), t->get_locus())); + } + default: + // error + error_at(t->get_locus(), "unrecognised token '%s' in struct pattern field", + t->get_token_description()); + return NULL; + } + case REF: + case MUT: { + // only identifier + bool has_ref = false; + if (t->get_id() == REF) { + has_ref = true; + lexer.skip_token(); + } + + bool has_mut = false; + if (lexer.peek_token()->get_id() == MUT) { + has_mut = true; + lexer.skip_token(); + } + + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + if (ident_tok == NULL) { + return NULL; + } + Identifier ident = ident_tok->get_str(); + + return ::std::unique_ptr( + new AST::StructPatternFieldIdent( + ::std::move(ident), has_ref, has_mut, ::std::move(outer_attrs), t->get_locus())); + } + default: + // not necessarily an error + return NULL; + } + } + + /* Parses a statement or expression (depending on whether a trailing semicolon exists). Useful for + * block expressions where it cannot be determined through lookahead whether it is a statement or + * expression to be parsed. */ + ExprOrStmt Parser::parse_stmt_or_expr_without_block() { + // quick exit for empty statement + const_TokenPtr t = lexer.peek_token(); + if (t->get_id() == SEMICOLON) { + lexer.skip_token(); + ::std::unique_ptr stmt(new AST::EmptyStmt(t->get_locus())); + return ExprOrStmt(::std::move(stmt)); + } + + // parse outer attributes + ::std::vector outer_attrs = parse_outer_attributes(); + + // parsing this will be annoying because of the many different possibilities + /* best may be just to copy paste in parse_item switch, and failing that try to parse outer + * attributes, and then pass them in to either a let statement or (fallback) expression + * statement. */ + // FIXME: think of a way to do this without such a large switch? + + /* FIXME: for expressions at least, the only way that they can really be parsed properly in + * this way is if they don't support operators on them. They must be pratt-parsed otherwise. + * As such due to composability, only explicit statements will have special cases here. This + * should roughly correspond to "expr-with-block", but this warning is here in case it isn't + * the case. */ + t = lexer.peek_token(); + switch (t->get_id()) { + case LET: { + // let statement + ::std::unique_ptr stmt(parse_let_stmt(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(stmt)); + } + case PUB: + case MOD: + case EXTERN_TOK: + case USE: + case FN_TOK: + case TYPE: + case STRUCT_TOK: + case ENUM_TOK: + case CONST: + case STATIC_TOK: + case TRAIT: + case IMPL: { + ::std::unique_ptr item(parse_vis_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + } + /* TODO: implement union keyword but not really because of context-dependence + * crappy hack way to parse a union written below to separate it from the good code. */ + // case UNION: + case UNSAFE: { // maybe - unsafe traits are a thing + // if any of these (should be all possible VisItem prefixes), parse a VisItem + // can't parse item because would require reparsing outer attributes + const_TokenPtr t2 = lexer.peek_token(1); + switch (t2->get_id()) { + case LEFT_CURLY: { + // unsafe block + ::std::unique_ptr stmt( + parse_expr_stmt_with_block(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(stmt)); + } + case TRAIT: { + // unsafe trait + ::std::unique_ptr item( + parse_vis_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + } + case EXTERN_TOK: + case FN_TOK: { + // unsafe function + ::std::unique_ptr item( + parse_vis_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + } + case IMPL: { + // unsafe trait impl + ::std::unique_ptr item( + parse_vis_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + } + default: + error_at(t2->get_locus(), + "unrecognised token '%s' after parsing unsafe - expected beginning of " + "expression or statement", + t->get_token_description()); + // skip somewhere? + return ExprOrStmt::create_error(); + } + } + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: { + /* path-based thing so struct/enum or path or macro invocation of a kind. however, the + * expressions are composable (i think) */ + + ::std::unique_ptr expr = parse_expr_without_block(); + + if (lexer.peek_token()->get_id() == SEMICOLON) { + // must be expression statement + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); + return ExprOrStmt(::std::move(stmt)); + } + + // return expression + return ExprOrStmt(::std::move(expr)); + } + /* FIXME: this is either a macro invocation or macro invocation semi. start parsing to + * determine which one it is. */ + // FIXME: or this is another path-based thing - struct/enum or path itself + // return parse_path_based_stmt_or_expr(::std::move(outer_attrs)); + // FIXME: old code there + case LOOP: + case WHILE: + case FOR: + case IF: + case MATCH_TOK: + case LEFT_CURLY: + case ASYNC: { + // all expressions with block, so cannot be final expr without block in function + ::std::unique_ptr stmt( + parse_expr_stmt_with_block(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(stmt)); + } + case LIFETIME: { + /* FIXME: are there any expressions without blocks that can have lifetime as their + * first token? Or is loop expr the only one? */ + // safe side for now: + const_TokenPtr t2 = lexer.peek_token(2); + if (lexer.peek_token(1)->get_id() == COLON + && (t2->get_id() == LOOP || t2->get_id() == WHILE || t2->get_id() == FOR)) { + ::std::unique_ptr stmt( + parse_expr_stmt_with_block(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(stmt)); + } else { + // should be expr without block + ::std::unique_ptr expr = parse_expr_without_block(); + + if (lexer.peek_token()->get_id() == SEMICOLON) { + // must be expression statement + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); + return ExprOrStmt(::std::move(stmt)); + } + + // return expression + return ExprOrStmt(::std::move(expr)); + } + } + // crappy hack to do union "keyword" + case IDENTIFIER: + // TODO: ensure std::string and literal comparison works + if (t->get_str() == "union") { + ::std::unique_ptr item(parse_vis_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + // or should this go straight to parsing union? + } else if (t->get_str() == "macro_rules") { + // macro_rules! macro item + ::std::unique_ptr item( + parse_macro_item(::std::move(outer_attrs))); + return ExprOrStmt(::std::move(item)); + } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION + || lexer.peek_token(1)->get_id() == EXCLAM + || lexer.peek_token(1)->get_id() == LEFT_CURLY) { + // path (probably) or macro invocation or struct or enum, so probably a macro + // invocation semi decide how to parse - probably parse path and then get macro + // from it + + // FIXME: old code was good until composability was required + // return parse_path_based_stmt_or_expr(::std::move(outer_attrs)); + ::std::unique_ptr expr = parse_expr_without_block(); + + if (lexer.peek_token()->get_id() == SEMICOLON) { + // must be expression statement + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); + return ExprOrStmt(::std::move(stmt)); + } + + // return expression + return ExprOrStmt(::std::move(expr)); + } + gcc_fallthrough(); + // TODO: find out how to disable gcc "implicit fallthrough" warning + default: { + // expression statement (without block) or expression itself - parse expression then + // make it statement if semi afterwards + + ::std::unique_ptr expr = parse_expr_without_block(); + + if (lexer.peek_token()->get_id() == SEMICOLON) { + // must be expression statement + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); + return ExprOrStmt(::std::move(stmt)); + } + + // return expression + return ExprOrStmt(::std::move(expr)); + } + } + } + + // Parses a statement or expression beginning with a path (i.e. macro, struct/enum, or path expr) + ExprOrStmt Parser::parse_path_based_stmt_or_expr(::std::vector outer_attrs) { + // attempt to parse path + location_t stmt_or_expr_loc = lexer.peek_token()->get_locus(); + AST::PathInExpression path = parse_path_in_expression(); + + // branch on next token + const_TokenPtr t2 = lexer.peek_token(); + switch (t2->get_id()) { + case EXCLAM: { + // macro invocation or macro invocation semi - depends on whether there is + // a final ';' convert path in expr to simple path (as that is used in + // macros) + AST::SimplePath macro_path = path.as_simple_path(); + if (macro_path.is_empty()) { + error_at(t2->get_locus(), "failed to convert parsed path to simple " + "path (for macro invocation or semi)"); + return ExprOrStmt::create_error(); + } + + // skip exclamation mark + lexer.skip_token(); + + const_TokenPtr t3 = lexer.peek_token(); + location_t tok_tree_loc = t3->get_locus(); + + AST::DelimType type = AST::PARENS; + switch (t3->get_id()) { + case LEFT_PAREN: + type = AST::PARENS; + break; + case LEFT_SQUARE: + type = AST::SQUARE; + break; + case LEFT_CURLY: + type = AST::CURLY; + break; + default: + error_at(t3->get_locus(), + "unrecognised token '%s' in macro invocation - (opening) " + "delimiter expected", + t3->get_token_description()); + return ExprOrStmt::create_error(); + } + lexer.skip_token(); + + // parse actual token trees + ::std::vector< ::std::unique_ptr > token_trees; + + t3 = lexer.peek_token(); + // parse token trees until the initial delimiter token is found again + while (!token_id_matches_delims(t3->get_id(), type)) { + ::std::unique_ptr tree = parse_token_tree(); + + if (tree == NULL) { + error_at(t3->get_locus(), + "failed to parse token tree for macro invocation (or semi) - " + "found " + "'%s'", + t3->get_token_description()); + return ExprOrStmt::create_error(); + } + + token_trees.push_back(::std::move(tree)); + + t3 = lexer.peek_token(); + } + + // parse end delimiters + t3 = lexer.peek_token(); + if (token_id_matches_delims(t3->get_id(), type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + /* with curly bracketed macros, assume it is a macro invocation unless + * a semicolon is explicitly put at the end. this is not necessarily + * true (i.e. context-dependence) and so may have to be fixed up via + * HACKs in semantic + * analysis (by checking whether it is the last elem in the vector). + */ + + if (lexer.peek_token()->get_id() == SEMICOLON) { + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::MacroInvocationSemi(::std::move(macro_path), type, + ::std::move(token_trees), ::std::move(outer_attrs), stmt_or_expr_loc)); + return ExprOrStmt(::std::move(stmt)); + } + + // otherwise, create macro invocation + AST::DelimTokenTree delim_tok_tree(type, ::std::move(token_trees), tok_tree_loc); + + ::std::unique_ptr expr( + new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), + ::std::move(outer_attrs), stmt_or_expr_loc)); + return ExprOrStmt(::std::move(expr)); + } else { + // tokens don't match opening delimiters, so produce error + error_at(t2->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a " + "macro invocation)", + t2->get_token_description(), + (type == AST::PARENS ? ")" : (type == AST::SQUARE ? "]" : "}"))); + return ExprOrStmt::create_error(); + } + } + case LEFT_CURLY: { + /* definitely not a block: + * path '{' ident ',' + * path '{' ident ':' [anything] ',' + * path '{' ident ':' [not a type] + * otherwise, assume block expr and thus path */ + bool not_a_block + = lexer.peek_token(1)->get_id() == IDENTIFIER + && (lexer.peek_token(2)->get_id() == COMMA + || (lexer.peek_token(2)->get_id() == COLON + && (lexer.peek_token(4)->get_id() == COMMA + || !can_tok_start_type(lexer.peek_token(3)->get_id())))); + ::std::unique_ptr expr = NULL; + + if (not_a_block) { + // assume struct expr struct (as struct-enum disambiguation requires name + // lookup) again, make statement if final ';' + expr + = parse_struct_expr_struct_partial(::std::move(path), ::std::move(outer_attrs)); + if (expr == NULL) { + error_at(t2->get_locus(), "failed to parse struct expr struct"); + return ExprOrStmt::create_error(); + } + } else { + // assume path - make statement if final ';' + // lexer.skip_token(); + + // HACK: add outer attrs to path + path.replace_outer_attrs(::std::move(outer_attrs)); + expr = ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + + // determine if statement if ends with semicolon + if (lexer.peek_token()->get_id() == SEMICOLON) { + // statement + lexer.skip_token(); + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), stmt_or_expr_loc)); + return ExprOrStmt(::std::move(stmt)); + } + + // otherwise, expression + return ExprOrStmt(::std::move(expr)); + } + case LEFT_PAREN: { + // assume struct expr tuple (as struct-enum disambiguation requires name + // lookup) again, make statement if final ';' + ::std::unique_ptr struct_expr + = parse_struct_expr_tuple_partial(::std::move(path), ::std::move(outer_attrs)); + if (struct_expr == NULL) { + error_at(t2->get_locus(), "failed to parse struct expr tuple"); + return ExprOrStmt::create_error(); + } + + // determine if statement if ends with semicolon + if (lexer.peek_token()->get_id() == SEMICOLON) { + // statement + lexer.skip_token(); + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(struct_expr), stmt_or_expr_loc)); + return ExprOrStmt(::std::move(stmt)); + } + + // otherwise, expression + return ExprOrStmt(::std::move(struct_expr)); + } + default: { + // assume path - make statement if final ';' + // lexer.skip_token(); + + // HACK: replace outer attributes in path + path.replace_outer_attrs(::std::move(outer_attrs)); + ::std::unique_ptr expr( + new AST::PathInExpression(::std::move(path))); + + if (lexer.peek_token()->get_id() == SEMICOLON) { + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::ExprStmtWithoutBlock(::std::move(expr), stmt_or_expr_loc)); + return ExprOrStmt(::std::move(stmt)); + } + + return ExprOrStmt(::std::move(expr)); + } + } + } + + // Parses a struct expression field. + ::std::unique_ptr Parser::parse_struct_expr_field() { + // DEBUG: + fprintf(stderr, "beginning struct/enum expr field parsing \n"); + + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case IDENTIFIER: + if (lexer.peek_token(1)->get_id() == COLON) { + // struct expr field with identifier and expr + Identifier ident = t->get_str(); + lexer.skip_token(1); + + // parse expression (required) + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(t->get_locus(), + "failed to parse struct expression field with identifier and expression"); + return NULL; + } + + // DEBUG: + fprintf(stderr, "struct/enum expr field parsing field identifier value done \n"); + + return ::std::unique_ptr( + new AST::StructExprFieldIdentifierValue(::std::move(ident), ::std::move(expr))); + } else { + // struct expr field with identifier only + Identifier ident = t->get_str(); + lexer.skip_token(); + + // DEBUG: + fprintf(stderr, "struct/enum expr field parsing field identifier done \n"); + + return ::std::unique_ptr( + new AST::StructExprFieldIdentifier(::std::move(ident))); + } + case INT_LITERAL: { + // parse tuple index field + int index = atoi(t->get_str().c_str()); + lexer.skip_token(); + + if (!skip_token(COLON)) { + // skip somewhere? + return NULL; + } + + // parse field expression (required) + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(t->get_locus(), + "failed to parse expr in struct (or enum) expr field with tuple index"); + return NULL; + } + + // DEBUG: + fprintf(stderr, "struct/enum expr field parsing field index value done \n"); + + return ::std::unique_ptr( + new AST::StructExprFieldIndexValue(index, ::std::move(expr))); + } + case DOT_DOT: + // this is a struct base and can't be parsed here, so just return nothing without + // erroring + + // DEBUG: + fprintf(stderr, "struct/enum expr field parsing failed - '..' \n"); + + return NULL; + default: + // DEBUG: + fprintf(stderr, "struct/enum expr field parsing failed - unrecognised char \n"); + + error_at(t->get_locus(), + "unrecognised token '%s' as first token of struct expr field - expected identifier " + "or int literal", + t->get_token_description()); + return NULL; + } + } + + // Parses a macro invocation or macro invocation semi. + ExprOrStmt Parser::parse_macro_invocation_maybe_semi(::std::vector outer_attrs) { + location_t macro_locus = lexer.peek_token()->get_locus(); + AST::SimplePath macro_path = parse_simple_path(); + if (macro_path.is_empty()) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse simple path in macro invocation or semi"); + return ExprOrStmt::create_error(); + } + + if (!skip_token(EXCLAM)) { + return ExprOrStmt::create_error(); + } + + const_TokenPtr t3 = lexer.peek_token(); + location_t tok_tree_loc = t3->get_locus(); + + AST::DelimType type = AST::PARENS; + switch (t3->get_id()) { + case LEFT_PAREN: + type = AST::PARENS; + break; + case LEFT_SQUARE: + type = AST::SQUARE; + break; + case LEFT_CURLY: + type = AST::CURLY; + break; + default: + error_at(t3->get_locus(), + "unrecognised token '%s' in macro invocation - (opening) " + "delimiter expected", + t3->get_token_description()); + return ExprOrStmt::create_error(); + } + lexer.skip_token(); + + // parse actual token trees + ::std::vector< ::std::unique_ptr > token_trees; + + t3 = lexer.peek_token(); + // parse token trees until the initial delimiter token is found again + while (!token_id_matches_delims(t3->get_id(), type)) { + ::std::unique_ptr tree = parse_token_tree(); + + if (tree == NULL) { + error_at(t3->get_locus(), + "failed to parse token tree for macro invocation (or semi) - found '%s'", + t3->get_token_description()); + return ExprOrStmt::create_error(); + } + + token_trees.push_back(::std::move(tree)); + + t3 = lexer.peek_token(); + } + + // parse end delimiters + t3 = lexer.peek_token(); + if (token_id_matches_delims(t3->get_id(), type)) { + // tokens match opening delimiter, so skip. + lexer.skip_token(); + + /* with curly bracketed macros, assume it is a macro invocation unless + * a semicolon is explicitly put at the end. this is not necessarily + * true (i.e. context-dependence) and so may have to be fixed up via + * HACKs in semantic + * analysis (by checking whether it is the last elem in the vector). + */ + + if (lexer.peek_token()->get_id() == SEMICOLON) { + lexer.skip_token(); + + ::std::unique_ptr stmt( + new AST::MacroInvocationSemi(::std::move(macro_path), type, + ::std::move(token_trees), ::std::move(outer_attrs), macro_locus)); + return ExprOrStmt(::std::move(stmt)); + } + + // otherwise, create macro invocation + AST::DelimTokenTree delim_tok_tree(type, ::std::move(token_trees), tok_tree_loc); + + ::std::unique_ptr expr( + new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), + ::std::move(outer_attrs), macro_locus)); + return ExprOrStmt(::std::move(expr)); + } else { + const_TokenPtr t = lexer.peek_token(); + // tokens don't match opening delimiters, so produce error + error_at(t->get_locus(), + "unexpected token '%s' - expecting closing delimiter '%s' (for a " + "macro invocation)", + t->get_token_description(), + (type == AST::PARENS ? ")" : (type == AST::SQUARE ? "]" : "}"))); + return ExprOrStmt::create_error(); + } + } + + // "Unexpected token" panic mode - flags gcc error at unexpected token + void Parser::unexpected_token(const_TokenPtr t) { + ::error_at(t->get_locus(), "unexpected %s\n", t->get_token_description()); + } + + // Crappy "error recovery" performed after error by skipping tokens until a semi-colon is found + void Parser::skip_after_semicolon() { + const_TokenPtr t = lexer.peek_token(); + + while (t->get_id() != END_OF_FILE && t->get_id() != SEMICOLON) { + lexer.skip_token(); + t = lexer.peek_token(); + } + + if (t->get_id() == SEMICOLON) + lexer.skip_token(); + } + +#if 0 + // Parses a variable declaration statement. + Tree Parser::parse_variable_declaration() { + // skip initial var keyword - TODO: fix + if (!skip_token(/*VAR*/ COLON)) { + skip_after_semicolon(); + return Tree::error(); + } + + // keep identifier token as used later + const_TokenPtr identifier = expect_token(IDENTIFIER); + if (identifier == NULL) { + skip_after_semicolon(); + return Tree::error(); + } + + // skip colon + if (!skip_token(COLON)) { + skip_after_semicolon(); + return Tree::error(); + } + + // parse the actual type of the variable + Tree type_tree = parse_type(); + + if (type_tree.is_error()) { + skip_after_semicolon(); + return Tree::error(); + } + + // skip the semicolon + skip_token(SEMICOLON); + + // check if current mapping of the scope already contains a mapping for identifier + if (scope.get_current_mapping().get(identifier->get_str())) { + // create error if this is true + error_at(identifier->get_locus(), "name %s already declared in this scope", + identifier->get_str().c_str()); + return Tree::error(); + } + + // create a new symbol using the given identifier + SymbolPtr sym(new Symbol(VARIABLE, identifier->get_str())); + // put new symbol into scope mapping + scope.get_current_mapping().insert(sym); + + // create GENERIC tree for variable declaration + Tree decl = build_decl(identifier->get_locus(), VAR_DECL, + get_identifier(sym->get_name().c_str()), type_tree.get_tree()); + // set decl_context of decl to main function (make it local variable of main function) + DECL_CONTEXT(decl.get_tree()) = main_fndecl; + + // keep VAR_DECL tree in top list of stack_var_decl_chain stack for block purposes + gcc_assert(!stack_var_decl_chain.empty()); + stack_var_decl_chain.back().append(decl); + + // associate new symbol with VAR_DECL tree + sym->set_tree_decl(decl); + + Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); + + return stmt; + } +#endif + + /* Checks if current token has inputted id - skips it and returns true if so, diagnoses an error + * and returns false otherwise. */ + bool Parser::skip_token(TokenId token_id) { + return expect_token(token_id) != const_TokenPtr(); + } + + /* Checks the current token - if id is same as expected, skips and returns it, otherwise diagnoses + * error and returns null. */ + const_TokenPtr Parser::expect_token(TokenId token_id) { + const_TokenPtr t = lexer.peek_token(); + if (t->get_id() == token_id) { + lexer.skip_token(); + return t; + } else { + error_at(t->get_locus(), "expecting %s but %s found!\n", get_token_description(token_id), + t->get_token_description()); + + return const_TokenPtr(); + } + } + +#if 0 + // Parses type in variable declaration. + Tree Parser::parse_type() { + const_TokenPtr t = lexer.peek_token(); + + Tree type; + + switch (t->get_id()) { + // TODO: fix + case /*INT*/ COLON: + lexer.skip_token(); + type = integer_type_node; + break; + case /*FLOAT*/ ELLIPSIS: + lexer.skip_token(); + type = float_type_node; + break; + case /*BOOL*/ BREAK: + lexer.skip_token(); + type = boolean_type_node; + break; + case IDENTIFIER: { + SymbolPtr s = query_type(t->get_str(), t->get_locus()); + lexer.skip_token(); + + if (s == NULL) + type = Tree::error(); + else { + type = TREE_TYPE(s->get_tree_decl().get_tree()); + } + } break; + case /*RECORD*/ DOT: + type = parse_record(); + break; + default: + unexpected_token(t); + return Tree::error(); + break; + } + + // start parsing index ranges: list of expression pairs (lower and upper indexes of array) + typedef std::vector > Dimensions; + Dimensions dimensions; + + t = lexer.peek_token(); + while (t->get_id() == LEFT_PAREN || t->get_id() == LEFT_SQUARE) { + lexer.skip_token(); + + // array bounds + Tree lower_bound, upper_bound; + + if (t->get_id() == LEFT_SQUARE) { + // for array of form [e] + Tree size = parse_integer_expression(); + skip_token(RIGHT_SQUARE); + + lower_bound = Tree(build_int_cst_type(integer_type_node, 0), size.get_locus()); + + // set upper to e - 1 + upper_bound = build_tree(MINUS_EXPR, size.get_locus(), integer_type_node, size, + build_int_cst(integer_type_node, 1)); + } else if (t->get_id() == LEFT_PAREN) { + // for array of form [e0:e1] + // parse e0 + lower_bound = parse_integer_expression(); + skip_token(COLON); + + // parse e1 + upper_bound = parse_integer_expression(); + skip_token(RIGHT_PAREN); + } else { + gcc_unreachable(); + } + + dimensions.push_back(std::make_pair(lower_bound, upper_bound)); + t = lexer.peek_token(); + } + + // start building array type + // transverse list in reverse order + for (Dimensions::reverse_iterator it = dimensions.rbegin(); it != dimensions.rend(); it++) { + // fold lower and upper expressions (simplify expressions if possible) + it->first = Tree(fold(it->first.get_tree()), it->first.get_locus()); + it->second = Tree(fold(it->second.get_tree()), it->second.get_locus()); + + if (!type.is_error()) { + // build GCC range type using lower and upper + Tree range_type + = build_range_type(integer_type_node, it->first.get_tree(), it->second.get_tree()); + // build array type + type = build_array_type(type.get_tree(), range_type.get_tree()); + } + } + + return type; + } +#endif + + // Parses an if statement. Probably important to study as it seems complex. + Tree Parser::parse_if_statement() { + // skip if statement token + if (!skip_token(IF)) { + skip_after_end(); + return Tree::error(); + } + + // parse expression in statement body + Tree expr = parse_boolean_expression(); + + // skip the "THEN" after expression + skip_token(LEFT_CURLY); + + // enter new block scope + enter_scope(); + // parse statement sequence? inside if body. Finish at "end if" or "else" + parse_statement_seq(&Parser::done_end_or_else); + + TreeSymbolMapping then_tree_scope = leave_scope(); + Tree then_stmt = then_tree_scope.bind_expr; + + Tree else_stmt; + const_TokenPtr tok = lexer.peek_token(); + // if there is an else, parse statement seq inside its body too + if (tok->get_id() == ELSE) { + // Consume 'else' + skip_token(ELSE); + + // enter block scope + enter_scope(); + parse_statement_seq(&Parser::done_end); + TreeSymbolMapping else_tree_scope = leave_scope(); + else_stmt = else_tree_scope.bind_expr; + + // Consume 'end' + skip_token(RIGHT_CURLY); + } else if (tok->get_id() == RIGHT_CURLY) { + // Consume 'end' + skip_token(RIGHT_CURLY); + } else { + unexpected_token(tok); + return Tree::error(); + } + + // build GENERIC if statement node. + return build_if_statement(expr, then_stmt, else_stmt); + } + + // Builds an if statement tree. + Tree Parser::build_if_statement(Tree bool_expr, Tree then_part, Tree else_part) { + if (bool_expr.is_error()) + return bool_expr; + + // create then label declaration tree + Tree then_label_decl = build_label_decl("then", then_part.get_locus()); + + // create else label declaration if it exists + Tree else_label_decl; + if (!else_part.is_null()) + else_label_decl = build_label_decl("else", else_part.get_locus()); + + // create endif label declaration + Tree endif_label_decl = build_label_decl("end_if", then_part.get_locus()); + + // create goto expressions for entering "if" branch, "else" branch, and code after if block + Tree goto_then + = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, then_label_decl); + Tree goto_endif + = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, endif_label_decl); + + Tree goto_else_or_endif; + if (!else_part.is_null()) + goto_else_or_endif + = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, else_label_decl); + else + goto_else_or_endif = goto_endif; + + // create statement list for if statement which will have required statements appended + TreeStmtList stmt_list; + + // create conditional branch expression and append to stmt_list + Tree cond_expr = build_tree( + COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, goto_then, goto_else_or_endif); + stmt_list.append(cond_expr); + + // define location related to "then" part and append to stmt_list + Tree then_label_expr + = build_tree(LABEL_EXPR, then_part.get_locus(), void_type_node, then_label_decl); + stmt_list.append(then_label_expr); + + // append parameter "then_part" to statement list + stmt_list.append(then_part); + + // if else part exists, append a goto endif + if (!else_part.is_null()) { + // Make sure after then part has been executed we go to the end if + stmt_list.append(goto_endif); + + // define location of else label, append it, and append else_part parameter tree + Tree else_label_expr + = build_tree(LABEL_EXPR, else_part.get_locus(), void_type_node, else_label_decl); + stmt_list.append(else_label_expr); + stmt_list.append(else_part); + // do not need to jump to endif as handled implicitly here + } + + // define label for endif, append to statement list + Tree endif_label_expr + = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, endif_label_decl); + stmt_list.append(endif_label_expr); + + // return the statement list in tree form + return stmt_list.get_tree(); + } + + // Builds a GENERIC tree LABEL_DECL (represents a label, as in a "goto" label). + Tree Parser::build_label_decl(const char* name, location_t loc) { + tree t = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node); + + gcc_assert(main_fndecl != NULL_TREE); + DECL_CONTEXT(t) = main_fndecl; + + return t; + } + + // Skips all tokens until EOF or }. Don't use. + void Parser::skip_after_end() { + const_TokenPtr t = lexer.peek_token(); + + while (t->get_id() != END_OF_FILE && t->get_id() != RIGHT_CURLY) { + lexer.skip_token(); + t = lexer.peek_token(); + } + + if (t->get_id() == RIGHT_CURLY) { + lexer.skip_token(); + } + } + + /* A slightly more aware error-handler that skips all tokens until it reaches the end of the + * block scope (i.e. when left curly brackets = right curly brackets). Note: assumes currently in + * the middle of a block. Use skip_after_next_block to skip based on the assumption that the block + * has not been entered yet. */ + void Parser::skip_after_end_block() { + const_TokenPtr t = lexer.peek_token(); + int curly_count = 1; + + while (curly_count > 0 && t->get_id() != END_OF_FILE) { + switch (t->get_id()) { + case LEFT_CURLY: + curly_count++; + break; + case RIGHT_CURLY: + curly_count--; + break; + default: + break; + } + lexer.skip_token(); + t = lexer.peek_token(); + } + } + + /* Skips tokens until the end of the next block. i.e. assumes that the block has not been entered + * yet. */ + void Parser::skip_after_next_block() { + const_TokenPtr t = lexer.peek_token(); + + // initial loop - skip until EOF if no left curlies encountered + while (t->get_id() != END_OF_FILE && t->get_id() != LEFT_CURLY) { + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // if next token is left, skip it and then skip after the block ends + if (t->get_id() == LEFT_CURLY) { + lexer.skip_token(); + + skip_after_end_block(); + } + // otherwise, do nothing as EOF + } + + // Skips all tokens until ] (the end of an attribute) - does not skip the ] (as designed for + // attribute body use) + void Parser::skip_after_end_attribute() { + const_TokenPtr t = lexer.peek_token(); + + while (t->get_id() != RIGHT_SQUARE) { + lexer.skip_token(); + t = lexer.peek_token(); + } + + // Don't skip the RIGHT_SQUARE token + /*if (t->get_id() == RIGHT_SQUARE) { + lexer.skip_token(); + }*/ + } + + /* Pratt parser impl of parse_expr. FIXME: this is only provisional and probably will be changed. + * FIXME: this may only parse expressions without blocks as they are the only expressions to have + * precedence? */ + ::std::unique_ptr Parser::parse_expr(int right_binding_power, + ::std::vector outer_attrs, ParseRestrictions restrictions) { + const_TokenPtr current_token = lexer.peek_token(); + lexer.skip_token(); + + // parse null denotation (unary part of expression) + ::std::unique_ptr expr + = null_denotation_NEW(current_token, ::std::move(outer_attrs), restrictions); + + // DEBUG + fprintf(stderr, "finished parsing null denotation\n"); + + if (expr == NULL) { + // DEBUG + fprintf(stderr, "null denotation is null; returning null for parse_expr\n"); + return NULL; + } + + // DEBUG + fprintf(stderr, "null denotation is not null - going on to left denotation\n"); + + // DEBUG + fprintf(stderr, "initial rbp: '%i', initial lbp: '%i' (for '%s')\n", right_binding_power, + left_binding_power(lexer.peek_token()), lexer.peek_token()->get_token_description()); + + // stop parsing if find lower priority token - parse higher priority first + while (right_binding_power < left_binding_power(lexer.peek_token())) { + current_token = lexer.peek_token(); + lexer.skip_token(); + + expr = left_denotation( + current_token, ::std::move(expr), ::std::vector(), restrictions); + + // DEBUG + fprintf(stderr, "successfully got left_denotation in parse_expr \n"); + + if (expr == NULL) { + + // DEBUG + fprintf(stderr, "left denotation is null; returning null for parse_expr\n"); + + return NULL; + } + + // DEBUG + fprintf(stderr, "left denotation is not null - going to next iteration \n"); + } + + // DEBUG + fprintf(stderr, "successfully parsed expr in parse_expr - returning \n"); + + return expr; + } + + /* Parse expression with lowest left binding power. FIXME: this may only apply to expressions + * without blocks as they are the only ones to have precedence? */ + ::std::unique_ptr Parser::parse_expr( + ::std::vector outer_attrs, ParseRestrictions restrictions) { + // HACK: only call parse_expr(LBP_LOWEST) after ensuring it is not an expression with block? + return parse_expr(LBP_LOWEST, ::std::move(outer_attrs), restrictions); + } + + // Pratt parser impl of parse_expression. + Tree Parser::parse_expression(int right_binding_power) { + const_TokenPtr current_token = lexer.peek_token(); + lexer.skip_token(); + + Tree expr = null_denotation(current_token); + + if (expr.is_error()) { + return Tree::error(); + } + + // stop parsing if find lower priority token - parse higher priority first + while (right_binding_power < left_binding_power(lexer.peek_token())) { + current_token = lexer.peek_token(); + lexer.skip_token(); + + expr = left_denotation(current_token, expr); + if (expr.is_error()) + return Tree::error(); + } + + return expr; + } + + // Parse an expression with lowest left binding power. + Tree Parser::parse_expression() { + return parse_expression(LBP_LOWEST); + } + + // Parses a boolean expression (basically parses expression and ensures boolean result). + Tree Parser::parse_boolean_expression() { + Tree expr = parse_expression(); + if (expr.is_error()) + return expr; + + if (expr.get_type() != boolean_type_node) { + error_at(expr.get_locus(), "expected expression of boolean type but its type is %s", + print_type(expr.get_type())); + return Tree::error(); + } + + return expr; + } + + // Parses an integer expression (basically parses expression and ensures integer result). + Tree Parser::parse_integer_expression() { + Tree expr = parse_expression(); + if (expr.is_error()) + return expr; + + if (expr.get_type() != integer_type_node) { + error_at(expr.get_locus(), "expected expression of integer type but its type is %s", + print_type(expr.get_type())); + return Tree::error(); + } + + return expr; + } + + /* Determines action to take when finding token at beginning of expression. + * FIXME: this may only apply to precedence-capable expressions (which are all expressions without + * blocks), so make return type ExprWithoutBlock? It would simplify stuff. */ + ::std::unique_ptr Parser::null_denotation_NEW( + const_TokenPtr tok, ::std::vector outer_attrs, ParseRestrictions restrictions) { + // note: tok is previous character in input stream, not current one, as parse_expr + // skips it before passing it in + + /* as a Pratt parser (which works by decomposing expressions into a null denotation and then a + * left denotation), null denotations handle primaries and unary operands (but only prefix + * unary operands) */ + + switch (tok->get_id()) { + /*case IDENTIFIER: { + // when encountering identifier, lookup in scope + SymbolPtr s = scope.lookup(tok->get_str()); + if (s == NULL) { + error_at(tok->get_locus(), "variable '%s' not declared in the current scope", + tok->get_str().c_str()); + + return Tree::error(); + } + // expression is just its VAR_DECL that was stored in the Symbol at declaration + return Tree(s->get_tree_decl(), tok->get_locus()); + }*/ + // symbol table must be created in semantic analysis pass, so can't use this + case IDENTIFIER: { + // DEBUG + fprintf(stderr, "beginning null denotation identifier handling\n"); + + // best option: parse as path, then extract identifier, macro, struct/enum, or just + // path info from it + AST::PathInExpression path = parse_path_in_expression_pratt(tok); + + // DEBUG: + fprintf( + stderr, "finished null denotation identifier path parsing - next is branching \n"); + + // branch on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: + // macro + return parse_macro_invocation_partial( + ::std::move(path), ::std::move(outer_attrs)); + case LEFT_CURLY: { + bool not_a_block + = lexer.peek_token(1)->get_id() == IDENTIFIER + && (lexer.peek_token(2)->get_id() == COMMA + || (lexer.peek_token(2)->get_id() == COLON + && (lexer.peek_token(4)->get_id() == COMMA + || !can_tok_start_type(lexer.peek_token(3)->get_id())))); + + /* definitely not a block: + * path '{' ident ',' + * path '{' ident ':' [anything] ',' + * path '{' ident ':' [not a type] + * otherwise, assume block expr and thus path */ + // DEBUG + fprintf(stderr, "values of lookahead: '%s' '%s' '%s' '%s' \n", + lexer.peek_token(1)->get_token_description(), + lexer.peek_token(2)->get_token_description(), + lexer.peek_token(3)->get_token_description(), + lexer.peek_token(4)->get_token_description()); + + fprintf(stderr, "can be struct expr: '%s', not a block: '%s'\n", + restrictions.can_be_struct_expr ? "true" : "false", + not_a_block ? "true" : "false"); + + // struct/enum expr struct + if (!restrictions.can_be_struct_expr && !not_a_block) { + // assume path is returned if not single segment + if (path.is_single_segment()) { + // have to return an identifier expression or something, idk + // HACK: may have to become permanent, but this is my current + // identifier expression + return ::std::unique_ptr( + new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); + } + // HACK: add outer attrs to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + return parse_struct_expr_struct_partial( + ::std::move(path), ::std::move(outer_attrs)); + } + case LEFT_PAREN: + // struct/enum expr tuple + if (!restrictions.can_be_struct_expr) { + // assume path is returned if not single segment + if (path.is_single_segment()) { + // have to return an identifier expression or something, idk + // HACK: may have to become permanent, but this is my current + // identifier expression + return ::std::unique_ptr( + new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); + } + // HACK: add outer attrs to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + return parse_struct_expr_tuple_partial( + ::std::move(path), ::std::move(outer_attrs)); + default: + // assume path is returned if not single segment + if (path.is_single_segment()) { + // have to return an identifier expression or something, idk + // HACK: may have to become permanent, but this is my current identifier + // expression + return ::std::unique_ptr( + new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); + } + // HACK: add outer attrs to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + gcc_unreachable(); + } + // FIXME: delegate to parse_literal_expr instead? would have to rejig tokens and whatever. + // FIXME: could also be path expression (and hence macro expression, struct/enum expr) + case LEFT_ANGLE: { + // qualified path + // HACK: add outer attrs to path + AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(true); + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::QualifiedPathInExpression(::std::move(path))); + } + case INT_LITERAL: + // we should check the range, but ignore for now + // encode as int? + return ::std::unique_ptr( + new AST::LiteralExpr(tok->get_str(), AST::Literal::INT, tok->get_locus())); + case FLOAT_LITERAL: + // encode as float? + return ::std::unique_ptr( + new AST::LiteralExpr(tok->get_str(), AST::Literal::FLOAT, tok->get_locus())); + case STRING_LITERAL: + return ::std::unique_ptr( + new AST::LiteralExpr(tok->get_str(), AST::Literal::STRING, tok->get_locus())); + case TRUE_LITERAL: + return ::std::unique_ptr( + new AST::LiteralExpr("true", AST::Literal::BOOL, tok->get_locus())); + case FALSE_LITERAL: + return ::std::unique_ptr( + new AST::LiteralExpr("false", AST::Literal::BOOL, tok->get_locus())); + case LEFT_PAREN: { // have to parse whole expression if inside brackets + /* recursively invoke parse_expression with lowest priority possible as it it were + * a top-level expression. */ + /*AST::Expr* expr = parse_expr(); + tok = lexer.peek_token(); + + // end of expression must be a close-bracket + if (tok->get_id() != RIGHT_PAREN) + error_at( + tok->get_locus(), "expecting ')' but %s found\n", tok->get_token_description()); + else + lexer.skip_token(); + + return expr; + // FIXME: this assumes grouped expression - could be tuple expression if commas + inside*/ + + return parse_grouped_or_tuple_expr(::std::move(outer_attrs), true); + } + /*case PLUS: { // unary plus operator + // invoke parse_expr recursively with appropriate priority, etc. for below + AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); + + if (expr == NULL) + return NULL; + // can only apply to integer and float expressions + if (expr->get_type() != integer_type_node || expr->get_type() != float_type_node) { + error_at(tok->get_locus(), + "operand of unary plus must be int or float but it is %s", + print_type(expr->get_type())); + return NULL; + } + + return Tree(expr, tok->get_locus()); + }*/ + // Rust has no unary plus operator + case MINUS: { // unary minus + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + ::std::unique_ptr expr + = parse_expr(LBP_UNARY_MINUS, ::std::vector(), entered_from_unary); + + if (expr == NULL) + return NULL; + // can only apply to integer and float expressions + /*if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { + error_at(tok->get_locus(), + "operand of unary minus must be int or float but it is %s", + print_type(expr.get_type())); + return Tree::error(); + }*/ + /* FIXME: when implemented the "get type" method on expr, ensure it is int or float + * type (except unsigned int). Actually, this would probably have to be done in + * semantic analysis (as type checking). */ + + /* FIXME: allow outer attributes on these expressions by having an outer attrs + * parameter in function*/ + return ::std::unique_ptr(new AST::NegationExpr(::std::move(expr), + AST::NegationExpr::NEGATE, ::std::move(outer_attrs), tok->get_locus())); + } + case EXCLAM: { // logical or bitwise not + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + ::std::unique_ptr expr + = parse_expr(LBP_UNARY_EXCLAM, ::std::vector(), entered_from_unary); + + if (expr == NULL) + return NULL; + // can only apply to boolean expressions + /*if (expr.get_type() != boolean_type_node) { + error_at(tok->get_locus(), + "operand of logical not must be a boolean but it is %s", + print_type(expr.get_type())); + return Tree::error(); + }*/ + // FIXME: type checking for boolean or integer expressions in semantic analysis + + // FIXME: allow outer attributes on these expressions + return ::std::unique_ptr(new AST::NegationExpr(::std::move(expr), + AST::NegationExpr::NOT, ::std::move(outer_attrs), tok->get_locus())); + } + case ASTERISK: { + // pointer dereference only - HACK: as struct expressions should always be value + // expressions, cannot be dereferenced + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + entered_from_unary.can_be_struct_expr = false; + ::std::unique_ptr expr = parse_expr( + LBP_UNARY_ASTERISK, ::std::vector(), entered_from_unary); + // FIXME: allow outer attributes on expression + return ::std::unique_ptr(new AST::DereferenceExpr( + ::std::move(expr), ::std::move(outer_attrs), tok->get_locus())); + } + case AMP: { + // (single) "borrow" expression - shared (mutable) or immutable + ::std::unique_ptr expr = NULL; + bool is_mut_borrow = false; + + // HACK: as struct expressions should always be value expressions, cannot be + // referenced + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + entered_from_unary.can_be_struct_expr = false; + + if (lexer.peek_token()->get_id() == MUT) { + lexer.skip_token(); + expr = parse_expr( + LBP_UNARY_AMP_MUT, ::std::vector(), entered_from_unary); + is_mut_borrow = true; + } else { + expr = parse_expr( + LBP_UNARY_AMP, ::std::vector(), entered_from_unary); + } + + // FIXME: allow outer attributes on expression + return ::std::unique_ptr(new AST::BorrowExpr(::std::move(expr), + is_mut_borrow, false, ::std::move(outer_attrs), tok->get_locus())); + } + case LOGICAL_AND: { + // (double) "borrow" expression - shared (mutable) or immutable + ::std::unique_ptr expr = NULL; + bool is_mut_borrow = false; + + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + + if (lexer.peek_token()->get_id() == MUT) { + lexer.skip_token(); + expr = parse_expr( + LBP_UNARY_AMP_MUT, ::std::vector(), entered_from_unary); + is_mut_borrow = true; + } else { + expr = parse_expr( + LBP_UNARY_AMP, ::std::vector(), entered_from_unary); + } + + // FIXME: allow outer attributes on expression + return ::std::unique_ptr(new AST::BorrowExpr(::std::move(expr), + is_mut_borrow, true, ::std::move(outer_attrs), tok->get_locus())); + } + case SCOPE_RESOLUTION: { + // TODO: fix: this is for global paths, i.e. ::std::string::whatever + error_at(tok->get_locus(), "found null denotation scope resolution operator, and " + "haven't written handling for it."); + return NULL; + } + case SELF: + case SELF_ALIAS: + case DOLLAR_SIGN: + case CRATE: + case SUPER: { + // DEBUG + fprintf( + stderr, "beginning null denotation self/self-alias/dollar/crate/super handling\n"); + + // best option: parse as path, then extract identifier, macro, struct/enum, or just + // path info from it + AST::PathInExpression path = parse_path_in_expression_pratt(tok); + + // DEBUG + fprintf(stderr, + "just finished parsing path (going to disambiguate) - peeked token is '%s'\n", + lexer.peek_token()->get_token_description()); + + // HACK: always make "self" by itself a path (regardless of next tokens) + if (tok->get_id() == SELF && path.is_single_segment()) { + // HACK: add outer attrs to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + + // branch on next token + const_TokenPtr t = lexer.peek_token(); + switch (t->get_id()) { + case EXCLAM: + // macro + return parse_macro_invocation_partial( + ::std::move(path), ::std::move(outer_attrs)); + case LEFT_CURLY: { + // struct/enum expr struct + fprintf(stderr, "can_be_struct_expr: %s\n", + restrictions.can_be_struct_expr ? "true" : "false"); + + bool not_a_block + = lexer.peek_token(1)->get_id() == IDENTIFIER + && (lexer.peek_token(2)->get_id() == COMMA + || (lexer.peek_token(2)->get_id() == COLON + && (lexer.peek_token(4)->get_id() == COMMA + || !can_tok_start_type(lexer.peek_token(3)->get_id())))); + + if (!restrictions.can_be_struct_expr && !not_a_block) { + // assume path is returned + // HACK: add outer attributes to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + return parse_struct_expr_struct_partial( + ::std::move(path), ::std::move(outer_attrs)); + } + case LEFT_PAREN: + // struct/enum expr tuple + if (!restrictions.can_be_struct_expr) { + // assume path is returned + // HACK: add outer attributes to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + return parse_struct_expr_tuple_partial( + ::std::move(path), ::std::move(outer_attrs)); + default: + // assume path is returned + // HACK: add outer attributes to path + path.replace_outer_attrs(::std::move(outer_attrs)); + return ::std::unique_ptr( + new AST::PathInExpression(::std::move(path))); + } + gcc_unreachable(); + } + case OR: + case PIPE: + case MOVE: + // closure expression + return parse_closure_expr_pratt(tok, ::std::move(outer_attrs)); + case DOT_DOT: + // either "range to" or "range full" expressions + return parse_nud_range_exclusive_expr(tok, ::std::move(outer_attrs)); + case DOT_DOT_EQ: + // range to inclusive expr + return parse_range_to_inclusive_expr(tok, ::std::move(outer_attrs)); + case RETURN_TOK: + // FIXME: is this really a null denotation expression? + return parse_return_expr(::std::move(outer_attrs), true); + case BREAK: + // FIXME: is this really a null denotation expression? + return parse_break_expr(::std::move(outer_attrs), true); + case CONTINUE: + return parse_continue_expr(::std::move(outer_attrs), true); + case LEFT_CURLY: + // ok - this is an expression with block for once. + return parse_block_expr(::std::move(outer_attrs), true); + case MATCH_TOK: + // also an expression with block + return parse_match_expr(::std::move(outer_attrs), true); + case LEFT_SQUARE: + // array definition expr (not indexing) + return parse_array_expr(::std::move(outer_attrs), true); + default: + error_at(tok->get_locus(), "found unexpected token '%s' in null denotation", + tok->get_token_description()); + return NULL; + } + } + + /* Called for each token that can appear in infix (between) position. Can be operators or other + * punctuation. + * Returns a function pointer to member function that implements the left denotation for the token + * given. */ + ::std::unique_ptr Parser::left_denotation(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions) { + // Token passed in has already been skipped, so peek gives "next" token + /*BinaryHandler binary_handler = get_binary_handler(tok->get_id()); + if (binary_handler == NULL) { + unexpected_token(tok); + return NULL; + } + + return (this->*binary_handler)(tok, left);*/ + // can't do with binary handler because same token used for several operators + + switch (tok->get_id()) { + // FIXME: allow for outer attributes to be applied + case QUESTION_MARK: { + location_t left_locus = left->get_locus_slow(); + // error propagation expression - unary postfix + return ::std::unique_ptr(new AST::ErrorPropagationExpr( + ::std::move(left), ::std::move(outer_attrs), left_locus)); + } + case PLUS: + // sum expression - binary infix + return parse_binary_plus_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case MINUS: + // difference expression - binary infix + return parse_binary_minus_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case ASTERISK: + // product expression - binary infix + return parse_binary_mult_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case DIV: + // quotient expression - binary infix + return parse_binary_div_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case PERCENT: + // modulo expression - binary infix + return parse_binary_mod_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case AMP: + // logical or bitwise and expression - binary infix + return parse_bitwise_and_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case PIPE: + // logical or bitwise or expression - binary infix + return parse_bitwise_or_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case CARET: + // logical or bitwise xor expression - binary infix + return parse_bitwise_xor_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LEFT_SHIFT: + // left shift expression - binary infix + return parse_left_shift_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case RIGHT_SHIFT: + // right shift expression - binary infix + return parse_right_shift_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case EQUAL_EQUAL: + // equal to expression - binary infix (no associativity) + return parse_binary_equal_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case NOT_EQUAL: + // not equal to expression - binary infix (no associativity) + return parse_binary_not_equal_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case RIGHT_ANGLE: + // greater than expression - binary infix (no associativity) + return parse_binary_greater_than_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LEFT_ANGLE: + // less than expression - binary infix (no associativity) + return parse_binary_less_than_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case GREATER_OR_EQUAL: + // greater than or equal to expression - binary infix (no associativity) + return parse_binary_greater_equal_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LESS_OR_EQUAL: + // less than or equal to expression - binary infix (no associativity) + return parse_binary_less_equal_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case OR: + // lazy logical or expression - binary infix + return parse_lazy_or_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LOGICAL_AND: + // lazy logical and expression - binary infix + return parse_lazy_and_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case AS: + // type cast expression - kind of binary infix (RHS is actually a TypeNoBounds) + return parse_type_cast_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case EQUAL: + // assignment expression - binary infix (note right-to-left associativity) + return parse_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case PLUS_EQ: + // plus-assignment expression - binary infix (note right-to-left associativity) + return parse_plus_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case MINUS_EQ: + // minus-assignment expression - binary infix (note right-to-left associativity) + return parse_minus_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case ASTERISK_EQ: + // multiply-assignment expression - binary infix (note right-to-left associativity) + return parse_mult_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case DIV_EQ: + // division-assignment expression - binary infix (note right-to-left associativity) + return parse_div_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case PERCENT_EQ: + // modulo-assignment expression - binary infix (note right-to-left associativity) + return parse_mod_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case AMP_EQ: + // bitwise and-assignment expression - binary infix (note right-to-left associativity) + return parse_and_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case PIPE_EQ: + // bitwise or-assignment expression - binary infix (note right-to-left associativity) + return parse_or_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case CARET_EQ: + // bitwise xor-assignment expression - binary infix (note right-to-left associativity) + return parse_xor_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LEFT_SHIFT_EQ: + // left shift-assignment expression - binary infix (note right-to-left associativity) + return parse_left_shift_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case RIGHT_SHIFT_EQ: + // right shift-assignment expression - binary infix (note right-to-left associativity) + return parse_right_shift_assig_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case DOT_DOT: + // range exclusive expression - binary infix (no associativity) + // either "range" or "range from" + return parse_led_range_exclusive_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case DOT_DOT_EQ: + // range inclusive expression - binary infix (no associativity) + // unambiguously RangeInclusiveExpr + return parse_range_inclusive_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case SCOPE_RESOLUTION: + // path expression - binary infix? FIXME should this even be parsed here? + error_at(tok->get_locus(), "found scope resolution operator in left denotation " + "function - this should probably be handled elsewhere."); + return NULL; + case DOT: { + // field expression or method call - relies on parentheses after next identifier + // or await if token after is "await" (unary postfix) + // or tuple index if token after is a decimal int literal + + const_TokenPtr next_tok = lexer.peek_token(); + if (next_tok->get_id() == IDENTIFIER && next_tok->get_str() == "await") { + // await expression + return parse_await_expr(tok, ::std::move(left), ::std::move(outer_attrs)); + } else if (next_tok->get_id() == INT_LITERAL) { + // tuple index expression - TODO check for decimal int literal + return parse_tuple_index_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + } else if (next_tok->get_id() == IDENTIFIER + && lexer.peek_token(1)->get_id() != LEFT_PAREN + && lexer.peek_token(1)->get_id() != SCOPE_RESOLUTION) { + // field expression (or should be) - FIXME: scope resolution right after + // identifier should always be method, I'm pretty sure + return parse_field_access_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + } else { + // method call (probably) + return parse_method_call_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + } + } + case LEFT_PAREN: + // function call - method call is based on dot notation first + return parse_function_call_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case LEFT_SQUARE: + // array or slice index expression (pseudo binary infix) + return parse_index_expr( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + case FLOAT_LITERAL: + // HACK: get around lexer mis-identifying '.0' or '.1' or whatever as a float literal + return parse_tuple_index_expr_float( + tok, ::std::move(left), ::std::move(outer_attrs), restrictions); + default: + error_at(tok->get_locus(), "found unexpected token '%s' in left denotation", + tok->get_token_description()); + return NULL; + } + } + + // Parses a binary addition expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_plus_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_PLUS, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::ADD, locus)); + } + + // Parses a binary subtraction expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_minus_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MINUS, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::SUBTRACT, locus)); + } + + // Parses a binary multiplication expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_mult_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MUL, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::MULTIPLY, locus)); + } + + // Parses a binary division expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_div_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_DIV, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::DIVIDE, locus)); + } + + // Parses a binary modulo expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_mod_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MOD, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::MODULUS, locus)); + } + + // Parses a binary bitwise (or eager logical) and expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_bitwise_and_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_AMP, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_AND, locus)); + } + + // Parses a binary bitwise (or eager logical) or expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_bitwise_or_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_PIPE, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_OR, locus)); + } + + // Parses a binary bitwise (or eager logical) xor expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_bitwise_xor_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_CARET, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_XOR, locus)); + } + + // Parses a binary left shift expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_left_shift_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_L_SHIFT, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::LEFT_SHIFT, locus)); + } + + // Parses a binary right shift expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_right_shift_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_R_SHIFT, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( + ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::RIGHT_SHIFT, locus)); + } + + // Parses a binary equal to expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_equal_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_EQUAL, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::EQUAL, locus)); + } + + // Parses a binary not equal to expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_not_equal_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_NOT_EQUAL, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::NOT_EQUAL, locus)); + } + + // Parses a binary greater than expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_greater_than_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_GREATER_THAN, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::GREATER_THAN, locus)); + } + + // Parses a binary less than expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_less_than_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_SMALLER_THAN, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::LESS_THAN, locus)); + } + + // Parses a binary greater than or equal to expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_greater_equal_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_GREATER_EQUAL, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::GREATER_OR_EQUAL, locus)); + } + + // Parses a binary less than or equal to expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_binary_less_equal_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_SMALLER_EQUAL, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::ComparisonExpr( + ::std::move(left), ::std::move(right), AST::ComparisonExpr::LESS_OR_EQUAL, locus)); + } + + // Parses a binary lazy boolean or expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_lazy_or_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_LOGICAL_OR, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::LazyBooleanExpr( + ::std::move(left), ::std::move(right), AST::LazyBooleanExpr::LOGICAL_OR, locus)); + } + + // Parses a binary lazy boolean and expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_lazy_and_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_LOGICAL_AND, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::LazyBooleanExpr( + ::std::move(left), ::std::move(right), AST::LazyBooleanExpr::LOGICAL_AND, locus)); + } + + // Parses a pseudo-binary infix type cast expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_type_cast_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr expr_to_cast, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, + ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr type = parse_type_no_bounds(); + if (type == NULL) + return NULL; + // FIXME: how do I get precedence put in here? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = expr_to_cast->get_locus_slow(); + + return ::std::unique_ptr( + new AST::TypeCastExpr(::std::move(expr_to_cast), ::std::move(type), locus)); + } + + // Parses a binary assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr( + new AST::AssignmentExpr(::std::move(left), ::std::move(right), locus)); + } + + // Parses a binary add-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_plus_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_PLUS_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::ADD, locus)); + } + + // Parses a binary minus-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_minus_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MINUS_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::SUBTRACT, locus)); + } + + // Parses a binary multiplication-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_mult_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MULT_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::MULTIPLY, locus)); + } + + // Parses a binary division-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_div_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_DIV_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::DIVIDE, locus)); + } + + // Parses a binary modulo-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_mod_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_MOD_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::MODULUS, locus)); + } + + // Parses a binary and-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_and_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_AMP_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_AND, locus)); + } + + // Parses a binary or-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_or_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_PIPE_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_OR, locus)); + } + + // Parses a binary xor-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_xor_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_CARET_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_XOR, locus)); + } + + // Parses a binary left shift-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_left_shift_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_L_SHIFT_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::LEFT_SHIFT, locus)); + } + + // Parses a binary right shift-assignment expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_right_shift_assig_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_R_SHIFT_ASSIG - 1, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr(new AST::CompoundAssignmentExpr( + ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::RIGHT_SHIFT, locus)); + } + + // Parses a postfix unary await expression (with Pratt parsing). + ::std::unique_ptr Parser::parse_await_expr(const_TokenPtr tok, + ::std::unique_ptr expr_to_await, ::std::vector outer_attrs) { + // skip "await" identifier (as "." has already been consumed in parse_expression) + // this assumes that the identifier was already identified as await + if (!skip_token(IDENTIFIER)) { + error_at(tok->get_locus(), + "failed to skip 'await' in await expr - this is probably a deep issue."); + // skip somewhere? + return NULL; + } + + // TODO: check inside async block in semantic analysis + location_t locus = expr_to_await->get_locus_slow(); + + return ::std::unique_ptr( + new AST::AwaitExpr(::std::move(expr_to_await), ::std::move(outer_attrs), locus)); + } + + /* Parses an exclusive range ('..') in left denotation position (i.e. RangeFromExpr or + * RangeFromToExpr). */ + ::std::unique_ptr Parser::parse_led_range_exclusive_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // FIXME: this probably parses expressions accidently or whatever + // try parsing RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_DOT_DOT, ::std::vector(), restrictions); + + location_t locus = left->get_locus_slow(); + + if (right == NULL) { + // range from expr + return ::std::unique_ptr( + new AST::RangeFromExpr(::std::move(left), locus)); + } else { + return ::std::unique_ptr( + new AST::RangeFromToExpr(::std::move(left), ::std::move(right), locus)); + } + // FIXME: make non-associative + } + + /* Parses an exclusive range ('..') in null denotation position (i.e. RangeToExpr or + * RangeFullExpr). */ + ::std::unique_ptr Parser::parse_nud_range_exclusive_expr( + const_TokenPtr tok, ::std::vector outer_attrs ATTRIBUTE_UNUSED) { + // FIXME: this probably parses expressions accidently or whatever + // try parsing RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right = parse_expr(LBP_DOT_DOT, ::std::vector()); + + location_t locus = tok->get_locus(); + + if (right == NULL) { + // range from expr + return ::std::unique_ptr(new AST::RangeFullExpr(locus)); + } else { + return ::std::unique_ptr( + new AST::RangeToExpr(::std::move(right), locus)); + } + // FIXME: make non-associative + } + + // Parses a full binary range inclusive expression. + ::std::unique_ptr Parser::parse_range_inclusive_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, + ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right + = parse_expr(LBP_DOT_DOT_EQ, ::std::vector(), restrictions); + if (right == NULL) + return NULL; + // FIXME: make non-associative + + // TODO: check types. actually, do so during semantic analysis + location_t locus = left->get_locus_slow(); + + return ::std::unique_ptr( + new AST::RangeFromToInclExpr(::std::move(left), ::std::move(right), locus)); + } + + // Parses an inclusive range-to prefix unary expression. + ::std::unique_ptr Parser::parse_range_to_inclusive_expr( + const_TokenPtr tok, ::std::vector outer_attrs ATTRIBUTE_UNUSED) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr right = parse_expr(LBP_DOT_DOT_EQ); + if (right == NULL) + return NULL; + // FIXME: make non-associative + + // TODO: check types. actually, do so during semantic analysis + + return ::std::unique_ptr( + new AST::RangeToInclExpr(::std::move(right), tok->get_locus())); + } + + // Parses a pseudo-binary infix tuple index expression. + ::std::unique_ptr Parser::parse_tuple_index_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr tuple_expr, + ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // parse int literal (as token already skipped) + const_TokenPtr index_tok = expect_token(INT_LITERAL); + if (index_tok == NULL) { + return NULL; + } + ::std::string index = index_tok->get_str(); + + // convert to integer + int index_int = atoi(index.c_str()); + + location_t locus = tuple_expr->get_locus_slow(); + + return ::std::unique_ptr(new AST::TupleIndexExpr( + ::std::move(tuple_expr), index_int, ::std::move(outer_attrs), locus)); + } + + // Parses a pseudo-binary infix array (or slice) index expression. + ::std::unique_ptr Parser::parse_index_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr array_expr, + ::std::vector outer_attrs, ParseRestrictions restrictions) { + // parse RHS (as tok has already been consumed in parse_expression) + ::std::unique_ptr index_expr + = parse_expr(LBP_ARRAY_REF, ::std::vector(), restrictions); + if (index_expr == NULL) + return NULL; + + // skip ']' at end of array + if (!skip_token(RIGHT_SQUARE)) { + // skip somewhere? + return NULL; + } + + // TODO: check types. actually, do so during semantic analysis + location_t locus = array_expr->get_locus_slow(); + + return ::std::unique_ptr(new AST::ArrayIndexExpr( + ::std::move(array_expr), ::std::move(index_expr), ::std::move(outer_attrs), locus)); + } + + // Parses a pseudo-binary infix struct field access expression. + ::std::unique_ptr Parser::parse_field_access_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr struct_expr, + ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // get field name identifier (assume that this is a field access expr and not say await) + const_TokenPtr ident_tok = expect_token(IDENTIFIER); + Identifier ident = ident_tok->get_str(); + + location_t locus = struct_expr->get_locus_slow(); + + // TODO: check types. actually, do so during semantic analysis + return ::std::unique_ptr(new AST::FieldAccessExpr( + ::std::move(struct_expr), ::std::move(ident), ::std::move(outer_attrs), locus)); + } + + // Parses a pseudo-binary infix method call expression. + ::std::unique_ptr Parser::parse_method_call_expr(const_TokenPtr tok, + ::std::unique_ptr receiver_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // parse path expr segment + AST::PathExprSegment segment = parse_path_expr_segment(); + if (segment.is_error()) { + error_at(tok->get_locus(), "failed to parse path expr segment of method call expr"); + return NULL; + } + + // skip left parentheses + if (!skip_token(LEFT_PAREN)) { + return NULL; + } + + // parse method params (if they exist) + ::std::vector< ::std::unique_ptr > params; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + ::std::unique_ptr param = parse_expr(); + if (param == NULL) { + error_at(t->get_locus(), "failed to parse method param in method call"); + return NULL; + } + params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // skip right paren + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + // TODO: check types. actually do so in semantic analysis pass. + location_t locus = receiver_expr->get_locus_slow(); + + return ::std::unique_ptr( + new AST::MethodCallExpr(::std::move(receiver_expr), ::std::move(segment), + ::std::move(params), ::std::move(outer_attrs), locus)); + } + + // Parses a pseudo-binary infix function call expression. + ::std::unique_ptr Parser::parse_function_call_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr function_expr, + ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // parse function params (if they exist) + ::std::vector< ::std::unique_ptr > params; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + ::std::unique_ptr param = parse_expr(); + if (param == NULL) { + error_at(t->get_locus(), "failed to parse function param in function call"); + return NULL; + } + params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + // skip ')' at end of param list + if (!skip_token(RIGHT_PAREN)) { + // skip somewhere? + return NULL; + } + + // TODO: check types. actually, do so during semantic analysis + location_t locus = function_expr->get_locus_slow(); + + return ::std::unique_ptr(new AST::CallExpr( + ::std::move(function_expr), ::std::move(params), ::std::move(outer_attrs), locus)); + } + + // Parses a macro invocation with a path in expression already parsed (but not '!' token). + ::std::unique_ptr Parser::parse_macro_invocation_partial( + AST::PathInExpression path, ::std::vector outer_attrs) { + // macro invocation + if (!skip_token(EXCLAM)) { + return NULL; + } + + // convert PathInExpression to SimplePath - if this isn't possible, error + AST::SimplePath converted_path = path.as_simple_path(); + if (converted_path.is_empty()) { + error_at( + lexer.peek_token()->get_locus(), "failed to parse simple path in macro invocation"); + return NULL; + } + + AST::DelimTokenTree tok_tree = parse_delim_token_tree(); + + fprintf(stderr, "successfully parsed macro invocation (via partial)\n"); + + location_t macro_locus = converted_path.get_locus(); + + return ::std::unique_ptr(new AST::MacroInvocation( + ::std::move(converted_path), ::std::move(tok_tree), ::std::move(outer_attrs), macro_locus)); + } + + // Parses a struct expr struct with a path in expression already parsed (but not '{' token). + ::std::unique_ptr Parser::parse_struct_expr_struct_partial( + AST::PathInExpression path, ::std::vector outer_attrs) { + // assume struct expr struct (as struct-enum disambiguation requires name + // lookup) again, make statement if final ';' + if (!skip_token(LEFT_CURLY)) { + return NULL; + } + + // parse inner attributes + ::std::vector inner_attrs = parse_inner_attributes(); + + // branch based on next token + const_TokenPtr t = lexer.peek_token(); + location_t path_locus = path.get_locus(); + switch (t->get_id()) { + case RIGHT_CURLY: + // struct with no body + lexer.skip_token(); + + return ::std::unique_ptr(new AST::StructExprStruct( + ::std::move(path), ::std::move(inner_attrs), ::std::move(outer_attrs), path_locus)); + case DOT_DOT: + /* technically this would give a struct base-only struct, but this + * algorithm should work too. As such, AST type not happening. */ + case IDENTIFIER: + case INT_LITERAL: { + // struct with struct expr fields + + // parse struct expr fields + ::std::vector< ::std::unique_ptr > fields; + + while (t->get_id() != RIGHT_CURLY && t->get_id() != DOT_DOT) { + ::std::unique_ptr field = parse_struct_expr_field(); + if (field == NULL) { + error_at(t->get_locus(), "failed to parse struct (or enum) expr field"); + return NULL; + } + + // DEBUG: + fprintf(stderr, "struct/enum expr field validated to not be null \n"); + + fields.push_back(::std::move(field)); + + // DEBUG: + fprintf(stderr, "struct/enum expr field pushed back \n"); + + if (lexer.peek_token()->get_id() != COMMA) { + // DEBUG: + fprintf( + stderr, "lack of comma detected in struct/enum expr fields - break \n"); + break; + } + lexer.skip_token(); + + // DEBUG: + fprintf(stderr, "struct/enum expr fields comma skipped \n"); + + t = lexer.peek_token(); + } + + // DEBUG: + fprintf(stderr, "struct/enum expr about to parse struct base \n"); + + // parse struct base if it exists + AST::StructBase struct_base = AST::StructBase::error(); + if (lexer.peek_token()->get_id() == DOT_DOT) { + lexer.skip_token(); + + // parse required struct base expr + ::std::unique_ptr base_expr = parse_expr(); + if (base_expr == NULL) { + error_at(lexer.peek_token()->get_locus(), + "failed to parse struct base expression in struct " + "expression"); + return NULL; + } + + // DEBUG: + fprintf(stderr, "struct/enum expr - parsed and validated base expr \n"); + + struct_base = AST::StructBase(::std::move(base_expr)); + + // DEBUG: + fprintf(stderr, "assigned struct base to new struct base \n"); + } + + if (!skip_token(RIGHT_CURLY)) { + return NULL; + } + + // DEBUG: + fprintf(stderr, "struct/enum expr skipped right curly - done and ready to return \n"); + + return ::std::unique_ptr( + new AST::StructExprStructFields(::std::move(path), ::std::move(fields), path_locus, + ::std::move(struct_base), ::std::move(inner_attrs), ::std::move(outer_attrs))); + } + default: + error_at(t->get_locus(), + "unrecognised token '%s' in struct (or enum) expression - " + "expected '}', identifier, int literal, or '..'", + t->get_token_description()); + return NULL; + } + } + + // Parses a struct expr tuple with a path in expression already parsed (but not '(' token). + ::std::unique_ptr Parser::parse_struct_expr_tuple_partial( + AST::PathInExpression path, ::std::vector outer_attrs) { + if (!skip_token(LEFT_PAREN)) { + return NULL; + } + + ::std::vector inner_attrs = parse_inner_attributes(); + + ::std::vector< ::std::unique_ptr > exprs; + + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != RIGHT_PAREN) { + // parse expression (required) + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(t->get_locus(), "failed to parse expression in struct " + "(or enum) expression tuple"); + return NULL; + } + exprs.push_back(::std::move(expr)); + + if (lexer.peek_token()->get_id() != COMMA) { + break; + } + lexer.skip_token(); + + t = lexer.peek_token(); + } + + if (!skip_token(RIGHT_PAREN)) { + return NULL; + } + + location_t path_locus = path.get_locus(); + + return ::std::unique_ptr(new AST::StructExprTuple(::std::move(path), + ::std::move(exprs), ::std::move(inner_attrs), ::std::move(outer_attrs), path_locus)); + } + + /* Parses a path in expression with the first token passed as a parameter (as it is skipped in + * token stream). Note that this only parses segment-first paths, not global ones. */ + AST::PathInExpression Parser::parse_path_in_expression_pratt(const_TokenPtr tok) { + // HACK-y way of making up for pratt-parsing consuming first token + + // DEBUG + fprintf(stderr, "current peek token when starting path pratt parse: '%s'\n", + lexer.peek_token()->get_token_description()); + + // create segment vector + ::std::vector segments; + + ::std::string initial_str; + + switch (tok->get_id()) { + case IDENTIFIER: + initial_str = tok->get_str(); + break; + case SUPER: + initial_str = "super"; + break; + case SELF: + initial_str = "self"; + break; + case SELF_ALIAS: + initial_str = "Self"; + break; + case CRATE: + initial_str = "crate"; + break; + case DOLLAR_SIGN: + if (lexer.peek_token()->get_id() == CRATE) { + initial_str = "$crate"; + break; + } + gcc_fallthrough(); + default: + error_at(tok->get_locus(), "unrecognised token '%s' in path in expression", + tok->get_token_description()); + return AST::PathInExpression::create_error(); + } + + // parse required initial segment + AST::PathExprSegment initial_segment(initial_str, tok->get_locus()); + // parse generic args (and turbofish), if they exist + /* use lookahead to determine if they actually exist (don't want to accidently parse + * over next ident segment) */ + if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION + && lexer.peek_token(1)->get_id() == LEFT_ANGLE) { + // skip scope resolution + lexer.skip_token(); + + AST::GenericArgs generic_args = parse_path_generic_args(); + + initial_segment + = AST::PathExprSegment(initial_str, tok->get_locus(), ::std::move(generic_args)); + } + if (initial_segment.is_error()) { + // skip after somewhere? + // don't necessarily throw error but yeah + + // DEBUG + fprintf(stderr, "initial segment is error - returning null\n"); + + return AST::PathInExpression::create_error(); + } + segments.push_back(::std::move(initial_segment)); + + // parse optional segments (as long as scope resolution operator exists) + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() == SCOPE_RESOLUTION) { + // skip scope resolution operator + lexer.skip_token(); + + // parse the actual segment - it is an error if it doesn't exist now + AST::PathExprSegment segment = parse_path_expr_segment(); + if (segment.is_error()) { + // skip after somewhere? + error_at(t->get_locus(), "could not parse path expression segment"); + return AST::PathInExpression::create_error(); + } + + segments.push_back(::std::move(segment)); + + t = lexer.peek_token(); + } + + // DEBUG: + fprintf(stderr, "current token (just about to return path to null denotation): '%s'\n", + lexer.peek_token()->get_token_description()); + + return AST::PathInExpression(::std::move(segments), tok->get_locus(), false); + } + + // Parses a closure expression with pratt parsing (from null denotation). + ::std::unique_ptr Parser::parse_closure_expr_pratt( + const_TokenPtr tok, ::std::vector outer_attrs) { + // TODO: does this need pratt parsing (for precedence)? probably not, but idk + location_t locus = tok->get_locus(); + bool has_move = false; + if (tok->get_id() == MOVE) { + has_move = true; + tok = lexer.peek_token(); + lexer.skip_token(); + // skip token and reassign + } + + // handle parameter list + ::std::vector params; + + switch (tok->get_id()) { + case OR: + // no parameters, don't skip token + break; + case PIPE: { + // actually may have parameters + // don't skip token + const_TokenPtr t = lexer.peek_token(); + while (t->get_id() != PIPE) { + AST::ClosureParam param = parse_closure_param(); + if (param.is_error()) { + // TODO is this really an error? + error_at(t->get_locus(), "could not parse closure param"); + return NULL; + } + params.push_back(::std::move(param)); + + if (lexer.peek_token()->get_id() != COMMA) { + // not an error but means param list is done + break; + } + // skip comma + lexer.skip_token(); + + t = lexer.peek_token(); + } + + if (!skip_token(PIPE)) { + return NULL; + } + break; + } + default: + error_at(tok->get_locus(), + "unexpected token '%s' in closure expression - expected '|' or '||'", + tok->get_token_description()); + // skip somewhere? + return NULL; + } + + // again branch based on next token + tok = lexer.peek_token(); + if (tok->get_id() == RETURN_TYPE) { + // must be return type closure with block expr + + // skip "return type" token + lexer.skip_token(); + + // parse actual type, which is required + ::std::unique_ptr type = parse_type_no_bounds(); + if (type == NULL) { + // error + error_at(tok->get_locus(), "failed to parse type for closure"); + // skip somewhere? + return NULL; + } + + // parse block expr, which is required + ::std::unique_ptr block = parse_block_expr(); + if (block == NULL) { + // error + error_at(lexer.peek_token()->get_locus(), "failed to parse block expr in closure"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr( + new AST::ClosureExprInnerTyped(::std::move(type), ::std::move(block), + ::std::move(params), locus, has_move, ::std::move(outer_attrs))); + } else { + // must be expr-only closure + + // parse expr, which is required + ::std::unique_ptr expr = parse_expr(); + if (expr == NULL) { + error_at(tok->get_locus(), "failed to parse expression in closure"); + // skip somewhere? + return NULL; + } + + return ::std::unique_ptr(new AST::ClosureExprInner( + ::std::move(expr), ::std::move(params), locus, has_move, ::std::move(outer_attrs))); + } + } + + /* Parses a tuple index expression (pratt-parsed) from a 'float' token as a result of lexer + * misidentification. */ + ::std::unique_ptr Parser::parse_tuple_index_expr_float(const_TokenPtr tok, + ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions ATTRIBUTE_UNUSED) { + // only works on float literals + if (tok->get_id() != FLOAT_LITERAL) { + return NULL; + } + + // DEBUG: + fprintf(stderr, "exact string form of float: '%s'\n", tok->get_str().c_str()); + + // get float string and remove dot and initial 0 + ::std::string index_str = tok->get_str(); + index_str.erase(index_str.begin()); + + // get int from string + int index = atoi(index_str.c_str()); + + location_t locus = tuple_expr->get_locus_slow(); + + return ::std::unique_ptr( + new AST::TupleIndexExpr(::std::move(tuple_expr), index, ::std::move(outer_attrs), locus)); + } + + // Determines action to take when finding token at beginning of expression. + Tree Parser::null_denotation(const_TokenPtr tok) { + // note: tok is previous character in input stream, not current one, as parse_expression + // skips it before passing it in + + /* as a Pratt parser (which works by decomposing expressions into a null denotation and then a + * left denotation), null denotations handle primaries and unary operands (but only prefix + * unary operands) */ + + switch (tok->get_id()) { + case IDENTIFIER: { + // when encountering identifier, lookup in scope + SymbolPtr s = scope.lookup(tok->get_str()); + if (s == NULL) { + error_at(tok->get_locus(), "variable '%s' not declared in the current scope", + tok->get_str().c_str()); + + return Tree::error(); + } + // expression is just its VAR_DECL that was stored in the Symbol at declaration + return Tree(s->get_tree_decl(), tok->get_locus()); + } + case INT_LITERAL: + // we should check the range, but ignore for now + // literal itself encodes value, so token's text has to be interpreted as int. use + // atoi for this + return Tree(build_int_cst_type(integer_type_node, atoi(tok->get_str().c_str())), + tok->get_locus()); + case FLOAT_LITERAL: { + REAL_VALUE_TYPE float_value; + // invoke real_from_string3 to get float value representation from string + real_from_string3(&float_value, tok->get_str().c_str(), TYPE_MODE(float_type_node)); + // this is because machine-dependent + + // create actual tree with that built constant value + return Tree(build_real(float_type_node, float_value), tok->get_locus()); + } + case STRING_LITERAL: { + // get c string from token + std::string str = tok->get_str(); + const char* c_str = str.c_str(); + + // use GCC's build_string_literal (with null terminator) to create tree + return Tree(build_string_literal(strlen(c_str) + 1, c_str), tok->get_locus()); + } + case TRUE_LITERAL: { + // construct tree with code INTEGER_CST and value 1 but with boolean_type_node + return Tree(build_int_cst_type(boolean_type_node, 1), tok->get_locus()); + break; + } + case FALSE_LITERAL: { + return Tree(build_int_cst_type(boolean_type_node, 0), tok->get_locus()); + break; + } + case LEFT_PAREN: { // have to parse whole expression if inside brackets + /* recursively invoke parse_expression with lowest priority possible as it it were + * a top-level expression. */ + Tree expr = parse_expression(); + tok = lexer.peek_token(); + + // end of expression must be a close-bracket + if (tok->get_id() != RIGHT_PAREN) + error_at( + tok->get_locus(), "expecting ')' but %s found\n", tok->get_token_description()); + else + lexer.skip_token(); + + return Tree(expr, tok->get_locus()); + } + case PLUS: { // unary plus operator + // invoke parse_expression recursively with appropriate priority, etc. for below + Tree expr = parse_expression(LBP_UNARY_PLUS); + + if (expr.is_error()) + return Tree::error(); + // can only apply to integer and float expressions + if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { + error_at(tok->get_locus(), + "operand of unary plus must be int or float but it is %s", + print_type(expr.get_type())); + return Tree::error(); + } + + return Tree(expr, tok->get_locus()); + } + case MINUS: { // unary minus - TODO: does not work on unsigned integers + Tree expr = parse_expression(LBP_UNARY_MINUS); + + if (expr.is_error()) + return Tree::error(); + // can only apply to integer and float expressions + if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { + error_at(tok->get_locus(), + "operand of unary minus must be int or float but it is %s", + print_type(expr.get_type())); + return Tree::error(); + } + + // create NEGATE_EXPR tree, which computes negation of operand + expr = build_tree(NEGATE_EXPR, tok->get_locus(), expr.get_type(), expr); + return expr; + } + case EXCLAM: { // logical not - TODO: this could also be bitwise not + Tree expr = parse_expression(LBP_UNARY_EXCLAM /*LOGICAL_NOT*/); + + if (expr.is_error()) + return Tree::error(); + // can only apply to boolean expressions + if (expr.get_type() != boolean_type_node) { + error_at(tok->get_locus(), + "operand of logical not must be a boolean but it is %s", + print_type(expr.get_type())); + return Tree::error(); + } + + // create TRUTH_NOT_EXPR tree, which computes logical negation of operand + expr = build_tree(TRUTH_NOT_EXPR, tok->get_locus(), boolean_type_node, expr); + return expr; + } + case ASTERISK: { + // TODO: fix: this is pointer dereference only, I think + Tree expr = parse_expression(LBP_UNARY_ASTERISK); + return expr; + } + case AMP: { + // TODO: fix: this is reference only, I think + Tree expr = NULL_TREE; + + if (lexer.peek_token()->get_id() == MUT) + expr = parse_expression(LBP_UNARY_AMP_MUT); + else + expr = parse_expression(LBP_UNARY_AMP); + + return expr; + } + case SCOPE_RESOLUTION: { + // TODO: fix: this is for global paths, i.e. ::std::string::whatever + } + default: + unexpected_token(tok); + return Tree::error(); + } + } + + /* Called for each token that can appear in infix (between) position. Can be operators or other + * punctuation. + * Returns a function pointer to member function that implements the left denotation for the token + * given. */ + Tree Parser::left_denotation(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + /*BinaryHandler binary_handler = get_binary_handler(tok->get_id()); + if (binary_handler == NULL) { + unexpected_token(tok); + return Tree::error(); + } + + return (this->*binary_handler)(tok, left);*/ + return Tree::error(); + } + + // Gets method for handling binary operation parsing for specific token type. + /*Parser::BinaryHandler Parser::get_binary_handler(TokenId id) { + switch (id) { +#define BINARY_HANDLER(name, token_id) \ + case token_id: \ + return &Parser::binary_##name; + BINARY_HANDLER_LIST +#undef BINARY_HANDLER + default: + return NULL; + } + }*/ + + /* Returns the type of the binary operation. May also modify input trees if types do not match, + * e.g. change a float and int to two floats in addition. */ + Tree Parser::coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right) { + Tree left_type = left->get_type(); + Tree right_type = right->get_type(); + + // return error if either types are invalid + if (left_type.is_error() || right_type.is_error()) + return Tree::error(); + + // good, easy, no type conversion required + if (left_type == right_type) { + if (left_type == integer_type_node || left_type == float_type_node) { + return left_type; + } + // dodgy type coercion happening if types don't match but are both numerical + } else if ((left_type == integer_type_node && right_type == float_type_node) + || (left_type == float_type_node && right_type == integer_type_node)) { + // rebuild one tree as float + if (left_type == integer_type_node) { + *left = build_tree(FLOAT_EXPR, left->get_locus(), float_type_node, left->get_tree()); + } else { + *right + = build_tree(FLOAT_EXPR, right->get_locus(), float_type_node, right->get_tree()); + } + + return float_type_node; + } + + // unhandled - e.g. int + boolean + error_at(tok->get_locus(), "invalid operands of type %s and %s for operator %s", + print_type(left_type), print_type(right_type), tok->get_token_description()); + return Tree::error(); + } + + // Verifies that both left and right trees are boolean-type nodes. + bool Parser::check_logical_operands(const_TokenPtr tok, Tree left, Tree right) { + // ensure both operands are boolean types + if (left.get_type() != boolean_type_node || right.get_type() != boolean_type_node) { + error_at(tok->get_locus(), + "operands of operator %s must be boolean but they are %s and %s\n", + tok->get_token_description(), print_type(left.get_type()), + print_type(right.get_type())); + + return false; + } + + return true; + } + + // Implementation of addition expression parsing. + Tree Parser::binary_plus(const_TokenPtr tok, Tree left) { + // parse RHS (as tok has already been consumed in parse_expression) + Tree right = parse_expression(LBP_PLUS); + if (right.is_error()) + return Tree::error(); + + /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may + * also modify input trees. */ + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + // construct tree with code PLUS_EXPR to represent binary addition + return build_tree(PLUS_EXPR, tok->get_locus(), tree_type, left, right); + } + + // Implementation of subtraction expression parsing. + Tree Parser::binary_minus(const_TokenPtr tok, Tree left) { + // parse RHS (as tok has already been consumed in parse_expression) + Tree right = parse_expression(LBP_PLUS); + if (right.is_error()) + return Tree::error(); + + /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may + * also modify input trees. */ + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + // construct tree with code MINUS_EXPR to represent binary subtraction + return build_tree(MINUS_EXPR, tok->get_locus(), tree_type, left, right); + } + + // Implementation of multiplication expression parsing. + Tree Parser::binary_mult(const_TokenPtr tok, Tree left) { + // parse RHS (as tok has already been consumed in parse_expression) + Tree right = parse_expression(LBP_PLUS); + if (right.is_error()) + return Tree::error(); + + /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may + * also modify input trees. */ + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + // construct tree with code MULT_EXPR to represent binary multiplication + return build_tree(MULT_EXPR, tok->get_locus(), tree_type, left, right); + } + + // Implementation of divison expression parsing. + Tree Parser::binary_div(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_DIV); + if (right.is_error()) + return Tree::error(); + + // if integer division, create C-like truncated division expression tree + if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { + return build_tree(TRUNC_DIV_EXPR, tok->get_locus(), integer_type_node, left, right); + } else { + // floating-point division + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + gcc_assert(tree_type == float_type_node); + + return build_tree(RDIV_EXPR, tok->get_locus(), tree_type, left, right); + } + } + + // Implementation of modulo expression parsing. + Tree Parser::binary_mod(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_MOD); + if (right.is_error()) + return Tree::error(); + + // if integer modulo, create truncated modulo expression + if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { + return build_tree(TRUNC_MOD_EXPR, tok->get_locus(), integer_type_node, left, right); + } else { + // no floating-point modulo + return Tree::error(); + } + } + + // Implementation of binary equal comparison relational operator parsing. + Tree Parser::binary_equal(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_EQUAL); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(EQ_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary different comparison relational operator parsing. + Tree Parser::binary_not_equal /*different*/ (const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_NOT_EQUAL); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(NE_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary smaller than comparison relational operator parsing. + Tree Parser::binary_smaller_than(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_SMALLER_THAN); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(LT_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary greater than comparison relational operator parsing. + Tree Parser::binary_greater_than(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_GREATER_THAN); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(GT_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary smaller than or equal to comparison relational operator parsing. + Tree Parser::binary_smaller_equal(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_SMALLER_EQUAL); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(LE_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary greater than or equal to comparison relational operator parsing. + Tree Parser::binary_greater_equal(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_GREATER_EQUAL); + if (right.is_error()) + return Tree::error(); + + Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); + if (tree_type.is_error()) + return Tree::error(); + + return build_tree(GE_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary "and" logical operator parsing. + Tree Parser::binary_logical_and(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_LOGICAL_AND); + if (right.is_error()) + return Tree::error(); + + if (!check_logical_operands(tok, left, right)) + return Tree::error(); + + return build_tree(TRUTH_ANDIF_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary "or" logical operator parsing. + Tree Parser::binary_logical_or(const_TokenPtr tok, Tree left) { + // parse RHS + Tree right = parse_expression(LBP_LOGICAL_OR); + if (right.is_error()) + return Tree::error(); + + if (!check_logical_operands(tok, left, right)) + return Tree::error(); + + return build_tree(TRUTH_ORIF_EXPR, tok->get_locus(), boolean_type_node, left, right); + } + + // Implementation of binary array reference ([) operator parsing; + Tree Parser::binary_array_index(const_TokenPtr tok, Tree left) { + // parse integer expression inside square brackets (array index) + Tree right = parse_integer_expression(); + if (right.is_error()) + return Tree::error(); + + // array close token + if (!skip_token(RIGHT_SQUARE)) + return Tree::error(); + + // verify left operand has array type + if (!is_array_type(left.get_type())) { + error_at(left.get_locus(), "does not have array type"); + return Tree::error(); + } + + // compute type of array element + Tree element_type = TREE_TYPE(left.get_type().get_tree()); + + // build GENERIC tree ARRAY_REF that represents array access + return build_tree(ARRAY_REF, tok->get_locus(), element_type, left, right, Tree(), Tree()); + } + + // Parses a binary field access on a record. + Tree Parser::binary_field_ref(const_TokenPtr tok, Tree left) { + const_TokenPtr identifier = expect_token(IDENTIFIER); + if (identifier == NULL) + return Tree::error(); + + // ensure left expression has record type + if (!is_record_type(left.get_type())) { + error_at(left.get_locus(), "does not have record type"); + return Tree::error(); + } + + // traverse each FIELD_DECL chaining through TREE_CHAIN + // list of fields in record type is available through TYPE_FIELDS + Tree field_decl = TYPE_FIELDS(left.get_type().get_tree()); + while (!field_decl.is_null()) { + // FIELD_DECL has a DECL_NAME containing an IDENTIFIER_POINTER to get field name + Tree decl_name = DECL_NAME(field_decl.get_tree()); + const char* field_name = IDENTIFIER_POINTER(decl_name.get_tree()); + + if (field_name == identifier->get_str()) + break; + + field_decl = TREE_CHAIN(field_decl.get_tree()); + } + + // if can't find a field with given name, this is an error + if (field_decl.is_null()) { + error_at(left.get_locus(), "record type does not have a field named '%s'", + identifier->get_str().c_str()); + return Tree::error(); + } + + // build COMPONENT_REF tree using left tree (record type) and appropriate FIELD_DECL + return build_tree(COMPONENT_REF, tok->get_locus(), TREE_TYPE(field_decl.get_tree()), left, + field_decl, Tree()); + } + + // Method stub + Tree Parser::binary_bitwise_or(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_left_shift(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_bitwise_and(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_bitwise_xor(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_right_shift(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_as_cast(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_div_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_mod_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_mult_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_plus_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_minus_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_assignment_expr( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_bitwise_or_assig( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_bitwise_xor_assig( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_bitwise_and_assig( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_left_shift_assig( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Method stub + Tree Parser::binary_right_shift_assig( + const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { + return NULL_TREE; + } + + // Parse variable assignment statement. This is not the same as variable declaration. + Tree Parser::parse_assignment_statement() { + Tree variable = parse_lhs_assignment_expression(); + + if (variable.is_error()) + return Tree::error(); + + // TODO: fix + const_TokenPtr assig_tok = expect_token(/*ASSIG*/ COLON); + if (assig_tok == NULL) { + skip_after_semicolon(); + return Tree::error(); + } + + // skip assignment token and parse expression + const_TokenPtr first_of_expr = lexer.peek_token(); + + Tree expr = parse_expression(); + if (expr.is_error()) + return Tree::error(); + + // skip semicolon token + skip_token(SEMICOLON); + + // enforce rule that rhs of assignment has to have same type as declared lhs type + if (variable.get_type() != expr.get_type()) { + // diagnostic + error_at(first_of_expr->get_locus(), + "cannot assign value of type %s to a variable of type %s", print_type(expr.get_type()), + print_type(variable.get_type())); + + return Tree::error(); + } + + Tree assig_expr + = build_tree(MODIFY_EXPR, assig_tok->get_locus(), void_type_node, variable, expr); + return assig_expr; + } + + // Print human-readable name for type. + const char* Parser::print_type(Tree type) { + gcc_assert(TYPE_P(type.get_tree())); + + if (type == void_type_node) + return "void"; + else if (type == integer_type_node) + return "int"; + else if (type == float_type_node) + return "float"; + else if (is_string_type(type)) + return "string"; + else if (type == boolean_type_node) + return "boolean"; + else + return "<>"; + } + + // Returns address to function declaration of printf. + Tree Parser::get_printf_addr() { + // only run if printf_fn is null to avoid making repeated function declarations + if (printf_fn.is_null()) { + // build const char* type (printf fixed parameter) + tree fndecl_type_param[] + = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; + + // build function type as vararg function + tree fndecl_type + = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); + + // build declaration + tree printf_fn_decl = build_fn_decl("printf", fndecl_type); + // mark as external + DECL_EXTERNAL(printf_fn_decl) = 1; + + // build an ADDR_EXPR, which returns a pointer to type of function type (function address) + printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), printf_fn_decl); + } + + return printf_fn; + } + + // Returns address to function declaration of puts. + Tree Parser::get_puts_addr() { + if (puts_fn.is_null()) { + // build const char* type (puts fixed parameter) + tree fndecl_type_param[] + = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; + + // build function type + tree fndecl_type = build_function_type_array(integer_type_node, 1, fndecl_type_param); + + // build declaration + tree puts_fn_decl = build_fn_decl("puts", fndecl_type); + // mark as external + DECL_EXTERNAL(puts_fn_decl) = 1; + + // build an ADDR_EXPR, which returns a pointer to type of function type (function address) + puts_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), puts_fn_decl); + } + + return puts_fn; + } + + // Returns address to function declaration of scanf. + Tree Parser::get_scanf_addr() { + // only run if scanf_fn is null to avoid making repeated function declarations + if (scanf_fn.is_null()) { + // build const char* type (scanf fixed parameter) + tree fndecl_type_param[] + = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; + + // build function type as vararg function + tree fndecl_type + = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); + + // build declaration + tree scanf_fn_decl = build_fn_decl("scanf", fndecl_type); + // mark as external + DECL_EXTERNAL(scanf_fn_decl) = 1; + + // build an ADDR_EXPR, which returns a pointer to type of function type (function address) + scanf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), scanf_fn_decl); + } + + return scanf_fn; + } + + // Parses a "write statement". + /*Tree Parser::parse_write_statement() { + // write_statement -> "write" expression ";" + + if (!skip_token(WRITE)) { + skip_after_semicolon(); + return Tree::error(); + } + + const_TokenPtr first_of_expr = lexer.peek_token(); + Tree expr = parse_expression(); + + skip_token(SEMICOLON); + + if (expr.is_error()) + return Tree::error(); + + // enable printing of value of expression + if (expr.get_type() == integer_type_node) { + // printf("%d\n", expr) + // build format string for integer (also add null terminator) and integer expression + const char* format_integer = "%d\n"; + tree args[] + = { build_string_literal(strlen(format_integer) + 1, format_integer), expr.get_tree() }; + + // used as trees do not allow calling a FUNCTIONAL_DECL directly + Tree printf_fn = get_printf_addr(); + + // build call to print function (printf_fn), in which two arguments in args are passed + // first argument is format string + tree stmt = build_call_array_loc( + first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); + + return stmt; + } else if (expr.get_type() == float_type_node) { + // printf("%f\n" (double)expr) + // have to convert float to double + const char* format_float = "%f\n"; + tree args[] = { build_string_literal(strlen(format_float) + 1, format_float), + convert(double_type_node, expr.get_tree()) }; + + Tree printf_fn = get_printf_addr(); + + // build call, etc. + tree stmt = build_call_array_loc( + first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); + + return stmt; + } else if (is_string_type(expr.get_type())) { + // Alternatively we could use printf('%s\n', expr) instead of puts(expr) + tree args[] = { expr.get_tree() }; + + Tree puts_fn = get_puts_addr(); + + tree stmt = build_call_array_loc( + first_of_expr->get_locus(), integer_type_node, puts_fn.get_tree(), 1, args); + + return stmt; + } else { + // no more valid types + error_at(first_of_expr->get_locus(), "value of type %s is not a valid write operand", + print_type(expr.get_type())); + return Tree::error(); + } + + gcc_unreachable(); + }*/ + + // Enters new scope (like block scope or whatever). + void Parser::enter_scope() { + // push new symbol mapping + scope.push_scope(); + + TreeStmtList stmt_list; + // Used as stack for statements. + stack_stmt_list.push_back(stmt_list); + + // Used as stack of var decls. + stack_var_decl_chain.push_back(TreeChain()); + // Used as stack for blocks. + stack_block_chain.push_back(BlockChain()); + } + + // Leaves current scope (as defined by blocks - like block scope). + Parser::TreeSymbolMapping Parser::leave_scope() { + // Get current list of statements and pop them from stack of statement lists + TreeStmtList current_stmt_list = get_current_stmt_list(); + stack_stmt_list.pop_back(); + + // Get current list of var decls and pop them from stack of var decl lists + TreeChain var_decl_chain = stack_var_decl_chain.back(); + stack_var_decl_chain.pop_back(); + + // Get current list of blocks and pop them from stack of block lists + BlockChain subblocks = stack_block_chain.back(); + stack_block_chain.pop_back(); + + // Create a new block from var decls and subblocks + tree new_block = build_block(var_decl_chain.first.get_tree(), subblocks.first.get_tree(), + /* supercontext */ NULL_TREE, /* chain */ NULL_TREE); + + // Add the new block to the current chain of blocks (if any) + if (!stack_block_chain.empty()) { + stack_block_chain.back().append(new_block); + } + + // Set the subblocks to have the new block as their parent + for (tree it = subblocks.first.get_tree(); it != NULL_TREE; it = BLOCK_CHAIN(it)) + BLOCK_SUPERCONTEXT(it) = new_block; + // Do it this way because of double-linkage + + // Create BIND_EXPR from decl chain, stmt list, and new block + tree bind_expr = build3(BIND_EXPR, void_type_node, var_decl_chain.first.get_tree(), + current_stmt_list.get_tree(), new_block); + + // create, basically, a tuple of bind_expr and new_block + TreeSymbolMapping tree_scope; + tree_scope.bind_expr = bind_expr; + tree_scope.block = new_block; + + // pop symbol mapping + scope.pop_scope(); + + return tree_scope; + } + +#if 0 + // Parses the "read" statement. + Tree Parser::parse_read_statement() { + if (!skip_token(READ)) { + skip_after_semicolon(); + return Tree::error(); + } + + const_TokenPtr first_of_expr = lexer.peek_token(); + Tree expr = parse_expression_naming_variable(); + + skip_token(SEMICOLON); + + if (expr.is_error()) + return Tree::error(); + + // force variable name instead of manually looking up identifier token + /* if (expr.get_tree_code() != VAR_DECL) { + error_at(first_of_expr->get_locus(), "invalid expression in read statement"); + return Tree::error(); + }*/ + // not used anymore due to parse_expression_naming_variable + + // Variable must be addressable (variable needs address computed) + TREE_ADDRESSABLE(expr.get_tree()) = 1; + + // determine appropriate format string + const char* format = NULL; + if (expr.get_type() == integer_type_node) { + format = "%d"; + } else if (expr.get_type() == float_type_node) { + format = "%f"; + } else { + error_at(first_of_expr->get_locus(), "variable of type %s is not a valid read operand", + print_type(expr.get_type())); + return Tree::error(); + } + + // build args for scanf + tree args[] = { build_string_literal(strlen(format) + 1, format), + build_tree(ADDR_EXPR, first_of_expr->get_locus(), + build_pointer_type(expr.get_type().get_tree()), expr) + .get_tree() }; + + // get scanf address + Tree scanf_fn = get_scanf_addr(); + + // create tree to call scanf + tree stmt = build_call_array_loc( + first_of_expr->get_locus(), integer_type_node, scanf_fn.get_tree(), 2, args); + + return stmt; + } +#endif + + // Parses a while statement. + Tree Parser::parse_while_statement() { + if (!skip_token(WHILE)) { + skip_after_end(); + return Tree::error(); + } + + // parse while's conditional expression + Tree expr = parse_boolean_expression(); + if (!skip_token(DO)) { + skip_after_end(); + return Tree::error(); + } + + // enter loop body scope + enter_scope(); + parse_statement_seq(&Parser::done_end); + TreeSymbolMapping while_body_tree_scope = leave_scope(); + + Tree while_body_stmt = while_body_tree_scope.bind_expr; + + skip_token(RIGHT_CURLY); + + // build while statement tree + return build_while_statement(expr, while_body_stmt); + } + + // Builds a while statement tree. + Tree Parser::build_while_statement(Tree bool_expr, Tree while_body) { + if (bool_expr.is_error()) + return Tree::error(); + + TreeStmtList stmt_list; + + // build label decl for while condition check + Tree while_check_label_decl = build_label_decl("while_check", bool_expr.get_locus()); + + // build label expr for while condition check and add to statement list + Tree while_check_label_expr + = build_tree(LABEL_EXPR, bool_expr.get_locus(), void_type_node, while_check_label_decl); + stmt_list.append(while_check_label_expr); + + // build label decl for loop body and end of loop + Tree while_body_label_decl = build_label_decl("while_body", while_body.get_locus()); + Tree end_of_while_label_decl = build_label_decl("end_of_while", UNKNOWN_LOCATION); + + // add cond_expr tree that evaluates condition expression and branches to correct label + Tree cond_expr = build_tree(COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, + build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, while_body_label_decl), + build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, end_of_while_label_decl)); + stmt_list.append(cond_expr); + + // define location of label for body of loop and append to while body + Tree while_body_label_expr + = build_tree(LABEL_EXPR, while_body.get_locus(), void_type_node, while_body_label_decl); + stmt_list.append(while_body_label_expr); + + stmt_list.append(while_body); + + // branch back to condition check (as it is a loop) + Tree goto_check + = build_tree(GOTO_EXPR, UNKNOWN_LOCATION, void_type_node, while_check_label_decl); + stmt_list.append(goto_check); + + // define location of label for end of the while loop + Tree end_of_while_label_expr + = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, end_of_while_label_decl); + stmt_list.append(end_of_while_label_expr); + + return stmt_list.get_tree(); + } + + // Parse a for statement. + Tree Parser::parse_for_statement() { + // for -> for := to do end + if (!skip_token(FOR)) { + skip_after_end(); + return Tree::error(); + } + + const_TokenPtr identifier = expect_token(IDENTIFIER); + if (identifier == NULL) { + skip_after_end(); + return Tree::error(); + } + + // TODO + if (!skip_token(/*ASSIG*/ COLON)) { + skip_after_end(); + return Tree::error(); + } + + // parse lower bound expression + Tree lower_bound = parse_integer_expression(); + + // TODO + if (!skip_token(/*TO*/ DOT)) { + skip_after_end(); + return Tree::error(); + } + + // parse upper bound expression + Tree upper_bound = parse_integer_expression(); + + if (!skip_token(DO)) { + skip_after_end(); + return Tree::error(); + } + + // enter loop body scope and parse internal statements + enter_scope(); + parse_statement_seq(&Parser::done_end); + + TreeSymbolMapping for_body_tree_scope = leave_scope(); + Tree for_body_stmt = for_body_tree_scope.bind_expr; + + skip_token(RIGHT_CURLY); + + // Induction variable ("loop counter" variable) handling + SymbolPtr ind_var = query_integer_variable(identifier->get_str(), identifier->get_locus()); + + // build for statement + return build_for_statement(ind_var, lower_bound, upper_bound, for_body_stmt); + } + + // Builds a for statement tree (piggybacks on while statement tree building). + Tree Parser::build_for_statement( + SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list) { + if (ind_var == NULL) + return Tree::error(); + Tree ind_var_decl = ind_var->get_tree_decl(); + + // lower + if (lower_bound.is_error()) + return Tree::error(); + + // upper + if (upper_bound.is_error()) + return Tree::error(); + + // ind_var = lower + TreeStmtList stmt_list; + + // initialise induction variable with value of lower bound and append to stmt_list + Tree init_ind_var + = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, lower_bound); + stmt_list.append(init_ind_var); + + // define condition ind_var <= upper for use in while loop + Tree while_condition = build_tree( + LE_EXPR, upper_bound.get_locus(), boolean_type_node, ind_var_decl, upper_bound); + + // simulate incrementing ind_var + Tree incr_ind_var = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, + build_tree(PLUS_EXPR, UNKNOWN_LOCATION, integer_type_node, ind_var_decl, + build_int_cst_type(integer_type_node, 1))); + + // Wrap as stmt list + TreeStmtList for_stmt_list = for_body_stmt_list; + for_stmt_list.append(incr_ind_var); + + // construct associated while statement and append to stmt_list + Tree while_stmt = build_while_statement(while_condition, for_stmt_list.get_tree()); + stmt_list.append(while_stmt); + + // return entire stmt_list + return stmt_list.get_tree(); + } + + // Gets type (as in typedef) of name in current scope. + SymbolPtr Parser::query_type(const std::string& name, location_t loc) { + SymbolPtr sym = scope.lookup(name); + if (sym == NULL) { + error_at(loc, "type '%s' not declared in the current scope", name.c_str()); + } else if (sym->get_kind() != TYPENAME) { + error_at(loc, "name '%s' is not a type", name.c_str()); + sym = SymbolPtr(); + } + + return sym; + } + + // Get variable of name in current scope. + SymbolPtr Parser::query_variable(const std::string& name, location_t loc) { + SymbolPtr sym = scope.lookup(name); + if (sym == NULL) { + error_at(loc, "variable '%s' not declared in the current scope", name.c_str()); + } else if (sym->get_kind() != VARIABLE) { + error_at(loc, "name '%s' is not a variable", name.c_str()); + sym = SymbolPtr(); + } + return sym; + } + + // Gets variable of name in current scope and ensures it has integer type. + SymbolPtr Parser::query_integer_variable(const std::string& name, location_t loc) { + SymbolPtr sym = query_variable(name, loc); + if (sym != NULL) { + Tree var_decl = sym->get_tree_decl(); + gcc_assert(!var_decl.is_null()); + + if (var_decl.get_type() != integer_type_node) { + error_at(loc, "variable '%s' does not have integer type", name.c_str()); + sym = SymbolPtr(); + } + } + + return sym; + } + + // Returns true if the next token is END, ELSE, or EOF; + bool Parser::done_end_or_else() { + const_TokenPtr t = lexer.peek_token(); + return (t->get_id() == RIGHT_CURLY || t->get_id() == ELSE || t->get_id() == END_OF_FILE); + } + + // Returns true if the next token is END or EOF. + bool Parser::done_end() { + const_TokenPtr t = lexer.peek_token(); + return (t->get_id() == RIGHT_CURLY || t->get_id() == END_OF_FILE); + } + + // Parses expression and ensures it is a variable declaration or array reference. + Tree Parser::parse_expression_naming_variable() { + Tree expr = parse_expression(); + if (expr.is_error()) + return expr; + + if (expr.get_tree_code() != VAR_DECL && expr.get_tree_code() != ARRAY_REF + && expr.get_tree_code() != COMPONENT_REF) { + error_at(expr.get_locus(), "does not designate a variable, array element or field"); + return Tree::error(); + } + + return expr; + } + + // Parses expression and ensures it is an assignment expression? + Tree Parser::parse_lhs_assignment_expression() { + return parse_expression_naming_variable(); + } + + // Parses type (as in typedef) declaration statement. + /*Tree Parser::parse_type_declaration() { + // type_declaration -> "type" identifier ":" type ";" + if (!skip_token(TYPE)) { + skip_after_semicolon(); + return Tree::error(); + } + + // get identifier + const_TokenPtr identifier = expect_token(IDENTIFIER); + if (identifier == NULL) { + skip_after_semicolon(); + return Tree::error(); + } + + // skip colon + if (!skip_token(COLON)) { + skip_after_semicolon(); + return Tree::error(); + } + + // get type of expression + Tree type_tree = parse_type(); + + if (type_tree.is_error()) { + skip_after_semicolon(); + return Tree::error(); + } + + skip_token(SEMICOLON); + + // ensure not already delcared in scope + if (scope.get_current_mapping().get(identifier->get_str())) { + error_at(identifier->get_locus(), "name '%s' already declared in this scope", + identifier->get_str().c_str()); + } + + // create new symbol for typedef and put in mapping for current scope + SymbolPtr sym(new Symbol(TYPENAME, identifier->get_str())); + scope.get_current_mapping().insert(sym); + + // build typedef tree + Tree decl = build_decl(identifier->get_locus(), TYPE_DECL, + get_identifier(sym->get_name().c_str()), type_tree.get_tree()); + DECL_CONTEXT(decl.get_tree()) = main_fndecl; + + // add type declaration to variable declaration stack + gcc_assert(!stack_var_decl_chain.empty()); + stack_var_decl_chain.back().append(decl); + + // set symbol's declaration tree to declaration tree + sym->set_tree_decl(decl); + + // build declaration statement for tree + Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); + + return stmt; + }*/ + + // Parses a record type field declaration. + /*Tree Parser::parse_field_declaration(std::vector& field_names) { + // identifier ':' type ';' + const_TokenPtr identifier = expect_token(IDENTIFIER); + if (identifier == NULL) { + skip_after_semicolon(); + return Tree::error(); + } + + skip_token(COLON); + + Tree type = parse_type(); + + skip_token(SEMICOLON); + + if (type.is_error()) + return Tree::error(); + + // pass vector of fields to avoid repeated field names - error if they exist + if (std::find(field_names.begin(), field_names.end(), identifier->get_str()) + != field_names.end()) { + error_at(identifier->get_locus(), "repeated field name"); + return Tree::error(); + } + + field_names.push_back(identifier->get_str()); + + // create GENERIC FIELD_DECL tree with name of tree and type + Tree field_decl = build_decl(identifier->get_locus(), FIELD_DECL, + get_identifier(identifier->get_str().c_str()), type.get_tree()); + // required for read statement to work on fields + TREE_ADDRESSABLE(field_decl.get_tree()) = 1; + + return field_decl; + }*/ + + // TODO: remove: here to solve link errors + Tree Parser::parse_record() { + return Tree::error(); + } + // Parses a record. + /*Tree Parser::parse_record() { + // "record" field-decl* "end" + const_TokenPtr record_tok = expect_token(RECORD); + if (record_tok == NULL) { + skip_after_semicolon(); + return Tree::error(); + } + + // create empty record type tree + Tree record_type = make_node(RECORD_TYPE); + Tree field_list, field_last; + std::vector field_names; + + // parse field declarations inside record until the end token is found + const_TokenPtr next = lexer.peek_token(); + while (next->get_id() != END) { + Tree field_decl = parse_field_declaration(field_names); + + if (!field_decl.is_error()) { + // set field declaration's decl_context to this record type + DECL_CONTEXT(field_decl.get_tree()) = record_type.get_tree(); + if (field_list.is_null()) + field_list = field_decl; + if (!field_last.is_null()) + // chain fields in record type by using tree_chain + TREE_CHAIN(field_last.get_tree()) = field_decl.get_tree(); + field_last = field_decl; + } + + next = lexer.peek_token(); + } + + skip_token(END); + + // first field sets TYPE_FIELDS attribute of the RECORD_TYPE tree + TYPE_FIELDS(record_type.get_tree()) = field_list.get_tree(); + // request GCC to layout type in memory + layout_type(record_type.get_tree()); + + return record_type; + }*/ + + // Dumps lexer output to stderr. + void Parser::debug_dump_lex_output() { + Rust::const_TokenPtr tok = lexer.peek_token(); + + while (true) { + bool has_text + = tok->get_id() == Rust::IDENTIFIER || tok->get_id() == Rust::INT_LITERAL + || tok->get_id() == Rust::FLOAT_LITERAL || tok->get_id() == Rust::STRING_LITERAL + || tok->get_id() == Rust::CHAR_LITERAL || tok->get_id() == Rust::BYTE_STRING_LITERAL + || tok->get_id() == Rust::BYTE_CHAR_LITERAL; + + location_t loc = tok->get_locus(); + + fprintf(stderr, "\n", tok->token_id_to_str(), + has_text ? (std::string(", text=") + tok->get_str() + std::string(", typehint=") + + std::string(tok->get_type_hint_str())) + .c_str() + : "", + LOCATION_FILE(loc), LOCATION_LINE(loc), LOCATION_COLUMN(loc)); + + if (tok->get_id() == Rust::END_OF_FILE) + break; + + lexer.skip_token(); + tok = lexer.peek_token(); + } + } + + // Parses crate and dumps AST to stderr, recursively. + void Parser::debug_dump_ast_output() { + AST::Crate crate = parse_crate(); + + // print crate "as string", which then calls each item as string, etc. + fprintf(stderr, crate.as_string().c_str()); + } +} \ No newline at end of file diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h new file mode 100644 index 0000000..94d1eab --- /dev/null +++ b/gcc/rust/parse/rust-parse.h @@ -0,0 +1,613 @@ +#ifndef RUST_PARSE_H +#define RUST_PARSE_H + +#include "rust-lex.h" +//#include "rust-tree.h" +#include "rust-scope.h" + +//#include "rust-ast-containers.h" +// TODO: change, maybe? +#include "rust-ast-full.h" + +namespace Rust { + /* HACK: used to resolve the expression-or-statement problem at the end of a block by allowing + * either to be returned (technically). Tagged union would probably take up the same amount of + * space. */ + struct ExprOrStmt { + ::std::unique_ptr expr; + ::std::unique_ptr stmt; + + /* I was going to resist the urge to make this a real class and make it POD, but construction + * in steps is too difficult. So it'll just also have a constructor. */ + + // expression constructor + ExprOrStmt(::std::unique_ptr expr) : expr(::std::move(expr)) {} + + // statement constructor + ExprOrStmt(::std::unique_ptr stmt) : stmt(::std::move(stmt)) {} + + // Returns whether this object is in an error state. + inline bool is_error() const { + return (expr == NULL && stmt == NULL) || (expr != NULL && stmt != NULL); + } + + // Returns an error state object. + static ExprOrStmt create_error() { + return ExprOrStmt(NULL, NULL); + } + + ~ExprOrStmt() = default; + + // no copy constructors/assignment copy as simple object like this shouldn't require it + + // move constructors + ExprOrStmt(ExprOrStmt&& other) = default; + ExprOrStmt& operator=(ExprOrStmt&& other) = default; + + private: + // private constructor only used for creating error state expr or stmt objects + ExprOrStmt(AST::ExprWithoutBlock* expr, AST::Stmt* stmt) : expr(expr), stmt(stmt) {} + + // make this work: have a disambiguation specifically for known statements (i.e. ';' and + // 'let'). then, have a special "parse expr or stmt" function that returns this type. inside + // it, it parses an expression, and then determines whether to return expr or stmt via whether + // the next token is a semicolon. should be able to disambiguate inside that function between + // stmts with blocks and without blocks. + }; + + /* Restrictions on parsing used to signal that certain ambiguous grammar features should be parsed + * in a certain way.*/ + struct ParseRestrictions { + bool can_be_struct_expr = true; + /* Whether the expression was entered from a unary expression - prevents stuff like struct + * exprs being parsed from a dereference. */ + bool entered_from_unary = false; + }; + + // Parser implementation for gccrs. + class Parser { + private: + void skip_after_semicolon(); + void skip_after_end(); + void skip_after_end_block(); + void skip_after_next_block(); + void skip_after_end_attribute(); + + bool skip_token(TokenId t); + const_TokenPtr expect_token(TokenId t); + void unexpected_token(const_TokenPtr t); + bool skip_generics_right_angle(); + + // expression parsing + int left_binding_power(const_TokenPtr tok); + Tree null_denotation(const_TokenPtr tok); + Tree left_denotation(const_TokenPtr tok, Tree left); + + Tree parse_expression(int right_binding_power); + + Tree coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right); + bool check_logical_operands(const_TokenPtr tok, Tree left, Tree right); + + Tree get_printf_addr(); + Tree get_puts_addr(); + + Tree get_scanf_addr(); + + Tree build_label_decl(const char* name, location_t loc); + Tree build_if_statement(Tree bool_expr, Tree then_part, Tree else_part); + Tree build_while_statement(Tree bool_expr, Tree while_body); + Tree build_for_statement( + SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list); + + const char* print_type(Tree type); + + TreeStmtList& get_current_stmt_list(); + + void enter_scope(); + + struct TreeSymbolMapping { + Tree bind_expr; + Tree block; + }; + + TreeSymbolMapping leave_scope(); + + SymbolPtr query_type(const std::string& name, location_t loc); + SymbolPtr query_variable(const std::string& name, location_t loc); + SymbolPtr query_integer_variable(const std::string& name, location_t loc); + + void parse_statement_seq(bool (Parser::*done)()); + + // AST-related stuff - maybe move or something? + ::std::vector parse_inner_attributes(); + AST::Attribute parse_inner_attribute(); + ::std::vector parse_outer_attributes(); + AST::Attribute parse_outer_attribute(); + AST::Attribute parse_attribute_body(); + ::std::unique_ptr parse_attr_input(); + + // Path-related + AST::SimplePath parse_simple_path(); + AST::SimplePathSegment parse_simple_path_segment(); + AST::TypePath parse_type_path(); + ::std::unique_ptr parse_type_path_segment(); + AST::PathIdentSegment parse_path_ident_segment(); + AST::GenericArgs parse_path_generic_args(); + AST::GenericArgsBinding parse_generic_args_binding(); + AST::TypePathFunction parse_type_path_function(); + AST::PathInExpression parse_path_in_expression(); + AST::PathExprSegment parse_path_expr_segment(); + AST::QualifiedPathInExpression parse_qualified_path_in_expression(bool pratt_parse = false); + AST::QualifiedPathType parse_qualified_path_type(bool pratt_parse = false); + AST::QualifiedPathInType parse_qualified_path_in_type(); + + // Token tree or macro related + AST::DelimTokenTree parse_delim_token_tree(); + ::std::unique_ptr parse_token_tree(); + ::std::unique_ptr parse_macro_rules_def( + ::std::vector outer_attrs); + ::std::unique_ptr parse_macro_invocation_semi( + ::std::vector outer_attrs); + ::std::unique_ptr parse_macro_invocation( + ::std::vector outer_attrs); + AST::MacroRule parse_macro_rule(); + AST::MacroMatcher parse_macro_matcher(); + ::std::unique_ptr parse_macro_match(); + ::std::unique_ptr parse_macro_match_fragment(); + ::std::unique_ptr parse_macro_match_repetition(); + + // Top-level item-related + ::std::vector< ::std::unique_ptr > parse_items(); + ::std::unique_ptr parse_item(bool called_from_statement); + ::std::unique_ptr parse_vis_item(::std::vector outer_attrs); + ::std::unique_ptr parse_macro_item(::std::vector outer_attrs); + AST::Visibility parse_visibility(); + + // VisItem subclass-related + ::std::unique_ptr parse_module( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_extern_crate( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_use_decl( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_use_tree(); + ::std::unique_ptr parse_function( + AST::Visibility vis, ::std::vector outer_attrs); + AST::FunctionQualifiers parse_function_qualifiers(); + ::std::vector< ::std::unique_ptr > parse_generic_params_in_angles(); + ::std::vector< ::std::unique_ptr > parse_generic_params(); + ::std::vector< ::std::unique_ptr > parse_lifetime_params(); + ::std::vector parse_lifetime_params_objs(); + AST::LifetimeParam parse_lifetime_param(); + ::std::vector< ::std::unique_ptr > parse_type_params(); + ::std::unique_ptr parse_type_param(); + ::std::vector parse_function_params(); + AST::FunctionParam parse_function_param(); + ::std::unique_ptr parse_function_return_type(); + AST::WhereClause parse_where_clause(); + ::std::unique_ptr parse_where_clause_item(); + ::std::unique_ptr parse_lifetime_where_clause_item(); + ::std::unique_ptr parse_type_bound_where_clause_item(); + ::std::vector parse_for_lifetimes(); + ::std::vector< ::std::unique_ptr > parse_type_param_bounds(); + ::std::unique_ptr parse_type_param_bound(); + ::std::unique_ptr parse_trait_bound(); + ::std::vector parse_lifetime_bounds(); + AST::Lifetime parse_lifetime(); + ::std::unique_ptr parse_type_alias( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_struct( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::vector parse_struct_fields(); + AST::StructField parse_struct_field(); + ::std::vector parse_tuple_fields(); + AST::TupleField parse_tuple_field(); + ::std::unique_ptr parse_enum( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::vector< ::std::unique_ptr > parse_enum_items(); + ::std::unique_ptr parse_enum_item(); + ::std::unique_ptr parse_union( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_const_item( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_static_item( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_trait( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_trait_item(); + ::std::unique_ptr parse_trait_type( + ::std::vector outer_attrs); + ::std::unique_ptr parse_trait_const( + ::std::vector outer_attrs); + AST::SelfParam parse_self_param(); + ::std::unique_ptr parse_impl( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_inherent_impl_item(); + ::std::unique_ptr parse_inherent_impl_function_or_method( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_trait_impl_item(); + ::std::unique_ptr parse_trait_impl_function_or_method( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_extern_block( + AST::Visibility vis, ::std::vector outer_attrs); + ::std::unique_ptr parse_external_item(); + AST::NamedFunctionParam parse_named_function_param(); + AST::Method parse_method(); + + // Expression-related (Pratt parsed) + ::std::unique_ptr parse_expr( + ::std::vector outer_attrs = ::std::vector(), + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_expr(int right_binding_power, + ::std::vector outer_attrs = ::std::vector(), + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr null_denotation_NEW(const_TokenPtr t, + ::std::vector outer_attrs = ::std::vector(), + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr left_denotation(const_TokenPtr t, + ::std::unique_ptr left, + ::std::vector outer_attrs = ::std::vector(), + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_plus_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_minus_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_mult_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_div_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_mod_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_bitwise_and_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_bitwise_or_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_bitwise_xor_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_left_shift_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_right_shift_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_equal_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_not_equal_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_greater_than_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_less_than_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_greater_equal_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_binary_less_equal_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_lazy_or_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_lazy_and_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_type_cast_expr(const_TokenPtr tok, + ::std::unique_ptr expr_to_cast, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_plus_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_minus_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_mult_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_div_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_mod_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_and_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_or_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_xor_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_left_shift_assig_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_right_shift_assig_expr( + const_TokenPtr tok, ::std::unique_ptr left, + ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_await_expr(const_TokenPtr tok, + ::std::unique_ptr expr_to_await, ::std::vector outer_attrs); + ::std::unique_ptr parse_method_call_expr(const_TokenPtr tok, + ::std::unique_ptr receiver_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_function_call_expr(const_TokenPtr tok, + ::std::unique_ptr function_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_led_range_exclusive_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_nud_range_exclusive_expr( + const_TokenPtr tok, ::std::vector outer_attrs); + ::std::unique_ptr parse_range_inclusive_expr(const_TokenPtr tok, + ::std::unique_ptr left, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_range_to_inclusive_expr( + const_TokenPtr tok, ::std::vector outer_attrs); + ::std::unique_ptr parse_tuple_index_expr(const_TokenPtr tok, + ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_field_access_expr(const_TokenPtr tok, + ::std::unique_ptr struct_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_index_expr(const_TokenPtr tok, + ::std::unique_ptr array_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + ::std::unique_ptr parse_macro_invocation_partial( + AST::PathInExpression path, ::std::vector outer_attrs); + ::std::unique_ptr parse_struct_expr_struct_partial( + AST::PathInExpression path, ::std::vector outer_attrs); + ::std::unique_ptr parse_struct_expr_tuple_partial( + AST::PathInExpression path, ::std::vector outer_attrs); + AST::PathInExpression parse_path_in_expression_pratt(const_TokenPtr tok); + ::std::unique_ptr parse_closure_expr_pratt(const_TokenPtr tok, + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_tuple_index_expr_float(const_TokenPtr tok, + ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, + ParseRestrictions restrictions = ParseRestrictions()); + + // Expression-related (non-Pratt parsed) + ::std::unique_ptr parse_expr_without_block( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_block_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_if_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_if_let_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_loop_expr( + ::std::vector outer_attrs = ::std::vector(), + AST::LoopLabel label = AST::LoopLabel::error()); + ::std::unique_ptr parse_while_loop_expr( + ::std::vector outer_attrs = ::std::vector(), + AST::LoopLabel label = AST::LoopLabel::error()); + ::std::unique_ptr parse_while_let_loop_expr( + ::std::vector outer_attrs = ::std::vector(), + AST::LoopLabel label = AST::LoopLabel::error()); + ::std::unique_ptr parse_for_loop_expr( + ::std::vector outer_attrs = ::std::vector(), + AST::LoopLabel label = AST::LoopLabel::error()); + ::std::unique_ptr parse_match_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + AST::MatchArm parse_match_arm(); + ::std::vector< ::std::unique_ptr > parse_match_arm_patterns( + TokenId end_token_id); + ::std::unique_ptr parse_labelled_loop_expr( + ::std::vector outer_attrs = ::std::vector()); + AST::LoopLabel parse_loop_label(); + ::std::unique_ptr parse_async_block_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_unsafe_block_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_grouped_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_closure_expr( + ::std::vector outer_attrs = ::std::vector()); + AST::ClosureParam parse_closure_param(); + ::std::unique_ptr parse_literal_expr( + ::std::vector outer_attrs = ::std::vector()); + ::std::unique_ptr parse_return_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_break_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_continue_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_array_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_grouped_or_tuple_expr( + ::std::vector outer_attrs = ::std::vector(), + bool pratt_parse = false); + ::std::unique_ptr parse_struct_expr_field(); + + // Type-related + ::std::unique_ptr parse_type(); + ::std::unique_ptr parse_type_no_bounds(); + ::std::unique_ptr parse_slice_or_array_type(); + ::std::unique_ptr parse_raw_pointer_type(); + ::std::unique_ptr parse_reference_type(); + ::std::unique_ptr parse_bare_function_type( + ::std::vector for_lifetimes); + ::std::unique_ptr parse_paren_prefixed_type(); + ::std::unique_ptr parse_paren_prefixed_type_no_bounds(); + ::std::unique_ptr parse_for_prefixed_type(); + AST::MaybeNamedParam parse_maybe_named_param(); + + // Statement-related + ::std::unique_ptr parse_stmt(); + ::std::unique_ptr parse_let_stmt(::std::vector outer_attrs); + ::std::unique_ptr parse_expr_stmt(::std::vector outer_attrs); + ::std::unique_ptr parse_expr_stmt_with_block( + ::std::vector outer_attrs); + ::std::unique_ptr parse_expr_stmt_without_block( + ::std::vector outer_attrs); + ExprOrStmt parse_stmt_or_expr_without_block(); + ExprOrStmt parse_macro_invocation_maybe_semi(::std::vector outer_attrs); + ExprOrStmt parse_path_based_stmt_or_expr(::std::vector outer_attrs); + + // Pattern-related + ::std::unique_ptr parse_pattern(); + ::std::unique_ptr parse_literal_or_range_pattern(); + ::std::unique_ptr parse_range_pattern_bound(); + ::std::unique_ptr parse_reference_pattern(); + ::std::unique_ptr parse_grouped_or_tuple_pattern(); + ::std::unique_ptr parse_slice_pattern(); + ::std::unique_ptr parse_identifier_pattern(); + ::std::unique_ptr parse_ident_leading_pattern(); + ::std::unique_ptr parse_tuple_struct_items(); + AST::StructPatternElements parse_struct_pattern_elems(); + ::std::unique_ptr parse_struct_pattern_field(); + + // void parse_crate(); + // AST::Module parse_module(); + // void parse_module_item(AST::Module module_for_items, AST::AttributeList + // item_outer_attributes); AST::Visibility parse_visibility(); + + bool done_end(); + bool done_end_or_else(); + bool done_end_of_file(); + + typedef Tree (Parser::*BinaryHandler)(const_TokenPtr, Tree); + BinaryHandler get_binary_handler(TokenId id); + + public: + // Construct parser with specified lexer reference. + Parser(Lexer& parLexer) : lexer(parLexer), printf_fn(), puts_fn(), scanf_fn() {} + + // (old) Main entry point for parser. + void parse_program(); + + // Main entry point for parser. + AST::Crate parse_crate(); + + Tree parse_statement(); + + Tree parse_variable_declaration(); + Tree parse_type_declaration(); + + // Tree parse_type(); + Tree parse_record(); + Tree parse_field_declaration(std::vector& field_names); + + Tree parse_assignment_statement(); + Tree parse_if_statement(); + Tree parse_while_statement(); + Tree parse_for_statement(); + Tree parse_read_statement(); + Tree parse_write_statement(); + + Tree parse_expression(); + Tree parse_expression_naming_variable(); + Tree parse_lhs_assignment_expression(); + Tree parse_boolean_expression(); + Tree parse_integer_expression(); + + // Dumps all lexer output. + void debug_dump_lex_output(); + void debug_dump_ast_output(); + + private: + // The lexer associated with the parser. + Lexer& lexer; + // The current scope. + Scope scope; + + // The simulated "main" function inside which the entire program lies. + tree main_fndecl; + + // Address to function declaration of printf. + Tree printf_fn; + // Address to function declaration of puts. + Tree puts_fn; + // Address to function declaration of scanf. + Tree scanf_fn; + + // The statement stack. + std::vector stack_stmt_list; + // The VAR_DECL stack. + std::vector stack_var_decl_chain; + + // The block stack. + std::vector stack_block_chain; + +// x-macro list for binary operators - only defined here to be inside Parser class +#define BINARY_HANDLER_LIST \ + BINARY_HANDLER(plus, PLUS) \ + BINARY_HANDLER(minus, MINUS) \ + BINARY_HANDLER(mult, ASTERISK) \ + BINARY_HANDLER(div, DIV) \ + BINARY_HANDLER(mod, PERCENT) \ + BINARY_HANDLER(bitwise_and, AMP) \ + BINARY_HANDLER(bitwise_or, PIPE) \ + BINARY_HANDLER(bitwise_xor, CARET) \ + BINARY_HANDLER(left_shift, LEFT_SHIFT) \ + BINARY_HANDLER(right_shift, RIGHT_SHIFT) \ + \ + BINARY_HANDLER(equal, EQUAL_EQUAL) \ + BINARY_HANDLER(not_equal, NOT_EQUAL) \ + BINARY_HANDLER(smaller_than, LEFT_ANGLE) \ + BINARY_HANDLER(smaller_equal, LESS_OR_EQUAL) \ + BINARY_HANDLER(greater_than, RIGHT_ANGLE) \ + BINARY_HANDLER(greater_equal, GREATER_OR_EQUAL) \ + \ + BINARY_HANDLER(logical_and, LOGICAL_AND) \ + BINARY_HANDLER(logical_or, OR) \ + \ + BINARY_HANDLER(as_cast, AS) \ + /* should this really be an operator? */ \ + \ + BINARY_HANDLER(array_index, LEFT_SQUARE) \ + \ + BINARY_HANDLER(field_ref, DOT) \ + /*BINARY_HANDLER(method_call, DOT)*/ \ + BINARY_HANDLER(error_propagation, QUESTION_MARK) \ + /* not a binary operator, technically, but still left denotation */ \ + BINARY_HANDLER(assignment_expr, EQUAL) \ + /* should this really be an operator? or a binary one? */ \ + /* if it should, also add all operation-assign below:*/ \ + BINARY_HANDLER(plus_assig, PLUS_EQ) \ + BINARY_HANDLER(minus_assig, MINUS_EQ) \ + BINARY_HANDLER(mult_assig, ASTERISK_EQ) \ + BINARY_HANDLER(div_assig, DIV_EQ) \ + BINARY_HANDLER(mod_assig, PERCENT_EQ) \ + BINARY_HANDLER(bitwise_and_assig, AMP_EQ) \ + BINARY_HANDLER(bitwise_or_assig, PIPE_EQ) \ + BINARY_HANDLER(bitwise_xor_assig, CARET_EQ) \ + BINARY_HANDLER(left_shift_assig, LEFT_SHIFT_EQ) \ + BINARY_HANDLER(right_shift_assig, RIGHT_SHIFT_EQ) \ + \ + BINARY_HANDLER(range_exclusive, DOT_DOT) \ + BINARY_HANDLER(range_inclusive, DOT_DOT_EQ) \ + \ + BINARY_HANDLER(path, SCOPE_RESOLUTION) \ + \ + BINARY_HANDLER(return, RETURN_TOK) \ + BINARY_HANDLER(break, BREAK) \ + BINARY_HANDLER(closure, MOVE) + +// create declarations for binary op handling +#define BINARY_HANDLER(name, _) Tree binary_##name(const_TokenPtr tok, Tree left); + BINARY_HANDLER_LIST +#undef BINARY_HANDLER + }; +} + +#endif // RUST_PARSE_H \ No newline at end of file diff --git a/gcc/rust/parse/rust-scope.cc b/gcc/rust/parse/rust-scope.cc new file mode 100644 index 0000000..d38a078 --- /dev/null +++ b/gcc/rust/parse/rust-scope.cc @@ -0,0 +1,43 @@ +#include "rust-scope.h" + +#include // for std::make_pair + +namespace Rust { + Scope::Scope() {} + + void SymbolMapping::insert(SymbolPtr s) { + gcc_assert(s != NULL); + std::pair p = map.insert(std::make_pair(s->get_name(), s)); + + gcc_assert(p.second); + } + + SymbolPtr SymbolMapping::get(const std::string& str) const { + Map::const_iterator it = map.find(str); + if (it != map.end()) { + return it->second; + } + + return SymbolPtr(); + } + + SymbolPtr Scope::lookup(const std::string& str) { + // Traverse stack from top (end of MapStack) to bottom, so use reverse_iterator. + for (MapStack::reverse_iterator map = map_stack.rbegin(); map != map_stack.rend(); map++) { + if (SymbolPtr sym = map->get(str)) { + return sym; + } + } + + return SymbolPtr(); + } + + void Scope::push_scope() { + map_stack.push_back(SymbolMapping()); + } + + void Scope::pop_scope() { + gcc_assert(!map_stack.empty()); + map_stack.pop_back(); + } +} \ No newline at end of file diff --git a/gcc/rust/parse/rust-scope.h b/gcc/rust/parse/rust-scope.h new file mode 100644 index 0000000..7ac38c9 --- /dev/null +++ b/gcc/rust/parse/rust-scope.h @@ -0,0 +1,61 @@ +#ifndef RUST_SCOPE_H +#define RUST_SCOPE_H + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +// order: config, system, coretypes, tree +// may not all be required + +#include +#include +#include + +#include "rust-tree.h" +#include "rust-symbol.h" + +// maybe split out scope into Symbol, SymbolMapping, and Scope headers + +namespace Rust { + // Map of strings (identifiers) to SymbolPtrs + struct SymbolMapping { + public: + // Inserts a new Symbol into the map using its name as the key. Also checks name is unique. + void insert(SymbolPtr s); + // Returns the mapped Symbol for the given string. May return a null Symbol. + SymbolPtr get(const std::string& str) const; + + private: + typedef std::map Map; + // SymbolMapping's map. + Map map; + }; + + // Scope class that holds mapping in it. + class Scope { + public: + // Gets current mapping (created in last push that hasn't been popped yet). + SymbolMapping& get_current_mapping() { + gcc_assert(!map_stack.empty()); + return map_stack.back(); + } + + // Create new mapping. + void push_scope(); + // Get rid of mapping? + void pop_scope(); + + Scope(); + + // Get the last mapping for a given string (or null if no such mapping exists). + SymbolPtr lookup(const std::string& str); + + private: + typedef std::vector MapStack; + // Scope's MapStack. + MapStack map_stack; + }; // TODO: have multiple scopes (for modules, function, etc) at once? +} + +#endif // RUST_SCOPE_H \ No newline at end of file diff --git a/gcc/rust/parse/rust-symbol.h b/gcc/rust/parse/rust-symbol.h new file mode 100644 index 0000000..439325b --- /dev/null +++ b/gcc/rust/parse/rust-symbol.h @@ -0,0 +1,78 @@ +#ifndef RUST_SYMBOL_H +#define RUST_SYMBOL_H + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +// order: config, system, coretypes, tree + +#include +//#include // as shared_ptr is not available in std memory in c++03 +// replaced with proper memory in c++11 +#include + +namespace Rust { + // Kinds of symbols. + enum SymbolKind { INVALID, VARIABLE, TYPENAME /*change to STRUCT*/, FUNCTION }; + // TODO: possibly add typedef, struct, union, "enum" + + /* TODO: apparently Rust's type symbol table is separate to its identifier symbol table, so have a + * different symbol table for each? */ + + /* The symbol table(s) will be generated as a pass over the AST (the first, probably) and each + * scope, including module namespacing, will be a separate symbol table (with earlier ones still + * accessible but searched afterward). It will be preserved in later passes over the AST to type + * check and maybe bind identifiers together or something. + * It may have to be preserved, at least partially, for GENERIC lowering. */ + + // A symbol used for identifiers, etc. - TODO: extend to support namespacing (Rust paths?) + struct Symbol { + public: + // Constructs a new symbol of name with no declaration tree set. + Symbol(SymbolKind kind, const std::string& name_) : + kind(kind), name(name_), decl(error_mark_node) { + gcc_assert(name.size() > 0); + } + + // Gets symbol's kind. + SymbolKind get_kind() const { + return kind; + } + + // Gets symbol's name. + std::string get_name() const { + return name; + } + + // Sets symbol's declaration tree. + void set_tree_decl(Tree decl_) { + // Ensure declaration tree is a variable or type declaration. + gcc_assert((decl_.get_tree_code() == VAR_DECL) || (decl_.get_tree_code() == TYPE_DECL)); + decl = decl_; + } + + // Gets tree with the location of variable declaration. + Tree get_tree_decl() const { + return decl; + } + + private: + // Symbol's kind. + SymbolKind kind; + // Symbol's name. + std::string name; + // Symbol's declaration tree. + Tree decl; + + // Note: in other languages, other info about symbols would also be kept, e.g. "kind" + // Also would be able to store more than just variable declaration trees. + }; + + // Symbol shared pointer. + typedef std::shared_ptr SymbolPtr; + // Const symbol shared pointer (i.e. to const Symbol). + typedef std::shared_ptr const_SymbolPtr; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/parse/rust-tree.h b/gcc/rust/parse/rust-tree.h new file mode 100644 index 0000000..6318a50 --- /dev/null +++ b/gcc/rust/parse/rust-tree.h @@ -0,0 +1,167 @@ +#ifndef RUST_TREE_H +#define RUST_TREE_H + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-iterator.h" +#include "input.h" +// order: config, system, coretypes, tree, tree-iterator, input +// may not need all of them + +namespace Rust { + // Wrapper around tree to keep location and tree in one data structure. + struct Tree { + public: + Tree() : t(NULL_TREE), loc(UNKNOWN_LOCATION) {} + Tree(tree t_) : t(t_), loc(EXPR_LOCATION(t)) {} + Tree(tree t_, location_t loc_) : t(t_), loc(loc_) {} + Tree(Tree t_, location_t loc_) : t(t_.get_tree()), loc(loc_) {} + + // Get tree's location_t. + location_t get_locus() const { + return loc; + } + + // Sets tree's location_t. + void set_locus(location_t loc_) { + loc = loc_; + } + + // Gets tree's tree in GCC form. + tree get_tree() const { + return t; + } + + // Gets tree's GCC tree code. + tree_code get_tree_code() const { + return TREE_CODE(t); + } + + // Sets tree's GCC tree. + void set_tree(tree t_) { + t = t_; + } + + // Returns if tree is an error node? + bool is_error() const { + return error_operand_p(t); + } + + // Returns whether tree node is null. + bool is_null() { + return t == NULL_TREE; + } + + // Creates an error Tree. + static Tree error() { + return Tree(error_mark_node); + } + + // Gets tree's GCC type. + Tree get_type() const { + return TREE_TYPE(t); + } + + private: + // The tree object's gcc tree representation. + tree t; + // The tree's location. + location_t loc; + }; + + // Comparison by identity as tree is a pointer. + inline bool operator==(Tree t1, Tree t2) { + return t1.get_tree() == t2.get_tree(); + } + inline bool operator!=(Tree t1, Tree t2) { + return !(t1 == t2); + } + + inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1) { + return build1_loc(loc, tc, type.get_tree(), t1.get_tree()); + } + + inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2) { + return build2_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree()); + } + + inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3) { + return build3_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree()); + } + + inline Tree build_tree( + tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4) { + return build4_loc( + loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), t4.get_tree()); + } + + inline Tree build_tree( + tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4, Tree t5) { + return build5_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), + t4.get_tree(), t5.get_tree()); + } + + // Wrapper around STATEMENT_LIST, used to represent lists of statements. Adapter for TREE_LIST. + struct TreeStmtList { + public: + // Create new statement list from nothing. + TreeStmtList() : list(alloc_stmt_list()) {} + // Create new statement list from given tree. + TreeStmtList(Tree param_tree) : list(param_tree.get_tree()) {} + + // Append to statement list. + void append(Tree param_tree) { + append_to_statement_list(param_tree.get_tree(), &list); + } + + // Get the statement list. + tree get_tree() const { + return list; + } + + private: + // The statement list. + tree list; + }; + + // TODO: Check if already exists in GCC + template + struct TreeChainBase { + Tree first; + Tree last; + + TreeChainBase() : first(), last() {} + + void append(Tree t) { + gcc_assert(!t.is_null()); + if (first.is_null()) { + first = last = t; + } else { + Append()(last, t); + last = t; + } + } + }; + + struct tree_chain_append { + void operator()(Tree t, Tree a) { + TREE_CHAIN(t.get_tree()) = a.get_tree(); + } + }; + + // Single-linked list implemented with trees. Used for VAR_DECLs. + struct TreeChain : TreeChainBase {}; + + struct block_chain_append { + void operator()(Tree t, Tree a) { + BLOCK_CHAIN(t.get_tree()) = a.get_tree(); + } + }; + + // Single-linked list implemented with trees. Used for chains of blocks. + struct BlockChain : TreeChainBase {}; +} + +#endif // RUST_TREE_H \ No newline at end of file diff --git a/gcc/rust/rust-buffered-queue.h b/gcc/rust/rust-buffered-queue.h new file mode 100644 index 0000000..ac0ea1a --- /dev/null +++ b/gcc/rust/rust-buffered-queue.h @@ -0,0 +1,130 @@ +#ifndef RUST_BUFFERED_QUEUE_H +#define RUST_BUFFERED_QUEUE_H + +#include + +#include "config.h" +#include "system.h" +// order: config, system + +namespace Rust { + // Buffered queue implementation. Items are of type T, queue source is of type Source. + template + class buffered_queue { + public: + // Construct empty queue from Source& src. + buffered_queue(Source& src) : source(src), start(0), end(0), buffer() {} + + // Returns token at position start + n (i.e. n tokens ahead). + T peek(int n) { + // n should not be behind + gcc_assert(n >= 0); + + int num_queued_items = end - start; + int num_items_required = n + 1; + + // if required items go past end of queue, add them to queue + if (num_items_required > num_queued_items) { + int num_items_to_read = num_items_required - num_queued_items; + + // if queue length + extra items is larger than buffer size, expand buffer + if (end + num_items_to_read > (int)buffer.size()) { + // Resize the buffer by 1.5x + int new_size = (buffer.size() + num_items_to_read); + new_size += (new_size >> 1); + + // create new queue buffer with new size + std::vector new_queue(new_size); + std::copy(buffer.begin() + start, buffer.begin() + end, new_queue.begin()); + start = 0; + end = num_queued_items; + + // swap member buffer and new queue buffer + std::swap(buffer, new_queue); + + // validate that buffer is large enough now + gcc_assert(end + num_queued_items < (int)buffer.size()); + } + + // iterate through buffer and invoke operator () on source on values past original end + for (int i = 0; i < num_items_to_read; i++) { + buffer[end + i] = source(); + } + + // move end based on additional items added + end += num_items_to_read; + } + + gcc_assert(0 <= start); + gcc_assert(start <= end); + gcc_assert(end <= (int)buffer.size()); + + gcc_assert(start + n < end); + + // return value at start + n in buffer + return buffer[start + n]; + } + + // TODO: add faster peek current token to remove overhead of conditional branches? + + // Advances start by n + 1. + void skip(int n) { + // Call peek to ensure requested n is actually in queue. + peek(n); + + // Clear values from start to n (inclusive). + for (int i = 0; i < (n + 1); i++) { + // Clear value at index + buffer[start + i] = T(); + } + + // Move start forward by n + 1. + start += (n + 1); + + // Ensure start is not impossible somehow + gcc_assert(0 <= start); + gcc_assert(start <= end); + + // Compact buffer if empty + if (start == end) { + start = end = 0; + } + } + + /* Inserts element at front of vector. Really dirty hack with terrible performance, only use + * when really needed. */ + void insert_at_front(T elem_to_insert) { + // TODO: test as this may not work properly + + // Insert actual element in buffer at start. + buffer.insert(buffer.begin(), 1, elem_to_insert); + + // Increase the end number since added element means all others have shifted one along + end++; + } + + // Replaces the current value in the buffer. Total HACK. + void replace_current_value(T replacement) { + // call peek to ensure value exists + peek(0); + + buffer[start] = replacement; + + // don't move start or end + } + + private: + // Source of tokens for queue. + Source& source; + + // Begin of range in buffer, inclusive. + int start; + // End of range in buffer, exclusive. + int end; + + // Queue buffer. + std::vector buffer; + }; +} + +#endif \ No newline at end of file diff --git a/gcc/rust/rust-c.h b/gcc/rust/rust-c.h deleted file mode 100644 index d75d9e7..0000000 --- a/gcc/rust/rust-c.h +++ /dev/null @@ -1,45 +0,0 @@ -/* rust-c.h -- Header file for rust frontend gcc C interface. - Copyright (C) 2009-2019 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#ifndef RUST_RUST_C_H -#define RUST_RUST_C_H - -#define RUST_EXTERN_C - -class Linemap; - -extern Linemap* rust_get_linemap(); - -extern void rust_create_rustly(bool only_check_syntax, Linemap* linemap); - -extern void rust_parse_input_files (const char**, unsigned int); - -extern unsigned int rust_field_alignment (tree); - -extern void rust_write_globals (void); - -extern void rust_preserve_from_gc (tree); - -extern bool saw_errors (void); - -extern unsigned int rust_field_alignment (tree); - -extern void rust_write_export_data (const char *, unsigned int); - -#endif /* !defined(RUST_RUST_C_H) */ diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 8580f09..feecba9 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1,6 +1,7 @@ -// go-gcc.cc -- Go frontend to gcc IR. +// rust-gcc.cc -- Rust frontend to gcc IR. // Copyright (C) 2011-2019 Free Software Foundation, Inc. // Contributed by Ian Lance Taylor, Google. +// forked from gccgo // This file is part of GCC. @@ -43,79 +44,61 @@ #include "realmpfr.h" #include "builtins.h" -#include "rust-c.h" #include "rust-location.h" #include "rust-linemap.h" #include "backend.h" +#include "rust-object-export.h" // A class wrapping a tree. class Gcc_tree { - public: - Gcc_tree(tree t) - : t_(t) - { } +public: + Gcc_tree (tree t) : t_ (t) {} - tree - get_tree() const - { return this->t_; } + tree get_tree () const { return this->t_; } - void - set_tree(tree t) - { this->t_ = t; } + void set_tree (tree t) { this->t_ = t; } - private: +private: tree t_; }; // In gcc, types, expressions, and statements are all trees. class Btype : public Gcc_tree { - public: - Btype(tree t) - : Gcc_tree(t) - { } +public: + Btype (tree t) : Gcc_tree (t) {} }; class Bexpression : public Gcc_tree { - public: - Bexpression(tree t) - : Gcc_tree(t) - { } +public: + Bexpression (tree t) : Gcc_tree (t) {} }; class Bstatement : public Gcc_tree { - public: - Bstatement(tree t) - : Gcc_tree(t) - { } +public: + Bstatement (tree t) : Gcc_tree (t) {} }; class Bfunction : public Gcc_tree { - public: - Bfunction(tree t) - : Gcc_tree(t) - { } +public: + Bfunction (tree t) : Gcc_tree (t) {} }; class Bblock : public Gcc_tree { - public: - Bblock(tree t) - : Gcc_tree(t) - { } +public: + Bblock (tree t) : Gcc_tree (t) {} }; class Blabel : public Gcc_tree { - public: - Blabel(tree t) - : Gcc_tree(t) - { } +public: + Blabel (tree t) : Gcc_tree (t) {} }; // Bvariable is a bit more complicated, because of zero-sized types. @@ -129,25 +112,18 @@ class Blabel : public Gcc_tree class Bvariable { - public: - Bvariable(tree t) - : t_(t), orig_type_(NULL) - { } +public: + Bvariable (tree t) : t_ (t), orig_type_ (NULL) {} - Bvariable(tree t, tree orig_type) - : t_(t), orig_type_(orig_type) - { } + Bvariable (tree t, tree orig_type) : t_ (t), orig_type_ (orig_type) {} // Get the tree for use as an expression. - tree - get_tree(Location) const; + tree get_tree (Location) const; // Get the actual decl; - tree - get_decl() const - { return this->t_; } + tree get_decl () const { return this->t_; } - private: +private: tree t_; tree orig_type_; }; @@ -156,811 +132,667 @@ class Bvariable // zero-sized global, create an expression that refers to the decl but // has zero size. tree -Bvariable::get_tree(Location location) const +Bvariable::get_tree (Location location) const { - if (this->orig_type_ == NULL - || this->t_ == error_mark_node - || TREE_TYPE(this->t_) == this->orig_type_) + if (this->orig_type_ == NULL || this->t_ == error_mark_node + || TREE_TYPE (this->t_) == this->orig_type_) return this->t_; // Return *(orig_type*)&decl. */ - tree t = build_fold_addr_expr_loc(location.gcc_location(), this->t_); - t = fold_build1_loc(location.gcc_location(), NOP_EXPR, - build_pointer_type(this->orig_type_), t); - return build_fold_indirect_ref_loc(location.gcc_location(), t); + tree t = build_fold_addr_expr_loc (location.gcc_location (), this->t_); + t = fold_build1_loc (location.gcc_location (), NOP_EXPR, + build_pointer_type (this->orig_type_), t); + return build_fold_indirect_ref_loc (location.gcc_location (), t); } -// This file implements the interface between the Go frontend proper +// This file implements the interface between the Rust frontend proper // and the gcc IR. This implements specific instantiations of -// abstract classes defined by the Go frontend proper. The Go +// abstract classes defined by the Rust frontend proper. The Rust // frontend proper class methods of these classes to generate the // backend representation. class Gcc_backend : public Backend { - public: - Gcc_backend(); +public: + Gcc_backend (); // Types. - Btype* - error_type() - { return this->make_type(error_mark_node); } + Btype *error_type () { return this->make_type (error_mark_node); } - Btype* - void_type() - { return this->make_type(void_type_node); } + Btype *void_type () { return this->make_type (void_type_node); } - Btype* - bool_type() - { return this->make_type(boolean_type_node); } + Btype *bool_type () { return this->make_type (boolean_type_node); } - Btype* - integer_type(bool, int); + Btype *integer_type (bool, int); - Btype* - float_type(int); + Btype *float_type (int); - Btype* - complex_type(int); + Btype *complex_type (int); - Btype* - pointer_type(Btype*); + Btype *pointer_type (Btype *); - Btype* - function_type(const Btyped_identifier&, - const std::vector&, - const std::vector&, - Btype*, - const Location); + Btype *function_type (const Btyped_identifier &, + const std::vector &, + const std::vector &, Btype *, + const Location); - Btype* - struct_type(const std::vector&); + Btype *struct_type (const std::vector &); - Btype* - array_type(Btype*, Bexpression*); + Btype *array_type (Btype *, Bexpression *); - Btype* - placeholder_pointer_type(const std::string&, Location, bool); + Btype *placeholder_pointer_type (const std::string &, Location, bool); - bool - set_placeholder_pointer_type(Btype*, Btype*); + bool set_placeholder_pointer_type (Btype *, Btype *); - bool - set_placeholder_function_type(Btype*, Btype*); + bool set_placeholder_function_type (Btype *, Btype *); - Btype* - placeholder_struct_type(const std::string&, Location); + Btype *placeholder_struct_type (const std::string &, Location); - bool - set_placeholder_struct_type(Btype* placeholder, - const std::vector&); + bool set_placeholder_struct_type (Btype *placeholder, + const std::vector &); - Btype* - placeholder_array_type(const std::string&, Location); + Btype *placeholder_array_type (const std::string &, Location); - bool - set_placeholder_array_type(Btype*, Btype*, Bexpression*); + bool set_placeholder_array_type (Btype *, Btype *, Bexpression *); - Btype* - named_type(const std::string&, Btype*, Location); + Btype *named_type (const std::string &, Btype *, Location); - Btype* - circular_pointer_type(Btype*, bool); + Btype *circular_pointer_type (Btype *, bool); - bool - is_circular_pointer_type(Btype*); + bool is_circular_pointer_type (Btype *); - int64_t - type_size(Btype*); + int64_t type_size (Btype *); - int64_t - type_alignment(Btype*); + int64_t type_alignment (Btype *); - int64_t - type_field_alignment(Btype*); + int64_t type_field_alignment (Btype *); - int64_t - type_field_offset(Btype*, size_t index); + int64_t type_field_offset (Btype *, size_t index); // Expressions. - Bexpression* - zero_expression(Btype*); + Bexpression *zero_expression (Btype *); - Bexpression* - error_expression() - { return this->make_expression(error_mark_node); } + Bexpression *error_expression () + { + return this->make_expression (error_mark_node); + } - Bexpression* - nil_pointer_expression() - { return this->make_expression(null_pointer_node); } + Bexpression *nil_pointer_expression () + { + return this->make_expression (null_pointer_node); + } - Bexpression* - var_expression(Bvariable* var, Location); + Bexpression *var_expression (Bvariable *var, Location); - Bexpression* - indirect_expression(Btype*, Bexpression* expr, bool known_valid, Location); + Bexpression *indirect_expression (Btype *, Bexpression *expr, + bool known_valid, Location); - Bexpression* - named_constant_expression(Btype* btype, const std::string& name, - Bexpression* val, Location); + Bexpression *named_constant_expression (Btype *btype, const std::string &name, + Bexpression *val, Location); - Bexpression* - integer_constant_expression(Btype* btype, mpz_t val); + Bexpression *integer_constant_expression (Btype *btype, mpz_t val); - Bexpression* - float_constant_expression(Btype* btype, mpfr_t val); + Bexpression *float_constant_expression (Btype *btype, mpfr_t val); - Bexpression* - complex_constant_expression(Btype* btype, mpc_t val); + Bexpression *complex_constant_expression (Btype *btype, mpc_t val); - Bexpression* - string_constant_expression(const std::string& val); + Bexpression *string_constant_expression (const std::string &val); - Bexpression* - boolean_constant_expression(bool val); + Bexpression *boolean_constant_expression (bool val); - Bexpression* - real_part_expression(Bexpression* bcomplex, Location); + Bexpression *real_part_expression (Bexpression *bcomplex, Location); - Bexpression* - imag_part_expression(Bexpression* bcomplex, Location); + Bexpression *imag_part_expression (Bexpression *bcomplex, Location); - Bexpression* - complex_expression(Bexpression* breal, Bexpression* bimag, Location); + Bexpression *complex_expression (Bexpression *breal, Bexpression *bimag, + Location); - Bexpression* - convert_expression(Btype* type, Bexpression* expr, Location); + Bexpression *convert_expression (Btype *type, Bexpression *expr, Location); - Bexpression* - function_code_expression(Bfunction*, Location); + Bexpression *function_code_expression (Bfunction *, Location); - Bexpression* - address_expression(Bexpression*, Location); + Bexpression *address_expression (Bexpression *, Location); - Bexpression* - struct_field_expression(Bexpression*, size_t, Location); + Bexpression *struct_field_expression (Bexpression *, size_t, Location); - Bexpression* - compound_expression(Bstatement*, Bexpression*, Location); + Bexpression *compound_expression (Bstatement *, Bexpression *, Location); - Bexpression* - conditional_expression(Bfunction*, Btype*, Bexpression*, Bexpression*, - Bexpression*, Location); + Bexpression *conditional_expression (Bfunction *, Btype *, Bexpression *, + Bexpression *, Bexpression *, Location); - Bexpression* - unary_expression(Operator, Bexpression*, Location); + Bexpression *unary_expression (Operator, Bexpression *, Location); - Bexpression* - binary_expression(Operator, Bexpression*, Bexpression*, Location); + Bexpression *binary_expression (Operator, Bexpression *, Bexpression *, + Location); - Bexpression* - constructor_expression(Btype*, const std::vector&, Location); + Bexpression *constructor_expression (Btype *, + const std::vector &, + Location); - Bexpression* - array_constructor_expression(Btype*, const std::vector&, - const std::vector&, Location); + Bexpression *array_constructor_expression (Btype *, + const std::vector &, + const std::vector &, + Location); - Bexpression* - pointer_offset_expression(Bexpression* base, Bexpression* offset, Location); + Bexpression *pointer_offset_expression (Bexpression *base, + Bexpression *offset, Location); - Bexpression* - array_index_expression(Bexpression* array, Bexpression* index, Location); + Bexpression *array_index_expression (Bexpression *array, Bexpression *index, + Location); - Bexpression* - call_expression(Bfunction* caller, Bexpression* fn, - const std::vector& args, - Bexpression* static_chain, Location); + Bexpression *call_expression (Bfunction *caller, Bexpression *fn, + const std::vector &args, + Bexpression *static_chain, Location); // Statements. - Bstatement* - error_statement() - { return this->make_statement(error_mark_node); } + Bstatement *error_statement () + { + return this->make_statement (error_mark_node); + } - Bstatement* - expression_statement(Bfunction*, Bexpression*); + Bstatement *expression_statement (Bfunction *, Bexpression *); - Bstatement* - init_statement(Bfunction*, Bvariable* var, Bexpression* init); + Bstatement *init_statement (Bfunction *, Bvariable *var, Bexpression *init); - Bstatement* - assignment_statement(Bfunction*, Bexpression* lhs, Bexpression* rhs, - Location); + Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, + Bexpression *rhs, Location); - Bstatement* - return_statement(Bfunction*, const std::vector&, - Location); + Bstatement *return_statement (Bfunction *, const std::vector &, + Location); - Bstatement* - if_statement(Bfunction*, Bexpression* condition, Bblock* then_block, - Bblock* else_block, Location); + Bstatement *if_statement (Bfunction *, Bexpression *condition, + Bblock *then_block, Bblock *else_block, Location); - Bstatement* - switch_statement(Bfunction* function, Bexpression* value, - const std::vector >& cases, - const std::vector& statements, - Location); + Bstatement * + switch_statement (Bfunction *function, Bexpression *value, + const std::vector > &cases, + const std::vector &statements, Location); - Bstatement* - compound_statement(Bstatement*, Bstatement*); + Bstatement *compound_statement (Bstatement *, Bstatement *); - Bstatement* - statement_list(const std::vector&); + Bstatement *statement_list (const std::vector &); - Bstatement* - exception_handler_statement(Bstatement* bstat, Bstatement* except_stmt, - Bstatement* finally_stmt, Location); + Bstatement *exception_handler_statement (Bstatement *bstat, + Bstatement *except_stmt, + Bstatement *finally_stmt, Location); // Blocks. - Bblock* - block(Bfunction*, Bblock*, const std::vector&, - Location, Location); + Bblock *block (Bfunction *, Bblock *, const std::vector &, + Location, Location); - void - block_add_statements(Bblock*, const std::vector&); + void block_add_statements (Bblock *, const std::vector &); - Bstatement* - block_statement(Bblock*); + Bstatement *block_statement (Bblock *); // Variables. - Bvariable* - error_variable() - { return new Bvariable(error_mark_node); } + Bvariable *error_variable () { return new Bvariable (error_mark_node); } - Bvariable* - global_variable(const std::string& var_name, - const std::string& asm_name, - Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, - Location location); + Bvariable *global_variable (const std::string &var_name, + const std::string &asm_name, Btype *btype, + bool is_external, bool is_hidden, + bool in_unique_section, Location location); - void - global_variable_set_init(Bvariable*, Bexpression*); + void global_variable_set_init (Bvariable *, Bexpression *); - Bvariable* - local_variable(Bfunction*, const std::string&, Btype*, Bvariable*, bool, - Location); + Bvariable *local_variable (Bfunction *, const std::string &, Btype *, + Bvariable *, bool, Location); - Bvariable* - parameter_variable(Bfunction*, const std::string&, Btype*, bool, - Location); + Bvariable *parameter_variable (Bfunction *, const std::string &, Btype *, + bool, Location); - Bvariable* - static_chain_variable(Bfunction*, const std::string&, Btype*, Location); + Bvariable *static_chain_variable (Bfunction *, const std::string &, Btype *, + Location); - Bvariable* - temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, bool, - Location, Bstatement**); + Bvariable *temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *, + bool, Location, Bstatement **); - Bvariable* - implicit_variable(const std::string&, const std::string&, Btype*, - bool, bool, bool, int64_t); + Bvariable *implicit_variable (const std::string &, const std::string &, + Btype *, bool, bool, bool, int64_t); - void - implicit_variable_set_init(Bvariable*, const std::string&, Btype*, - bool, bool, bool, Bexpression*); + void implicit_variable_set_init (Bvariable *, const std::string &, Btype *, + bool, bool, bool, Bexpression *); - Bvariable* - implicit_variable_reference(const std::string&, const std::string&, Btype*); + Bvariable *implicit_variable_reference (const std::string &, + const std::string &, Btype *); - Bvariable* - immutable_struct(const std::string&, const std::string&, - bool, bool, Btype*, Location); + Bvariable *immutable_struct (const std::string &, const std::string &, bool, + bool, Btype *, Location); - void - immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*, - Location, Bexpression*); + void immutable_struct_set_init (Bvariable *, const std::string &, bool, bool, + Btype *, Location, Bexpression *); - Bvariable* - immutable_struct_reference(const std::string&, const std::string&, - Btype*, Location); + Bvariable *immutable_struct_reference (const std::string &, + const std::string &, Btype *, + Location); // Labels. - Blabel* - label(Bfunction*, const std::string& name, Location); + Blabel *label (Bfunction *, const std::string &name, Location); - Bstatement* - label_definition_statement(Blabel*); + Bstatement *label_definition_statement (Blabel *); - Bstatement* - goto_statement(Blabel*, Location); + Bstatement *goto_statement (Blabel *, Location); - Bexpression* - label_address(Blabel*, Location); + Bexpression *label_address (Blabel *, Location); // Functions. - Bfunction* - error_function() - { return this->make_function(error_mark_node); } + Bfunction *error_function () { return this->make_function (error_mark_node); } - Bfunction* - function(Btype* fntype, const std::string& name, const std::string& asm_name, - unsigned int flags, Location); - - Bstatement* - function_defer_statement(Bfunction* function, Bexpression* undefer, - Bexpression* defer, Location); + Bfunction *function (Btype *fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, + Location); - bool - function_set_parameters(Bfunction* function, const std::vector&); + Bstatement *function_defer_statement (Bfunction *function, + Bexpression *undefer, + Bexpression *defer, Location); - bool - function_set_body(Bfunction* function, Bstatement* code_stmt); + bool function_set_parameters (Bfunction *function, + const std::vector &); - Bfunction* - lookup_builtin(const std::string&); + bool function_set_body (Bfunction *function, Bstatement *code_stmt); - void - write_global_definitions(const std::vector&, - const std::vector&, - const std::vector&, - const std::vector&); + Bfunction *lookup_builtin (const std::string &); - void - write_export_data(const char* bytes, unsigned int size); + void write_global_definitions (const std::vector &, + const std::vector &, + const std::vector &, + const std::vector &); + void write_export_data (const char *bytes, unsigned int size); - private: +private: // Make a Bexpression from a tree. - Bexpression* - make_expression(tree t) - { return new Bexpression(t); } + Bexpression *make_expression (tree t) { return new Bexpression (t); } // Make a Bstatement from a tree. - Bstatement* - make_statement(tree t) - { return new Bstatement(t); } + Bstatement *make_statement (tree t) { return new Bstatement (t); } // Make a Btype from a tree. - Btype* - make_type(tree t) - { return new Btype(t); } + Btype *make_type (tree t) { return new Btype (t); } - Bfunction* - make_function(tree t) - { return new Bfunction(t); } + Bfunction *make_function (tree t) { return new Bfunction (t); } - Btype* - fill_in_struct(Btype*, const std::vector&); + Btype *fill_in_struct (Btype *, const std::vector &); - Btype* - fill_in_array(Btype*, Btype*, Bexpression*); + Btype *fill_in_array (Btype *, Btype *, Bexpression *); - tree - non_zero_size_type(tree); + tree non_zero_size_type (tree); - tree - convert_tree(tree, tree, Location); + tree convert_tree (tree, tree, Location); private: - void - define_builtin(built_in_function bcode, const char* name, const char* libname, - tree fntype, bool const_p, bool noreturn_p); + static const int builtin_const = 1 << 0; + static const int builtin_noreturn = 1 << 1; + static const int builtin_novops = 1 << 2; + + void define_builtin (built_in_function bcode, const char *name, + const char *libname, tree fntype, int flags); - // A mapping of the GCC built-ins exposed to GCCGo. - std::map builtin_functions_; + // A mapping of the GCC built-ins exposed to GCCRust. + std::map builtin_functions_; }; // A helper function to create a GCC identifier from a C++ string. static inline tree -get_identifier_from_string(const std::string& str) +get_identifier_from_string (const std::string &str) { - return get_identifier_with_length(str.data(), str.length()); + return get_identifier_with_length (str.data (), str.length ()); } -// Define the built-in functions that are exposed to GCCGo. +// Define the built-in functions that are exposed to GCCRust. -Gcc_backend::Gcc_backend() +Gcc_backend::Gcc_backend () { /* We need to define the fetch_and_add functions, since we use them for ++ and --. */ - tree t = this->integer_type(true, BITS_PER_UNIT)->get_tree(); - tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); - this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", - NULL, build_function_type_list(t, p, t, NULL_TREE), - false, false); - - t = this->integer_type(true, BITS_PER_UNIT * 2)->get_tree(); - p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); - this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", - NULL, build_function_type_list(t, p, t, NULL_TREE), - false, false); - - t = this->integer_type(true, BITS_PER_UNIT * 4)->get_tree(); - p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); - this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", - NULL, build_function_type_list(t, p, t, NULL_TREE), - false, false); - - t = this->integer_type(true, BITS_PER_UNIT * 8)->get_tree(); - p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); - this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", - NULL, build_function_type_list(t, p, t, NULL_TREE), - false, false); + tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree (); + tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", + NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree (); + p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", + NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree (); + p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", + NULL, build_function_type_list (t, p, t, NULL_TREE), 0); + + t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree (); + p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); + this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", + NULL, build_function_type_list (t, p, t, NULL_TREE), 0); // We use __builtin_expect for magic import functions. - this->define_builtin(BUILT_IN_EXPECT, "__builtin_expect", NULL, - build_function_type_list(long_integer_type_node, - long_integer_type_node, - long_integer_type_node, - NULL_TREE), - true, false); + this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL, + build_function_type_list (long_integer_type_node, + long_integer_type_node, + long_integer_type_node, + NULL_TREE), + builtin_const); // We use __builtin_memcmp for struct comparisons. - this->define_builtin(BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", - build_function_type_list(integer_type_node, - const_ptr_type_node, - const_ptr_type_node, - size_type_node, - NULL_TREE), - false, false); + this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", + build_function_type_list (integer_type_node, + const_ptr_type_node, + const_ptr_type_node, + size_type_node, NULL_TREE), + 0); // We use __builtin_memmove for copying data. - this->define_builtin(BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", - build_function_type_list(void_type_node, - ptr_type_node, - const_ptr_type_node, - size_type_node, - NULL_TREE), - false, false); + this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", + build_function_type_list (void_type_node, ptr_type_node, + const_ptr_type_node, + size_type_node, NULL_TREE), + 0); // We use __builtin_memset for zeroing data. - this->define_builtin(BUILT_IN_MEMSET, "__builtin_memset", "memset", - build_function_type_list(void_type_node, - ptr_type_node, - integer_type_node, - size_type_node, - NULL_TREE), - false, false); + this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset", + build_function_type_list (void_type_node, ptr_type_node, + integer_type_node, + size_type_node, NULL_TREE), + 0); // Used by runtime/internal/sys and math/bits. - this->define_builtin(BUILT_IN_CTZ, "__builtin_ctz", "ctz", - build_function_type_list(integer_type_node, - unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", - build_function_type_list(integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_CLZ, "__builtin_clz", "clz", - build_function_type_list(integer_type_node, - unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_CLZLL, "__builtin_clzll", "clzll", - build_function_type_list(integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", - build_function_type_list(integer_type_node, - unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll", - build_function_type_list(integer_type_node, - long_long_unsigned_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", - build_function_type_list(uint16_type_node, - uint16_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", - build_function_type_list(uint32_type_node, - uint32_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", - build_function_type_list(uint64_type_node, - uint64_type_node, - NULL_TREE), - true, false); + this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz", + build_function_type_list (integer_type_node, + unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", + build_function_type_list (integer_type_node, + long_long_unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz", + build_function_type_list (integer_type_node, + unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll", + build_function_type_list (integer_type_node, + long_long_unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", + build_function_type_list (integer_type_node, + unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll", + "popcountll", + build_function_type_list (integer_type_node, + long_long_unsigned_type_node, + NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", + build_function_type_list (uint16_type_node, + uint16_type_node, NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", + build_function_type_list (uint32_type_node, + uint32_type_node, NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", + build_function_type_list (uint64_type_node, + uint64_type_node, NULL_TREE), + builtin_const); // We provide some functions for the math library. - tree math_function_type = build_function_type_list(double_type_node, - double_type_node, - NULL_TREE); - tree math_function_type_long = - build_function_type_list(long_double_type_node, long_double_type_node, - NULL_TREE); - tree math_function_type_two = build_function_type_list(double_type_node, - double_type_node, - double_type_node, - NULL_TREE); - tree math_function_type_long_two = - build_function_type_list(long_double_type_node, long_double_type_node, - long_double_type_node, NULL_TREE); - this->define_builtin(BUILT_IN_ACOS, "__builtin_acos", "acos", - math_function_type, true, false); - this->define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin", - math_function_type, true, false); - this->define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan", - math_function_type, true, false); - this->define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2", - math_function_type_two, true, false); - this->define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", - math_function_type_long_two, true, false); - this->define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil", - math_function_type, true, false); - this->define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_COS, "__builtin_cos", "cos", - math_function_type, true, false); - this->define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp", - math_function_type, true, false); - this->define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1", - math_function_type, true, false); - this->define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs", - math_function_type, true, false); - this->define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor", - math_function_type, true, false); - this->define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod", - math_function_type_two, true, false); - this->define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", - math_function_type_long_two, true, false); - this->define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", - build_function_type_list(double_type_node, - double_type_node, - integer_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", - build_function_type_list(long_double_type_node, - long_double_type_node, - integer_type_node, - NULL_TREE), - true, false); - this->define_builtin(BUILT_IN_LOG, "__builtin_log", "log", - math_function_type, true, false); - this->define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p", - math_function_type, true, false); - this->define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10", - math_function_type, true, false); - this->define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2", - math_function_type, true, false); - this->define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin", - math_function_type, true, false); - this->define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", - math_function_type, true, false); - this->define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan", - math_function_type, true, false); - this->define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl", - math_function_type_long, true, false); - this->define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc", - math_function_type, true, false); - this->define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", - math_function_type_long, true, false); + tree math_function_type + = build_function_type_list (double_type_node, double_type_node, NULL_TREE); + tree math_function_type_long + = build_function_type_list (long_double_type_node, long_double_type_node, + NULL_TREE); + tree math_function_type_two + = build_function_type_list (double_type_node, double_type_node, + double_type_node, NULL_TREE); + tree math_function_type_long_two + = build_function_type_list (long_double_type_node, long_double_type_node, + long_double_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ACOS, "__builtin_acos", "acos", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_ASIN, "__builtin_asin", "asin", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_ASINL, "__builtin_asinl", "asinl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_ATAN, "__builtin_atan", "atan", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_ATANL, "__builtin_atanl", "atanl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_ATAN2, "__builtin_atan2", "atan2", + math_function_type_two, builtin_const); + this->define_builtin (BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", + math_function_type_long_two, builtin_const); + this->define_builtin (BUILT_IN_CEIL, "__builtin_ceil", "ceil", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_CEILL, "__builtin_ceill", "ceill", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_COS, "__builtin_cos", "cos", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_COSL, "__builtin_cosl", "cosl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_EXP, "__builtin_exp", "exp", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_EXPL, "__builtin_expl", "expl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_EXPM1, "__builtin_expm1", "expm1", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_FABS, "__builtin_fabs", "fabs", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_FLOOR, "__builtin_floor", "floor", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_FLOORL, "__builtin_floorl", "floorl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_FMOD, "__builtin_fmod", "fmod", + math_function_type_two, builtin_const); + this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", + math_function_type_long_two, builtin_const); + this->define_builtin (BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", + build_function_type_list (double_type_node, + double_type_node, + integer_type_node, NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", + build_function_type_list (long_double_type_node, + long_double_type_node, + integer_type_node, NULL_TREE), + builtin_const); + this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_LOGL, "__builtin_logl", "logl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_LOG1P, "__builtin_log1p", "log1p", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_LOG10, "__builtin_log10", "log10", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_LOG10L, "__builtin_log10l", "log10l", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_LOG2, "__builtin_log2", "log2", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_LOG2L, "__builtin_log2l", "log2l", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_SIN, "__builtin_sin", "sin", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_SINL, "__builtin_sinl", "sinl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_TAN, "__builtin_tan", "tan", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_TANL, "__builtin_tanl", "tanl", + math_function_type_long, builtin_const); + this->define_builtin (BUILT_IN_TRUNC, "__builtin_trunc", "trunc", + math_function_type, builtin_const); + this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", + math_function_type_long, builtin_const); // We use __builtin_return_address in the thunk we build for // functions which call recover, and for runtime.getcallerpc. - t = build_function_type_list(ptr_type_node, unsigned_type_node, NULL_TREE); - this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", - NULL, t, false, false); + t = build_function_type_list (ptr_type_node, unsigned_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", + NULL, t, 0); // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. - t = build_function_type_list(ptr_type_node, NULL_TREE); - this->define_builtin(BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", - NULL, t, false, false); + t = build_function_type_list (ptr_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t, 0); // The runtime calls __builtin_extract_return_addr when recording // the address to which a function returns. - this->define_builtin(BUILT_IN_EXTRACT_RETURN_ADDR, - "__builtin_extract_return_addr", NULL, - build_function_type_list(ptr_type_node, - ptr_type_node, - NULL_TREE), - false, false); + this->define_builtin ( + BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL, + build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0); // The compiler uses __builtin_trap for some exception handling // cases. - this->define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL, - build_function_type(void_type_node, void_list_node), - false, true); + this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL, + build_function_type (void_type_node, void_list_node), + builtin_noreturn); // The runtime uses __builtin_prefetch. - this->define_builtin(BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, - build_varargs_function_type_list(void_type_node, - const_ptr_type_node, - NULL_TREE), - false, false); + this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, + build_varargs_function_type_list (void_type_node, + const_ptr_type_node, + NULL_TREE), + builtin_novops); // The compiler uses __builtin_unreachable for cases that cannot // occur. - this->define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, - build_function_type(void_type_node, void_list_node), - true, true); + this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, + build_function_type (void_type_node, void_list_node), + builtin_const | builtin_noreturn); // We provide some atomic functions. - t = build_function_type_list(uint32_type_node, - ptr_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, - t, false, false); - - t = build_function_type_list(uint64_type_node, - ptr_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, - t, false, false); - - t = build_function_type_list(void_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, - t, false, false); - - t = build_function_type_list(void_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, - t, false, false); - - t = build_function_type_list(uint32_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, - t, false, false); - - t = build_function_type_list(uint64_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, - t, false, false); - - t = build_function_type_list(boolean_type_node, - ptr_type_node, - ptr_type_node, - uint32_type_node, - boolean_type_node, - integer_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, - "__atomic_compare_exchange_4", NULL, - t, false, false); - - t = build_function_type_list(boolean_type_node, - ptr_type_node, - ptr_type_node, - uint64_type_node, - boolean_type_node, - integer_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, - "__atomic_compare_exchange_8", NULL, - t, false, false); - - t = build_function_type_list(uint32_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", NULL, - t, false, false); - - t = build_function_type_list(uint64_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", NULL, - t, false, false); - - t = build_function_type_list(unsigned_char_type_node, - ptr_type_node, - unsigned_char_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", NULL, - t, false, false); - this->define_builtin(BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL, - t, false, false); - - t = build_function_type_list(unsigned_char_type_node, - ptr_type_node, - unsigned_char_type_node, - integer_type_node, - NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, - t, false, false); - this->define_builtin(BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, - t, false, false); + t = build_function_type_list (uint32_type_node, ptr_type_node, + integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, 0); + + t = build_function_type_list (uint64_type_node, ptr_type_node, + integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, 0); + + t = build_function_type_list (void_type_node, ptr_type_node, uint32_type_node, + integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t, + 0); + + t = build_function_type_list (void_type_node, ptr_type_node, uint64_type_node, + integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t, + 0); + + t = build_function_type_list (uint32_type_node, ptr_type_node, + uint32_type_node, integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, + t, 0); + + t = build_function_type_list (uint64_type_node, ptr_type_node, + uint64_type_node, integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, + t, 0); + + t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, + uint32_type_node, boolean_type_node, + integer_type_node, integer_type_node, + NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, + "__atomic_compare_exchange_4", NULL, t, 0); + + t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, + uint64_type_node, boolean_type_node, + integer_type_node, integer_type_node, + NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, + "__atomic_compare_exchange_8", NULL, t, 0); + + t = build_function_type_list (uint32_type_node, ptr_type_node, + uint32_type_node, integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", + NULL, t, 0); + + t = build_function_type_list (uint64_type_node, ptr_type_node, + uint64_type_node, integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", + NULL, t, 0); + + t = build_function_type_list (unsigned_char_type_node, ptr_type_node, + unsigned_char_type_node, integer_type_node, + NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", + NULL, t, 0); + this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", + NULL, t, 0); + + t = build_function_type_list (unsigned_char_type_node, ptr_type_node, + unsigned_char_type_node, integer_type_node, + NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, + t, 0); + this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, + t, 0); } // Get an unnamed integer type. -Btype* -Gcc_backend::integer_type(bool is_unsigned, int bits) +Btype * +Gcc_backend::integer_type (bool is_unsigned, int bits) { tree type; if (is_unsigned) { if (bits == INT_TYPE_SIZE) - type = unsigned_type_node; + type = unsigned_type_node; else if (bits == CHAR_TYPE_SIZE) - type = unsigned_char_type_node; + type = unsigned_char_type_node; else if (bits == SHORT_TYPE_SIZE) - type = short_unsigned_type_node; + type = short_unsigned_type_node; else if (bits == LONG_TYPE_SIZE) - type = long_unsigned_type_node; + type = long_unsigned_type_node; else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_unsigned_type_node; + type = long_long_unsigned_type_node; else - type = make_unsigned_type(bits); + type = make_unsigned_type (bits); } else { if (bits == INT_TYPE_SIZE) - type = integer_type_node; + type = integer_type_node; else if (bits == CHAR_TYPE_SIZE) - type = signed_char_type_node; + type = signed_char_type_node; else if (bits == SHORT_TYPE_SIZE) - type = short_integer_type_node; + type = short_integer_type_node; else if (bits == LONG_TYPE_SIZE) - type = long_integer_type_node; + type = long_integer_type_node; else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_integer_type_node; + type = long_long_integer_type_node; else - type = make_signed_type(bits); + type = make_signed_type (bits); } - return this->make_type(type); + return this->make_type (type); } // Get an unnamed float type. -Btype* -Gcc_backend::float_type(int bits) +Btype * +Gcc_backend::float_type (int bits) { tree type; if (bits == FLOAT_TYPE_SIZE) @@ -971,17 +803,17 @@ Gcc_backend::float_type(int bits) type = long_double_type_node; else { - type = make_node(REAL_TYPE); - TYPE_PRECISION(type) = bits; - layout_type(type); + type = make_node (REAL_TYPE); + TYPE_PRECISION (type) = bits; + layout_type (type); } - return this->make_type(type); + return this->make_type (type); } // Get an unnamed complex type. -Btype* -Gcc_backend::complex_type(int bits) +Btype * +Gcc_backend::complex_type (int bits) { tree type; if (bits == FLOAT_TYPE_SIZE * 2) @@ -992,221 +824,216 @@ Gcc_backend::complex_type(int bits) type = complex_long_double_type_node; else { - type = make_node(REAL_TYPE); - TYPE_PRECISION(type) = bits / 2; - layout_type(type); - type = build_complex_type(type); + type = make_node (REAL_TYPE); + TYPE_PRECISION (type) = bits / 2; + layout_type (type); + type = build_complex_type (type); } - return this->make_type(type); + return this->make_type (type); } // Get a pointer type. -Btype* -Gcc_backend::pointer_type(Btype* to_type) +Btype * +Gcc_backend::pointer_type (Btype *to_type) { - tree to_type_tree = to_type->get_tree(); + tree to_type_tree = to_type->get_tree (); if (to_type_tree == error_mark_node) - return this->error_type(); - tree type = build_pointer_type(to_type_tree); - return this->make_type(type); + return this->error_type (); + tree type = build_pointer_type (to_type_tree); + return this->make_type (type); } // Make a function type. -Btype* -Gcc_backend::function_type(const Btyped_identifier& receiver, - const std::vector& parameters, - const std::vector& results, - Btype* result_struct, - Location) +Btype * +Gcc_backend::function_type (const Btyped_identifier &receiver, + const std::vector ¶meters, + const std::vector &results, + Btype *result_struct, Location) { tree args = NULL_TREE; - tree* pp = &args; + tree *pp = &args; if (receiver.btype != NULL) { - tree t = receiver.btype->get_tree(); + tree t = receiver.btype->get_tree (); if (t == error_mark_node) - return this->error_type(); - *pp = tree_cons(NULL_TREE, t, NULL_TREE); - pp = &TREE_CHAIN(*pp); + return this->error_type (); + *pp = tree_cons (NULL_TREE, t, NULL_TREE); + pp = &TREE_CHAIN (*pp); } - for (std::vector::const_iterator p = parameters.begin(); - p != parameters.end(); - ++p) + for (std::vector::const_iterator p = parameters.begin (); + p != parameters.end (); ++p) { - tree t = p->btype->get_tree(); + tree t = p->btype->get_tree (); if (t == error_mark_node) - return this->error_type(); - *pp = tree_cons(NULL_TREE, t, NULL_TREE); - pp = &TREE_CHAIN(*pp); + return this->error_type (); + *pp = tree_cons (NULL_TREE, t, NULL_TREE); + pp = &TREE_CHAIN (*pp); } - // Varargs is handled entirely at the Go level. When converted to + // Varargs is handled entirely at the Rust level. When converted to // GENERIC functions are not varargs. *pp = void_list_node; tree result; - if (results.empty()) + if (results.empty ()) result = void_type_node; - else if (results.size() == 1) - result = results.front().btype->get_tree(); + else if (results.size () == 1) + result = results.front ().btype->get_tree (); else { - gcc_assert(result_struct != NULL); - result = result_struct->get_tree(); + gcc_assert (result_struct != NULL); + result = result_struct->get_tree (); } if (result == error_mark_node) - return this->error_type(); + return this->error_type (); // The libffi library cannot represent a zero-sized object. To // avoid causing confusion on 32-bit SPARC, we treat a function that // returns a zero-sized value as returning void. That should do no // harm since there is no actual value to be returned. See // https://gcc.gnu.org/PR72814 for details. - if (result != void_type_node && int_size_in_bytes(result) == 0) + if (result != void_type_node && int_size_in_bytes (result) == 0) result = void_type_node; - tree fntype = build_function_type(result, args); + tree fntype = build_function_type (result, args); if (fntype == error_mark_node) - return this->error_type(); + return this->error_type (); - return this->make_type(build_pointer_type(fntype)); + return this->make_type (build_pointer_type (fntype)); } // Make a struct type. -Btype* -Gcc_backend::struct_type(const std::vector& fields) +Btype * +Gcc_backend::struct_type (const std::vector &fields) { - return this->fill_in_struct(this->make_type(make_node(RECORD_TYPE)), fields); + return this->fill_in_struct (this->make_type (make_node (RECORD_TYPE)), + fields); } // Fill in the fields of a struct type. -Btype* -Gcc_backend::fill_in_struct(Btype* fill, - const std::vector& fields) +Btype * +Gcc_backend::fill_in_struct (Btype *fill, + const std::vector &fields) { - tree fill_tree = fill->get_tree(); + tree fill_tree = fill->get_tree (); tree field_trees = NULL_TREE; - tree* pp = &field_trees; - for (std::vector::const_iterator p = fields.begin(); - p != fields.end(); - ++p) + tree *pp = &field_trees; + for (std::vector::const_iterator p = fields.begin (); + p != fields.end (); ++p) { - tree name_tree = get_identifier_from_string(p->name); - tree type_tree = p->btype->get_tree(); + tree name_tree = get_identifier_from_string (p->name); + tree type_tree = p->btype->get_tree (); if (type_tree == error_mark_node) - return this->error_type(); - tree field = build_decl(p->location.gcc_location(), FIELD_DECL, name_tree, - type_tree); - DECL_CONTEXT(field) = fill_tree; + return this->error_type (); + tree field = build_decl (p->location.gcc_location (), FIELD_DECL, + name_tree, type_tree); + DECL_CONTEXT (field) = fill_tree; *pp = field; - pp = &DECL_CHAIN(field); + pp = &DECL_CHAIN (field); } - TYPE_FIELDS(fill_tree) = field_trees; - layout_type(fill_tree); + TYPE_FIELDS (fill_tree) = field_trees; + layout_type (fill_tree); - // Because Go permits converting between named struct types and + // Because Rust permits converting between named struct types and // equivalent struct types, for which we use VIEW_CONVERT_EXPR, and // because we don't try to maintain TYPE_CANONICAL for struct types, // we need to tell the middle-end to use structural equality. - SET_TYPE_STRUCTURAL_EQUALITY(fill_tree); + SET_TYPE_STRUCTURAL_EQUALITY (fill_tree); return fill; } // Make an array type. -Btype* -Gcc_backend::array_type(Btype* element_btype, Bexpression* length) +Btype * +Gcc_backend::array_type (Btype *element_btype, Bexpression *length) { - return this->fill_in_array(this->make_type(make_node(ARRAY_TYPE)), - element_btype, length); + return this->fill_in_array (this->make_type (make_node (ARRAY_TYPE)), + element_btype, length); } // Fill in an array type. -Btype* -Gcc_backend::fill_in_array(Btype* fill, Btype* element_type, - Bexpression* length) +Btype * +Gcc_backend::fill_in_array (Btype *fill, Btype *element_type, + Bexpression *length) { - tree element_type_tree = element_type->get_tree(); - tree length_tree = length->get_tree(); + tree element_type_tree = element_type->get_tree (); + tree length_tree = length->get_tree (); if (element_type_tree == error_mark_node || length_tree == error_mark_node) - return this->error_type(); + return this->error_type (); - gcc_assert(TYPE_SIZE(element_type_tree) != NULL_TREE); + gcc_assert (TYPE_SIZE (element_type_tree) != NULL_TREE); - length_tree = fold_convert(sizetype, length_tree); + length_tree = fold_convert (sizetype, length_tree); // build_index_type takes the maximum index, which is one less than // the length. - tree index_type_tree = build_index_type(fold_build2(MINUS_EXPR, sizetype, - length_tree, - size_one_node)); - - tree fill_tree = fill->get_tree(); - TREE_TYPE(fill_tree) = element_type_tree; - TYPE_DOMAIN(fill_tree) = index_type_tree; - TYPE_ADDR_SPACE(fill_tree) = TYPE_ADDR_SPACE(element_type_tree); - layout_type(fill_tree); - - if (TYPE_STRUCTURAL_EQUALITY_P(element_type_tree)) - SET_TYPE_STRUCTURAL_EQUALITY(fill_tree); - else if (TYPE_CANONICAL(element_type_tree) != element_type_tree - || TYPE_CANONICAL(index_type_tree) != index_type_tree) - TYPE_CANONICAL(fill_tree) = - build_array_type(TYPE_CANONICAL(element_type_tree), - TYPE_CANONICAL(index_type_tree)); + tree index_type_tree = build_index_type ( + fold_build2 (MINUS_EXPR, sizetype, length_tree, size_one_node)); + + tree fill_tree = fill->get_tree (); + TREE_TYPE (fill_tree) = element_type_tree; + TYPE_DOMAIN (fill_tree) = index_type_tree; + TYPE_ADDR_SPACE (fill_tree) = TYPE_ADDR_SPACE (element_type_tree); + layout_type (fill_tree); + + if (TYPE_STRUCTURAL_EQUALITY_P (element_type_tree)) + SET_TYPE_STRUCTURAL_EQUALITY (fill_tree); + else if (TYPE_CANONICAL (element_type_tree) != element_type_tree + || TYPE_CANONICAL (index_type_tree) != index_type_tree) + TYPE_CANONICAL (fill_tree) + = build_array_type (TYPE_CANONICAL (element_type_tree), + TYPE_CANONICAL (index_type_tree)); return fill; } // Create a placeholder for a pointer type. -Btype* -Gcc_backend::placeholder_pointer_type(const std::string& name, - Location location, bool) +Btype * +Gcc_backend::placeholder_pointer_type (const std::string &name, + Location location, bool) { - tree ret = build_distinct_type_copy(ptr_type_node); - if (!name.empty()) + tree ret = build_distinct_type_copy (ptr_type_node); + if (!name.empty ()) { - tree decl = build_decl(location.gcc_location(), TYPE_DECL, - get_identifier_from_string(name), - ret); - TYPE_NAME(ret) = decl; + tree decl = build_decl (location.gcc_location (), TYPE_DECL, + get_identifier_from_string (name), ret); + TYPE_NAME (ret) = decl; } - return this->make_type(ret); + return this->make_type (ret); } // Set the real target type for a placeholder pointer type. bool -Gcc_backend::set_placeholder_pointer_type(Btype* placeholder, - Btype* to_type) +Gcc_backend::set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) { - tree pt = placeholder->get_tree(); + tree pt = placeholder->get_tree (); if (pt == error_mark_node) return false; - gcc_assert(TREE_CODE(pt) == POINTER_TYPE); - tree tt = to_type->get_tree(); + gcc_assert (TREE_CODE (pt) == POINTER_TYPE); + tree tt = to_type->get_tree (); if (tt == error_mark_node) { - placeholder->set_tree(error_mark_node); + placeholder->set_tree (error_mark_node); return false; } - gcc_assert(TREE_CODE(tt) == POINTER_TYPE); - TREE_TYPE(pt) = TREE_TYPE(tt); - TYPE_CANONICAL(pt) = TYPE_CANONICAL(tt); - if (TYPE_NAME(pt) != NULL_TREE) + gcc_assert (TREE_CODE (tt) == POINTER_TYPE); + TREE_TYPE (pt) = TREE_TYPE (tt); + TYPE_CANONICAL (pt) = TYPE_CANONICAL (tt); + if (TYPE_NAME (pt) != NULL_TREE) { // Build the data structure gcc wants to see for a typedef. - tree copy = build_variant_type_copy(pt); - TYPE_NAME(copy) = NULL_TREE; - DECL_ORIGINAL_TYPE(TYPE_NAME(pt)) = copy; + tree copy = build_variant_type_copy (pt); + TYPE_NAME (copy) = NULL_TREE; + DECL_ORIGINAL_TYPE (TYPE_NAME (pt)) = copy; } return true; } @@ -1214,160 +1041,153 @@ Gcc_backend::set_placeholder_pointer_type(Btype* placeholder, // Set the real values for a placeholder function type. bool -Gcc_backend::set_placeholder_function_type(Btype* placeholder, Btype* ft) +Gcc_backend::set_placeholder_function_type (Btype *placeholder, Btype *ft) { - return this->set_placeholder_pointer_type(placeholder, ft); + return this->set_placeholder_pointer_type (placeholder, ft); } // Create a placeholder for a struct type. -Btype* -Gcc_backend::placeholder_struct_type(const std::string& name, - Location location) +Btype * +Gcc_backend::placeholder_struct_type (const std::string &name, + Location location) { - tree ret = make_node(RECORD_TYPE); - if (!name.empty()) + tree ret = make_node (RECORD_TYPE); + if (!name.empty ()) { - tree decl = build_decl(location.gcc_location(), TYPE_DECL, - get_identifier_from_string(name), - ret); - TYPE_NAME(ret) = decl; + tree decl = build_decl (location.gcc_location (), TYPE_DECL, + get_identifier_from_string (name), ret); + TYPE_NAME (ret) = decl; // The struct type that eventually replaces this placeholder will require // structural equality. The placeholder must too, so that the requirement // for structural equality propagates to references that are constructed // before the replacement occurs. - SET_TYPE_STRUCTURAL_EQUALITY(ret); + SET_TYPE_STRUCTURAL_EQUALITY (ret); } - return this->make_type(ret); + return this->make_type (ret); } // Fill in the fields of a placeholder struct type. bool -Gcc_backend::set_placeholder_struct_type( - Btype* placeholder, - const std::vector& fields) +Gcc_backend::set_placeholder_struct_type ( + Btype *placeholder, const std::vector &fields) { - tree t = placeholder->get_tree(); - gcc_assert(TREE_CODE(t) == RECORD_TYPE && TYPE_FIELDS(t) == NULL_TREE); - Btype* r = this->fill_in_struct(placeholder, fields); + tree t = placeholder->get_tree (); + gcc_assert (TREE_CODE (t) == RECORD_TYPE && TYPE_FIELDS (t) == NULL_TREE); + Btype *r = this->fill_in_struct (placeholder, fields); - if (TYPE_NAME(t) != NULL_TREE) + if (TYPE_NAME (t) != NULL_TREE) { // Build the data structure gcc wants to see for a typedef. - tree copy = build_distinct_type_copy(t); - TYPE_NAME(copy) = NULL_TREE; - DECL_ORIGINAL_TYPE(TYPE_NAME(t)) = copy; - TYPE_SIZE(copy) = NULL_TREE; - Btype* bc = this->make_type(copy); - this->fill_in_struct(bc, fields); + tree copy = build_distinct_type_copy (t); + TYPE_NAME (copy) = NULL_TREE; + DECL_ORIGINAL_TYPE (TYPE_NAME (t)) = copy; + TYPE_SIZE (copy) = NULL_TREE; + Btype *bc = this->make_type (copy); + this->fill_in_struct (bc, fields); delete bc; } - return r->get_tree() != error_mark_node; + return r->get_tree () != error_mark_node; } // Create a placeholder for an array type. -Btype* -Gcc_backend::placeholder_array_type(const std::string& name, - Location location) +Btype * +Gcc_backend::placeholder_array_type (const std::string &name, Location location) { - tree ret = make_node(ARRAY_TYPE); - tree decl = build_decl(location.gcc_location(), TYPE_DECL, - get_identifier_from_string(name), - ret); - TYPE_NAME(ret) = decl; - return this->make_type(ret); + tree ret = make_node (ARRAY_TYPE); + tree decl = build_decl (location.gcc_location (), TYPE_DECL, + get_identifier_from_string (name), ret); + TYPE_NAME (ret) = decl; + return this->make_type (ret); } // Fill in the fields of a placeholder array type. bool -Gcc_backend::set_placeholder_array_type(Btype* placeholder, - Btype* element_btype, - Bexpression* length) +Gcc_backend::set_placeholder_array_type (Btype *placeholder, + Btype *element_btype, + Bexpression *length) { - tree t = placeholder->get_tree(); - gcc_assert(TREE_CODE(t) == ARRAY_TYPE && TREE_TYPE(t) == NULL_TREE); - Btype* r = this->fill_in_array(placeholder, element_btype, length); + tree t = placeholder->get_tree (); + gcc_assert (TREE_CODE (t) == ARRAY_TYPE && TREE_TYPE (t) == NULL_TREE); + Btype *r = this->fill_in_array (placeholder, element_btype, length); // Build the data structure gcc wants to see for a typedef. - tree copy = build_distinct_type_copy(t); - TYPE_NAME(copy) = NULL_TREE; - DECL_ORIGINAL_TYPE(TYPE_NAME(t)) = copy; + tree copy = build_distinct_type_copy (t); + TYPE_NAME (copy) = NULL_TREE; + DECL_ORIGINAL_TYPE (TYPE_NAME (t)) = copy; - return r->get_tree() != error_mark_node; + return r->get_tree () != error_mark_node; } // Return a named version of a type. -Btype* -Gcc_backend::named_type(const std::string& name, Btype* btype, - Location location) +Btype * +Gcc_backend::named_type (const std::string &name, Btype *btype, + Location location) { - tree type = btype->get_tree(); + tree type = btype->get_tree (); if (type == error_mark_node) - return this->error_type(); + return this->error_type (); - // The middle-end expects a basic type to have a name. In Go every + // The middle-end expects a basic type to have a name. In Rust every // basic type will have a name. The first time we see a basic type, - // give it whatever Go name we have at this point. - if (TYPE_NAME(type) == NULL_TREE - && location.gcc_location() == BUILTINS_LOCATION - && (TREE_CODE(type) == INTEGER_TYPE - || TREE_CODE(type) == REAL_TYPE - || TREE_CODE(type) == COMPLEX_TYPE - || TREE_CODE(type) == BOOLEAN_TYPE)) - { - tree decl = build_decl(BUILTINS_LOCATION, TYPE_DECL, - get_identifier_from_string(name), - type); - TYPE_NAME(type) = decl; - return this->make_type(type); - } - - tree copy = build_variant_type_copy(type); - tree decl = build_decl(location.gcc_location(), TYPE_DECL, - get_identifier_from_string(name), - copy); - DECL_ORIGINAL_TYPE(decl) = type; - TYPE_NAME(copy) = decl; - return this->make_type(copy); + // give it whatever Rust name we have at this point. + if (TYPE_NAME (type) == NULL_TREE + && location.gcc_location () == BUILTINS_LOCATION + && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE + || TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == BOOLEAN_TYPE)) + { + tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, + get_identifier_from_string (name), type); + TYPE_NAME (type) = decl; + return this->make_type (type); + } + + tree copy = build_variant_type_copy (type); + tree decl = build_decl (location.gcc_location (), TYPE_DECL, + get_identifier_from_string (name), copy); + DECL_ORIGINAL_TYPE (decl) = type; + TYPE_NAME (copy) = decl; + return this->make_type (copy); } // Return a pointer type used as a marker for a circular type. -Btype* -Gcc_backend::circular_pointer_type(Btype*, bool) +Btype * +Gcc_backend::circular_pointer_type (Btype *, bool) { - return this->make_type(ptr_type_node); + return this->make_type (ptr_type_node); } // Return whether we might be looking at a circular type. bool -Gcc_backend::is_circular_pointer_type(Btype* btype) +Gcc_backend::is_circular_pointer_type (Btype *btype) { - return btype->get_tree() == ptr_type_node; + return btype->get_tree () == ptr_type_node; } // Return the size of a type. int64_t -Gcc_backend::type_size(Btype* btype) +Gcc_backend::type_size (Btype *btype) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); if (t == error_mark_node) return 1; if (t == void_type_node) return 0; - t = TYPE_SIZE_UNIT(t); - gcc_assert(tree_fits_uhwi_p (t)); - unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t); - int64_t ret = static_cast(val_wide); - if (ret < 0 || static_cast(ret) != val_wide) + t = TYPE_SIZE_UNIT (t); + gcc_assert (tree_fits_uhwi_p (t)); + unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW (t); + int64_t ret = static_cast (val_wide); + if (ret < 0 || static_cast (ret) != val_wide) return -1; return ret; } @@ -1375,409 +1195,402 @@ Gcc_backend::type_size(Btype* btype) // Return the alignment of a type. int64_t -Gcc_backend::type_alignment(Btype* btype) +Gcc_backend::type_alignment (Btype *btype) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); if (t == error_mark_node) return 1; - return TYPE_ALIGN_UNIT(t); + return TYPE_ALIGN_UNIT (t); } // Return the alignment of a struct field of type BTYPE. int64_t -Gcc_backend::type_field_alignment(Btype* btype) +Gcc_backend::type_field_alignment (Btype *btype) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); if (t == error_mark_node) return 1; - return rust_field_alignment(t); + return rust_field_alignment (t); } // Return the offset of a field in a struct. int64_t -Gcc_backend::type_field_offset(Btype* btype, size_t index) +Gcc_backend::type_field_offset (Btype *btype, size_t index) { - tree struct_tree = btype->get_tree(); + tree struct_tree = btype->get_tree (); if (struct_tree == error_mark_node) return 0; - gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE); - tree field = TYPE_FIELDS(struct_tree); + gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE); + tree field = TYPE_FIELDS (struct_tree); for (; index > 0; --index) { - field = DECL_CHAIN(field); - gcc_assert(field != NULL_TREE); + field = DECL_CHAIN (field); + gcc_assert (field != NULL_TREE); } - HOST_WIDE_INT offset_wide = int_byte_position(field); - int64_t ret = static_cast(offset_wide); - gcc_assert(ret == offset_wide); + HOST_WIDE_INT offset_wide = int_byte_position (field); + int64_t ret = static_cast (offset_wide); + gcc_assert (ret == offset_wide); return ret; } // Return the zero value for a type. -Bexpression* -Gcc_backend::zero_expression(Btype* btype) +Bexpression * +Gcc_backend::zero_expression (Btype *btype) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); tree ret; if (t == error_mark_node) ret = error_mark_node; else - ret = build_zero_cst(t); - return this->make_expression(ret); + ret = build_zero_cst (t); + return this->make_expression (ret); } // An expression that references a variable. -Bexpression* -Gcc_backend::var_expression(Bvariable* var, Location location) +Bexpression * +Gcc_backend::var_expression (Bvariable *var, Location location) { - tree ret = var->get_tree(location); + tree ret = var->get_tree (location); if (ret == error_mark_node) - return this->error_expression(); - return this->make_expression(ret); + return this->error_expression (); + return this->make_expression (ret); } // An expression that indirectly references an expression. -Bexpression* -Gcc_backend::indirect_expression(Btype* btype, Bexpression* expr, - bool known_valid, Location location) +Bexpression * +Gcc_backend::indirect_expression (Btype *btype, Bexpression *expr, + bool known_valid, Location location) { - tree expr_tree = expr->get_tree(); - tree type_tree = btype->get_tree(); + tree expr_tree = expr->get_tree (); + tree type_tree = btype->get_tree (); if (expr_tree == error_mark_node || type_tree == error_mark_node) - return this->error_expression(); + return this->error_expression (); // If the type of EXPR is a recursive pointer type, then we // need to insert a cast before indirecting. - tree target_type_tree = TREE_TYPE(TREE_TYPE(expr_tree)); - if (VOID_TYPE_P(target_type_tree)) - expr_tree = fold_convert_loc(location.gcc_location(), - build_pointer_type(type_tree), expr_tree); + tree target_type_tree = TREE_TYPE (TREE_TYPE (expr_tree)); + if (VOID_TYPE_P (target_type_tree)) + expr_tree = fold_convert_loc (location.gcc_location (), + build_pointer_type (type_tree), expr_tree); - tree ret = build_fold_indirect_ref_loc(location.gcc_location(), - expr_tree); + tree ret = build_fold_indirect_ref_loc (location.gcc_location (), expr_tree); if (known_valid) - TREE_THIS_NOTRAP(ret) = 1; - return this->make_expression(ret); + TREE_THIS_NOTRAP (ret) = 1; + return this->make_expression (ret); } // Return an expression that declares a constant named NAME with the // constant value VAL in BTYPE. -Bexpression* -Gcc_backend::named_constant_expression(Btype* btype, const std::string& name, - Bexpression* val, Location location) +Bexpression * +Gcc_backend::named_constant_expression (Btype *btype, const std::string &name, + Bexpression *val, Location location) { - tree type_tree = btype->get_tree(); - tree const_val = val->get_tree(); + tree type_tree = btype->get_tree (); + tree const_val = val->get_tree (); if (type_tree == error_mark_node || const_val == error_mark_node) - return this->error_expression(); + return this->error_expression (); - tree name_tree = get_identifier_from_string(name); - tree decl = build_decl(location.gcc_location(), CONST_DECL, name_tree, - type_tree); - DECL_INITIAL(decl) = const_val; - TREE_CONSTANT(decl) = 1; - TREE_READONLY(decl) = 1; + tree name_tree = get_identifier_from_string (name); + tree decl + = build_decl (location.gcc_location (), CONST_DECL, name_tree, type_tree); + DECL_INITIAL (decl) = const_val; + TREE_CONSTANT (decl) = 1; + TREE_READONLY (decl) = 1; - rust_preserve_from_gc(decl); - return this->make_expression(decl); + rust_preserve_from_gc (decl); + return this->make_expression (decl); } // Return a typed value as a constant integer. -Bexpression* -Gcc_backend::integer_constant_expression(Btype* btype, mpz_t val) +Bexpression * +Gcc_backend::integer_constant_expression (Btype *btype, mpz_t val) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); if (t == error_mark_node) - return this->error_expression(); + return this->error_expression (); - tree ret = double_int_to_tree(t, mpz_get_double_int(t, val, true)); - return this->make_expression(ret); + tree ret = double_int_to_tree (t, mpz_get_double_int (t, val, true)); + return this->make_expression (ret); } // Return a typed value as a constant floating-point number. -Bexpression* -Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val) +Bexpression * +Gcc_backend::float_constant_expression (Btype *btype, mpfr_t val) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); tree ret; if (t == error_mark_node) - return this->error_expression(); + return this->error_expression (); REAL_VALUE_TYPE r1; - real_from_mpfr(&r1, val, t, GMP_RNDN); + real_from_mpfr (&r1, val, t, GMP_RNDN); REAL_VALUE_TYPE r2; - real_convert(&r2, TYPE_MODE(t), &r1); - ret = build_real(t, r2); - return this->make_expression(ret); + real_convert (&r2, TYPE_MODE (t), &r1); + ret = build_real (t, r2); + return this->make_expression (ret); } // Return a typed real and imaginary value as a constant complex number. -Bexpression* -Gcc_backend::complex_constant_expression(Btype* btype, mpc_t val) +Bexpression * +Gcc_backend::complex_constant_expression (Btype *btype, mpc_t val) { - tree t = btype->get_tree(); + tree t = btype->get_tree (); tree ret; if (t == error_mark_node) - return this->error_expression(); + return this->error_expression (); REAL_VALUE_TYPE r1; - real_from_mpfr(&r1, mpc_realref(val), TREE_TYPE(t), GMP_RNDN); + real_from_mpfr (&r1, mpc_realref (val), TREE_TYPE (t), GMP_RNDN); REAL_VALUE_TYPE r2; - real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1); + real_convert (&r2, TYPE_MODE (TREE_TYPE (t)), &r1); REAL_VALUE_TYPE r3; - real_from_mpfr(&r3, mpc_imagref(val), TREE_TYPE(t), GMP_RNDN); + real_from_mpfr (&r3, mpc_imagref (val), TREE_TYPE (t), GMP_RNDN); REAL_VALUE_TYPE r4; - real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3); + real_convert (&r4, TYPE_MODE (TREE_TYPE (t)), &r3); - ret = build_complex(t, build_real(TREE_TYPE(t), r2), - build_real(TREE_TYPE(t), r4)); - return this->make_expression(ret); + ret = build_complex (t, build_real (TREE_TYPE (t), r2), + build_real (TREE_TYPE (t), r4)); + return this->make_expression (ret); } // Make a constant string expression. -Bexpression* -Gcc_backend::string_constant_expression(const std::string& val) +Bexpression * +Gcc_backend::string_constant_expression (const std::string &val) { - tree index_type = build_index_type(size_int(val.length())); - tree const_char_type = build_qualified_type(unsigned_char_type_node, - TYPE_QUAL_CONST); - tree string_type = build_array_type(const_char_type, index_type); - TYPE_STRING_FLAG(string_type) = 1; - tree string_val = build_string(val.length(), val.data()); - TREE_TYPE(string_val) = string_type; + tree index_type = build_index_type (size_int (val.length ())); + tree const_char_type + = build_qualified_type (unsigned_char_type_node, TYPE_QUAL_CONST); + tree string_type = build_array_type (const_char_type, index_type); + TYPE_STRING_FLAG (string_type) = 1; + tree string_val = build_string (val.length (), val.data ()); + TREE_TYPE (string_val) = string_type; - return this->make_expression(string_val); + return this->make_expression (string_val); } // Make a constant boolean expression. -Bexpression* -Gcc_backend::boolean_constant_expression(bool val) +Bexpression * +Gcc_backend::boolean_constant_expression (bool val) { tree bool_cst = val ? boolean_true_node : boolean_false_node; - return this->make_expression(bool_cst); + return this->make_expression (bool_cst); } // Return the real part of a complex expression. -Bexpression* -Gcc_backend::real_part_expression(Bexpression* bcomplex, Location location) +Bexpression * +Gcc_backend::real_part_expression (Bexpression *bcomplex, Location location) { - tree complex_tree = bcomplex->get_tree(); + tree complex_tree = bcomplex->get_tree (); if (complex_tree == error_mark_node) - return this->error_expression(); - gcc_assert(COMPLEX_FLOAT_TYPE_P(TREE_TYPE(complex_tree))); - tree ret = fold_build1_loc(location.gcc_location(), REALPART_EXPR, - TREE_TYPE(TREE_TYPE(complex_tree)), - complex_tree); - return this->make_expression(ret); + return this->error_expression (); + gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree))); + tree ret + = fold_build1_loc (location.gcc_location (), REALPART_EXPR, + TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree); + return this->make_expression (ret); } // Return the imaginary part of a complex expression. -Bexpression* -Gcc_backend::imag_part_expression(Bexpression* bcomplex, Location location) +Bexpression * +Gcc_backend::imag_part_expression (Bexpression *bcomplex, Location location) { - tree complex_tree = bcomplex->get_tree(); + tree complex_tree = bcomplex->get_tree (); if (complex_tree == error_mark_node) - return this->error_expression(); - gcc_assert(COMPLEX_FLOAT_TYPE_P(TREE_TYPE(complex_tree))); - tree ret = fold_build1_loc(location.gcc_location(), IMAGPART_EXPR, - TREE_TYPE(TREE_TYPE(complex_tree)), - complex_tree); - return this->make_expression(ret); + return this->error_expression (); + gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree))); + tree ret + = fold_build1_loc (location.gcc_location (), IMAGPART_EXPR, + TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree); + return this->make_expression (ret); } // Make a complex expression given its real and imaginary parts. -Bexpression* -Gcc_backend::complex_expression(Bexpression* breal, Bexpression* bimag, - Location location) +Bexpression * +Gcc_backend::complex_expression (Bexpression *breal, Bexpression *bimag, + Location location) { - tree real_tree = breal->get_tree(); - tree imag_tree = bimag->get_tree(); + tree real_tree = breal->get_tree (); + tree imag_tree = bimag->get_tree (); if (real_tree == error_mark_node || imag_tree == error_mark_node) - return this->error_expression(); - gcc_assert(TYPE_MAIN_VARIANT(TREE_TYPE(real_tree)) - == TYPE_MAIN_VARIANT(TREE_TYPE(imag_tree))); - gcc_assert(SCALAR_FLOAT_TYPE_P(TREE_TYPE(real_tree))); - tree ret = fold_build2_loc(location.gcc_location(), COMPLEX_EXPR, - build_complex_type(TREE_TYPE(real_tree)), - real_tree, imag_tree); - return this->make_expression(ret); + return this->error_expression (); + gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (real_tree)) + == TYPE_MAIN_VARIANT (TREE_TYPE (imag_tree))); + gcc_assert (SCALAR_FLOAT_TYPE_P (TREE_TYPE (real_tree))); + tree ret = fold_build2_loc (location.gcc_location (), COMPLEX_EXPR, + build_complex_type (TREE_TYPE (real_tree)), + real_tree, imag_tree); + return this->make_expression (ret); } // An expression that converts an expression to a different type. -Bexpression* -Gcc_backend::convert_expression(Btype* type, Bexpression* expr, - Location location) +Bexpression * +Gcc_backend::convert_expression (Btype *type, Bexpression *expr, + Location location) { - tree type_tree = type->get_tree(); - tree expr_tree = expr->get_tree(); - if (type_tree == error_mark_node - || expr_tree == error_mark_node - || TREE_TYPE(expr_tree) == error_mark_node) - return this->error_expression(); + tree type_tree = type->get_tree (); + tree expr_tree = expr->get_tree (); + if (type_tree == error_mark_node || expr_tree == error_mark_node + || TREE_TYPE (expr_tree) == error_mark_node) + return this->error_expression (); tree ret; - if (this->type_size(type) == 0 - || TREE_TYPE(expr_tree) == void_type_node) + if (this->type_size (type) == 0 || TREE_TYPE (expr_tree) == void_type_node) { // Do not convert zero-sized types. ret = expr_tree; } - else if (TREE_CODE(type_tree) == INTEGER_TYPE) - ret = fold(convert_to_integer(type_tree, expr_tree)); - else if (TREE_CODE(type_tree) == REAL_TYPE) - ret = fold(convert_to_real(type_tree, expr_tree)); - else if (TREE_CODE(type_tree) == COMPLEX_TYPE) - ret = fold(convert_to_complex(type_tree, expr_tree)); - else if (TREE_CODE(type_tree) == POINTER_TYPE - && TREE_CODE(TREE_TYPE(expr_tree)) == INTEGER_TYPE) - ret = fold(convert_to_pointer(type_tree, expr_tree)); - else if (TREE_CODE(type_tree) == RECORD_TYPE - || TREE_CODE(type_tree) == ARRAY_TYPE) - ret = fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR, - type_tree, expr_tree); + else if (TREE_CODE (type_tree) == INTEGER_TYPE) + ret = fold (convert_to_integer (type_tree, expr_tree)); + else if (TREE_CODE (type_tree) == REAL_TYPE) + ret = fold (convert_to_real (type_tree, expr_tree)); + else if (TREE_CODE (type_tree) == COMPLEX_TYPE) + ret = fold (convert_to_complex (type_tree, expr_tree)); + else if (TREE_CODE (type_tree) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE) + ret = fold (convert_to_pointer (type_tree, expr_tree)); + else if (TREE_CODE (type_tree) == RECORD_TYPE + || TREE_CODE (type_tree) == ARRAY_TYPE) + ret = fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR, + type_tree, expr_tree); else - ret = fold_convert_loc(location.gcc_location(), type_tree, expr_tree); + ret = fold_convert_loc (location.gcc_location (), type_tree, expr_tree); - return this->make_expression(ret); + return this->make_expression (ret); } // Get the address of a function. -Bexpression* -Gcc_backend::function_code_expression(Bfunction* bfunc, Location location) +Bexpression * +Gcc_backend::function_code_expression (Bfunction *bfunc, Location location) { - tree func = bfunc->get_tree(); + tree func = bfunc->get_tree (); if (func == error_mark_node) - return this->error_expression(); + return this->error_expression (); - tree ret = build_fold_addr_expr_loc(location.gcc_location(), func); - return this->make_expression(ret); + tree ret = build_fold_addr_expr_loc (location.gcc_location (), func); + return this->make_expression (ret); } // Get the address of an expression. -Bexpression* -Gcc_backend::address_expression(Bexpression* bexpr, Location location) +Bexpression * +Gcc_backend::address_expression (Bexpression *bexpr, Location location) { - tree expr = bexpr->get_tree(); + tree expr = bexpr->get_tree (); if (expr == error_mark_node) - return this->error_expression(); + return this->error_expression (); - tree ret = build_fold_addr_expr_loc(location.gcc_location(), expr); - return this->make_expression(ret); + tree ret = build_fold_addr_expr_loc (location.gcc_location (), expr); + return this->make_expression (ret); } // Return an expression for the field at INDEX in BSTRUCT. -Bexpression* -Gcc_backend::struct_field_expression(Bexpression* bstruct, size_t index, - Location location) +Bexpression * +Gcc_backend::struct_field_expression (Bexpression *bstruct, size_t index, + Location location) { - tree struct_tree = bstruct->get_tree(); + tree struct_tree = bstruct->get_tree (); if (struct_tree == error_mark_node - || TREE_TYPE(struct_tree) == error_mark_node) - return this->error_expression(); - gcc_assert(TREE_CODE(TREE_TYPE(struct_tree)) == RECORD_TYPE); - tree field = TYPE_FIELDS(TREE_TYPE(struct_tree)); + || TREE_TYPE (struct_tree) == error_mark_node) + return this->error_expression (); + gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE); + tree field = TYPE_FIELDS (TREE_TYPE (struct_tree)); if (field == NULL_TREE) - { - // This can happen for a type which refers to itself indirectly - // and then turns out to be erroneous. - return this->error_expression(); - } + { + // This can happen for a type which refers to itself indirectly + // and then turns out to be erroneous. + return this->error_expression (); + } for (unsigned int i = index; i > 0; --i) - { - field = DECL_CHAIN(field); - gcc_assert(field != NULL_TREE); - } - if (TREE_TYPE(field) == error_mark_node) - return this->error_expression(); - tree ret = fold_build3_loc(location.gcc_location(), COMPONENT_REF, - TREE_TYPE(field), struct_tree, field, - NULL_TREE); - if (TREE_CONSTANT(struct_tree)) - TREE_CONSTANT(ret) = 1; - return this->make_expression(ret); + { + field = DECL_CHAIN (field); + gcc_assert (field != NULL_TREE); + } + if (TREE_TYPE (field) == error_mark_node) + return this->error_expression (); + tree ret = fold_build3_loc (location.gcc_location (), COMPONENT_REF, + TREE_TYPE (field), struct_tree, field, NULL_TREE); + if (TREE_CONSTANT (struct_tree)) + TREE_CONSTANT (ret) = 1; + return this->make_expression (ret); } // Return an expression that executes BSTAT before BEXPR. -Bexpression* -Gcc_backend::compound_expression(Bstatement* bstat, Bexpression* bexpr, - Location location) +Bexpression * +Gcc_backend::compound_expression (Bstatement *bstat, Bexpression *bexpr, + Location location) { - tree stat = bstat->get_tree(); - tree expr = bexpr->get_tree(); + tree stat = bstat->get_tree (); + tree expr = bexpr->get_tree (); if (stat == error_mark_node || expr == error_mark_node) - return this->error_expression(); - tree ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR, - TREE_TYPE(expr), stat, expr); - return this->make_expression(ret); + return this->error_expression (); + tree ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, + TREE_TYPE (expr), stat, expr); + return this->make_expression (ret); } // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise. -Bexpression* -Gcc_backend::conditional_expression(Bfunction*, Btype* btype, - Bexpression* condition, - Bexpression* then_expr, - Bexpression* else_expr, Location location) -{ - tree type_tree = btype == NULL ? void_type_node : btype->get_tree(); - tree cond_tree = condition->get_tree(); - tree then_tree = then_expr->get_tree(); - tree else_tree = else_expr == NULL ? NULL_TREE : else_expr->get_tree(); - if (type_tree == error_mark_node - || cond_tree == error_mark_node - || then_tree == error_mark_node - || else_tree == error_mark_node) - return this->error_expression(); - tree ret = build3_loc(location.gcc_location(), COND_EXPR, type_tree, - cond_tree, then_tree, else_tree); - return this->make_expression(ret); +Bexpression * +Gcc_backend::conditional_expression (Bfunction *, Btype *btype, + Bexpression *condition, + Bexpression *then_expr, + Bexpression *else_expr, Location location) +{ + tree type_tree = btype == NULL ? void_type_node : btype->get_tree (); + tree cond_tree = condition->get_tree (); + tree then_tree = then_expr->get_tree (); + tree else_tree = else_expr == NULL ? NULL_TREE : else_expr->get_tree (); + if (type_tree == error_mark_node || cond_tree == error_mark_node + || then_tree == error_mark_node || else_tree == error_mark_node) + return this->error_expression (); + tree ret = build3_loc (location.gcc_location (), COND_EXPR, type_tree, + cond_tree, then_tree, else_tree); + return this->make_expression (ret); } // Return an expression for the unary operation OP EXPR. -Bexpression* -Gcc_backend::unary_expression(Operator op, Bexpression* expr, Location location) +Bexpression * +Gcc_backend::unary_expression (Operator op, Bexpression *expr, + Location location) { - tree expr_tree = expr->get_tree(); - if (expr_tree == error_mark_node - || TREE_TYPE(expr_tree) == error_mark_node) - return this->error_expression(); + tree expr_tree = expr->get_tree (); + if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node) + return this->error_expression (); - tree type_tree = TREE_TYPE(expr_tree); + tree type_tree = TREE_TYPE (expr_tree); enum tree_code code; switch (op) { - case OPERATOR_MINUS: - { - tree computed_type = excess_precision_type(type_tree); - if (computed_type != NULL_TREE) - { - expr_tree = convert(computed_type, expr_tree); - type_tree = computed_type; - } - code = NEGATE_EXPR; - break; + case OPERATOR_MINUS: { + tree computed_type = excess_precision_type (type_tree); + if (computed_type != NULL_TREE) + { + expr_tree = convert (computed_type, expr_tree); + type_tree = computed_type; + } + code = NEGATE_EXPR; + break; } case OPERATOR_NOT: code = TRUTH_NOT_EXPR; @@ -1786,19 +1599,19 @@ Gcc_backend::unary_expression(Operator op, Bexpression* expr, Location location) code = BIT_NOT_EXPR; break; default: - gcc_unreachable(); + gcc_unreachable (); break; } - tree ret = fold_build1_loc(location.gcc_location(), code, type_tree, - expr_tree); - return this->make_expression(ret); + tree ret + = fold_build1_loc (location.gcc_location (), code, type_tree, expr_tree); + return this->make_expression (ret); } -// Convert a gofrontend operator to an equivalent tree_code. +// Convert a rustfrontend operator to an equivalent tree_code. static enum tree_code -operator_to_tree_code(Operator op, tree type) +operator_to_tree_code (Operator op, tree type) { enum tree_code code; switch (op) @@ -1843,7 +1656,7 @@ operator_to_tree_code(Operator op, tree type) code = MULT_EXPR; break; case OPERATOR_DIV: - if (TREE_CODE(type) == REAL_TYPE || TREE_CODE(type) == COMPLEX_TYPE) + if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == COMPLEX_TYPE) code = RDIV_EXPR; else code = TRUNC_DIV_EXPR; @@ -1864,7 +1677,7 @@ operator_to_tree_code(Operator op, tree type) code = BIT_AND_EXPR; break; default: - gcc_unreachable(); + gcc_unreachable (); } return code; @@ -1872,24 +1685,24 @@ operator_to_tree_code(Operator op, tree type) // Return an expression for the binary operation LEFT OP RIGHT. -Bexpression* -Gcc_backend::binary_expression(Operator op, Bexpression* left, - Bexpression* right, Location location) +Bexpression * +Gcc_backend::binary_expression (Operator op, Bexpression *left, + Bexpression *right, Location location) { - tree left_tree = left->get_tree(); - tree right_tree = right->get_tree(); - if (left_tree == error_mark_node - || right_tree == error_mark_node) - return this->error_expression(); - enum tree_code code = operator_to_tree_code(op, TREE_TYPE(left_tree)); + tree left_tree = left->get_tree (); + tree right_tree = right->get_tree (); + if (left_tree == error_mark_node || right_tree == error_mark_node) + return this->error_expression (); + enum tree_code code = operator_to_tree_code (op, TREE_TYPE (left_tree)); bool use_left_type = op != OPERATOR_OROR && op != OPERATOR_ANDAND; - tree type_tree = use_left_type ? TREE_TYPE(left_tree) : TREE_TYPE(right_tree); - tree computed_type = excess_precision_type(type_tree); + tree type_tree + = use_left_type ? TREE_TYPE (left_tree) : TREE_TYPE (right_tree); + tree computed_type = excess_precision_type (type_tree); if (computed_type != NULL_TREE) { - left_tree = convert(computed_type, left_tree); - right_tree = convert(computed_type, right_tree); + left_tree = convert (computed_type, left_tree); + right_tree = convert (computed_type, right_tree); type_tree = computed_type; } @@ -1908,306 +1721,297 @@ Gcc_backend::binary_expression(Operator op, Bexpression* left, break; } - tree ret = fold_build2_loc(location.gcc_location(), code, type_tree, - left_tree, right_tree); - return this->make_expression(ret); + tree ret = fold_build2_loc (location.gcc_location (), code, type_tree, + left_tree, right_tree); + return this->make_expression (ret); } // Return an expression that constructs BTYPE with VALS. -Bexpression* -Gcc_backend::constructor_expression(Btype* btype, - const std::vector& vals, - Location location) +Bexpression * +Gcc_backend::constructor_expression (Btype *btype, + const std::vector &vals, + Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_expression(); + return this->error_expression (); vec *init; - vec_alloc(init, vals.size()); + vec_alloc (init, vals.size ()); tree sink = NULL_TREE; bool is_constant = true; - tree field = TYPE_FIELDS(type_tree); - for (std::vector::const_iterator p = vals.begin(); - p != vals.end(); - ++p, field = DECL_CHAIN(field)) - { - gcc_assert(field != NULL_TREE); - tree val = (*p)->get_tree(); - if (TREE_TYPE(field) == error_mark_node - || val == error_mark_node - || TREE_TYPE(val) == error_mark_node) - return this->error_expression(); - - if (int_size_in_bytes(TREE_TYPE(field)) == 0) + tree field = TYPE_FIELDS (type_tree); + for (std::vector::const_iterator p = vals.begin (); + p != vals.end (); ++p, field = DECL_CHAIN (field)) + { + gcc_assert (field != NULL_TREE); + tree val = (*p)->get_tree (); + if (TREE_TYPE (field) == error_mark_node || val == error_mark_node + || TREE_TYPE (val) == error_mark_node) + return this->error_expression (); + + if (int_size_in_bytes (TREE_TYPE (field)) == 0) { // GIMPLE cannot represent indices of zero-sized types so // trying to construct a map with zero-sized keys might lead // to errors. Instead, we evaluate each expression that // would have been added as a map element for its // side-effects and construct an empty map. - append_to_statement_list(val, &sink); + append_to_statement_list (val, &sink); continue; } constructor_elt empty = {NULL, NULL}; - constructor_elt* elt = init->quick_push(empty); + constructor_elt *elt = init->quick_push (empty); elt->index = field; - elt->value = this->convert_tree(TREE_TYPE(field), val, location); - if (!TREE_CONSTANT(elt->value)) + elt->value = this->convert_tree (TREE_TYPE (field), val, location); + if (!TREE_CONSTANT (elt->value)) is_constant = false; } - gcc_assert(field == NULL_TREE); - tree ret = build_constructor(type_tree, init); + gcc_assert (field == NULL_TREE); + tree ret = build_constructor (type_tree, init); if (is_constant) - TREE_CONSTANT(ret) = 1; + TREE_CONSTANT (ret) = 1; if (sink != NULL_TREE) - ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR, - type_tree, sink, ret); - return this->make_expression(ret); + ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree, + sink, ret); + return this->make_expression (ret); } -Bexpression* -Gcc_backend::array_constructor_expression( - Btype* array_btype, const std::vector& indexes, - const std::vector& vals, Location location) +Bexpression * +Gcc_backend::array_constructor_expression ( + Btype *array_btype, const std::vector &indexes, + const std::vector &vals, Location location) { - tree type_tree = array_btype->get_tree(); + tree type_tree = array_btype->get_tree (); if (type_tree == error_mark_node) - return this->error_expression(); + return this->error_expression (); - gcc_assert(indexes.size() == vals.size()); + gcc_assert (indexes.size () == vals.size ()); - tree element_type = TREE_TYPE(type_tree); - HOST_WIDE_INT element_size = int_size_in_bytes(element_type); + tree element_type = TREE_TYPE (type_tree); + HOST_WIDE_INT element_size = int_size_in_bytes (element_type); vec *init; - vec_alloc(init, element_size == 0 ? 0 : vals.size()); + vec_alloc (init, element_size == 0 ? 0 : vals.size ()); tree sink = NULL_TREE; bool is_constant = true; - for (size_t i = 0; i < vals.size(); ++i) + for (size_t i = 0; i < vals.size (); ++i) { - tree index = size_int(indexes[i]); - tree val = (vals[i])->get_tree(); + tree index = size_int (indexes[i]); + tree val = (vals[i])->get_tree (); - if (index == error_mark_node - || val == error_mark_node) - return this->error_expression(); + if (index == error_mark_node || val == error_mark_node) + return this->error_expression (); if (element_size == 0) - { - // GIMPLE cannot represent arrays of zero-sized types so trying - // to construct an array of zero-sized values might lead to errors. - // Instead, we evaluate each expression that would have been added as - // an array value for its side-effects and construct an empty array. - append_to_statement_list(val, &sink); - continue; - } - - if (!TREE_CONSTANT(val)) - is_constant = false; + { + // GIMPLE cannot represent arrays of zero-sized types so trying + // to construct an array of zero-sized values might lead to errors. + // Instead, we evaluate each expression that would have been added as + // an array value for its side-effects and construct an empty array. + append_to_statement_list (val, &sink); + continue; + } + + if (!TREE_CONSTANT (val)) + is_constant = false; constructor_elt empty = {NULL, NULL}; - constructor_elt* elt = init->quick_push(empty); + constructor_elt *elt = init->quick_push (empty); elt->index = index; elt->value = val; } - tree ret = build_constructor(type_tree, init); + tree ret = build_constructor (type_tree, init); if (is_constant) - TREE_CONSTANT(ret) = 1; + TREE_CONSTANT (ret) = 1; if (sink != NULL_TREE) - ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR, - type_tree, sink, ret); - return this->make_expression(ret); + ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree, + sink, ret); + return this->make_expression (ret); } // Return an expression for the address of BASE[INDEX]. -Bexpression* -Gcc_backend::pointer_offset_expression(Bexpression* base, Bexpression* index, - Location location) +Bexpression * +Gcc_backend::pointer_offset_expression (Bexpression *base, Bexpression *index, + Location location) { - tree base_tree = base->get_tree(); - tree index_tree = index->get_tree(); - tree element_type_tree = TREE_TYPE(TREE_TYPE(base_tree)); - if (base_tree == error_mark_node - || TREE_TYPE(base_tree) == error_mark_node - || index_tree == error_mark_node - || element_type_tree == error_mark_node) - return this->error_expression(); + tree base_tree = base->get_tree (); + tree index_tree = index->get_tree (); + tree element_type_tree = TREE_TYPE (TREE_TYPE (base_tree)); + if (base_tree == error_mark_node || TREE_TYPE (base_tree) == error_mark_node + || index_tree == error_mark_node || element_type_tree == error_mark_node) + return this->error_expression (); - tree element_size = TYPE_SIZE_UNIT(element_type_tree); - index_tree = fold_convert_loc(location.gcc_location(), sizetype, index_tree); - tree offset = fold_build2_loc(location.gcc_location(), MULT_EXPR, sizetype, - index_tree, element_size); - tree ptr = fold_build2_loc(location.gcc_location(), POINTER_PLUS_EXPR, - TREE_TYPE(base_tree), base_tree, offset); - return this->make_expression(ptr); + tree element_size = TYPE_SIZE_UNIT (element_type_tree); + index_tree + = fold_convert_loc (location.gcc_location (), sizetype, index_tree); + tree offset = fold_build2_loc (location.gcc_location (), MULT_EXPR, sizetype, + index_tree, element_size); + tree ptr = fold_build2_loc (location.gcc_location (), POINTER_PLUS_EXPR, + TREE_TYPE (base_tree), base_tree, offset); + return this->make_expression (ptr); } // Return an expression representing ARRAY[INDEX] -Bexpression* -Gcc_backend::array_index_expression(Bexpression* array, Bexpression* index, - Location location) +Bexpression * +Gcc_backend::array_index_expression (Bexpression *array, Bexpression *index, + Location location) { - tree array_tree = array->get_tree(); - tree index_tree = index->get_tree(); - if (array_tree == error_mark_node - || TREE_TYPE(array_tree) == error_mark_node + tree array_tree = array->get_tree (); + tree index_tree = index->get_tree (); + if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node || index_tree == error_mark_node) - return this->error_expression(); + return this->error_expression (); // A function call that returns a zero sized object will have been // changed to return void. If we see void here, assume we are // dealing with a zero sized type and just evaluate the operands. tree ret; - if (TREE_TYPE(array_tree) != void_type_node) - ret = build4_loc(location.gcc_location(), ARRAY_REF, - TREE_TYPE(TREE_TYPE(array_tree)), array_tree, - index_tree, NULL_TREE, NULL_TREE); + if (TREE_TYPE (array_tree) != void_type_node) + ret = build4_loc (location.gcc_location (), ARRAY_REF, + TREE_TYPE (TREE_TYPE (array_tree)), array_tree, + index_tree, NULL_TREE, NULL_TREE); else - ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR, - void_type_node, array_tree, index_tree); + ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, + void_type_node, array_tree, index_tree); - return this->make_expression(ret); + return this->make_expression (ret); } // Create an expression for a call to FN_EXPR with FN_ARGS. -Bexpression* -Gcc_backend::call_expression(Bfunction*, // containing fcn for call - Bexpression* fn_expr, - const std::vector& fn_args, - Bexpression* chain_expr, - Location location) -{ - tree fn = fn_expr->get_tree(); - if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node) - return this->error_expression(); - - gcc_assert(FUNCTION_POINTER_TYPE_P(TREE_TYPE(fn))); - tree rettype = TREE_TYPE(TREE_TYPE(TREE_TYPE(fn))); - - size_t nargs = fn_args.size(); - tree* args = nargs == 0 ? NULL : new tree[nargs]; +Bexpression * +Gcc_backend::call_expression (Bfunction *, // containing fcn for call + Bexpression *fn_expr, + const std::vector &fn_args, + Bexpression *chain_expr, Location location) +{ + tree fn = fn_expr->get_tree (); + if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node) + return this->error_expression (); + + gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn))); + tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))); + + size_t nargs = fn_args.size (); + tree *args = nargs == 0 ? NULL : new tree[nargs]; for (size_t i = 0; i < nargs; ++i) { - args[i] = fn_args.at(i)->get_tree(); + args[i] = fn_args.at (i)->get_tree (); if (args[i] == error_mark_node) - return this->error_expression(); + return this->error_expression (); } tree fndecl = fn; - if (TREE_CODE(fndecl) == ADDR_EXPR) - fndecl = TREE_OPERAND(fndecl, 0); + if (TREE_CODE (fndecl) == ADDR_EXPR) + fndecl = TREE_OPERAND (fndecl, 0); // This is to support builtin math functions when using 80387 math. tree excess_type = NULL_TREE; - if (optimize - && TREE_CODE(fndecl) == FUNCTION_DECL + if (optimize && TREE_CODE (fndecl) == FUNCTION_DECL && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) - && DECL_IS_BUILTIN (fndecl) - && nargs > 0 - && ((SCALAR_FLOAT_TYPE_P(rettype) - && SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[0]))) - || (COMPLEX_FLOAT_TYPE_P(rettype) - && COMPLEX_FLOAT_TYPE_P(TREE_TYPE(args[0]))))) - { - excess_type = excess_precision_type(TREE_TYPE(args[0])); + && DECL_IS_UNDECLARED_BUILTIN (fndecl) && nargs > 0 + && ((SCALAR_FLOAT_TYPE_P (rettype) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[0]))) + || (COMPLEX_FLOAT_TYPE_P (rettype) + && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[0]))))) + { + excess_type = excess_precision_type (TREE_TYPE (args[0])); if (excess_type != NULL_TREE) { - tree excess_fndecl = mathfn_built_in(excess_type, - DECL_FUNCTION_CODE(fndecl)); + tree excess_fndecl + = mathfn_built_in (excess_type, DECL_FUNCTION_CODE (fndecl)); if (excess_fndecl == NULL_TREE) excess_type = NULL_TREE; else { - fn = build_fold_addr_expr_loc(location.gcc_location(), - excess_fndecl); + fn = build_fold_addr_expr_loc (location.gcc_location (), + excess_fndecl); for (size_t i = 0; i < nargs; ++i) { - if (SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[i])) - || COMPLEX_FLOAT_TYPE_P(TREE_TYPE(args[i]))) - args[i] = ::convert(excess_type, args[i]); + if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[i])) + || COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[i]))) + args[i] = ::convert (excess_type, args[i]); } } } } - tree ret = - build_call_array_loc(location.gcc_location(), - excess_type != NULL_TREE ? excess_type : rettype, - fn, nargs, args); + tree ret + = build_call_array_loc (location.gcc_location (), + excess_type != NULL_TREE ? excess_type : rettype, + fn, nargs, args); if (chain_expr) - CALL_EXPR_STATIC_CHAIN (ret) = chain_expr->get_tree(); + CALL_EXPR_STATIC_CHAIN (ret) = chain_expr->get_tree (); if (excess_type != NULL_TREE) { // Calling convert here can undo our excess precision change. // That may or may not be a bug in convert_to_real. - ret = build1_loc(location.gcc_location(), NOP_EXPR, rettype, ret); + ret = build1_loc (location.gcc_location (), NOP_EXPR, rettype, ret); } delete[] args; - return this->make_expression(ret); + return this->make_expression (ret); } // An expression as a statement. -Bstatement* -Gcc_backend::expression_statement(Bfunction*, Bexpression* expr) +Bstatement * +Gcc_backend::expression_statement (Bfunction *, Bexpression *expr) { - return this->make_statement(expr->get_tree()); + return this->make_statement (expr->get_tree ()); } // Variable initialization. -Bstatement* -Gcc_backend::init_statement(Bfunction*, Bvariable* var, Bexpression* init) +Bstatement * +Gcc_backend::init_statement (Bfunction *, Bvariable *var, Bexpression *init) { - tree var_tree = var->get_decl(); - tree init_tree = init->get_tree(); + tree var_tree = var->get_decl (); + tree init_tree = init->get_tree (); if (var_tree == error_mark_node || init_tree == error_mark_node) - return this->error_statement(); - gcc_assert(TREE_CODE(var_tree) == VAR_DECL); + return this->error_statement (); + gcc_assert (TREE_CODE (var_tree) == VAR_DECL); // To avoid problems with GNU ld, we don't make zero-sized // externally visible variables. That might lead us to doing an // initialization of a zero-sized expression to a non-zero sized // variable, or vice-versa. Avoid crashes by omitting the // initializer. Such initializations don't mean anything anyhow. - if (int_size_in_bytes(TREE_TYPE(var_tree)) != 0 - && init_tree != NULL_TREE - && TREE_TYPE(init_tree) != void_type_node - && int_size_in_bytes(TREE_TYPE(init_tree)) != 0) + if (int_size_in_bytes (TREE_TYPE (var_tree)) != 0 && init_tree != NULL_TREE + && TREE_TYPE (init_tree) != void_type_node + && int_size_in_bytes (TREE_TYPE (init_tree)) != 0) { - DECL_INITIAL(var_tree) = init_tree; + DECL_INITIAL (var_tree) = init_tree; init_tree = NULL_TREE; } - tree ret = build1_loc(DECL_SOURCE_LOCATION(var_tree), DECL_EXPR, - void_type_node, var_tree); + tree ret = build1_loc (DECL_SOURCE_LOCATION (var_tree), DECL_EXPR, + void_type_node, var_tree); if (init_tree != NULL_TREE) - ret = build2_loc(DECL_SOURCE_LOCATION(var_tree), COMPOUND_EXPR, - void_type_node, init_tree, ret); + ret = build2_loc (DECL_SOURCE_LOCATION (var_tree), COMPOUND_EXPR, + void_type_node, init_tree, ret); - return this->make_statement(ret); + return this->make_statement (ret); } // Assignment. -Bstatement* -Gcc_backend::assignment_statement(Bfunction* bfn, Bexpression* lhs, - Bexpression* rhs, Location location) +Bstatement * +Gcc_backend::assignment_statement (Bfunction *bfn, Bexpression *lhs, + Bexpression *rhs, Location location) { - tree lhs_tree = lhs->get_tree(); - tree rhs_tree = rhs->get_tree(); + tree lhs_tree = lhs->get_tree (); + tree rhs_tree = rhs->get_tree (); if (lhs_tree == error_mark_node || rhs_tree == error_mark_node) - return this->error_statement(); + return this->error_statement (); // To avoid problems with GNU ld, we don't make zero-sized // externally visible variables. That might lead us to doing an @@ -2215,71 +2019,69 @@ Gcc_backend::assignment_statement(Bfunction* bfn, Bexpression* lhs, // expression; avoid crashes here by avoiding assignments of // zero-sized expressions. Such assignments don't really mean // anything anyhow. - if (TREE_TYPE(lhs_tree) == void_type_node - || int_size_in_bytes(TREE_TYPE(lhs_tree)) == 0 - || TREE_TYPE(rhs_tree) == void_type_node - || int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0) - return this->compound_statement(this->expression_statement(bfn, lhs), - this->expression_statement(bfn, rhs)); + if (TREE_TYPE (lhs_tree) == void_type_node + || int_size_in_bytes (TREE_TYPE (lhs_tree)) == 0 + || TREE_TYPE (rhs_tree) == void_type_node + || int_size_in_bytes (TREE_TYPE (rhs_tree)) == 0) + return this->compound_statement (this->expression_statement (bfn, lhs), + this->expression_statement (bfn, rhs)); - rhs_tree = this->convert_tree(TREE_TYPE(lhs_tree), rhs_tree, location); + rhs_tree = this->convert_tree (TREE_TYPE (lhs_tree), rhs_tree, location); - return this->make_statement(fold_build2_loc(location.gcc_location(), - MODIFY_EXPR, - void_type_node, - lhs_tree, rhs_tree)); + return this->make_statement (fold_build2_loc (location.gcc_location (), + MODIFY_EXPR, void_type_node, + lhs_tree, rhs_tree)); } // Return. -Bstatement* -Gcc_backend::return_statement(Bfunction* bfunction, - const std::vector& vals, - Location location) +Bstatement * +Gcc_backend::return_statement (Bfunction *bfunction, + const std::vector &vals, + Location location) { - tree fntree = bfunction->get_tree(); + tree fntree = bfunction->get_tree (); if (fntree == error_mark_node) - return this->error_statement(); - tree result = DECL_RESULT(fntree); + return this->error_statement (); + tree result = DECL_RESULT (fntree); if (result == error_mark_node) - return this->error_statement(); + return this->error_statement (); // If the result size is zero bytes, we have set the function type // to have a result type of void, so don't return anything. // See the function_type method. - tree res_type = TREE_TYPE(result); - if (res_type == void_type_node || int_size_in_bytes(res_type) == 0) + tree res_type = TREE_TYPE (result); + if (res_type == void_type_node || int_size_in_bytes (res_type) == 0) { tree stmt_list = NULL_TREE; - for (std::vector::const_iterator p = vals.begin(); - p != vals.end(); - p++) + for (std::vector::const_iterator p = vals.begin (); + p != vals.end (); p++) { - tree val = (*p)->get_tree(); + tree val = (*p)->get_tree (); if (val == error_mark_node) - return this->error_statement(); - append_to_statement_list(val, &stmt_list); + return this->error_statement (); + append_to_statement_list (val, &stmt_list); } - tree ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, - void_type_node, NULL_TREE); - append_to_statement_list(ret, &stmt_list); - return this->make_statement(stmt_list); + tree ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR, + void_type_node, NULL_TREE); + append_to_statement_list (ret, &stmt_list); + return this->make_statement (stmt_list); } tree ret; - if (vals.empty()) - ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node, - NULL_TREE); - else if (vals.size() == 1) + if (vals.empty ()) + ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR, + void_type_node, NULL_TREE); + else if (vals.size () == 1) { - tree val = vals.front()->get_tree(); + tree val = vals.front ()->get_tree (); if (val == error_mark_node) - return this->error_statement(); - tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR, - void_type_node, result, - vals.front()->get_tree()); - ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, - void_type_node, set); + return this->error_statement (); + tree set + = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, + void_type_node, result, vals.front ()->get_tree ()); + ret = fold_build1_loc (location.gcc_location (), RETURN_EXPR, + void_type_node, set); } else { @@ -2288,203 +2090,191 @@ Gcc_backend::return_statement(Bfunction* bfunction, // temporary variable to the DECL_RESULT in the return // statement. tree stmt_list = NULL_TREE; - tree rettype = TREE_TYPE(result); + tree rettype = TREE_TYPE (result); - if (DECL_STRUCT_FUNCTION(fntree) == NULL) - push_struct_function(fntree); + if (DECL_STRUCT_FUNCTION (fntree) == NULL) + push_struct_function (fntree); else - push_cfun(DECL_STRUCT_FUNCTION(fntree)); - tree rettmp = create_tmp_var(rettype, "RESULT"); - pop_cfun(); - - tree field = TYPE_FIELDS(rettype); - for (std::vector::const_iterator p = vals.begin(); - p != vals.end(); - p++, field = DECL_CHAIN(field)) + push_cfun (DECL_STRUCT_FUNCTION (fntree)); + tree rettmp = create_tmp_var (rettype, "RESULT"); + pop_cfun (); + + tree field = TYPE_FIELDS (rettype); + for (std::vector::const_iterator p = vals.begin (); + p != vals.end (); p++, field = DECL_CHAIN (field)) { - gcc_assert(field != NULL_TREE); - tree ref = fold_build3_loc(location.gcc_location(), COMPONENT_REF, - TREE_TYPE(field), rettmp, field, - NULL_TREE); - tree val = (*p)->get_tree(); + gcc_assert (field != NULL_TREE); + tree ref + = fold_build3_loc (location.gcc_location (), COMPONENT_REF, + TREE_TYPE (field), rettmp, field, NULL_TREE); + tree val = (*p)->get_tree (); if (val == error_mark_node) - return this->error_statement(); - tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR, - void_type_node, - ref, (*p)->get_tree()); - append_to_statement_list(set, &stmt_list); + return this->error_statement (); + tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, + void_type_node, ref, (*p)->get_tree ()); + append_to_statement_list (set, &stmt_list); } - gcc_assert(field == NULL_TREE); - tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR, - void_type_node, - result, rettmp); - tree ret_expr = fold_build1_loc(location.gcc_location(), RETURN_EXPR, - void_type_node, set); - append_to_statement_list(ret_expr, &stmt_list); + gcc_assert (field == NULL_TREE); + tree set = fold_build2_loc (location.gcc_location (), MODIFY_EXPR, + void_type_node, result, rettmp); + tree ret_expr = fold_build1_loc (location.gcc_location (), RETURN_EXPR, + void_type_node, set); + append_to_statement_list (ret_expr, &stmt_list); ret = stmt_list; } - return this->make_statement(ret); + return this->make_statement (ret); } // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an // error occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and if not -// NULL, it will always be executed. This is used for handling defers in Go +// NULL, it will always be executed. This is used for handling defers in Rust // functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } -Bstatement* -Gcc_backend::exception_handler_statement(Bstatement* bstat, - Bstatement* except_stmt, - Bstatement* finally_stmt, - Location location) +Bstatement * +Gcc_backend::exception_handler_statement (Bstatement *bstat, + Bstatement *except_stmt, + Bstatement *finally_stmt, + Location location) { - tree stat_tree = bstat->get_tree(); - tree except_tree = except_stmt == NULL ? NULL_TREE : except_stmt->get_tree(); - tree finally_tree = finally_stmt == NULL - ? NULL_TREE - : finally_stmt->get_tree(); + tree stat_tree = bstat->get_tree (); + tree except_tree = except_stmt == NULL ? NULL_TREE : except_stmt->get_tree (); + tree finally_tree + = finally_stmt == NULL ? NULL_TREE : finally_stmt->get_tree (); - if (stat_tree == error_mark_node - || except_tree == error_mark_node + if (stat_tree == error_mark_node || except_tree == error_mark_node || finally_tree == error_mark_node) - return this->error_statement(); + return this->error_statement (); if (except_tree != NULL_TREE) - stat_tree = build2_loc(location.gcc_location(), TRY_CATCH_EXPR, - void_type_node, stat_tree, - build2_loc(location.gcc_location(), CATCH_EXPR, - void_type_node, NULL, except_tree)); + stat_tree = build2_loc (location.gcc_location (), TRY_CATCH_EXPR, + void_type_node, stat_tree, + build2_loc (location.gcc_location (), CATCH_EXPR, + void_type_node, NULL, except_tree)); if (finally_tree != NULL_TREE) - stat_tree = build2_loc(location.gcc_location(), TRY_FINALLY_EXPR, - void_type_node, stat_tree, finally_tree); - return this->make_statement(stat_tree); + stat_tree = build2_loc (location.gcc_location (), TRY_FINALLY_EXPR, + void_type_node, stat_tree, finally_tree); + return this->make_statement (stat_tree); } // If. -Bstatement* -Gcc_backend::if_statement(Bfunction*, Bexpression* condition, - Bblock* then_block, Bblock* else_block, - Location location) +Bstatement * +Gcc_backend::if_statement (Bfunction *, Bexpression *condition, + Bblock *then_block, Bblock *else_block, + Location location) { - tree cond_tree = condition->get_tree(); - tree then_tree = then_block->get_tree(); - tree else_tree = else_block == NULL ? NULL_TREE : else_block->get_tree(); - if (cond_tree == error_mark_node - || then_tree == error_mark_node + tree cond_tree = condition->get_tree (); + tree then_tree = then_block->get_tree (); + tree else_tree = else_block == NULL ? NULL_TREE : else_block->get_tree (); + if (cond_tree == error_mark_node || then_tree == error_mark_node || else_tree == error_mark_node) - return this->error_statement(); - tree ret = build3_loc(location.gcc_location(), COND_EXPR, void_type_node, - cond_tree, then_tree, else_tree); - return this->make_statement(ret); + return this->error_statement (); + tree ret = build3_loc (location.gcc_location (), COND_EXPR, void_type_node, + cond_tree, then_tree, else_tree); + return this->make_statement (ret); } // Switch. -Bstatement* -Gcc_backend::switch_statement( - Bfunction* function, - Bexpression* value, - const std::vector >& cases, - const std::vector& statements, - Location switch_location) +Bstatement * +Gcc_backend::switch_statement ( + Bfunction *function, Bexpression *value, + const std::vector > &cases, + const std::vector &statements, Location switch_location) { - gcc_assert(cases.size() == statements.size()); + gcc_assert (cases.size () == statements.size ()); - tree decl = function->get_tree(); - if (DECL_STRUCT_FUNCTION(decl) == NULL) - push_struct_function(decl); + tree decl = function->get_tree (); + if (DECL_STRUCT_FUNCTION (decl) == NULL) + push_struct_function (decl); else - push_cfun(DECL_STRUCT_FUNCTION(decl)); + push_cfun (DECL_STRUCT_FUNCTION (decl)); tree stmt_list = NULL_TREE; - std::vector >::const_iterator pc = cases.begin(); - for (std::vector::const_iterator ps = statements.begin(); - ps != statements.end(); - ++ps, ++pc) + std::vector >::const_iterator pc = cases.begin (); + for (std::vector::const_iterator ps = statements.begin (); + ps != statements.end (); ++ps, ++pc) { - if (pc->empty()) + if (pc->empty ()) { - location_t loc = (*ps != NULL - ? EXPR_LOCATION((*ps)->get_tree()) - : UNKNOWN_LOCATION); - tree label = create_artificial_label(loc); - tree c = build_case_label(NULL_TREE, NULL_TREE, label); - append_to_statement_list(c, &stmt_list); + location_t loc = (*ps != NULL ? EXPR_LOCATION ((*ps)->get_tree ()) + : UNKNOWN_LOCATION); + tree label = create_artificial_label (loc); + tree c = build_case_label (NULL_TREE, NULL_TREE, label); + append_to_statement_list (c, &stmt_list); } else { - for (std::vector::const_iterator pcv = pc->begin(); - pcv != pc->end(); - ++pcv) + for (std::vector::const_iterator pcv = pc->begin (); + pcv != pc->end (); ++pcv) { - tree t = (*pcv)->get_tree(); + tree t = (*pcv)->get_tree (); if (t == error_mark_node) - return this->error_statement(); - location_t loc = EXPR_LOCATION(t); - tree label = create_artificial_label(loc); - tree c = build_case_label((*pcv)->get_tree(), NULL_TREE, label); - append_to_statement_list(c, &stmt_list); + return this->error_statement (); + location_t loc = EXPR_LOCATION (t); + tree label = create_artificial_label (loc); + tree c = build_case_label ((*pcv)->get_tree (), NULL_TREE, label); + append_to_statement_list (c, &stmt_list); } } if (*ps != NULL) { - tree t = (*ps)->get_tree(); + tree t = (*ps)->get_tree (); if (t == error_mark_node) - return this->error_statement(); - append_to_statement_list(t, &stmt_list); + return this->error_statement (); + append_to_statement_list (t, &stmt_list); } } - pop_cfun(); + pop_cfun (); - tree tv = value->get_tree(); + tree tv = value->get_tree (); if (tv == error_mark_node) - return this->error_statement(); - tree t = build2_loc(switch_location.gcc_location(), SWITCH_EXPR, - NULL_TREE, tv, stmt_list); - return this->make_statement(t); + return this->error_statement (); + tree t = build2_loc (switch_location.gcc_location (), SWITCH_EXPR, NULL_TREE, + tv, stmt_list); + return this->make_statement (t); } // Pair of statements. -Bstatement* -Gcc_backend::compound_statement(Bstatement* s1, Bstatement* s2) +Bstatement * +Gcc_backend::compound_statement (Bstatement *s1, Bstatement *s2) { tree stmt_list = NULL_TREE; - tree t = s1->get_tree(); + tree t = s1->get_tree (); if (t == error_mark_node) - return this->error_statement(); - append_to_statement_list(t, &stmt_list); - t = s2->get_tree(); + return this->error_statement (); + append_to_statement_list (t, &stmt_list); + t = s2->get_tree (); if (t == error_mark_node) - return this->error_statement(); - append_to_statement_list(t, &stmt_list); + return this->error_statement (); + append_to_statement_list (t, &stmt_list); // If neither statement has any side effects, stmt_list can be NULL // at this point. if (stmt_list == NULL_TREE) stmt_list = integer_zero_node; - return this->make_statement(stmt_list); + return this->make_statement (stmt_list); } // List of statements. -Bstatement* -Gcc_backend::statement_list(const std::vector& statements) +Bstatement * +Gcc_backend::statement_list (const std::vector &statements) { tree stmt_list = NULL_TREE; - for (std::vector::const_iterator p = statements.begin(); - p != statements.end(); - ++p) + for (std::vector::const_iterator p = statements.begin (); + p != statements.end (); ++p) { - tree t = (*p)->get_tree(); + tree t = (*p)->get_tree (); if (t == error_mark_node) - return this->error_statement(); - append_to_statement_list(t, &stmt_list); + return this->error_statement (); + append_to_statement_list (t, &stmt_list); } - return this->make_statement(stmt_list); + return this->make_statement (stmt_list); } // Make a block. For some reason gcc uses a dual structure for @@ -2492,459 +2282,437 @@ Gcc_backend::statement_list(const std::vector& statements) // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in // the Bblock. -Bblock* -Gcc_backend::block(Bfunction* function, Bblock* enclosing, - const std::vector& vars, - Location start_location, - Location) +Bblock * +Gcc_backend::block (Bfunction *function, Bblock *enclosing, + const std::vector &vars, + Location start_location, Location) { - tree block_tree = make_node(BLOCK); + tree block_tree = make_node (BLOCK); if (enclosing == NULL) { - tree fndecl = function->get_tree(); - gcc_assert(fndecl != NULL_TREE); + tree fndecl = function->get_tree (); + gcc_assert (fndecl != NULL_TREE); // We may have already created a block for local variables when // we take the address of a parameter. - if (DECL_INITIAL(fndecl) == NULL_TREE) + if (DECL_INITIAL (fndecl) == NULL_TREE) { - BLOCK_SUPERCONTEXT(block_tree) = fndecl; - DECL_INITIAL(fndecl) = block_tree; + BLOCK_SUPERCONTEXT (block_tree) = fndecl; + DECL_INITIAL (fndecl) = block_tree; } else { - tree superblock_tree = DECL_INITIAL(fndecl); - BLOCK_SUPERCONTEXT(block_tree) = superblock_tree; - tree* pp; - for (pp = &BLOCK_SUBBLOCKS(superblock_tree); - *pp != NULL_TREE; - pp = &BLOCK_CHAIN(*pp)) + tree superblock_tree = DECL_INITIAL (fndecl); + BLOCK_SUPERCONTEXT (block_tree) = superblock_tree; + tree *pp; + for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE; + pp = &BLOCK_CHAIN (*pp)) ; *pp = block_tree; } } else { - tree superbind_tree = enclosing->get_tree(); - tree superblock_tree = BIND_EXPR_BLOCK(superbind_tree); - gcc_assert(TREE_CODE(superblock_tree) == BLOCK); - - BLOCK_SUPERCONTEXT(block_tree) = superblock_tree; - tree* pp; - for (pp = &BLOCK_SUBBLOCKS(superblock_tree); - *pp != NULL_TREE; - pp = &BLOCK_CHAIN(*pp)) + tree superbind_tree = enclosing->get_tree (); + tree superblock_tree = BIND_EXPR_BLOCK (superbind_tree); + gcc_assert (TREE_CODE (superblock_tree) == BLOCK); + + BLOCK_SUPERCONTEXT (block_tree) = superblock_tree; + tree *pp; + for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE; + pp = &BLOCK_CHAIN (*pp)) ; *pp = block_tree; } - tree* pp = &BLOCK_VARS(block_tree); - for (std::vector::const_iterator pv = vars.begin(); - pv != vars.end(); - ++pv) + tree *pp = &BLOCK_VARS (block_tree); + for (std::vector::const_iterator pv = vars.begin (); + pv != vars.end (); ++pv) { - *pp = (*pv)->get_decl(); + *pp = (*pv)->get_decl (); if (*pp != error_mark_node) - pp = &DECL_CHAIN(*pp); + pp = &DECL_CHAIN (*pp); } *pp = NULL_TREE; - TREE_USED(block_tree) = 1; + TREE_USED (block_tree) = 1; - tree bind_tree = build3_loc(start_location.gcc_location(), BIND_EXPR, - void_type_node, BLOCK_VARS(block_tree), - NULL_TREE, block_tree); - TREE_SIDE_EFFECTS(bind_tree) = 1; - return new Bblock(bind_tree); + tree bind_tree + = build3_loc (start_location.gcc_location (), BIND_EXPR, void_type_node, + BLOCK_VARS (block_tree), NULL_TREE, block_tree); + TREE_SIDE_EFFECTS (bind_tree) = 1; + return new Bblock (bind_tree); } // Add statements to a block. void -Gcc_backend::block_add_statements(Bblock* bblock, - const std::vector& statements) +Gcc_backend::block_add_statements (Bblock *bblock, + const std::vector &statements) { tree stmt_list = NULL_TREE; - for (std::vector::const_iterator p = statements.begin(); - p != statements.end(); - ++p) + for (std::vector::const_iterator p = statements.begin (); + p != statements.end (); ++p) { - tree s = (*p)->get_tree(); + tree s = (*p)->get_tree (); if (s != error_mark_node) - append_to_statement_list(s, &stmt_list); + append_to_statement_list (s, &stmt_list); } - tree bind_tree = bblock->get_tree(); - gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR); - BIND_EXPR_BODY(bind_tree) = stmt_list; + tree bind_tree = bblock->get_tree (); + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + BIND_EXPR_BODY (bind_tree) = stmt_list; } // Return a block as a statement. -Bstatement* -Gcc_backend::block_statement(Bblock* bblock) +Bstatement * +Gcc_backend::block_statement (Bblock *bblock) { - tree bind_tree = bblock->get_tree(); - gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR); - return this->make_statement(bind_tree); + tree bind_tree = bblock->get_tree (); + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + return this->make_statement (bind_tree); } -// This is not static because we declare it with GTY(()) in go-c.h. -tree go_non_zero_struct; +// This is not static because we declare it with GTY(()) in rust-c.h. +tree rust_non_zero_struct; // Return a type corresponding to TYPE with non-zero size. tree -Gcc_backend::non_zero_size_type(tree type) +Gcc_backend::non_zero_size_type (tree type) { - if (int_size_in_bytes(type) != 0) + if (int_size_in_bytes (type) != 0) return type; - switch (TREE_CODE(type)) + switch (TREE_CODE (type)) { case RECORD_TYPE: - if (TYPE_FIELDS(type) != NULL_TREE) + if (TYPE_FIELDS (type) != NULL_TREE) { - tree ns = make_node(RECORD_TYPE); + tree ns = make_node (RECORD_TYPE); tree field_trees = NULL_TREE; tree *pp = &field_trees; - for (tree field = TYPE_FIELDS(type); - field != NULL_TREE; - field = DECL_CHAIN(field)) + for (tree field = TYPE_FIELDS (type); field != NULL_TREE; + field = DECL_CHAIN (field)) { - tree ft = TREE_TYPE(field); - if (field == TYPE_FIELDS(type)) - ft = non_zero_size_type(ft); - tree f = build_decl(DECL_SOURCE_LOCATION(field), FIELD_DECL, - DECL_NAME(field), ft); - DECL_CONTEXT(f) = ns; + tree ft = TREE_TYPE (field); + if (field == TYPE_FIELDS (type)) + ft = non_zero_size_type (ft); + tree f = build_decl (DECL_SOURCE_LOCATION (field), FIELD_DECL, + DECL_NAME (field), ft); + DECL_CONTEXT (f) = ns; *pp = f; - pp = &DECL_CHAIN(f); + pp = &DECL_CHAIN (f); } - TYPE_FIELDS(ns) = field_trees; - layout_type(ns); + TYPE_FIELDS (ns) = field_trees; + layout_type (ns); return ns; } - if (go_non_zero_struct == NULL_TREE) + if (rust_non_zero_struct == NULL_TREE) { - type = make_node(RECORD_TYPE); - tree field = build_decl(UNKNOWN_LOCATION, FIELD_DECL, - get_identifier("dummy"), - boolean_type_node); - DECL_CONTEXT(field) = type; - TYPE_FIELDS(type) = field; - layout_type(type); - go_non_zero_struct = type; + type = make_node (RECORD_TYPE); + tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier ("dummy"), boolean_type_node); + DECL_CONTEXT (field) = type; + TYPE_FIELDS (type) = field; + layout_type (type); + rust_non_zero_struct = type; } - return go_non_zero_struct; + return rust_non_zero_struct; - case ARRAY_TYPE: - { - tree element_type = non_zero_size_type(TREE_TYPE(type)); - return build_array_type_nelts(element_type, 1); + case ARRAY_TYPE: { + tree element_type = non_zero_size_type (TREE_TYPE (type)); + return build_array_type_nelts (element_type, 1); } default: - gcc_unreachable(); + gcc_unreachable (); } - gcc_unreachable(); + gcc_unreachable (); } -// Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Go type +// Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Rust type // can be created multiple times and thus have multiple tree // representations. Make sure this does not confuse the middle-end. tree -Gcc_backend::convert_tree(tree type_tree, tree expr_tree, Location location) +Gcc_backend::convert_tree (tree type_tree, tree expr_tree, Location location) { - if (type_tree == TREE_TYPE(expr_tree)) + if (type_tree == TREE_TYPE (expr_tree)) return expr_tree; - if (type_tree == error_mark_node - || expr_tree == error_mark_node - || TREE_TYPE(expr_tree) == error_mark_node) + if (type_tree == error_mark_node || expr_tree == error_mark_node + || TREE_TYPE (expr_tree) == error_mark_node) return error_mark_node; - gcc_assert(TREE_CODE(type_tree) == TREE_CODE(TREE_TYPE(expr_tree))); - if (POINTER_TYPE_P(type_tree) - || INTEGRAL_TYPE_P(type_tree) - || SCALAR_FLOAT_TYPE_P(type_tree) - || COMPLEX_FLOAT_TYPE_P(type_tree)) - return fold_convert_loc(location.gcc_location(), type_tree, expr_tree); - else if (TREE_CODE(type_tree) == RECORD_TYPE - || TREE_CODE(type_tree) == ARRAY_TYPE) + gcc_assert (TREE_CODE (type_tree) == TREE_CODE (TREE_TYPE (expr_tree))); + if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree) + || SCALAR_FLOAT_TYPE_P (type_tree) || COMPLEX_FLOAT_TYPE_P (type_tree)) + return fold_convert_loc (location.gcc_location (), type_tree, expr_tree); + else if (TREE_CODE (type_tree) == RECORD_TYPE + || TREE_CODE (type_tree) == ARRAY_TYPE) { - gcc_assert(int_size_in_bytes(type_tree) - == int_size_in_bytes(TREE_TYPE(expr_tree))); - if (TYPE_MAIN_VARIANT(type_tree) - == TYPE_MAIN_VARIANT(TREE_TYPE(expr_tree))) - return fold_build1_loc(location.gcc_location(), NOP_EXPR, - type_tree, expr_tree); - return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR, - type_tree, expr_tree); + gcc_assert (int_size_in_bytes (type_tree) + == int_size_in_bytes (TREE_TYPE (expr_tree))); + if (TYPE_MAIN_VARIANT (type_tree) + == TYPE_MAIN_VARIANT (TREE_TYPE (expr_tree))) + return fold_build1_loc (location.gcc_location (), NOP_EXPR, type_tree, + expr_tree); + return fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR, + type_tree, expr_tree); } - gcc_unreachable(); + gcc_unreachable (); } // Make a global variable. -Bvariable* -Gcc_backend::global_variable(const std::string& var_name, - const std::string& asm_name, - Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, - Location location) +Bvariable * +Gcc_backend::global_variable (const std::string &var_name, + const std::string &asm_name, Btype *btype, + bool is_external, bool is_hidden, + bool in_unique_section, Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); + return this->error_variable (); // The GNU linker does not like dynamic variables with zero size. tree orig_type_tree = type_tree; - if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0) - type_tree = this->non_zero_size_type(type_tree); + if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0) + type_tree = this->non_zero_size_type (type_tree); - tree decl = build_decl(location.gcc_location(), VAR_DECL, - get_identifier_from_string(var_name), - type_tree); + tree decl = build_decl (location.gcc_location (), VAR_DECL, + get_identifier_from_string (var_name), type_tree); if (is_external) - DECL_EXTERNAL(decl) = 1; + DECL_EXTERNAL (decl) = 1; else - TREE_STATIC(decl) = 1; + TREE_STATIC (decl) = 1; if (!is_hidden) { - TREE_PUBLIC(decl) = 1; - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + TREE_PUBLIC (decl) = 1; + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); } else { - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); } - TREE_USED(decl) = 1; + TREE_USED (decl) = 1; if (in_unique_section) resolve_unique_section (decl, 0, 1); - rust_preserve_from_gc(decl); + rust_preserve_from_gc (decl); - return new Bvariable(decl, orig_type_tree); + return new Bvariable (decl, orig_type_tree); } // Set the initial value of a global variable. void -Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr) +Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) { - tree expr_tree = expr->get_tree(); + tree expr_tree = expr->get_tree (); if (expr_tree == error_mark_node) return; - gcc_assert(TREE_CONSTANT(expr_tree)); - tree var_decl = var->get_decl(); + gcc_assert (TREE_CONSTANT (expr_tree)); + tree var_decl = var->get_decl (); if (var_decl == error_mark_node) return; - DECL_INITIAL(var_decl) = expr_tree; + DECL_INITIAL (var_decl) = expr_tree; - // If this variable goes in a unique section, it may need to go into + // If this variable rustes in a unique section, it may need to rust into // a different one now that DECL_INITIAL is set. - if (symtab_node::get(var_decl) - && symtab_node::get(var_decl)->implicit_section) + if (symtab_node::get (var_decl) + && symtab_node::get (var_decl)->implicit_section) { - set_decl_section_name (var_decl, NULL); - resolve_unique_section (var_decl, - compute_reloc_for_constant (expr_tree), + set_decl_section_name (var_decl, (const char *) NULL); + resolve_unique_section (var_decl, compute_reloc_for_constant (expr_tree), 1); } } // Make a local variable. -Bvariable* -Gcc_backend::local_variable(Bfunction* function, const std::string& name, - Btype* btype, Bvariable* decl_var, - bool is_address_taken, Location location) +Bvariable * +Gcc_backend::local_variable (Bfunction *function, const std::string &name, + Btype *btype, Bvariable *decl_var, + bool is_address_taken, Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - tree decl = build_decl(location.gcc_location(), VAR_DECL, - get_identifier_from_string(name), - type_tree); - DECL_CONTEXT(decl) = function->get_tree(); - TREE_USED(decl) = 1; + return this->error_variable (); + tree decl = build_decl (location.gcc_location (), VAR_DECL, + get_identifier_from_string (name), type_tree); + DECL_CONTEXT (decl) = function->get_tree (); + TREE_USED (decl) = 1; if (is_address_taken) - TREE_ADDRESSABLE(decl) = 1; + TREE_ADDRESSABLE (decl) = 1; if (decl_var != NULL) { - DECL_HAS_VALUE_EXPR_P(decl) = 1; - SET_DECL_VALUE_EXPR(decl, decl_var->get_decl()); + DECL_HAS_VALUE_EXPR_P (decl) = 1; + SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ()); } - rust_preserve_from_gc(decl); - return new Bvariable(decl); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Make a function parameter variable. -Bvariable* -Gcc_backend::parameter_variable(Bfunction* function, const std::string& name, - Btype* btype, bool is_address_taken, - Location location) +Bvariable * +Gcc_backend::parameter_variable (Bfunction *function, const std::string &name, + Btype *btype, bool is_address_taken, + Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - tree decl = build_decl(location.gcc_location(), PARM_DECL, - get_identifier_from_string(name), - type_tree); - DECL_CONTEXT(decl) = function->get_tree(); - DECL_ARG_TYPE(decl) = type_tree; - TREE_USED(decl) = 1; + return this->error_variable (); + tree decl = build_decl (location.gcc_location (), PARM_DECL, + get_identifier_from_string (name), type_tree); + DECL_CONTEXT (decl) = function->get_tree (); + DECL_ARG_TYPE (decl) = type_tree; + TREE_USED (decl) = 1; if (is_address_taken) - TREE_ADDRESSABLE(decl) = 1; - rust_preserve_from_gc(decl); - return new Bvariable(decl); + TREE_ADDRESSABLE (decl) = 1; + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Make a static chain variable. -Bvariable* -Gcc_backend::static_chain_variable(Bfunction* function, const std::string& name, - Btype* btype, Location location) +Bvariable * +Gcc_backend::static_chain_variable (Bfunction *function, + const std::string &name, Btype *btype, + Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - tree decl = build_decl(location.gcc_location(), PARM_DECL, - get_identifier_from_string(name), type_tree); - tree fndecl = function->get_tree(); - DECL_CONTEXT(decl) = fndecl; - DECL_ARG_TYPE(decl) = type_tree; - TREE_USED(decl) = 1; - DECL_ARTIFICIAL(decl) = 1; - DECL_IGNORED_P(decl) = 1; - TREE_READONLY(decl) = 1; - - struct function *f = DECL_STRUCT_FUNCTION(fndecl); + return this->error_variable (); + tree decl = build_decl (location.gcc_location (), PARM_DECL, + get_identifier_from_string (name), type_tree); + tree fndecl = function->get_tree (); + DECL_CONTEXT (decl) = fndecl; + DECL_ARG_TYPE (decl) = type_tree; + TREE_USED (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_READONLY (decl) = 1; + + struct function *f = DECL_STRUCT_FUNCTION (fndecl); if (f == NULL) { - push_struct_function(fndecl); - pop_cfun(); - f = DECL_STRUCT_FUNCTION(fndecl); + push_struct_function (fndecl); + pop_cfun (); + f = DECL_STRUCT_FUNCTION (fndecl); } - gcc_assert(f->static_chain_decl == NULL); + gcc_assert (f->static_chain_decl == NULL); f->static_chain_decl = decl; - DECL_STATIC_CHAIN(fndecl) = 1; + DECL_STATIC_CHAIN (fndecl) = 1; - rust_preserve_from_gc(decl); - return new Bvariable(decl); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Make a temporary variable. -Bvariable* -Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, - Btype* btype, Bexpression* binit, - bool is_address_taken, - Location location, - Bstatement** pstatement) -{ - gcc_assert(function != NULL); - tree decl = function->get_tree(); - tree type_tree = btype->get_tree(); - tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree(); - if (type_tree == error_mark_node - || init_tree == error_mark_node +Bvariable * +Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, + Btype *btype, Bexpression *binit, + bool is_address_taken, Location location, + Bstatement **pstatement) +{ + gcc_assert (function != NULL); + tree decl = function->get_tree (); + tree type_tree = btype->get_tree (); + tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree (); + if (type_tree == error_mark_node || init_tree == error_mark_node || decl == error_mark_node) { - *pstatement = this->error_statement(); - return this->error_variable(); + *pstatement = this->error_statement (); + return this->error_variable (); } tree var; // We can only use create_tmp_var if the type is not addressable. - if (!TREE_ADDRESSABLE(type_tree)) + if (!TREE_ADDRESSABLE (type_tree)) { - if (DECL_STRUCT_FUNCTION(decl) == NULL) - push_struct_function(decl); + if (DECL_STRUCT_FUNCTION (decl) == NULL) + push_struct_function (decl); else - push_cfun(DECL_STRUCT_FUNCTION(decl)); + push_cfun (DECL_STRUCT_FUNCTION (decl)); - var = create_tmp_var(type_tree, "GOTMP"); - pop_cfun(); + var = create_tmp_var (type_tree, "RUSTTMP"); + pop_cfun (); } else { - gcc_assert(bblock != NULL); - var = build_decl(location.gcc_location(), VAR_DECL, - create_tmp_var_name("GOTMP"), - type_tree); - DECL_ARTIFICIAL(var) = 1; - DECL_IGNORED_P(var) = 1; - TREE_USED(var) = 1; - DECL_CONTEXT(var) = decl; + gcc_assert (bblock != NULL); + var = build_decl (location.gcc_location (), VAR_DECL, + create_tmp_var_name ("RUSTTMP"), type_tree); + DECL_ARTIFICIAL (var) = 1; + DECL_IGNORED_P (var) = 1; + TREE_USED (var) = 1; + DECL_CONTEXT (var) = decl; // We have to add this variable to the BLOCK and the BIND_EXPR. - tree bind_tree = bblock->get_tree(); - gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR); - tree block_tree = BIND_EXPR_BLOCK(bind_tree); - gcc_assert(TREE_CODE(block_tree) == BLOCK); - DECL_CHAIN(var) = BLOCK_VARS(block_tree); - BLOCK_VARS(block_tree) = var; - BIND_EXPR_VARS(bind_tree) = BLOCK_VARS(block_tree); + tree bind_tree = bblock->get_tree (); + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + tree block_tree = BIND_EXPR_BLOCK (bind_tree); + gcc_assert (TREE_CODE (block_tree) == BLOCK); + DECL_CHAIN (var) = BLOCK_VARS (block_tree); + BLOCK_VARS (block_tree) = var; + BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree); } - if (this->type_size(btype) != 0 - && init_tree != NULL_TREE - && TREE_TYPE(init_tree) != void_type_node) - DECL_INITIAL(var) = this->convert_tree(type_tree, init_tree, location); + if (this->type_size (btype) != 0 && init_tree != NULL_TREE + && TREE_TYPE (init_tree) != void_type_node) + DECL_INITIAL (var) = this->convert_tree (type_tree, init_tree, location); if (is_address_taken) - TREE_ADDRESSABLE(var) = 1; + TREE_ADDRESSABLE (var) = 1; - *pstatement = this->make_statement(build1_loc(location.gcc_location(), - DECL_EXPR, - void_type_node, var)); + *pstatement = this->make_statement ( + build1_loc (location.gcc_location (), DECL_EXPR, void_type_node, var)); // For a zero sized type, don't initialize VAR with BINIT, but still // evaluate BINIT for its side effects. if (init_tree != NULL_TREE - && (this->type_size(btype) == 0 - || TREE_TYPE(init_tree) == void_type_node)) - *pstatement = - this->compound_statement(this->expression_statement(function, binit), - *pstatement); + && (this->type_size (btype) == 0 + || TREE_TYPE (init_tree) == void_type_node)) + *pstatement + = this->compound_statement (this->expression_statement (function, binit), + *pstatement); - return new Bvariable(var); + return new Bvariable (var); } // Create an implicit variable that is compiler-defined. This is used when // generating GC root variables and storing the values of a slice initializer. -Bvariable* -Gcc_backend::implicit_variable(const std::string& name, - const std::string& asm_name, - Btype* type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) +Bvariable * +Gcc_backend::implicit_variable (const std::string &name, + const std::string &asm_name, Btype *type, + bool is_hidden, bool is_constant, + bool is_common, int64_t alignment) { - tree type_tree = type->get_tree(); + tree type_tree = type->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - - tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, - get_identifier_from_string(name), type_tree); - DECL_EXTERNAL(decl) = 0; - TREE_PUBLIC(decl) = !is_hidden; - TREE_STATIC(decl) = 1; - TREE_USED(decl) = 1; - DECL_ARTIFICIAL(decl) = 1; + return this->error_variable (); + + tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL, + get_identifier_from_string (name), type_tree); + DECL_EXTERNAL (decl) = 0; + TREE_PUBLIC (decl) = !is_hidden; + TREE_STATIC (decl) = 1; + TREE_USED (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; if (is_common) { - DECL_COMMON(decl) = 1; + DECL_COMMON (decl) = 1; // When the initializer for one implicit_variable refers to another, // it needs to know the visibility of the referenced struct so that @@ -2953,109 +2721,108 @@ Gcc_backend::implicit_variable(const std::string& name, // which will change the return value of compute_reloc_for_constant. // We can't reliably call make_decl_one_only yet, because we don't // yet know the initializer. This issue doesn't arise in C because - // Go initializers, unlike C initializers, can be indirectly + // Rust initializers, unlike C initializers, can be indirectly // recursive. To ensure that compute_reloc_for_constant computes // the right value if some other initializer refers to this one, we // mark this symbol as weak here. We undo that below in // immutable_struct_set_init before calling mark_decl_one_only. - DECL_WEAK(decl) = 1; + DECL_WEAK (decl) = 1; } if (is_constant) { - TREE_READONLY(decl) = 1; - TREE_CONSTANT(decl) = 1; + TREE_READONLY (decl) = 1; + TREE_CONSTANT (decl) = 1; } if (alignment != 0) { - SET_DECL_ALIGN(decl, alignment * BITS_PER_UNIT); - DECL_USER_ALIGN(decl) = 1; + SET_DECL_ALIGN (decl, alignment * BITS_PER_UNIT); + DECL_USER_ALIGN (decl) = 1; } - if (! asm_name.empty()) - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + if (!asm_name.empty ()) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); - rust_preserve_from_gc(decl); - return new Bvariable(decl); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Set the initalizer for a variable created by implicit_variable. // This is where we finish compiling the variable. void -Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&, - Btype*, bool, bool, bool is_common, - Bexpression* init) +Gcc_backend::implicit_variable_set_init (Bvariable *var, const std::string &, + Btype *, bool, bool, bool is_common, + Bexpression *init) { - tree decl = var->get_decl(); + tree decl = var->get_decl (); tree init_tree; if (init == NULL) init_tree = NULL_TREE; else - init_tree = init->get_tree(); + init_tree = init->get_tree (); if (decl == error_mark_node || init_tree == error_mark_node) return; - DECL_INITIAL(decl) = init_tree; + DECL_INITIAL (decl) = init_tree; // Now that DECL_INITIAL is set, we can't call make_decl_one_only. // See the comment where DECL_WEAK is set in implicit_variable. if (is_common) { - DECL_WEAK(decl) = 0; - make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl)); + DECL_WEAK (decl) = 0; + make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); } - resolve_unique_section(decl, 2, 1); + resolve_unique_section (decl, 2, 1); - rest_of_decl_compilation(decl, 1, 0); + rest_of_decl_compilation (decl, 1, 0); } // Return a reference to an implicit variable defined in another package. -Bvariable* -Gcc_backend::implicit_variable_reference(const std::string& name, - const std::string& asm_name, - Btype* btype) +Bvariable * +Gcc_backend::implicit_variable_reference (const std::string &name, + const std::string &asm_name, + Btype *btype) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); + return this->error_variable (); - tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, - get_identifier_from_string(name), type_tree); - DECL_EXTERNAL(decl) = 1; - TREE_PUBLIC(decl) = 1; - TREE_STATIC(decl) = 0; - DECL_ARTIFICIAL(decl) = 1; - if (! asm_name.empty()) - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); - rust_preserve_from_gc(decl); - return new Bvariable(decl); + tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL, + get_identifier_from_string (name), type_tree); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_STATIC (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + if (!asm_name.empty ()) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Create a named immutable initialized data structure. -Bvariable* -Gcc_backend::immutable_struct(const std::string& name, - const std::string& asm_name, - bool is_hidden, - bool is_common, Btype* btype, Location location) +Bvariable * +Gcc_backend::immutable_struct (const std::string &name, + const std::string &asm_name, bool is_hidden, + bool is_common, Btype *btype, Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE); - tree decl = build_decl(location.gcc_location(), VAR_DECL, - get_identifier_from_string(name), - build_qualified_type(type_tree, TYPE_QUAL_CONST)); - TREE_STATIC(decl) = 1; - TREE_USED(decl) = 1; - TREE_READONLY(decl) = 1; - TREE_CONSTANT(decl) = 1; - DECL_ARTIFICIAL(decl) = 1; + return this->error_variable (); + gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE); + tree decl = build_decl (location.gcc_location (), VAR_DECL, + get_identifier_from_string (name), + build_qualified_type (type_tree, TYPE_QUAL_CONST)); + TREE_STATIC (decl) = 1; + TREE_USED (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_CONSTANT (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; if (!is_hidden) - TREE_PUBLIC(decl) = 1; - if (! asm_name.empty()) - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + TREE_PUBLIC (decl) = 1; + if (!asm_name.empty ()) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); // When the initializer for one immutable_struct refers to another, // it needs to know the visibility of the referenced struct so that @@ -3064,195 +2831,194 @@ Gcc_backend::immutable_struct(const std::string& name, // which will change the return value of compute_reloc_for_constant. // We can't reliably call make_decl_one_only yet, because we don't // yet know the initializer. This issue doesn't arise in C because - // Go initializers, unlike C initializers, can be indirectly + // Rust initializers, unlike C initializers, can be indirectly // recursive. To ensure that compute_reloc_for_constant computes // the right value if some other initializer refers to this one, we // mark this symbol as weak here. We undo that below in // immutable_struct_set_init before calling mark_decl_one_only. if (is_common) - DECL_WEAK(decl) = 1; + DECL_WEAK (decl) = 1; // We don't call rest_of_decl_compilation until we have the // initializer. - rust_preserve_from_gc(decl); - return new Bvariable(decl); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Set the initializer for a variable created by immutable_struct. // This is where we finish compiling the variable. void -Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&, - bool, bool is_common, Btype*, Location, - Bexpression* initializer) +Gcc_backend::immutable_struct_set_init (Bvariable *var, const std::string &, + bool, bool is_common, Btype *, Location, + Bexpression *initializer) { - tree decl = var->get_decl(); - tree init_tree = initializer->get_tree(); + tree decl = var->get_decl (); + tree init_tree = initializer->get_tree (); if (decl == error_mark_node || init_tree == error_mark_node) return; - DECL_INITIAL(decl) = init_tree; + DECL_INITIAL (decl) = init_tree; // Now that DECL_INITIAL is set, we can't call make_decl_one_only. // See the comment where DECL_WEAK is set in immutable_struct. if (is_common) { - DECL_WEAK(decl) = 0; - make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl)); + DECL_WEAK (decl) = 0; + make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); } // These variables are often unneeded in the final program, so put // them in their own section so that linker GC can discard them. - resolve_unique_section(decl, - compute_reloc_for_constant (init_tree), - 1); + resolve_unique_section (decl, compute_reloc_for_constant (init_tree), 1); - rest_of_decl_compilation(decl, 1, 0); + rest_of_decl_compilation (decl, 1, 0); } // Return a reference to an immutable initialized data structure // defined in another package. -Bvariable* -Gcc_backend::immutable_struct_reference(const std::string& name, - const std::string& asm_name, - Btype* btype, - Location location) +Bvariable * +Gcc_backend::immutable_struct_reference (const std::string &name, + const std::string &asm_name, + Btype *btype, Location location) { - tree type_tree = btype->get_tree(); + tree type_tree = btype->get_tree (); if (type_tree == error_mark_node) - return this->error_variable(); - gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE); - tree decl = build_decl(location.gcc_location(), VAR_DECL, - get_identifier_from_string(name), - build_qualified_type(type_tree, TYPE_QUAL_CONST)); - TREE_READONLY(decl) = 1; - TREE_CONSTANT(decl) = 1; - DECL_ARTIFICIAL(decl) = 1; - TREE_PUBLIC(decl) = 1; - DECL_EXTERNAL(decl) = 1; - if (! asm_name.empty()) - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); - rust_preserve_from_gc(decl); - return new Bvariable(decl); + return this->error_variable (); + gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE); + tree decl = build_decl (location.gcc_location (), VAR_DECL, + get_identifier_from_string (name), + build_qualified_type (type_tree, TYPE_QUAL_CONST)); + TREE_READONLY (decl) = 1; + TREE_CONSTANT (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = 1; + if (!asm_name.empty ()) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + rust_preserve_from_gc (decl); + return new Bvariable (decl); } // Make a label. -Blabel* -Gcc_backend::label(Bfunction* function, const std::string& name, - Location location) +Blabel * +Gcc_backend::label (Bfunction *function, const std::string &name, + Location location) { tree decl; - if (name.empty()) + if (name.empty ()) { - tree func_tree = function->get_tree(); - if (DECL_STRUCT_FUNCTION(func_tree) == NULL) - push_struct_function(func_tree); + tree func_tree = function->get_tree (); + if (DECL_STRUCT_FUNCTION (func_tree) == NULL) + push_struct_function (func_tree); else - push_cfun(DECL_STRUCT_FUNCTION(func_tree)); + push_cfun (DECL_STRUCT_FUNCTION (func_tree)); - decl = create_artificial_label(location.gcc_location()); + decl = create_artificial_label (location.gcc_location ()); - pop_cfun(); + pop_cfun (); } else { - tree id = get_identifier_from_string(name); - decl = build_decl(location.gcc_location(), LABEL_DECL, id, - void_type_node); - DECL_CONTEXT(decl) = function->get_tree(); + tree id = get_identifier_from_string (name); + decl + = build_decl (location.gcc_location (), LABEL_DECL, id, void_type_node); + DECL_CONTEXT (decl) = function->get_tree (); } - return new Blabel(decl); + return new Blabel (decl); } // Make a statement which defines a label. -Bstatement* -Gcc_backend::label_definition_statement(Blabel* label) +Bstatement * +Gcc_backend::label_definition_statement (Blabel *label) { - tree lab = label->get_tree(); - tree ret = fold_build1_loc(DECL_SOURCE_LOCATION(lab), LABEL_EXPR, - void_type_node, lab); - return this->make_statement(ret); + tree lab = label->get_tree (); + tree ret = fold_build1_loc (DECL_SOURCE_LOCATION (lab), LABEL_EXPR, + void_type_node, lab); + return this->make_statement (ret); } // Make a goto statement. -Bstatement* -Gcc_backend::goto_statement(Blabel* label, Location location) +Bstatement * +Gcc_backend::goto_statement (Blabel *label, Location location) { - tree lab = label->get_tree(); - tree ret = fold_build1_loc(location.gcc_location(), GOTO_EXPR, void_type_node, - lab); - return this->make_statement(ret); + tree lab = label->get_tree (); + tree ret = fold_build1_loc (location.gcc_location (), GOTO_EXPR, + void_type_node, lab); + return this->make_statement (ret); } // Get the address of a label. -Bexpression* -Gcc_backend::label_address(Blabel* label, Location location) +Bexpression * +Gcc_backend::label_address (Blabel *label, Location location) { - tree lab = label->get_tree(); - TREE_USED(lab) = 1; - TREE_ADDRESSABLE(lab) = 1; - tree ret = fold_convert_loc(location.gcc_location(), ptr_type_node, - build_fold_addr_expr_loc(location.gcc_location(), - lab)); - return this->make_expression(ret); + tree lab = label->get_tree (); + TREE_USED (lab) = 1; + TREE_ADDRESSABLE (lab) = 1; + tree ret + = fold_convert_loc (location.gcc_location (), ptr_type_node, + build_fold_addr_expr_loc (location.gcc_location (), + lab)); + return this->make_expression (ret); } // Declare or define a new function. -Bfunction* -Gcc_backend::function(Btype* fntype, const std::string& name, - const std::string& asm_name, unsigned int flags, - Location location) +Bfunction * +Gcc_backend::function (Btype *fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, + Location location) { - tree functype = fntype->get_tree(); + tree functype = fntype->get_tree (); if (functype != error_mark_node) { - gcc_assert(FUNCTION_POINTER_TYPE_P(functype)); - functype = TREE_TYPE(functype); + gcc_assert (FUNCTION_POINTER_TYPE_P (functype)); + functype = TREE_TYPE (functype); } - tree id = get_identifier_from_string(name); + tree id = get_identifier_from_string (name); if (functype == error_mark_node || id == error_mark_node) - return this->error_function(); + return this->error_function (); - tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype); - if (! asm_name.empty()) - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + tree decl + = build_decl (location.gcc_location (), FUNCTION_DECL, id, functype); + if (!asm_name.empty ()) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); if ((flags & function_is_visible) != 0) - TREE_PUBLIC(decl) = 1; + TREE_PUBLIC (decl) = 1; if ((flags & function_is_declaration) != 0) - DECL_EXTERNAL(decl) = 1; + DECL_EXTERNAL (decl) = 1; else { - tree restype = TREE_TYPE(functype); - tree resdecl = - build_decl(location.gcc_location(), RESULT_DECL, NULL_TREE, restype); - DECL_ARTIFICIAL(resdecl) = 1; - DECL_IGNORED_P(resdecl) = 1; - DECL_CONTEXT(resdecl) = decl; - DECL_RESULT(decl) = resdecl; + tree restype = TREE_TYPE (functype); + tree resdecl = build_decl (location.gcc_location (), RESULT_DECL, + NULL_TREE, restype); + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_CONTEXT (resdecl) = decl; + DECL_RESULT (decl) = resdecl; } if ((flags & function_is_inlinable) == 0) - DECL_UNINLINABLE(decl) = 1; + DECL_UNINLINABLE (decl) = 1; if ((flags & function_no_split_stack) != 0) { tree attr = get_identifier ("no_split_stack"); - DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE); + DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE, NULL_TREE); } if ((flags & function_does_not_return) != 0) - TREE_THIS_VOLATILE(decl) = 1; + TREE_THIS_VOLATILE (decl) = 1; if ((flags & function_in_unique_section) != 0) - resolve_unique_section(decl, 0, 1); + resolve_unique_section (decl, 0, 1); if ((flags & function_only_inline) != 0) { TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL(decl) = 1; - DECL_DECLARED_INLINE_P(decl) = 1; + DECL_EXTERNAL (decl) = 1; + DECL_DECLARED_INLINE_P (decl) = 1; } // Optimize thunk functions for size. A thunk created for a defer @@ -3269,29 +3035,31 @@ Gcc_backend::function(Btype* fntype, const std::string& name, // Optimizing the function for size avoids duplicating the epilogue. // This optimization shouldn't matter for any thunk since all thunks // are small. - size_t pos = name.find("..thunk"); + size_t pos = name.find ("..thunk"); if (pos != std::string::npos) { - for (pos += 7; pos < name.length(); ++pos) + for (pos += 7; pos < name.length (); ++pos) { if (name[pos] < '0' || name[pos] > '9') break; } - if (pos == name.length()) + if (pos == name.length ()) { struct cl_optimization cur_opts; - cl_optimization_save(&cur_opts, &global_options); + cl_optimization_save (&cur_opts, &global_options, + &global_options_set); global_options.x_optimize_size = 1; global_options.x_optimize_fast = 0; global_options.x_optimize_debug = 0; - DECL_FUNCTION_SPECIFIC_OPTIMIZATION(decl) = - build_optimization_node(&global_options); - cl_optimization_restore(&global_options, &cur_opts); + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) + = build_optimization_node (&global_options, &global_options_set); + cl_optimization_restore (&global_options, &global_options_set, + &cur_opts); } } - rust_preserve_from_gc(decl); - return new Bfunction(decl); + rust_preserve_from_gc (decl); + return new Bfunction (decl); } // Create a statement that runs all deferred calls for FUNCTION. This should @@ -3299,88 +3067,87 @@ Gcc_backend::function(Btype* fntype, const std::string& name, // finish: // try { UNDEFER; } catch { CHECK_DEFER; goto finish; } -Bstatement* -Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer, - Bexpression* defer, Location location) +Bstatement * +Gcc_backend::function_defer_statement (Bfunction *function, + Bexpression *undefer, Bexpression *defer, + Location location) { - tree undefer_tree = undefer->get_tree(); - tree defer_tree = defer->get_tree(); - tree fntree = function->get_tree(); + tree undefer_tree = undefer->get_tree (); + tree defer_tree = defer->get_tree (); + tree fntree = function->get_tree (); - if (undefer_tree == error_mark_node - || defer_tree == error_mark_node + if (undefer_tree == error_mark_node || defer_tree == error_mark_node || fntree == error_mark_node) - return this->error_statement(); + return this->error_statement (); - if (DECL_STRUCT_FUNCTION(fntree) == NULL) - push_struct_function(fntree); + if (DECL_STRUCT_FUNCTION (fntree) == NULL) + push_struct_function (fntree); else - push_cfun(DECL_STRUCT_FUNCTION(fntree)); + push_cfun (DECL_STRUCT_FUNCTION (fntree)); tree stmt_list = NULL; - Blabel* blabel = this->label(function, "", location); - Bstatement* label_def = this->label_definition_statement(blabel); - append_to_statement_list(label_def->get_tree(), &stmt_list); + Blabel *blabel = this->label (function, "", location); + Bstatement *label_def = this->label_definition_statement (blabel); + append_to_statement_list (label_def->get_tree (), &stmt_list); - Bstatement* jump_stmt = this->goto_statement(blabel, location); - tree jump = jump_stmt->get_tree(); - tree catch_body = build2(COMPOUND_EXPR, void_type_node, defer_tree, jump); - catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body); - tree try_catch = - build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body); - append_to_statement_list(try_catch, &stmt_list); - pop_cfun(); + Bstatement *jump_stmt = this->goto_statement (blabel, location); + tree jump = jump_stmt->get_tree (); + tree catch_body = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump); + catch_body = build2 (CATCH_EXPR, void_type_node, NULL, catch_body); + tree try_catch + = build2 (TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body); + append_to_statement_list (try_catch, &stmt_list); + pop_cfun (); - return this->make_statement(stmt_list); + return this->make_statement (stmt_list); } // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. // This will only be called for a function definition. bool -Gcc_backend::function_set_parameters(Bfunction* function, - const std::vector& param_vars) +Gcc_backend::function_set_parameters ( + Bfunction *function, const std::vector ¶m_vars) { - tree func_tree = function->get_tree(); + tree func_tree = function->get_tree (); if (func_tree == error_mark_node) return false; tree params = NULL_TREE; tree *pp = ¶ms; - for (std::vector::const_iterator pv = param_vars.begin(); - pv != param_vars.end(); - ++pv) + for (std::vector::const_iterator pv = param_vars.begin (); + pv != param_vars.end (); ++pv) { - *pp = (*pv)->get_decl(); - gcc_assert(*pp != error_mark_node); - pp = &DECL_CHAIN(*pp); + *pp = (*pv)->get_decl (); + gcc_assert (*pp != error_mark_node); + pp = &DECL_CHAIN (*pp); } *pp = NULL_TREE; - DECL_ARGUMENTS(func_tree) = params; + DECL_ARGUMENTS (func_tree) = params; return true; } // Set the function body for FUNCTION using the code in CODE_BLOCK. bool -Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt) +Gcc_backend::function_set_body (Bfunction *function, Bstatement *code_stmt) { - tree func_tree = function->get_tree(); - tree code = code_stmt->get_tree(); + tree func_tree = function->get_tree (); + tree code = code_stmt->get_tree (); if (func_tree == error_mark_node || code == error_mark_node) return false; - DECL_SAVED_TREE(func_tree) = code; + DECL_SAVED_TREE (func_tree) = code; return true; } // Look up a named built-in function in the current backend implementation. // Returns NULL if no built-in function by that name exists. -Bfunction* -Gcc_backend::lookup_builtin(const std::string& name) +Bfunction * +Gcc_backend::lookup_builtin (const std::string &name) { - if (this->builtin_functions_.count(name) != 0) + if (this->builtin_functions_.count (name) != 0) return this->builtin_functions_[name]; return NULL; } @@ -3390,88 +3157,82 @@ Gcc_backend::lookup_builtin(const std::string& name) // emit early debugging information. void -Gcc_backend::write_global_definitions( - const std::vector& type_decls, - const std::vector& constant_decls, - const std::vector& function_decls, - const std::vector& variable_decls) +Gcc_backend::write_global_definitions ( + const std::vector &type_decls, + const std::vector &constant_decls, + const std::vector &function_decls, + const std::vector &variable_decls) { - size_t count_definitions = type_decls.size() + constant_decls.size() - + function_decls.size() + variable_decls.size(); + size_t count_definitions = type_decls.size () + constant_decls.size () + + function_decls.size () + variable_decls.size (); - tree* defs = new tree[count_definitions]; + tree *defs = new tree[count_definitions]; // Convert all non-erroneous declarations into Gimple form. size_t i = 0; - for (std::vector::const_iterator p = variable_decls.begin(); - p != variable_decls.end(); - ++p) + for (std::vector::const_iterator p = variable_decls.begin (); + p != variable_decls.end (); ++p) { - tree v = (*p)->get_decl(); + tree v = (*p)->get_decl (); if (v != error_mark_node) - { - defs[i] = v; - rust_preserve_from_gc(defs[i]); - ++i; - } - } - - for (std::vector::const_iterator p = type_decls.begin(); - p != type_decls.end(); - ++p) - { - tree type_tree = (*p)->get_tree(); - if (type_tree != error_mark_node - && IS_TYPE_OR_DECL_P(type_tree)) - { - defs[i] = TYPE_NAME(type_tree); - gcc_assert(defs[i] != NULL); - rust_preserve_from_gc(defs[i]); - ++i; - } - } - for (std::vector::const_iterator p = constant_decls.begin(); - p != constant_decls.end(); - ++p) - { - if ((*p)->get_tree() != error_mark_node) - { - defs[i] = (*p)->get_tree(); - rust_preserve_from_gc(defs[i]); - ++i; - } - } - for (std::vector::const_iterator p = function_decls.begin(); - p != function_decls.end(); - ++p) - { - tree decl = (*p)->get_tree(); + { + defs[i] = v; + rust_preserve_from_gc (defs[i]); + ++i; + } + } + + for (std::vector::const_iterator p = type_decls.begin (); + p != type_decls.end (); ++p) + { + tree type_tree = (*p)->get_tree (); + if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree)) + { + defs[i] = TYPE_NAME (type_tree); + gcc_assert (defs[i] != NULL); + rust_preserve_from_gc (defs[i]); + ++i; + } + } + for (std::vector::const_iterator p = constant_decls.begin (); + p != constant_decls.end (); ++p) + { + if ((*p)->get_tree () != error_mark_node) + { + defs[i] = (*p)->get_tree (); + rust_preserve_from_gc (defs[i]); + ++i; + } + } + for (std::vector::const_iterator p = function_decls.begin (); + p != function_decls.end (); ++p) + { + tree decl = (*p)->get_tree (); if (decl != error_mark_node) - { - rust_preserve_from_gc(decl); - if (DECL_STRUCT_FUNCTION(decl) == NULL) - allocate_struct_function(decl, false); - cgraph_node::finalize_function(decl, true); + { + rust_preserve_from_gc (decl); + if (DECL_STRUCT_FUNCTION (decl) == NULL) + allocate_struct_function (decl, false); + cgraph_node::finalize_function (decl, true); - defs[i] = decl; - ++i; - } + defs[i] = decl; + ++i; + } } // Pass everything back to the middle-end. - wrapup_global_declarations(defs, i); + wrapup_global_declarations (defs, i); delete[] defs; } void -Gcc_backend::write_export_data(const char* bytes, unsigned int size) +Gcc_backend::write_export_data (const char *bytes, unsigned int size) { - rust_write_export_data(bytes, size); + rust_write_export_data (bytes, size); } - // Define a builtin function. BCODE is the builtin function code // defined by builtins.def. NAME is the name of the builtin function. // LIBNAME is the name of the corresponding library function, and is @@ -3480,34 +3241,37 @@ Gcc_backend::write_export_data(const char* bytes, unsigned int size) // NORETURN_P is true if the function has the noreturn attribute. void -Gcc_backend::define_builtin(built_in_function bcode, const char* name, - const char* libname, tree fntype, bool const_p, - bool noreturn_p) -{ - tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL, - libname, NULL_TREE); - if (const_p) - TREE_READONLY(decl) = 1; - if (noreturn_p) - TREE_THIS_VOLATILE(decl) = 1; - set_builtin_decl(bcode, decl, true); - this->builtin_functions_[name] = this->make_function(decl); +Gcc_backend::define_builtin (built_in_function bcode, const char *name, + const char *libname, tree fntype, int flags) +{ + tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, + libname, NULL_TREE); + if ((flags & builtin_const) != 0) + TREE_READONLY (decl) = 1; + if ((flags & builtin_noreturn) != 0) + TREE_THIS_VOLATILE (decl) = 1; + if ((flags & builtin_novops) != 0) + DECL_IS_NOVOPS (decl) = 1; + set_builtin_decl (bcode, decl, true); + this->builtin_functions_[name] = this->make_function (decl); if (libname != NULL) { - decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL, - NULL, NULL_TREE); - if (const_p) - TREE_READONLY(decl) = 1; - if (noreturn_p) - TREE_THIS_VOLATILE(decl) = 1; - this->builtin_functions_[libname] = this->make_function(decl); + decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL, + NULL, NULL_TREE); + if ((flags & builtin_const) != 0) + TREE_READONLY (decl) = 1; + if ((flags & builtin_noreturn) != 0) + TREE_THIS_VOLATILE (decl) = 1; + if ((flags & builtin_novops) != 0) + DECL_IS_NOVOPS (decl) = 1; + this->builtin_functions_[libname] = this->make_function (decl); } } // Return the backend generator. -Backend* -go_get_backend() +Backend * +rust_get_backend () { - return new Gcc_backend(); + return new Gcc_backend (); } diff --git a/gcc/rust/rust-lang.c b/gcc/rust/rust-lang.c deleted file mode 100644 index 6e1be89e..0000000 --- a/gcc/rust/rust-lang.c +++ /dev/null @@ -1,567 +0,0 @@ -/* rust-lang.c -- Rust frontend gcc interface. - Copyright (C) 2009-2019 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "gimple-expr.h" -#include "diagnostic.h" -#include "opts.h" -#include "fold-const.h" -#include "gimplify.h" -#include "stor-layout.h" -#include "debug.h" -#include "convert.h" -#include "langhooks.h" -#include "langhooks-def.h" -#include "common/common-target.h" - -#include - -#include "rust-c.h" - -#ifndef TARGET_AIX -#define TARGET_AIX 0 -#endif - -/* Language-dependent contents of a type. */ - -struct GTY(()) lang_type -{ - char dummy; -}; - -/* Language-dependent contents of a decl. */ - -struct GTY(()) lang_decl -{ - char dummy; -}; - -/* Language-dependent contents of an identifier. This must include a - tree_identifier. */ - -struct GTY(()) lang_identifier -{ - struct tree_identifier common; -}; - -/* The resulting tree type. */ - -union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) -lang_tree_node -{ - union tree_node GTY((tag ("0"), - desc ("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag ("1"))) identifier; -}; - -/* We don't use language_function. */ - -struct GTY(()) language_function -{ - int dummy; -}; - -/* Option information we need to pass to rust_create_rustgo. */ - -static const char *rust_pkgpath = NULL; -static const char *rust_prefix = NULL; -static const char *rust_relative_import_path = NULL; -static const char *rust_c_header = NULL; - -/* Language hooks. */ - -static bool -rust_langhook_init (void) -{ - build_common_tree_nodes (false); - - /* I don't know why this has to be done explicitly. */ - void_list_node = build_tree_list (NULL_TREE, void_type_node); - - build_common_builtin_nodes (); - - /* The default precision for floating point numbers. This is used - for floating point constants with abstract type. This may - eventually be controllable by a command line option. */ - mpfr_set_default_prec (256); - - /* Go uses exceptions. */ - using_eh_for_cleanups (); - - return true; -} - -/* The option mask. */ - -static unsigned int -rust_langhook_option_lang_mask (void) -{ - return CL_Rust; -} - -/* Initialize the options structure. */ - -static void -rust_langhook_init_options_struct (struct gcc_options *opts) -{ - /* Go says that signed overflow is precisely defined. */ - opts->x_flag_wrapv = 1; - - /* We default to using strict aliasing, since Go pointers are safe. - This is turned off for code that imports the "unsafe" package, - because using unsafe.pointer violates C style aliasing - requirements. */ - opts->x_flag_strict_aliasing = 1; - - /* Default to avoiding range issues for complex multiply and - divide. */ - opts->x_flag_complex_method = 2; - - /* The builtin math functions should not set errno. */ - opts->x_flag_errno_math = 0; - opts->frontend_set_flag_errno_math = true; - - /* Exceptions are used to handle recovering from panics. */ - opts->x_flag_exceptions = 1; - opts->x_flag_non_call_exceptions = 1; - - /* We need to keep pointers live for the garbage collector. */ - opts->x_flag_keep_gc_roots_live = 1; - - /* Go programs expect runtime.Callers to work, and that uses - libbacktrace that uses debug info. Set the debug info level to 1 - by default. In post_options we will set the debug type if the - debug info level was not set back to 0 on the command line. */ - opts->x_debug_info_level = DINFO_LEVEL_TERSE; -} - -/* Infrastructure for a vector of char * pointers. */ - -typedef const char *rust_char_p; - -/* The list of directories to search after all the Go specific - directories have been searched. */ - -static vec rust_search_dirs; - -/* Handle Go specific options. Return 0 if we didn't do anything. */ - -static bool -rust_langhook_handle_option ( - size_t scode, - const char *arg, - HOST_WIDE_INT value, - int kind ATTRIBUTE_UNUSED, - location_t loc ATTRIBUTE_UNUSED, - const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) -{ - enum opt_code code = (enum opt_code) scode; - bool ret = true; - - switch (code) - { - /*case OPT_I: - rust_add_search_path (arg); - break;*/ - - /* case OPT_L: */ - /* /\* A -L option is assumed to come from the compiler driver. */ - /* This is a system directory. We search the following */ - /* directories, if they exist, before this one: */ - /* dir/go/VERSION */ - /* dir/go/VERSION/MACHINE */ - /* This is like include/c++. *\/ */ - /* { */ - /* static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; */ - /* size_t len; */ - /* char *p; */ - /* struct stat st; */ - - /* len = strlen (arg); */ - /* p = XALLOCAVEC (char, */ - /* (len + sizeof "rust" + sizeof DEFAULT_TARGET_VERSION */ - /* + sizeof DEFAULT_TARGET_MACHINE + 3)); */ - /* strcpy (p, arg); */ - /* if (len > 0 && !IS_DIR_SEPARATOR (p[len - 1])) */ - /* strcat (p, dir_separator_str); */ - /* strcat (p, "rust"); */ - /* strcat (p, dir_separator_str); */ - /* strcat (p, DEFAULT_TARGET_VERSION); */ - /* if (stat (p, &st) == 0 && S_ISDIR (st.st_mode)) */ - /* { */ - /* rust_add_search_path (p); */ - /* strcat (p, dir_separator_str); */ - /* strcat (p, DEFAULT_TARGET_MACHINE); */ - /* if (stat (p, &st) == 0 && S_ISDIR (st.st_mode)) */ - /* rust_add_search_path (p); */ - /* } */ - - /* /\* Search ARG too, but only after we've searched to Rust */ - /* specific directories for all -L arguments. *\/ */ - /* rust_search_dirs.safe_push (arg); */ - /* } */ - /* break; */ - - default: - /* Just return 1 to indicate that the option is valid. */ - break; - } - - return ret; -} - -/* Run after parsing options. */ - -static bool -rust_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED) -{ - unsigned int ix; - const char *dir; - - gcc_assert (num_in_fnames > 0); - - // FIXME - /* FOR_EACH_VEC_ELT (rust_search_dirs, ix, dir) */ - /* rust_add_search_path (dir); */ - /* rust_search_dirs.release (); */ - - /* if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT) */ - /* flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD; */ - - /* Tail call optimizations can confuse uses of runtime.Callers. */ - if (!global_options_set.x_flag_optimize_sibling_calls) - global_options.x_flag_optimize_sibling_calls = 0; - - /* If the debug info level is still 1, as set in init_options, make - sure that some debugging type is selected. */ - if (global_options.x_debug_info_level == DINFO_LEVEL_TERSE - && global_options.x_write_symbols == NO_DEBUG) - global_options.x_write_symbols = PREFERRED_DEBUGGING_TYPE; - - /* We turn on stack splitting if we can. */ - if (!global_options_set.x_flag_split_stack - && targetm_common.supports_split_stack (false, &global_options)) - global_options.x_flag_split_stack = 1; - - /* If stack splitting is turned on, and the user did not explicitly - request function partitioning, turn off partitioning, as it - confuses the linker when trying to handle partitioned split-stack - code that calls a non-split-stack function. */ - if (global_options.x_flag_split_stack - && global_options.x_flag_reorder_blocks_and_partition - && !global_options_set.x_flag_reorder_blocks_and_partition) - global_options.x_flag_reorder_blocks_and_partition = 0; - - /* Returning false means that the backend should be used. */ - return false; -} - -static void -rust_langhook_parse_file (void) -{ - // RUSTLY MAIN - - // TODO - // rust_parse_input_files (in_fnames, num_in_fnames, flag_syntax_only); - - /* Final processing of globals and early debug info generation. */ - // rust_write_globals (); - - rust_create_rustly(flag_syntax_only, rust_get_linemap()); - rust_parse_input_files(in_fnames, num_in_fnames); -} - -static tree -rust_langhook_type_for_size (unsigned int bits, int unsignedp) -{ - tree type; - if (unsignedp) - { - if (bits == INT_TYPE_SIZE) - type = unsigned_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = unsigned_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_unsigned_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_unsigned_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_unsigned_type_node; - else - type = make_unsigned_type(bits); - } - else - { - if (bits == INT_TYPE_SIZE) - type = integer_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = signed_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_integer_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_integer_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_integer_type_node; - else - type = make_signed_type(bits); - } - return type; -} - -static tree -rust_langhook_type_for_mode (machine_mode mode, int unsignedp) -{ - tree type; - /* Rust has no vector types. Build them here. FIXME: It does not - make sense for the middle-end to ask the frontend for a type - which the frontend does not support. However, at least for now - it is required. See PR 46805. */ - if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL - && valid_vector_subparts_p (GET_MODE_NUNITS (mode))) - { - unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode), - GET_MODE_NUNITS (mode)); - tree bool_type = build_nonstandard_boolean_type (elem_bits); - return build_vector_type_for_mode (bool_type, mode); - } - else if (VECTOR_MODE_P (mode) - && valid_vector_subparts_p (GET_MODE_NUNITS (mode))) - { - tree inner; - - inner = rust_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp); - if (inner != NULL_TREE) - return build_vector_type_for_mode (inner, mode); - return NULL_TREE; - } - - scalar_int_mode imode; - scalar_float_mode fmode; - complex_mode cmode; - if (is_int_mode (mode, &imode)) - return rust_langhook_type_for_size (GET_MODE_BITSIZE (imode), unsignedp); - else if (is_float_mode (mode, &fmode)) - { - switch (GET_MODE_BITSIZE (fmode)) - { - case 32: - return float_type_node; - case 64: - return double_type_node; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (fmode == TYPE_MODE(long_double_type_node)) - return long_double_type_node; - } - } - else if (is_complex_float_mode (mode, &cmode)) - { - switch (GET_MODE_BITSIZE (cmode)) - { - case 64: - return complex_float_type_node; - case 128: - return complex_double_type_node; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (cmode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - } - } - -#if HOST_BITS_PER_WIDE_INT >= 64 - /* The middle-end and some backends rely on TImode being supported - for 64-bit HWI. */ - if (mode == TImode) - { - type = build_nonstandard_integer_type (GET_MODE_BITSIZE (TImode), - unsignedp); - if (type && TYPE_MODE (type) == TImode) - return type; - } -#endif - return NULL_TREE; -} - -/* Record a builtin function. We just ignore builtin functions. */ - -static tree -rust_langhook_builtin_function (tree decl) -{ - return decl; -} - -/* Return true if we are in the global binding level. */ - -static bool -rust_langhook_global_bindings_p (void) -{ - return current_function_decl == NULL_TREE; -} - -/* Push a declaration into the current binding level. We can't - usefully implement this since we don't want to convert from tree - back to one of our internal data structures. I think the only way - this is used is to record a decl which is to be returned by - getdecls, and we could implement it for that purpose if - necessary. */ - -static tree -rust_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -/* This hook is used to get the current list of declarations as trees. - We don't support that; instead we use the write_globals hook. This - can't simply crash because it is called by -gstabs. */ - -static tree -rust_langhook_getdecls (void) -{ - return NULL; -} - -/* Rust specific gimplification. We need to gimplify - CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle - it. */ - -static int -rust_langhook_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) -{ - if (TREE_CODE (*expr_p) == CALL_EXPR - && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE) - gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, - is_gimple_val, fb_rvalue); - return GS_UNHANDLED; -} - -/* Return a decl for the exception personality function. The function - itself is implemented in librust/runtime/rust-unwind.c. */ - -static tree -rust_langhook_eh_personality (void) -{ - static tree personality_decl; - if (personality_decl == NULL_TREE) - { - personality_decl = build_personality_function ("gccrust"); - rust_preserve_from_gc (personality_decl); - } - return personality_decl; -} - -/* Functions called directly by the generic backend. */ - -tree -convert (tree type, tree expr) -{ - if (type == error_mark_node - || expr == error_mark_node - || TREE_TYPE (expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE (expr)) - return expr; - - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) - return fold_convert (type, expr); - - switch (TREE_CODE (type)) - { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert (type, expr); - case INTEGER_TYPE: - return fold (convert_to_integer (type, expr)); - case POINTER_TYPE: - return fold (convert_to_pointer (type, expr)); - case REAL_TYPE: - return fold (convert_to_real (type, expr)); - case COMPLEX_TYPE: - return fold (convert_to_complex (type, expr)); - default: - break; - } - - gcc_unreachable (); -} - -/* FIXME: This is a hack to preserve trees that we create from the - garbage collector. */ - -static GTY(()) tree rust_gc_root; - -void -rust_preserve_from_gc (tree t) -{ - rust_gc_root = tree_cons (NULL_TREE, t, rust_gc_root); -} - -/* Convert an identifier for use in an error message. */ - -const char * -rust_localize_identifier (const char *ident) -{ - return identifier_to_locale (ident); -} - -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -#undef LANG_HOOKS_OPTION_LANG_MASK -#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -#undef LANG_HOOKS_HANDLE_OPTION -#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -#undef LANG_HOOKS_GIMPLIFY_EXPR -#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT rust_langhook_init -#define LANG_HOOKS_OPTION_LANG_MASK rust_langhook_option_lang_mask -#define LANG_HOOKS_INIT_OPTIONS_STRUCT rust_langhook_init_options_struct -#define LANG_HOOKS_HANDLE_OPTION rust_langhook_handle_option -#define LANG_HOOKS_POST_OPTIONS rust_langhook_post_options -#define LANG_HOOKS_PARSE_FILE rust_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE rust_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE rust_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION rust_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P rust_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL rust_langhook_pushdecl -#define LANG_HOOKS_GETDECLS rust_langhook_getdecls -#define LANG_HOOKS_GIMPLIFY_EXPR rust_langhook_gimplify_expr -#define LANG_HOOKS_EH_PERSONALITY rust_langhook_eh_personality - -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -#include "gt-rust-rust-lang.h" -#include "gtype-rust.h" diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc new file mode 100644 index 0000000..28cddde --- /dev/null +++ b/gcc/rust/rust-lang.cc @@ -0,0 +1,385 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "gimple-expr.h" +#include "diagnostic.h" +#include "opts.h" +#include "fold-const.h" +#include "gimplify.h" +#include "stor-layout.h" +#include "debug.h" +#include "convert.h" +#include "langhooks.h" +#include "langhooks-def.h" +#include "common/common-target.h" + +#include +// note: header files must be in this order or else forward declarations don't work properly. Kinda +// dumb system, but have to live with it. clang-format seems to mess it up +/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic, opts, fold-const, + * gimplify, stor-layout, debug, convert, langhooks, langhooks-def, common-target */ + +// FIXME: test saving intellisense +#include "options.h" + +// version check to stop compiling if c++ isn't c++11 or higher +#if __cplusplus < 201103 +#error \ + "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." +#endif +// TODO: is this best way to do it? Is it allowed? (should be) + +/* General TODOs: + * - maybe convert all raw pointer-returning/passing functions that conceptually return a unique + * pointer actually return a unique pointer. i.e. parse methods and constructors for AST objects. + * make_unique should probably be avoided to keep C++11 compatibility. + * - convert all copies of expensive-to-copy (deep copy) AST objects into moves, if possible. Don't + * remove clone functionality - it may be required for e.g. HIR conversion. */ + +#include "rust-system.h" +#include "rust-parse.h" +#include "rust-session-manager.h" + +// Language-dependent contents of a type. GTY() mark used for garbage collector. +struct GTY(()) lang_type { + char dummy; +}; + +// Language-dependent contents of a decl. +struct GTY(()) lang_decl { + char dummy; +}; + +// Language-dependent contents of an identifier. This must include a tree_identifier. +struct GTY(()) lang_identifier { + struct tree_identifier common; +}; + +// The resulting tree type. +union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), + chain_next( + "CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " + "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node { + union tree_node GTY((tag("0"), desc("tree_node_structure (&%h)"))) generic; + struct lang_identifier GTY((tag("1"))) identifier; +}; + +// We don't use language_function. +struct GTY(()) language_function { + int dummy; +}; + +// Kinda HACK-ish - store parsing session as static variable +static Rust::Session session; + +/* Language hooks. */ + +/* Initial lang hook called (possibly), used for initialisation. + * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, and + * build_common_builtin_nodes, as well as set global variable void_list_node. + * Apparently called after option handling? */ +static bool grs_langhook_init(void) { + /* Something to do with this: + This allows the code in d-builtins.cc to not have to worry about + converting (C signed char *) to (D char *) for string arguments of + built-in functions. The parameter (signed_char = false) specifies + whether char is signed. */ + build_common_tree_nodes(false); + + // Creates a new TREE_LIST node with purpose NULL_TREE and value void_type_node + void_list_node = build_tree_list(NULL_TREE, void_type_node); + + // Builds built-ins for middle-end after all front-end built-ins are already instantiated + build_common_builtin_nodes(); + + mpfr_set_default_prec(128); + + using_eh_for_cleanups(); + + // initialise compiler session + session.init(); + + return true; +} + +/* The option mask (something to do with options for specific frontends or something). */ +static unsigned int grs_langhook_option_lang_mask(void) { + return CL_Rust; +} + +/* Initialize the options structure. */ +static void grs_langhook_init_options_struct(struct gcc_options* opts) { + // nothing yet - used by frontends to change specific options for the language + session.init_options(); +} + +/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and + * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. + * This function must create a complete parse tree in a global var, and then return. + * + * Some consider this the "start of compilation". */ +static void grs_langhook_parse_file(void) { + fprintf(stderr, "Preparing to parse files. \n"); + + // grs_parse_files(num_in_fnames, in_fnames); + session.parse_files(num_in_fnames, in_fnames); +} + +/* Seems to get the exact type for a specific type - e.g. for scalar float with 32-bit bitsize, it + * returns float, and for 64-bit bitsize, it returns double. Used to map RTL nodes to machine modes or + * something like that. */ +static tree grs_langhook_type_for_mode(machine_mode mode, int unsignedp) { + // TODO: change all this later to match rustc types + if (mode == TYPE_MODE(float_type_node)) + return float_type_node; + + if (mode == TYPE_MODE(double_type_node)) + return double_type_node; + + if (mode == TYPE_MODE(intQI_type_node)) // quarter integer mode - single byte treated as integer + return unsignedp ? unsigned_intQI_type_node : intQI_type_node; + if (mode == TYPE_MODE(intHI_type_node)) // half integer mode - two-byte integer + return unsignedp ? unsigned_intHI_type_node : intHI_type_node; + if (mode == TYPE_MODE(intSI_type_node)) // single integer mode - four-byte integer + return unsignedp ? unsigned_intSI_type_node : intSI_type_node; + if (mode == TYPE_MODE(intDI_type_node)) // double integer mode - eight-byte integer + return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + if (mode == TYPE_MODE(intTI_type_node)) // tetra integer mode - 16-byte integer + return unsignedp ? unsigned_intTI_type_node : intTI_type_node; + + if (mode == TYPE_MODE(integer_type_node)) + return unsignedp ? unsigned_type_node : integer_type_node; + + if (mode == TYPE_MODE(long_integer_type_node)) + return unsignedp ? long_unsigned_type_node : long_integer_type_node; + + if (mode == TYPE_MODE(long_long_integer_type_node)) + return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; + + if (COMPLEX_MODE_P(mode)) { + if (mode == TYPE_MODE(complex_float_type_node)) + return complex_float_type_node; + if (mode == TYPE_MODE(complex_double_type_node)) + return complex_double_type_node; + if (mode == TYPE_MODE(complex_long_double_type_node)) + return complex_long_double_type_node; + if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) + return complex_integer_type_node; + } + /* gcc_unreachable */ + return NULL; +} + +/* This appears to be used for creating different types for different bit sizes (e.g. int and long). + * Also, the Go frontend calls this from type_for_mode to determine the type from a specific bitsize + * for integer types. + * FIXME: change this when working on AST-GENERIC conversion to allow the full range of Rust type + * sizes. */ +static tree grs_langhook_type_for_size( + unsigned int bits ATTRIBUTE_UNUSED, int unsignedp ATTRIBUTE_UNUSED) { + gcc_unreachable(); + return NULL_TREE; + // nothing at the moment, but change later +} + +// Record a builtin function. We just ignore builtin functions. +static tree grs_langhook_builtin_function(tree decl ATTRIBUTE_UNUSED) { + return decl; +} + +/* Return true if we are in the global binding level (which is never, apparently). */ +static bool grs_langhook_global_bindings_p(void) { + // return current_function_decl == NULL_TREE; + // gcc_unreachable(); + // return true; + return false; +} + +/* Push a declaration into the current binding level. We can't + usefully implement this since we don't want to convert from tree + back to one of our internal data structures. I think the only way + this is used is to record a decl which is to be returned by + getdecls, and we could implement it for that purpose if + necessary. */ +static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { + gcc_unreachable(); + return NULL; +} + +/* This hook is used to get the current list of declarations as trees. + We don't support that; instead we use the write_globals hook. This + can't simply crash because it is called by -gstabs. */ +static tree grs_langhook_getdecls(void) { + // gcc_unreachable(); + return NULL; +} + +// Handle Rust-specific options. Return false if nothing happened. +static bool grs_langhook_handle_option(size_t scode, const char* arg, HOST_WIDE_INT value, + int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, + const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { + // Convert integer code to lang.opt enum codes with names. + enum opt_code code = (enum opt_code)scode; + // used to store whether results of various stuff are successful + // bool ret = true; + + // delegate to session manager + return session.handle_option(code, arg, value, kind, loc, handlers); + + // Handles options as listed in lang.opt. + /*switch (code) { + case OPT_I: + // TODO: add search path + break; + case OPT_L: + // TODO: add library link path or something + break; + case OPT_frust_dump: + // enable dump and return whether this was successful + ret = rust_enable_dump(arg) ? true : false; + break; + // no option handling for -o + default: + // return 1 to indicate option is valid + break; + } + + return ret;*/ +} + +/* Run after parsing options. */ +static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { + // can be used to override other options if required + + // satisfies an assert in init_excess_precision in toplev.c + if (flag_excess_precision/*_cmdline*/ == EXCESS_PRECISION_DEFAULT) + flag_excess_precision/*_cmdline*/ = EXCESS_PRECISION_STANDARD; + + /* Returning false means that the backend should be used. */ + return false; +} + +/* Rust-specific gimplification. May need to gimplify e.g. CALL_EXPR_STATIC_CHAIN */ +static int grs_langhook_gimplify_expr(tree* expr_p ATTRIBUTE_UNUSED, + gimple_seq* pre_p ATTRIBUTE_UNUSED, gimple_seq* post_p ATTRIBUTE_UNUSED) { + if (TREE_CODE (*expr_p) == CALL_EXPR + && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE) + gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, + is_gimple_val, fb_rvalue); + return GS_UNHANDLED; +} + +static tree +grs_langhook_eh_personality (void) +{ + static tree personality_decl; + if (personality_decl == NULL_TREE) + { + personality_decl = build_personality_function ("gccrs"); + rust_preserve_from_gc (personality_decl); + } + return personality_decl; +} + +tree +convert (tree type, tree expr) +{ + if (type == error_mark_node + || expr == error_mark_node + || TREE_TYPE (expr) == error_mark_node) + return error_mark_node; + + if (type == TREE_TYPE (expr)) + return expr; + + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold_convert (type, expr); + + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case BOOLEAN_TYPE: + return fold_convert (type, expr); + case INTEGER_TYPE: + return fold (convert_to_integer (type, expr)); + case POINTER_TYPE: + return fold (convert_to_pointer (type, expr)); + case REAL_TYPE: + return fold (convert_to_real (type, expr)); + case COMPLEX_TYPE: + return fold (convert_to_complex (type, expr)); + default: + break; + } + + gcc_unreachable (); +} + +/* FIXME: This is a hack to preserve trees that we create from the + garbage collector. */ + +static GTY(()) tree rust_gc_root; + +void +rust_preserve_from_gc (tree t) +{ + rust_gc_root = tree_cons (NULL_TREE, t, rust_gc_root); +} + +/* Convert an identifier for use in an error message. */ + +const char * +rust_localize_identifier (const char *ident) +{ + return identifier_to_locale (ident); +} + +/* The language hooks data structure. This is the main interface between the GCC front-end + * and the GCC middle-end/back-end. A list of language hooks could be found in + * /langhooks.h + */ +#undef LANG_HOOKS_NAME +#undef LANG_HOOKS_INIT +#undef LANG_HOOKS_OPTION_LANG_MASK +#undef LANG_HOOKS_INIT_OPTIONS_STRUCT +#undef LANG_HOOKS_HANDLE_OPTION +#undef LANG_HOOKS_POST_OPTIONS +#undef LANG_HOOKS_PARSE_FILE +#undef LANG_HOOKS_TYPE_FOR_MODE +#undef LANG_HOOKS_TYPE_FOR_SIZE +#undef LANG_HOOKS_BUILTIN_FUNCTION +#undef LANG_HOOKS_GLOBAL_BINDINGS_P +#undef LANG_HOOKS_PUSHDECL +#undef LANG_HOOKS_GETDECLS +#undef LANG_HOOKS_WRITE_GLOBALS +#undef LANG_HOOKS_GIMPLIFY_EXPR +#undef LANG_HOOKS_EH_PERSONALITY + +#define LANG_HOOKS_NAME "GNU Rust" +#define LANG_HOOKS_INIT grs_langhook_init +#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask +#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct +#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option +#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options +/* Main lang-hook, apparently. Finds input file names in global vars in_fnames and num_in_fnames + * From this, frontend can take over and do actual parsing and initial compilation. + * This hook must create a complete parse tree in a global var, and then return. */ +#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file +#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode +#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size +#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function +#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p +#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl +#define LANG_HOOKS_GETDECLS grs_langhook_getdecls +#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals +#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr +#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality + +// Expands all LANG_HOOKS_x of GCC +struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; + +// These are for GCC's garbage collector to work properly or something +#include "gt-rust-rust-lang.h" +#include "gtype-rust.h" diff --git a/gcc/rust/rust-object-export.c b/gcc/rust/rust-object-export.c new file mode 100644 index 0000000..3d09aa7 --- /dev/null +++ b/gcc/rust/rust-object-export.c @@ -0,0 +1,193 @@ +/* rust-backend.c -- Rust frontend interface to gcc backend. + Copyright (C) 2010-2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "memmodel.h" +#include "tm_p.h" +#include "diagnostic.h" +#include "simple-object.h" +#include "stor-layout.h" +#include "intl.h" +#include "output.h" /* for assemble_string */ +#include "common/common-target.h" + +/* The segment name we pass to simple_object_start_read to find Rust + export data. */ + +#ifndef RUST_EXPORT_SEGMENT_NAME +#define RUST_EXPORT_SEGMENT_NAME "__GNU_RUST" +#endif + +/* The section name we use when reading and writing export data. */ + +#ifndef RUST_EXPORT_SECTION_NAME +#define RUST_EXPORT_SECTION_NAME ".rust_export" +#endif + +#ifndef TARGET_AIX +#define TARGET_AIX 0 +#endif + +/* This file holds all the cases where the Rust frontend needs + information from gcc's backend. */ + +/* Return whether or not GCC has reported any errors. */ + +bool +saw_errors (void) +{ + return errorcount != 0 || sorrycount != 0; +} + +/* Return the alignment in bytes of a struct field of type T. */ + +unsigned int +rust_field_alignment (tree t) +{ + unsigned int v; + + v = TYPE_ALIGN (t); + +#ifdef BIGGEST_FIELD_ALIGNMENT + if (v > BIGGEST_FIELD_ALIGNMENT) + v = BIGGEST_FIELD_ALIGNMENT; +#endif + +#ifdef ADJUST_FIELD_ALIGN + v = ADJUST_FIELD_ALIGN (NULL_TREE, t, v); +#endif + + return v / BITS_PER_UNIT; +} + +/* This is called by the Rust frontend proper if the unsafe package was + imported. When that happens we cannot do type-based alias + analysis. */ + +void +rust_imported_unsafe (void) +{ + flag_strict_aliasing = false; + TREE_OPTIMIZATION (optimization_default_node)->x_flag_strict_aliasing = false; + + /* Let the backend know that the options have changed. */ + targetm.override_options_after_change (); +} + +/* This is called by the Rust frontend proper to add data to the + section containing Rust export data. */ + +void +rust_write_export_data (const char *bytes, unsigned int size) +{ + static section* sec; + + if (sec == NULL) + { + gcc_assert (targetm_common.have_named_sections); + sec = get_section (RUST_EXPORT_SECTION_NAME, + TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, + NULL); + } + + switch_to_section (sec); + assemble_string (bytes, size); +} + +/* The rust_read_export_data function is called by the Rust frontend + proper to read Rust export data from an object file. FD is a file + descriptor open for reading. OFFSET is the offset within the file + where the object file starts; this will be 0 except when reading an + archive. On success this returns NULL and sets *PBUF to a buffer + allocated using malloc, of size *PLEN, holding the export data. If + the data is not found, this returns NULL and sets *PBUF to NULL and + *PLEN to 0. If some error occurs, this returns an error message + and sets *PERR to an errno value or 0 if there is no relevant + errno. */ + +const char * +rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, + int *perr) +{ + simple_object_read *sobj; + const char *errmsg; + off_t sec_offset; + off_t sec_length; + int found; + char *buf; + ssize_t c; + + *pbuf = NULL; + *plen = 0; + + sobj = simple_object_start_read (fd, offset, RUST_EXPORT_SEGMENT_NAME, + &errmsg, perr); + if (sobj == NULL) + { + /* If we get an error here, just pretend that we didn't find any + export data. This is the right thing to do if the error is + that the file was not recognized as an object file. This + will ignore file I/O errors, but it's not too big a deal + because we will wind up giving some other error later. */ + return NULL; + } + + found = simple_object_find_section (sobj, RUST_EXPORT_SECTION_NAME, + &sec_offset, &sec_length, + &errmsg, perr); + simple_object_release_read (sobj); + if (!found) + return errmsg; + + if (lseek (fd, offset + sec_offset, SEEK_SET) < 0) + { + *perr = errno; + return _("lseek failed while reading export data"); + } + + buf = XNEWVEC (char, sec_length); + if (buf == NULL) + { + *perr = errno; + return _("memory allocation failed while reading export data"); + } + + c = read (fd, buf, sec_length); + if (c < 0) + { + *perr = errno; + free (buf); + return _("read failed while reading export data"); + } + + if (c < sec_length) + { + free (buf); + return _("short read while reading export data"); + } + + *pbuf = buf; + *plen = sec_length; + + return NULL; +} diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h new file mode 100644 index 0000000..4e84895 --- /dev/null +++ b/gcc/rust/rust-object-export.h @@ -0,0 +1,9 @@ +#pragma once + +extern unsigned int rust_field_alignment (tree t); + +extern const char * +rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, + int *perr); +extern void +rust_write_export_data (const char *bytes, unsigned int size); diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc new file mode 100644 index 0000000..443818c --- /dev/null +++ b/gcc/rust/rust-session-manager.cc @@ -0,0 +1,654 @@ +#include "rust-session-manager.h" + +#include "diagnostic.h" +#include "input.h" + +#include "rust-lex.h" +#include "rust-parse.h" + +#include + +namespace Rust { + // Simple wrapper for FILE* that simplifies destruction. + struct RAIIFile { + FILE* file; + + RAIIFile(const char* filename) : file(fopen(filename, "r")) {} + + ~RAIIFile() { + fclose(file); + } + }; + + // Implicitly enable a target_feature (and recursively enable dependencies). + void Session::implicitly_enable_feature(::std::string feature_name) { + // TODO: is this really required since features added would be complete via target spec? + + if (!options.target_data.has_key_value_pair("target_data", feature_name)) { + // if feature has dependencies, enable them + if (feature_name == "aes") { + implicitly_enable_feature("sse2"); + } else if (feature_name == "avx") { + implicitly_enable_feature("sse4.2"); + } else if (feature_name == "avx2") { + implicitly_enable_feature("avx"); + } else if (feature_name == "fma") { + implicitly_enable_feature("avx"); + } else if (feature_name == "pclmulqdq") { + implicitly_enable_feature("sse2"); + } else if (feature_name == "sha") { + implicitly_enable_feature("sse2"); + } else if (feature_name == "sse2") { + implicitly_enable_feature("sse"); + } else if (feature_name == "sse3") { + implicitly_enable_feature("sse2"); + } else if (feature_name == "sse4.1") { + implicitly_enable_feature("sse3"); + } else if (feature_name == "sse4.2") { + implicitly_enable_feature("sse4.1"); + } else if (feature_name == "ssse3") { + implicitly_enable_feature("sse3"); + } + + options.target_data.insert_key_value_pair("target_feature", ::std::move(feature_name)); + } + } + + // Meant to enable all target features. As this will be done by target hook, this method's + // deprecated. + void Session::enable_features() { + bool has_target_crt_static = false; + const char* target = "PLACEHOLDER"; + + fprintf(stderr, "ERROR: Somewhere in call chain Session::enable_features is called.\n"); + + if (has_target_crt_static) { + // enable "crt-static" attribute + } + + /* TODO: do this via target hook. have one for each target that implicitly enables the + * features for that platform. Would probably have to make custom target hook. */ + + /* + if (target == "x86" || target == "x86_64") { + if (TARGET_ISA_AES) { + // enable aes, implicitly enable sse2 + implicitly_enable_feature("aes"); + } + + if (TARGET_ISA_AVX) { + // enable avx, implicitly enable sse4.2 + implicitly_enable_feature("sse4.2"); + } + + if (TARGET_ISA_AVX2) { + // enable avx2, implicitly enable avx + implicitly_enable_feature("avx"); + } + + if (TARGET_ISA_BMI) { + // enable bmi1 + implicitly_enable_feature("bmi1"); + } + + if (TARGET_ISA_BMI2) { + // enable bmi2 + implicitly_enable_feature("bmi2"); + } + + if (TARGET_ISA_FMA) { + // enable fma, implicitly enable avx + implicitly_enable_feature("fma"); + } + + if (TARGET_ISA_FXSR) { + // enable fxsr + implicitly_enable_feature("fxsr"); + } + + if (TARGET_ISA_LZCNT) { + // enable lzcnt + implicitly_enable_feature("lzcnt"); + } + + if (TARGET_ISA_VPCLMULQDQ) { + // enable pclmulqdq, implicitly enable sse2 + implicitly_enable_feature("pclmulqdq"); + } + + if (TARGET_ISA_POPCNT) { + // enable popcnt + implicitly_enable_feature("popcnt"); + } + + if (TARGET_ISA_RDRND) { + // enable rdrand + implicitly_enable_feature("rdrand"); + } + + if (TARGET_ISA_RDSEED) { + // enable rdseed + implicitly_enable_feature("rdseed"); + } + + if (TARGET_ISA_SHA) { + // enable sha, implicitly enable sse2 + implicitly_enable_feature("sha"); + } + + if (TARGET_ISA_SSE) { + // enable sse + implicitly_enable_feature("sse"); + } + + if (TARGET_ISA_SSE2) { + // enable sse2, implicitly enable sse + implicitly_enable_feature("sse2"); + } + + if (TARGET_ISA_SSE3) { + // enable sse3, implicitly enable sse2 + implicitly_enable_feature("sse3"); + } + + if (TARGET_ISA_SSE4_1) { + // enable sse4.1, implicitly enable sse3 + implicitly_enable_feature("sse4.1"); + } + + if (TARGET_ISA_SSE4_2) { + // enable sse4.2, implicitly enable sse4.1 + implicitly_enable_feature("sse4.2"); + } + + if (TARGET_ISA_SSSE3) { + // enable ssse3, implicitly enable sse3 + implicitly_enable_feature("ssse3"); + } + + if (TARGET_ISA_XSAVE) { + // enable xsave + implicitly_enable_feature("xsave"); + } + + if (TARGET_ISA_XSAVEC) { + // enable xsavec + implicitly_enable_feature("xsavec"); + } + + if (TARGET_ISA_XSAVEOPT) { + // enable xsaveopt + implicitly_enable_feature("xsaveopt"); + } + + if (TARGET_ISA_XSAVES) { + // enable xsaves + implicitly_enable_feature("xsaves"); + } + } + options.target_data.features.shrink_to_fit(); + ::std::sort(options.target_data.features.begin(), options.target_data.features.end());*/ + } + + void Session::init() { + // nothing yet + } + + // Initialise default options. Actually called before handle_option, unlike init itself. + void Session::init_options() { + options.dump_option = CompileOptions::NO_DUMP; + } + + // Handle option selection. + bool Session::handle_option(enum opt_code code, const char* arg, + HOST_WIDE_INT value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED, + location_t loc ATTRIBUTE_UNUSED, const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { + // used to store whether results of various stuff are successful + bool ret = true; + + // Handles options as listed in lang.opt. + switch (code) { + case OPT_I: + // TODO: add search path + break; + case OPT_L: + // TODO: add library link path or something + break; + case OPT_frust_dump_: + // enable dump and return whether this was successful + if (arg != NULL) { + ret = enable_dump(::std::string(arg)); + } else { + ret = false; + } + break; + // no option handling for -o + default: + // return 1 to indicate option is valid + break; + } + + return ret; + } + + /* Enables a certain dump depending on the name passed in. Returns true if name is valid, false + * otherwise. */ + bool Session::enable_dump(::std::string arg) { + // FIXME: change dumping algorithm when new non-inhibiting dump system is created + if (arg == "all") { + error_at( + UNKNOWN_LOCATION, "dumping all is not supported as of now. choose 'lex' or 'parse'"); + return false; + } else if (arg == "lex") { + options.dump_option = CompileOptions::LEXER_DUMP; + } else if (arg == "parse") { + options.dump_option = CompileOptions::PARSER_AST_DUMP; + } else if (arg == "register_plugins") { + options.dump_option = CompileOptions::REGISTER_PLUGINS_DUMP; + } else if (arg == "injection") { + options.dump_option = CompileOptions::INJECTION_DUMP; + } else if (arg == "expansion") { + options.dump_option = CompileOptions::EXPANSION_DUMP; + } else if (arg == "name_resolution") { + options.dump_option = CompileOptions::NAME_RESOLUTION_DUMP; + } else if (arg == "") { + error_at(UNKNOWN_LOCATION, "dump option was not given a name. choose 'lex' or 'parse'"); + return false; + } else { + error_at(UNKNOWN_LOCATION, "dump option '%s' was unrecognised. choose 'lex' or 'parse'", + arg.c_str()); + return false; + } + return true; + } + + /* Actual main entry point for front-end. Called from langhook to parse files. */ + void Session::parse_files(int num_files, const char** files) { + for (int i = 0; i < num_files; i++) { + parse_file(files[i]); + } + // TODO: should semantic analysis be dealed with here? or per file? for now, per-file. + } + + // Parses a single file with filename filename. + void Session::parse_file(const char* filename) { + RAIIFile file_wrap(filename); + + if (file_wrap.file == NULL) { + fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); + } + + // parse file here + // create lexer and parser - these are file-specific and so aren't instance variables + Rust::Lexer lex(filename, file_wrap.file); + Rust::Parser parser(lex); + + // determine parsing method from options + /* FIXME: currently, the dump means that full compilation will not occur as of present. In + * future, dumps should not inhibit full compilation. */ + switch (options.dump_option) { + case CompileOptions::NO_DUMP: + fatal_error(UNKNOWN_LOCATION, "no-dump parsing has not been enabled yet"); + return; + case CompileOptions::LEXER_DUMP: + parser.debug_dump_lex_output(); + return; + case CompileOptions::PARSER_AST_DUMP: + parser.debug_dump_ast_output(); + return; + case CompileOptions::REGISTER_PLUGINS_DUMP: + case CompileOptions::INJECTION_DUMP: + case CompileOptions::EXPANSION_DUMP: + case CompileOptions::NAME_RESOLUTION_DUMP: + // will break later after more stages + break; + // semantic analysis when completed + default: + fatal_error(UNKNOWN_LOCATION, "unrecognised dump option: '%u'", options.dump_option); + return; + } + + /* basic pipeline: + * - lex + * - parse + * - register plugins (dummy stage for now) - attribute injection? what is this? + * (attribute injection is injecting attributes specified in command line into crate root) + * - injection (some lint checks or dummy, register builtin macros, crate injection) + * - expansion (expands all macros, maybe build test harness, AST validation, maybe macro + * crate) + * - name resolution (name resolution, maybe feature checking, maybe buffered lints) + * TODO not done */ + + // generate crate from parser + AST::Crate parsed_crate = parser.parse_crate(); + + fprintf(stderr, "\033[0;31mSUCCESSFULLY PARSED CRATE \n\033[0m"); + + // register plugins pipeline stage + register_plugins(parsed_crate); + fprintf(stderr, "\033[0;31mSUCCESSFULLY REGISTERED PLUGINS \n\033[0m"); + + if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) { + // TODO: what do I dump here? + return; + } + + // injection pipeline stage + injection(parsed_crate); + fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED INJECTION \n\033[0m"); + + if (options.dump_option == CompileOptions::INJECTION_DUMP) { + // TODO: what do I dump here? injected crate names? + return; + } + + // expansion pipeline stage + expansion(parsed_crate); + fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED EXPANSION \n\033[0m"); + + if (options.dump_option == CompileOptions::EXPANSION_DUMP) { + // TODO: what do I dump here? expanded macros? AST with expanded macros? + return; + } + + // name resolution pipeline stage + name_resolution(parsed_crate); + fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED NAME RESOLUTION \n\033[0m"); + + if (options.dump_option == CompileOptions::NAME_RESOLUTION_DUMP) { + // TODO: what do I dump here? resolved names? AST with resolved names? + return; + } + } + + // Checks whether 'cfg' attribute prevents compilation. + bool check_cfg(const AST::Attribute& attr ATTRIBUTE_UNUSED) { + // if "has sub items", and if 'cfg' attr, recursively call this on sub items? + + // TODO: actually implement. assume true for now + + return true; + } + // TODO: deprecated - don't use + + // Checks whether any 'cfg' attribute on the item prevents compilation of that item. + bool check_item_cfg(::std::vector attrs) { + for (const auto& attr : attrs) { + if (attr.get_path() == "cfg" && !check_cfg(attr)) { + return false; + } + } + + return true; + } + // TODO: deprecated - don't use + + // TODO: actually implement method + void load_extern_crate(::std::string crate_name ATTRIBUTE_UNUSED) {} + // TODO: deprecated - don't use + + // Parses up to the "load (external) crates" part of the frontend. + // TODO: lots of this code is probably actually useful outside of dumping, so maybe split off + // function + void Session::debug_dump_load_crates(Parser& parser) { + // parse crate as AST + AST::Crate crate = parser.parse_crate(); + + /* TODO: search through inner attrs and see whether any of those attr paths contain "no_core", + * "no_std", "compiler_builtins". If so/not, save certain crate names. In these names, insert + * items at beginning of crate items. This is crate injection. Also, inject prelude use decl + * at beginning (first name is assumed to be prelude - prelude is a use decl automatically + * generated to enable using Option and Copy without qualifying it or importing it via 'use' + * manually) */ + + ::std::vector< ::std::string> crate_names; + for (const auto& item : crate.items) { + // if item is extern crate, add name? to list of stuff ONLY IF config is checked + // if item is module, iterate this loop inside it as well (recursive?) ONLY IF config is + // checked + + // TODO: actually do the checks somewhere - probably in the items + + item->add_crate_name(crate_names); + } + + /* loop through list of crate names/paths/whatever, attempting to load each one. save loaded + * crates to a Session variable? Or save to current AST::Crate? */ + for (const auto& name : crate_names) { + load_extern_crate(name /*, basename = ""?*/); + } + // for each loaded crate, load dependencies of it as well + } + // TODO: deprecated - don't use + + void Session::register_plugins(AST::Crate& crate ATTRIBUTE_UNUSED) { + fprintf(stderr, "ran register_plugins (with no body)\n"); + } + + // TODO: move somewhere else + bool contains_name(::std::vector attrs, ::std::string name) { + for (const auto& attr : attrs) { + if (attr.get_path() == name) { + return true; + } + } + + return false; + } + + void Session::injection(AST::Crate& crate) { + fprintf(stderr, "started injection\n"); + + // lint checks in future maybe? + + // register builtin macros + /* In rustc, builtin macros are divided into 3 categories depending on use - "bang" macros, + * "attr" macros, and "derive" macros. I think the meanings of these categories should be + * fairly obvious to anyone who has used rust. Builtin macro list by category: Bang + * - asm + * - assert + * - cfg + * - column + * - compile_error + * - concat_idents + * - concat + * - env + * - file + * - format_args_nl + * - format_args + * - global_asm + * - include_bytes + * - include_str + * - include + * - line + * - log_syntax + * - module_path + * - option_env + * - stringify + * - trace_macros + * Attr + * - bench + * - global_allocator + * - test + * - test_case + * Derive + * - Clone + * - Copy + * - Debug + * - Default + * - Eq + * - Hash + * - Ord + * - PartialEq + * - PartialOrd + * - RustcDecodable + * - RustcEncodable + * rustc also has a "quote" macro that is defined differently and is supposedly not stable so + * eh. */ + /* TODO: actually implement injection of these macros. In particular, derive macros, cfg, and + * test should be prioritised since they seem to be used the most. */ + + // crate injection + ::std::vector< ::std::string> names; + if (contains_name(crate.inner_attrs, "no_core")) { + // no prelude + injected_crate_name = ""; + } else if (contains_name(crate.inner_attrs, "no_std")) { + names.push_back("core"); + + if (!contains_name(crate.inner_attrs, "compiler_builtins")) { + names.push_back("compiler_builtins"); + } + + injected_crate_name = "core"; + } else { + names.push_back("std"); + + injected_crate_name = "std"; + } + + // reverse iterate through names to insert crate items in "forward" order at beginning of + // crate + for (auto it = names.rbegin(); it != names.rend(); ++it) { + // create "macro use" attribute for use on extern crate item to enable loading macros from + // it + AST::Attribute attr(AST::SimplePath::from_str("macro_use"), NULL); + + // create "extern crate" item with the name + ::std::unique_ptr extern_crate(new AST::ExternCrate( + *it, AST::Visibility::create_error(), { ::std::move(attr) }, UNKNOWN_LOCATION)); + + // insert at beginning + crate.items.insert(crate.items.begin(), ::std::move(extern_crate)); + } + + // create use tree path + // prelude is injected_crate_name + ::std::vector segments + = { AST::SimplePathSegment(injected_crate_name), AST::SimplePathSegment("prelude"), + AST::SimplePathSegment("v1") }; + // create use tree and decl + ::std::unique_ptr use_tree(new AST::UseTreeGlob( + AST::UseTreeGlob::PATH_PREFIXED, AST::SimplePath(::std::move(segments)), UNKNOWN_LOCATION)); + AST::Attribute prelude_attr(AST::SimplePath::from_str("prelude_import"), NULL); + ::std::unique_ptr use_decl(new AST::UseDeclaration(::std::move(use_tree), + AST::Visibility::create_error(), { ::std::move(prelude_attr) }, UNKNOWN_LOCATION)); + + crate.items.insert(crate.items.begin(), ::std::move(use_decl)); + + /* TODO: potentially add checking attribute crate type? I can't figure out what this does + * currently comment says "Unconditionally collect crate types from attributes to make them + * used", which presumably refers to checking the linkage info by "crate_type". It also seems + * to ensure that an invalid crate type is not specified, so maybe just do that. Valid crate + * types: bin lib dylib staticlib cdylib rlib proc-macro */ + + fprintf(stderr, "finished injection\n"); + } + + void Session::expansion(AST::Crate& crate ATTRIBUTE_UNUSED) { + fprintf(stderr, "started expansion\n"); + + // rustc has a modification to windows PATH temporarily here, which may end up being required + + // create macro expansion config? + // if not, would at least have to configure recursion_limit + + // create extctxt? from parse session, cfg, and resolver? + // expand by calling cxtctxt object's monotonic_expander's expand_crate method. + + // error reporting - check unused macros, get missing fragment specifiers + + // build test harness + + // ast validation (also with proc macro decls) + + // maybe create macro crate if not rustdoc + + fprintf(stderr, "finished expansion\n"); + } + + void Session::name_resolution(AST::Crate& crate ATTRIBUTE_UNUSED) { + fprintf(stderr, "started name resolution\n"); + + fprintf(stderr, "finished name resolution\n"); + } + + // NOTEs: + /* mrustc compile pipeline: + * - target load (pass target spec to parser?) + * - parse (convert source to AST) + * - load crates (load any explicitly mentioned extern crates [not all of them]) + * - expand (AST transformations from attributes and macros, loads remaining extern crates + * [std/core and any triggered by macro expansion]) + * - implicit crates (test harness, allocator crate, panic crate) + * - resolve use (annotate every 'use' item with source [supposedly handles nasty recursion]) + * - resolve index (generate index of visible items for every module [avoids recursion in next + * pass]) + * - resolve absolute (resolve all paths into either variable names [types/values] or absolute + * paths) + * - HIR lower (convert modified AST to simpler HIR [both expressions and module tree]) + * - resolve type aliases (replace any usages of type aliases with actual type [except associated + * types]) + * - resolve bind (iterate HIR tree and set binding annotations on all concrete types [avoids + * path lookups later]) + * - resolve HIR markings (generate "markings" [e.g. for Copy/Send/Sync/...] for all types + * - sort impls (small pass - sort impls into groups) + * - resolve UFCS outer (determine source trait for all top-level ::Type [qualified] paths) + * - resolve UFCS paths (do the same, but include for exprs this time. also normalises results of + * previous pass [expanding known associated types]) + * - constant evaluate (evaluate all constants) + * - typecheck outer (checks impls are sane) + * - typecheck expressions (resolve and check types for all exprs) + * - expand HIR annotate (annotate how exprs are used - used for closure extractions and + * reborrows) + * - expand HIR closures (extract closures into structs implementing Fn* traits) + * - expand HIR vtables (generate vtables for types with dyn dispatch) + * - expand HIR calls (converts method and callable calls into explicit function calls) + * - expand HIR reborrows (apply reborrow rules [taking '&mut *v' instead of 'v']) + * - expand HIR erasedtype (replace all erased types 'impl Trait' with the true type) + * - typecheck expressions (validate - double check that previous passes haven't broke type + * system rules) + * - lower MIR (convert HIR exprs into a control-flow graph [MIR]) + * - MIR validate (check that the generated MIR is consistent) + * - MIR cleanup (perform various transformations on MIR - replace reads of const items with the + * item itself; convert casts to unsized types into 'MakeDst' operations) + * - MIR optimise (perform various simple optimisations on the MIR - constant propagation, dead + * code elimination, borrow elimination, some inlining) + * - MIR validate PO (re-validate the MIR) + * - MIR validate full (optionally: perform expensive state-tracking validation on MIR) + * - trans enumerate (enumerate all items needed for code generation, primarily types used for + * generics) + * - trans auto impls (create magic trait impls as enumerated in previous pass) + * - trans monomorph (generate monomorphised copies of all functions [with generics replaced with + * real types]) + * - MIR optimise inline (run optimisation again, this time with full type info [primarily for + * inlining]) + * - HIR serialise (write out HIR dump [module tree and generic/inline MIR]) + * - trans codegen (generate final output file: emit C source file and call C compiler) */ + + /* rustc compile pipeline (basic, in way less detail): + * - parse input (parse .rs to AST) + * - name resolution, macro expansion, and configuration (process AST recursively, resolving + * paths, expanding macros, processing #[cfg] nodes [i.e. maybe stripping stuff from AST]) + * - lower to HIR + * - type check and other analyses (e.g. privacy checking) + * - lower to MIR and post-processing (and do stuff like borrow checking) + * - translation to LLVM IR and LLVM optimisations (produce the .o files) + * - linking (link together .o files) */ + + /* Pierced-together rustc compile pipeline (from source): + * - parse input (parse file to crate) + * - register plugins (attributes injection, set various options, register lints, load plugins) + * - expansion/configure and expand (initial 'cfg' processing, 'loading compiler plugins', + * syntax expansion, secondary 'cfg' expansion, synthesis of a test harness if required, + * injection of any std lib dependency and prelude, and name resolution) - actually documented + * inline + * - seeming pierced-together order: pre-AST expansion lint checks, registering builtin + * macros, crate injection, then expand all macros, then maybe build test harness, AST validation, + * maybe create a macro crate (if not rustdoc), name resolution, complete gated feature + * checking, add all buffered lints + * - create global context (lower to HIR) + * - analysis on global context (HIR optimisations? create MIR?) + * - code generation + * - link */ +} \ No newline at end of file diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h new file mode 100644 index 0000000..38eb494 --- /dev/null +++ b/gcc/rust/rust-session-manager.h @@ -0,0 +1,175 @@ +#ifndef RUST_SESSION_MANAGER_H +#define RUST_SESSION_MANAGER_H +// Session manager - controls compiler session. + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "options.h" +#include "rust-system.h" +#include + +namespace Rust { + // parser forward decl + class Parser; + // crate forward decl + namespace AST { + struct Crate; + } + + // Data related to target, most useful for conditional compilation and whatever. + struct TargetOptions { + // TODO: maybe make private and access through helpers to allow changes to impl + std::unordered_map> features; + + public: + // Returns whether a key is defined in the feature set. + bool has_key(std::string key) const { + return features.find(key) != features.end(); + } + + // Returns whether a key exists with the given value in the feature set. + bool has_key_value_pair(std::string key, std::string value) const { + auto it = features.find(key); + if (it != features.end()) { + auto set = it->second; + auto it2 = set.find(value); + if (it2 != set.end()) + return true; + } + return false; + } + + // Returns the singular value from the key, or if the key has multiple, an empty string. + std::string get_singular_value(std::string key) const { + auto it = features.find(key); + if (it != features.end()) { + auto set = it->second; + if (set.size() == 1) + return *set.begin(); + } + return ""; + } + + // Returns all values associated with a key (including none), or an empty set if no key is found. + std::unordered_set< ::std::string> get_values_for_key(std::string key) const { + auto it = features.find(key); + if (it != features.end()) { + return it->second; + } + return {}; + } + + /* Inserts a key (no value) into the feature set. This will do nothing if the key already exists. + * This returns whether the insertion was successful (i.e. whether key already existed). */ + bool insert_key(std::string key) { + return features.insert(std::make_pair(key, std::unordered_set())).second; + } + + // Inserts a key-value pair into the feature set. + void insert_key_value_pair(std::string key, std::string value) { + auto existing_set = get_values_for_key(key); + existing_set.insert(std::move(value)); + features[std::move(key)] = std::move(existing_set); + } + + /* According to reference, Rust uses either multi-map key-values or just values (although + * values may be aliases for a key-value value). This seems like overkill. Thus, depending on + * whether the attributes used in cfg are fixed or not, I think I'll either put each + * non-multimap "key-value" as a separate field and have the multimap "key-values" in a + * regular map for that one key, or actually use a multimap. + * + * rustc itself uses a set of key-value tuples where the second tuple element is optional. + * This gets rid of the requirement to make a multi-map, I guess, but seems like it might make + * search slow (unless all "is defined"-only ones have empty string as second element). */ + /* cfg attributes: + * - target_arch: single value + * - target_feature: multiple values possible + * - target_os: single value + * - target_family: single value (or no value?) + * - unix: set when target_family = "unix" + * - windows: set when target_family = "windows" + * - if these are just syntactic sugar, then maybe have a separate set or map for this kind + * of stuff + * - target_env: set when needed for disambiguation about ABI - usually empty string for GNU, + * complicated + * - seems to be a single value (if any) + * - target_endian: single value; "little" or "big" + * - target_pointer_width: single value, "32" for 32-bit pointers, etc. + * - target_vendor, single value + * - test: set when testing is being done + * - again, seems similar to a "is defined" rather than "is equal to" like unix + * - debug_assertions: seems to "is defined" + * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" */ + }; + + // Defines compiler options (e.g. dump, etc.). + struct CompileOptions { + // TODO: use bitfield for smaller memory requirements? + + // FIXME: this is set up for "instead of" dumping - in future, dumps should not inhibit + // compilation + enum DumpOptions { + NO_DUMP, + LEXER_DUMP, + PARSER_AST_DUMP, + REGISTER_PLUGINS_DUMP, + INJECTION_DUMP, + EXPANSION_DUMP, + NAME_RESOLUTION_DUMP, + // TODO: add more? + } dump_option; + + // configuration options - actually useful for conditional compilation and whatever + // data related to target arch, features, os, family, env, endian, pointer width, vendor + TargetOptions target_data; + bool enable_test = false; + bool debug_assertions = false; + bool proc_macro = false; + }; + + /* Defines a compiler session. This is for a single compiler invocation, so potentially includes + * parsing multiple crates. */ + struct Session { + CompileOptions options; + // This should really be in a per-crate storage area but it is wiped with every file so eh. + ::std::string injected_crate_name; + + public: + /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). Note that this is + * called after option handling. */ + void init(); + bool handle_option(enum opt_code code, const char* arg, HOST_WIDE_INT value, int kind, + location_t loc, const struct cl_option_handlers* handlers); + void parse_files(int num_files, const char** files); + void init_options(); + + private: + // TODO: should this be private or public? + void parse_file(const char* filename); + bool enable_dump(::std::string arg); + + void debug_dump_load_crates(Parser& parser); + + void implicitly_enable_feature(::std::string feature_name); + void enable_features(); + + // pipeline stages - TODO maybe move? + /* Register plugins pipeline stage. TODO maybe move to another object? Currently dummy stage. + * In future will handle attribute injection (top-level inner attribute creation from command + * line arguments), setting options maybe, registering lints maybe, loading plugins maybe. */ + void register_plugins(AST::Crate& crate); + /* Injection pipeline stage. TODO maybe move to another object? Maybe have some lint checks + * (in future, obviously), register builtin macros, crate injection. */ + void injection(AST::Crate& crate); + /* Expansion pipeline stage. TODO maybe move to another object? Expands all macros, maybe + * build test harness in future, AST validation, maybe create macro crate (if not rustdoc).*/ + void expansion(AST::Crate& crate); + /* Name resolution pipeline stage. TODO maybe move to another object. Performs name + * resolution, maybe complete gated feature checking, maybe create buffered lints in future. + */ + void name_resolution(AST::Crate& crate); + }; +} + +#endif diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index d4c0ac1..f424a4b 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -37,11 +37,9 @@ #include #include #include -<<<<<<< HEAD -======= #include #include ->>>>>>> c611d209696bd5983b4b777be0beea80351dee46 +#include #if defined(HAVE_UNORDERED_MAP) @@ -150,4 +148,8 @@ struct hash // When using gcc, rust_unreachable is just gcc_unreachable. #define rust_unreachable() gcc_unreachable() +extern void rust_preserve_from_gc (tree t); + +extern const char* rust_localize_identifier (const char *ident); + #endif // !defined(RUST_SYSTEM_H) diff --git a/gcc/rust/rustc_parser/RustCNotes.txt b/gcc/rust/rustc_parser/RustCNotes.txt deleted file mode 100644 index cecc84f..0000000 --- a/gcc/rust/rustc_parser/RustCNotes.txt +++ /dev/null @@ -1,28 +0,0 @@ -rustc notes: - -parser main entry point is "parsing source module as crate" (parse_crate_mod in parser.rs) - -this then returns the a crate object with crate "attrs", "module" and "span" returned. -attributes (parse_inner_attributes, attr.rs) seem to be the #![trait: whatever] shitty @interface -equivalents. However, the loop is broken if there is not an inner attribute or doc comment, and it is -only called once from entry point, so maybe the attribute is more specific to something. -span seems to be the length of the tokens or something to do with that - -modules (parse_mod_items, parser.rs) are the rust name spacing system, obviously. parse_mod_items says -it "parses all of the items in a module." it calls parse_item while it continues to have a value (main -loop, presumably). all items are pushed onto a vector which is returned as the module item list in the -returned module object. - -parse_item (parser.rs) calls parse_outer_attributes and then calls (and returns) parse_item_ with -those attributes passed in. -parse_outer_attribtues (attr.rs) claims to "parse attributes that appear before an item" and returns a -vector of all attributes on the item. - -parse_item_ (parser.rs) is goddamn closure heaven and I honestly don't understand exactly what happens -for that reason, but... it seems to "collect_tokens" based on parse_item_implementation, and also has -something to do with unclosed brackets (these brackets). Then, it returns like the item parsed, I -imagine. -collect_tokens seems to just record all tokens encountered - -parse_item_implementation (parser.rs) is actually quite complicated and here we get to actual parsing -of top-level stuff, I think. diff --git a/gcc/rust/rustc_parser/grammar/.gitignore b/gcc/rust/rustc_parser/grammar/.gitignore deleted file mode 100644 index 3e44987..0000000 --- a/gcc/rust/rustc_parser/grammar/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.class -*.java -*.tokens diff --git a/gcc/rust/rustc_parser/grammar/lexer.l b/gcc/rust/rustc_parser/grammar/lexer.l deleted file mode 100644 index 1feb781..0000000 --- a/gcc/rust/rustc_parser/grammar/lexer.l +++ /dev/null @@ -1,350 +0,0 @@ -%{ -#include -#include - -static int num_hashes; -static int end_hashes; -static int saw_non_hash; - -%} - -%option stack -%option yylineno - -%x str -%x rawstr -%x rawstr_esc_begin -%x rawstr_esc_body -%x rawstr_esc_end -%x byte -%x bytestr -%x rawbytestr -%x rawbytestr_nohash -%x pound -%x shebang_or_attr -%x ltorchar -%x linecomment -%x doc_line -%x blockcomment -%x doc_block -%x suffix - -ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]* - -%% - -{ident} { BEGIN(INITIAL); } -(.|\n) { yyless(0); BEGIN(INITIAL); } - -[ \n\t\r] { } - -\xef\xbb\xbf { - // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise - if (yyget_lineno() != 1) { - return -1; - } -} - -\/\/(\/|\!) { BEGIN(doc_line); yymore(); } -\n { BEGIN(INITIAL); - yyleng--; - yytext[yyleng] = 0; - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -[^\n]* { yymore(); } - -\/\/|\/\/\/\/ { BEGIN(linecomment); } -\n { BEGIN(INITIAL); } -[^\n]* { } - -\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } -\/\* { yy_push_state(doc_block); yymore(); } -\*\/ { - yy_pop_state(); - if (yy_top_state() == doc_block) { - yymore(); - } else { - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -} -(.|\n) { yymore(); } - -\/\* { yy_push_state(blockcomment); } -\/\* { yy_push_state(blockcomment); } -\*\/ { yy_pop_state(); } -(.|\n) { } - -_ { return UNDERSCORE; } -abstract { return ABSTRACT; } -alignof { return ALIGNOF; } -as { return AS; } -become { return BECOME; } -box { return BOX; } -break { return BREAK; } -catch { return CATCH; } -const { return CONST; } -continue { return CONTINUE; } -crate { return CRATE; } -default { return DEFAULT; } -do { return DO; } -else { return ELSE; } -enum { return ENUM; } -extern { return EXTERN; } -false { return FALSE; } -final { return FINAL; } -fn { return FN; } -for { return FOR; } -if { return IF; } -impl { return IMPL; } -in { return IN; } -let { return LET; } -loop { return LOOP; } -macro { return MACRO; } -match { return MATCH; } -mod { return MOD; } -move { return MOVE; } -mut { return MUT; } -offsetof { return OFFSETOF; } -override { return OVERRIDE; } -priv { return PRIV; } -proc { return PROC; } -pure { return PURE; } -pub { return PUB; } -ref { return REF; } -return { return RETURN; } -self { return SELF; } -sizeof { return SIZEOF; } -static { return STATIC; } -struct { return STRUCT; } -super { return SUPER; } -trait { return TRAIT; } -true { return TRUE; } -type { return TYPE; } -typeof { return TYPEOF; } -union { return UNION; } -unsafe { return UNSAFE; } -unsized { return UNSIZED; } -use { return USE; } -virtual { return VIRTUAL; } -where { return WHERE; } -while { return WHILE; } -yield { return YIELD; } - -{ident} { return IDENT; } - -0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } -0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } - -[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; } -[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; } - -; { return ';'; } -, { return ','; } -\.\.\. { return DOTDOTDOT; } -\.\. { return DOTDOT; } -\. { return '.'; } -\( { return '('; } -\) { return ')'; } -\{ { return '{'; } -\} { return '}'; } -\[ { return '['; } -\] { return ']'; } -@ { return '@'; } -# { BEGIN(pound); yymore(); } -\! { BEGIN(shebang_or_attr); yymore(); } -\[ { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; -} -[^\[\n]*\n { - // Since the \n was eaten as part of the token, yylineno will have - // been incremented to the value 2 if the shebang was on the first - // line. This yyless undoes that, setting yylineno back to 1. - yyless(yyleng - 1); - if (yyget_lineno() == 1) { - BEGIN(INITIAL); - return SHEBANG_LINE; - } else { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; - } -} -. { BEGIN(INITIAL); yyless(1); return '#'; } - -\~ { return '~'; } -:: { return MOD_SEP; } -: { return ':'; } -\$ { return '$'; } -\? { return '?'; } - -== { return EQEQ; } -=> { return FAT_ARROW; } -= { return '='; } -\!= { return NE; } -\! { return '!'; } -\<= { return LE; } -\<\< { return SHL; } -\<\<= { return SHLEQ; } -\< { return '<'; } -\>= { return GE; } -\>\> { return SHR; } -\>\>= { return SHREQ; } -\> { return '>'; } - -\x27 { BEGIN(ltorchar); yymore(); } -static { BEGIN(INITIAL); return STATIC_LIFETIME; } -{ident} { BEGIN(INITIAL); return LIFETIME; } -\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } -\\u\{([0-9a-fA-F]_*){1,6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } -.\x27 { BEGIN(suffix); return LIT_CHAR; } -[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } -<> { BEGIN(INITIAL); return -1; } - -b\x22 { BEGIN(bytestr); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR; } - -<> { return -1; } -\\[n\nrt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -br\x22 { BEGIN(rawbytestr_nohash); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -br/# { - BEGIN(rawbytestr); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} -# { - if (!saw_non_hash) { - num_hashes++; - } else if (end_hashes != 0) { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - } - yymore(); -} -\x22# { - end_hashes = 1; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - yymore(); -} -(.|\n) { - if (!saw_non_hash) { - saw_non_hash = 1; - } - if (end_hashes != 0) { - end_hashes = 0; - } - yymore(); -} -<> { return -1; } - -b\x27 { BEGIN(byte); yymore(); } -\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\u([0-9a-fA-F]_*){4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\U([0-9a-fA-F]_*){8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -.\x27 { BEGIN(INITIAL); return LIT_BYTE; } -<> { BEGIN(INITIAL); return -1; } - -r\x22 { BEGIN(rawstr); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -r/# { - BEGIN(rawstr_esc_begin); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - -# { - num_hashes++; - yymore(); -} -\x22 { - BEGIN(rawstr_esc_body); - yymore(); -} -(.|\n) { return -1; } - -\x22/# { - BEGIN(rawstr_esc_end); - yymore(); - } -(.|\n) { - yymore(); - } - -# { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_STR_RAW; - } - yymore(); - } -[^#] { - end_hashes = 0; - BEGIN(rawstr_esc_body); - yymore(); - } - -<> { return -1; } - -\x22 { BEGIN(str); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR; } - -<> { return -1; } -\\[n\nr\rt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -\<- { return LARROW; } --\> { return RARROW; } -- { return '-'; } --= { return MINUSEQ; } -&& { return ANDAND; } -& { return '&'; } -&= { return ANDEQ; } -\|\| { return OROR; } -\| { return '|'; } -\|= { return OREQ; } -\+ { return '+'; } -\+= { return PLUSEQ; } -\* { return '*'; } -\*= { return STAREQ; } -\/ { return '/'; } -\/= { return SLASHEQ; } -\^ { return '^'; } -\^= { return CARETEQ; } -% { return '%'; } -%= { return PERCENTEQ; } - -<> { return 0; } - -%% diff --git a/gcc/rust/rustc_parser/grammar/parser-lalr-main.c b/gcc/rust/rustc_parser/grammar/parser-lalr-main.c deleted file mode 100644 index 6348190c..0000000 --- a/gcc/rust/rustc_parser/grammar/parser-lalr-main.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include - -extern int yylex(); -extern int rsparse(); - -#define PUSHBACK_LEN 4 - -static char pushback[PUSHBACK_LEN]; -static int verbose; - -void print(const char* format, ...) { - va_list args; - va_start(args, format); - if (verbose) { - vprintf(format, args); - } - va_end(args); -} - -// If there is a non-null char at the head of the pushback queue, -// dequeue it and shift the rest of the queue forwards. Otherwise, -// return the token from calling yylex. -int rslex() { - if (pushback[0] == '\0') { - return yylex(); - } else { - char c = pushback[0]; - memmove(pushback, pushback + 1, PUSHBACK_LEN - 1); - pushback[PUSHBACK_LEN - 1] = '\0'; - return c; - } -} - -// Note: this does nothing if the pushback queue is full. As long as -// there aren't more than PUSHBACK_LEN consecutive calls to push_back -// in an action, this shouldn't be a problem. -void push_back(char c) { - for (int i = 0; i < PUSHBACK_LEN; ++i) { - if (pushback[i] == '\0') { - pushback[i] = c; - break; - } - } -} - -extern int rsdebug; - -struct node { - struct node *next; - struct node *prev; - int own_string; - char const *name; - int n_elems; - struct node *elems[]; -}; - -struct node *nodes = NULL; -int n_nodes; - -struct node *mk_node(char const *name, int n, ...) { - va_list ap; - int i = 0; - unsigned sz = sizeof(struct node) + (n * sizeof(struct node *)); - struct node *nn, *nd = (struct node *)malloc(sz); - - print("# New %d-ary node: %s = %p\n", n, name, nd); - - nd->own_string = 0; - nd->prev = NULL; - nd->next = nodes; - if (nodes) { - nodes->prev = nd; - } - nodes = nd; - - nd->name = name; - nd->n_elems = n; - - va_start(ap, n); - while (i < n) { - nn = va_arg(ap, struct node *); - print("# arg[%d]: %p\n", i, nn); - print("# (%s ...)\n", nn->name); - nd->elems[i++] = nn; - } - va_end(ap); - n_nodes++; - return nd; -} - -struct node *mk_atom(char *name) { - struct node *nd = mk_node((char const *)strdup(name), 0); - nd->own_string = 1; - return nd; -} - -struct node *mk_none() { - return mk_atom(""); -} - -struct node *ext_node(struct node *nd, int n, ...) { - va_list ap; - int i = 0, c = nd->n_elems + n; - unsigned sz = sizeof(struct node) + (c * sizeof(struct node *)); - struct node *nn; - - print("# Extending %d-ary node by %d nodes: %s = %p", - nd->n_elems, c, nd->name, nd); - - if (nd->next) { - nd->next->prev = nd->prev; - } - if (nd->prev) { - nd->prev->next = nd->next; - } - nd = realloc(nd, sz); - nd->prev = NULL; - nd->next = nodes; - nodes->prev = nd; - nodes = nd; - - print(" ==> %p\n", nd); - - va_start(ap, n); - while (i < n) { - nn = va_arg(ap, struct node *); - print("# arg[%d]: %p\n", i, nn); - print("# (%s ...)\n", nn->name); - nd->elems[nd->n_elems++] = nn; - ++i; - } - va_end(ap); - return nd; -} - -int const indent_step = 4; - -void print_indent(int depth) { - while (depth) { - if (depth-- % indent_step == 0) { - print("|"); - } else { - print(" "); - } - } -} - -void print_node(struct node *n, int depth) { - int i = 0; - print_indent(depth); - if (n->n_elems == 0) { - print("%s\n", n->name); - } else { - print("(%s\n", n->name); - for (i = 0; i < n->n_elems; ++i) { - print_node(n->elems[i], depth + indent_step); - } - print_indent(depth); - print(")\n"); - } -} - -int main(int argc, char **argv) { - if (argc == 2 && strcmp(argv[1], "-v") == 0) { - verbose = 1; - } else { - verbose = 0; - } - int ret = 0; - struct node *tmp; - memset(pushback, '\0', PUSHBACK_LEN); - ret = rsparse(); - print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes); - if (nodes) { - print_node(nodes, 0); - } - while (nodes) { - tmp = nodes; - nodes = tmp->next; - if (tmp->own_string) { - free((void*)tmp->name); - } - free(tmp); - } - return ret; -} - -void rserror(char const *s) { - fprintf(stderr, "%s\n", s); -} diff --git a/gcc/rust/rustc_parser/grammar/parser-lalr.y b/gcc/rust/rustc_parser/grammar/parser-lalr.y deleted file mode 100644 index 5585c95..0000000 --- a/gcc/rust/rustc_parser/grammar/parser-lalr.y +++ /dev/null @@ -1,1982 +0,0 @@ -%{ -#define YYERROR_VERBOSE -#define YYSTYPE struct node * -struct node; -extern int yylex(); -extern void yyerror(char const *s); -extern struct node *mk_node(char const *name, int n, ...); -extern struct node *mk_atom(char *text); -extern struct node *mk_none(); -extern struct node *ext_node(struct node *nd, int n, ...); -extern void push_back(char c); -extern char *yytext; -%} -%debug - -%token SHL -%token SHR -%token LE -%token EQEQ -%token NE -%token GE -%token ANDAND -%token OROR -%token SHLEQ -%token SHREQ -%token MINUSEQ -%token ANDEQ -%token OREQ -%token PLUSEQ -%token STAREQ -%token SLASHEQ -%token CARETEQ -%token PERCENTEQ -%token DOTDOT -%token DOTDOTDOT -%token MOD_SEP -%token RARROW -%token LARROW -%token FAT_ARROW -%token LIT_BYTE -%token LIT_CHAR -%token LIT_INTEGER -%token LIT_FLOAT -%token LIT_STR -%token LIT_STR_RAW -%token LIT_BYTE_STR -%token LIT_BYTE_STR_RAW -%token IDENT -%token UNDERSCORE -%token LIFETIME - -// keywords -%token SELF -%token STATIC -%token ABSTRACT -%token ALIGNOF -%token AS -%token BECOME -%token BREAK -%token CATCH -%token CRATE -%token DO -%token ELSE -%token ENUM -%token EXTERN -%token FALSE -%token FINAL -%token FN -%token FOR -%token IF -%token IMPL -%token IN -%token LET -%token LOOP -%token MACRO -%token MATCH -%token MOD -%token MOVE -%token MUT -%token OFFSETOF -%token OVERRIDE -%token PRIV -%token PUB -%token PURE -%token REF -%token RETURN -%token SIZEOF -%token STRUCT -%token SUPER -%token UNION -%token UNSIZED -%token TRUE -%token TRAIT -%token TYPE -%token UNSAFE -%token VIRTUAL -%token YIELD -%token DEFAULT -%token USE -%token WHILE -%token CONTINUE -%token PROC -%token BOX -%token CONST -%token WHERE -%token TYPEOF -%token INNER_DOC_COMMENT -%token OUTER_DOC_COMMENT - -%token SHEBANG -%token SHEBANG_LINE -%token STATIC_LIFETIME - - /* - Quoting from the Bison manual: - - "Finally, the resolution of conflicts works by comparing the precedence - of the rule being considered with that of the lookahead token. If the - token's precedence is higher, the choice is to shift. If the rule's - precedence is higher, the choice is to reduce. If they have equal - precedence, the choice is made based on the associativity of that - precedence level. The verbose output file made by ‘-v’ (see Invoking - Bison) says how each conflict was resolved" - */ - -// We expect no shift/reduce or reduce/reduce conflicts in this grammar; -// all potential ambiguities are scrutinized and eliminated manually. -%expect 0 - -// fake-precedence symbol to cause '|' bars in lambda context to parse -// at low precedence, permit things like |x| foo = bar, where '=' is -// otherwise lower-precedence than '|'. Also used for proc() to cause -// things like proc() a + b to parse as proc() { a + b }. -%precedence LAMBDA - -%precedence SELF - -// MUT should be lower precedence than IDENT so that in the pat rule, -// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]" -%precedence MUT - -// IDENT needs to be lower than '{' so that 'foo {' is shifted when -// trying to decide if we've got a struct-construction expr (esp. in -// contexts like 'if foo { .') -// -// IDENT also needs to be lower precedence than '<' so that '<' in -// 'foo:bar . <' is shifted (in a trait reference occurring in a -// bounds list), parsing as foo:(bar) rather than (foo:bar). -%precedence IDENT - // Put the weak keywords that can be used as idents here as well -%precedence CATCH -%precedence DEFAULT -%precedence UNION - -// A couple fake-precedence symbols to use in rules associated with + -// and < in trailing type contexts. These come up when you have a type -// in the RHS of operator-AS, such as "foo as bar". The "<" there -// has to be shifted so the parser keeps trying to parse a type, even -// though it might well consider reducing the type "bar" and then -// going on to "<" as a subsequent binop. The "+" case is with -// trailing type-bounds ("foo as bar:A+B"), for the same reason. -%precedence SHIFTPLUS - -%precedence MOD_SEP -%precedence RARROW ':' - -// In where clauses, "for" should have greater precedence when used as -// a higher ranked constraint than when used as the beginning of a -// for_in_type (which is a ty) -%precedence FORTYPE -%precedence FOR - -// Binops & unops, and their precedences -%precedence '?' -%precedence BOX -%nonassoc DOTDOT - -// RETURN needs to be lower-precedence than tokens that start -// prefix_exprs -%precedence RETURN YIELD - -%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ -%right LARROW -%left OROR -%left ANDAND -%left EQEQ NE -%left '<' '>' LE GE -%left '|' -%left '^' -%left '&' -%left SHL SHR -%left '+' '-' -%precedence AS -%left '*' '/' '%' -%precedence '!' - -%precedence '{' '[' '(' '.' - -%precedence RANGE - -%start crate - -%% - -//////////////////////////////////////////////////////////////////////// -// Part 1: Items and attributes -//////////////////////////////////////////////////////////////////////// - -crate -: maybe_shebang inner_attrs maybe_mod_items { mk_node("crate", 2, $2, $3); } -| maybe_shebang maybe_mod_items { mk_node("crate", 1, $2); } -; - -maybe_shebang -: SHEBANG_LINE -| %empty -; - -maybe_inner_attrs -: inner_attrs -| %empty { $$ = mk_none(); } -; - -inner_attrs -: inner_attr { $$ = mk_node("InnerAttrs", 1, $1); } -| inner_attrs inner_attr { $$ = ext_node($1, 1, $2); } -; - -inner_attr -: SHEBANG '[' meta_item ']' { $$ = mk_node("InnerAttr", 1, $3); } -| INNER_DOC_COMMENT { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); } -; - -maybe_outer_attrs -: outer_attrs -| %empty { $$ = mk_none(); } -; - -outer_attrs -: outer_attr { $$ = mk_node("OuterAttrs", 1, $1); } -| outer_attrs outer_attr { $$ = ext_node($1, 1, $2); } -; - -outer_attr -: '#' '[' meta_item ']' { $$ = $3; } -| OUTER_DOC_COMMENT { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); } -; - -meta_item -: ident { $$ = mk_node("MetaWord", 1, $1); } -| ident '=' lit { $$ = mk_node("MetaNameValue", 2, $1, $3); } -| ident '(' meta_seq ')' { $$ = mk_node("MetaList", 2, $1, $3); } -| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); } -; - -meta_seq -: %empty { $$ = mk_none(); } -| meta_item { $$ = mk_node("MetaItems", 1, $1); } -| meta_seq ',' meta_item { $$ = ext_node($1, 1, $3); } -; - -maybe_mod_items -: mod_items -| %empty { $$ = mk_none(); } -; - -mod_items -: mod_item { $$ = mk_node("Items", 1, $1); } -| mod_items mod_item { $$ = ext_node($1, 1, $2); } -; - -attrs_and_vis -: maybe_outer_attrs visibility { $$ = mk_node("AttrsAndVis", 2, $1, $2); } -; - -mod_item -: attrs_and_vis item { $$ = mk_node("Item", 2, $1, $2); } -; - -// items that can appear outside of a fn block -item -: stmt_item -| item_macro -; - -// items that can appear in "stmts" -stmt_item -: item_static -| item_const -| item_type -| block_item -| view_item -; - -item_static -: STATIC ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $2, $4, $6); } -| STATIC MUT ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $3, $5, $7); } -; - -item_const -: CONST ident ':' ty '=' expr ';' { $$ = mk_node("ItemConst", 3, $2, $4, $6); } -; - -item_macro -: path_expr '!' maybe_ident parens_delimited_token_trees ';' { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -; - -view_item -: use_item -| extern_fn_item -| EXTERN CRATE ident ';' { $$ = mk_node("ViewItemExternCrate", 1, $3); } -| EXTERN CRATE ident AS ident ';' { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); } -; - -extern_fn_item -: EXTERN maybe_abi item_fn { $$ = mk_node("ViewItemExternFn", 2, $2, $3); } -; - -use_item -: USE view_path ';' { $$ = mk_node("ViewItemUse", 1, $2); } -; - -view_path -: path_no_types_allowed { $$ = mk_node("ViewPathSimple", 1, $1); } -| path_no_types_allowed MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); } -| MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); } -| path_no_types_allowed MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } -| MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $3); } -| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } -| MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); } -| path_no_types_allowed MOD_SEP '*' { $$ = mk_node("ViewPathGlob", 1, $1); } -| MOD_SEP '*' { $$ = mk_atom("ViewPathGlob"); } -| '*' { $$ = mk_atom("ViewPathGlob"); } -| '{' '}' { $$ = mk_atom("ViewPathListEmpty"); } -| '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $2); } -| '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); } -| path_no_types_allowed AS ident { $$ = mk_node("ViewPathSimple", 2, $1, $3); } -; - -block_item -: item_fn -| item_unsafe_fn -| item_mod -| item_foreign_mod { $$ = mk_node("ItemForeignMod", 1, $1); } -| item_struct -| item_enum -| item_union -| item_trait -| item_impl -; - -maybe_ty_ascription -: ':' ty_sum { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_init_expr -: '=' expr { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -// structs -item_struct -: STRUCT ident generic_params maybe_where_clause struct_decl_args -{ - $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';' -{ - $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params maybe_where_clause ';' -{ - $$ = mk_node("ItemStruct", 3, $2, $3, $4); -} -; - -struct_decl_args -: '{' struct_decl_fields '}' { $$ = $2; } -| '{' struct_decl_fields ',' '}' { $$ = $2; } -; - -struct_tuple_args -: '(' struct_tuple_fields ')' { $$ = $2; } -| '(' struct_tuple_fields ',' ')' { $$ = $2; } -; - -struct_decl_fields -: struct_decl_field { $$ = mk_node("StructFields", 1, $1); } -| struct_decl_fields ',' struct_decl_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_decl_field -: attrs_and_vis ident ':' ty_sum { $$ = mk_node("StructField", 3, $1, $2, $4); } -; - -struct_tuple_fields -: struct_tuple_field { $$ = mk_node("StructFields", 1, $1); } -| struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_tuple_field -: attrs_and_vis ty_sum { $$ = mk_node("StructField", 2, $1, $2); } -; - -// enums -item_enum -: ENUM ident generic_params maybe_where_clause '{' enum_defs '}' { $$ = mk_node("ItemEnum", 0); } -| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); } -; - -enum_defs -: enum_def { $$ = mk_node("EnumDefs", 1, $1); } -| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -enum_def -: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); } -; - -enum_args -: '{' struct_decl_fields '}' { $$ = mk_node("EnumArgs", 1, $2); } -| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); } -| '(' maybe_ty_sums ')' { $$ = mk_node("EnumArgs", 1, $2); } -| '=' expr { $$ = mk_node("EnumArgs", 1, $2); } -| %empty { $$ = mk_none(); } -; - -// unions -item_union -: UNION ident generic_params maybe_where_clause '{' struct_decl_fields '}' { $$ = mk_node("ItemUnion", 0); } -| UNION ident generic_params maybe_where_clause '{' struct_decl_fields ',' '}' { $$ = mk_node("ItemUnion", 0); } - -item_mod -: MOD ident ';' { $$ = mk_node("ItemMod", 1, $2); } -| MOD ident '{' maybe_mod_items '}' { $$ = mk_node("ItemMod", 2, $2, $4); } -| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); } -; - -item_foreign_mod -: EXTERN maybe_abi '{' maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 1, $4); } -| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); } -; - -maybe_abi -: str -| %empty { $$ = mk_none(); } -; - -maybe_foreign_items -: foreign_items -| %empty { $$ = mk_none(); } -; - -foreign_items -: foreign_item { $$ = mk_node("ForeignItems", 1, $1); } -| foreign_items foreign_item { $$ = ext_node($1, 1, $2); } -; - -foreign_item -: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); } -| attrs_and_vis item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $2); } -| attrs_and_vis UNSAFE item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $3); } -; - -item_foreign_static -: maybe_mut ident ':' ty ';' { $$ = mk_node("StaticItem", 3, $1, $2, $4); } -; - -item_foreign_fn -: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); } -; - -fn_decl_allow_variadic -: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_params_allow_variadic -: '(' ')' { $$ = mk_none(); } -| '(' params ')' { $$ = $2; } -| '(' params ',' ')' { $$ = $2; } -| '(' params ',' DOTDOTDOT ')' { $$ = $2; } -; - -visibility -: PUB { $$ = mk_atom("Public"); } -| %empty { $$ = mk_atom("Inherited"); } -; - -idents_or_self -: ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); } -| idents_or_self AS ident { $$ = mk_node("IdentsOrSelf", 2, $1, $3); } -| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); } -; - -ident_or_self -: ident -| SELF { $$ = mk_atom(yytext); } -; - -item_type -: TYPE ident generic_params maybe_where_clause '=' ty_sum ';' { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); } -; - -for_sized -: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); } -| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); } -| %empty { $$ = mk_none(); } -; - -item_trait -: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}' -{ - $$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9); -} -; - -maybe_trait_items -: trait_items -| %empty { $$ = mk_none(); } -; - -trait_items -: trait_item { $$ = mk_node("TraitItems", 1, $1); } -| trait_items trait_item { $$ = ext_node($1, 1, $2); } -; - -trait_item -: trait_const -| trait_type -| trait_method -| maybe_outer_attrs item_macro { $$ = mk_node("TraitMacroItem", 2, $1, $2); } -; - -trait_const -: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 4, $1, $3, $4, $5); } -; - -maybe_const_default -: '=' expr { $$ = mk_node("ConstDefault", 1, $2); } -| %empty { $$ = mk_none(); } -; - -trait_type -: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); } -; - -maybe_unsafe -: UNSAFE { $$ = mk_atom("Unsafe"); } -| %empty { $$ = mk_none(); } -; - -maybe_default_maybe_unsafe -: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); } -| DEFAULT { $$ = mk_atom("Default"); } -| UNSAFE { $$ = mk_atom("Unsafe"); } -| %empty { $$ = mk_none(); } - -trait_method -: type_method { $$ = mk_node("Required", 1, $1); } -| method { $$ = mk_node("Provided", 1, $1); } -; - -type_method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 6, $1, $3, $5, $6, $7, $8); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9); -} -; - -method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 7, $1, $3, $5, $6, $7, $8, $9); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -; - -impl_method -: attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $3, $5, $6, $7, $8, $9); -} -| attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -| attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 9, $1, $2, $3, $5, $7, $8, $9, $10, $11); -} -; - -// There are two forms of impl: -// -// impl (<...>)? TY { ... } -// impl (<...>)? TRAIT for TY { ... } -// -// Unfortunately since TY can begin with '<' itself -- as part of a -// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL: -// should we reduce one of the early rules of TY (such as maybe_once) -// or shall we continue shifting into the generic_params list for the -// impl? -// -// The production parser disambiguates a different case here by -// permitting / requiring the user to provide parens around types when -// they are ambiguous with traits. We do the same here, regrettably, -// by splitting ty into ty and ty_prim. -item_impl -: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8); -} -| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node("ItemImplDefault", 3, $1, $3, $4); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4); -} -; - -maybe_impl_items -: impl_items -| %empty { $$ = mk_none(); } -; - -impl_items -: impl_item { $$ = mk_node("ImplItems", 1, $1); } -| impl_item impl_items { $$ = ext_node($1, 1, $2); } -; - -impl_item -: impl_method -| attrs_and_vis item_macro { $$ = mk_node("ImplMacroItem", 2, $1, $2); } -| impl_const -| impl_type -; - -maybe_default -: DEFAULT { $$ = mk_atom("Default"); } -| %empty { $$ = mk_none(); } -; - -impl_const -: attrs_and_vis maybe_default item_const { $$ = mk_node("ImplConst", 3, $1, $2, $3); } -; - -impl_type -: attrs_and_vis maybe_default TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 5, $1, $2, $4, $5, $7); } -; - -item_fn -: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6); -} -| CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemFn", 5, $3, $4, $5, $6, $7); -} -; - -item_unsafe_fn -: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7); -} -| CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 5, $4, $5, $6, $7, $8); -} -| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9); -} -; - -fn_decl -: fn_params ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_decl_with_self -: fn_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_decl_with_self_allow_anon_params -: fn_anon_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_params -: '(' maybe_params ')' { $$ = $2; } -; - -fn_anon_params -: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); } -| '(' ')' { $$ = mk_none(); } -; - -fn_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } -| '(' maybe_params ')' { $$ = mk_node("SelfStatic", 1, $2); } -; - -fn_anon_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } -| '(' maybe_anon_params ')' { $$ = mk_node("SelfStatic", 1, $2); } -; - -maybe_params -: params -| params ',' -| %empty { $$ = mk_none(); } -; - -params -: param { $$ = mk_node("Args", 1, $1); } -| params ',' param { $$ = ext_node($1, 1, $3); } -; - -param -: pat ':' ty_sum { $$ = mk_node("Arg", 2, $1, $3); } -; - -inferrable_params -: inferrable_param { $$ = mk_node("InferrableParams", 1, $1); } -| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); } -; - -inferrable_param -: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); } -; - -maybe_comma_params -: ',' { $$ = mk_none(); } -| ',' params { $$ = $2; } -| ',' params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_comma_anon_params -: ',' { $$ = mk_none(); } -| ',' anon_params { $$ = $2; } -| ',' anon_params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_anon_params -: anon_params -| anon_params ',' -| %empty { $$ = mk_none(); } -; - -anon_params -: anon_param { $$ = mk_node("Args", 1, $1); } -| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); } -; - -// anon means it's allowed to be anonymous (type-only), but it can -// still have a name -anon_param -: named_arg ':' ty { $$ = mk_node("Arg", 2, $1, $3); } -| ty -; - -anon_params_allow_variadic_tail -: ',' DOTDOTDOT { $$ = mk_none(); } -| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); } -| %empty { $$ = mk_none(); } -; - -named_arg -: ident -| UNDERSCORE { $$ = mk_atom("PatWild"); } -| '&' ident { $$ = $2; } -| '&' UNDERSCORE { $$ = mk_atom("PatWild"); } -| ANDAND ident { $$ = $2; } -| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); } -| MUT ident { $$ = $2; } -; - -ret_ty -: RARROW '!' { $$ = mk_none(); } -| RARROW ty { $$ = mk_node("ret-ty", 1, $2); } -| %prec IDENT %empty { $$ = mk_none(); } -; - -generic_params -: '<' '>' { $$ = mk_node("Generics", 2, mk_none(), mk_none()); } -| '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' ty_params '>' { $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } -| '<' ty_params '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params ',' '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } -| %empty { $$ = mk_none(); } -; - -maybe_where_clause -: %empty { $$ = mk_none(); } -| where_clause -; - -where_clause -: WHERE where_predicates { $$ = mk_node("WhereClause", 1, $2); } -| WHERE where_predicates ',' { $$ = mk_node("WhereClause", 1, $2); } -; - -where_predicates -: where_predicate { $$ = mk_node("WherePredicates", 1, $1); } -| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); } -; - -where_predicate -: maybe_for_lifetimes lifetime ':' bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } -| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } -; - -maybe_for_lifetimes -: FOR '<' lifetimes '>' { $$ = mk_none(); } -| %prec FORTYPE %empty { $$ = mk_none(); } - -ty_params -: ty_param { $$ = mk_node("TyParams", 1, $1); } -| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); } -; - -// A path with no type parameters; e.g. `foo::bar::Baz` -// -// These show up in 'use' view-items, because these are processed -// without respect to types. -path_no_types_allowed -: ident { $$ = mk_node("ViewPath", 1, $1); } -| MOD_SEP ident { $$ = mk_node("ViewPath", 1, $2); } -| SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } -| MOD_SEP SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } -| SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } -| MOD_SEP SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } -| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); } -; - -// A path with a lifetime and type parameters, with no double colons -// before the type parameters; e.g. `foo::bar<'a>::Baz` -// -// These show up in "trait references", the components of -// type-parameter bounds lists, as well as in the prefix of the -// path_generic_args_and_bounds rule, which is the full form of a -// named typed expression. -// -// They do not have (nor need) an extra '::' before '<' because -// unlike in expr context, there are no "less-than" type exprs to -// be ambiguous with. -path_generic_args_without_colons -: %prec IDENT - ident { $$ = mk_node("components", 1, $1); } -| %prec IDENT - ident generic_args { $$ = mk_node("components", 2, $1, $2); } -| %prec IDENT - ident '(' maybe_ty_sums ')' ret_ty { $$ = mk_node("components", 2, $1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident generic_args { $$ = ext_node($1, 2, $3, $4); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); } -; - -generic_args -: '<' generic_values '>' { $$ = $2; } -| '<' generic_values SHR { push_back('>'); $$ = $2; } -| '<' generic_values GE { push_back('='); $$ = $2; } -| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -// If generic_args starts with "<<", the first arg must be a -// TyQualifiedPath because that's the only type that can start with a -// '<'. This rule parses that as the first ty_sum and then continues -// with the rest of generic_values. -| SHL ty_qualified_path_and_generic_values '>' { $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHR { push_back('>'); $$ = $2; } -| SHL ty_qualified_path_and_generic_values GE { push_back('='); $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -; - -generic_values -: maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 1, $1); } -; - -maybe_ty_sums_and_or_bindings -: ty_sums -| ty_sums ',' -| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); } -| bindings -| bindings ',' -| %empty { $$ = mk_none(); } -; - -maybe_bindings -: ',' bindings { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 2: Patterns -//////////////////////////////////////////////////////////////////////// - -pat -: UNDERSCORE { $$ = mk_atom("PatWild"); } -| '&' pat { $$ = mk_node("PatRegion", 1, $2); } -| '&' MUT pat { $$ = mk_node("PatRegion", 1, $3); } -| ANDAND pat { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); } -| '(' ')' { $$ = mk_atom("PatUnit"); } -| '(' pat_tup ')' { $$ = mk_node("PatTup", 1, $2); } -| '[' pat_vec ']' { $$ = mk_node("PatVec", 1, $2); } -| lit_or_path -| lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node("PatRange", 2, $1, $3); } -| path_expr '{' pat_struct '}' { $$ = mk_node("PatStruct", 2, $1, $3); } -| path_expr '(' ')' { $$ = mk_node("PatEnum", 2, $1, mk_none()); } -| path_expr '(' pat_tup ')' { $$ = mk_node("PatEnum", 2, $1, $3); } -| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); } -| binding_mode ident { $$ = mk_node("PatIdent", 2, $1, $2); } -| ident '@' pat { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); } -| binding_mode ident '@' pat { $$ = mk_node("PatIdent", 3, $1, $2, $4); } -| BOX pat { $$ = mk_node("PatUniq", 1, $2); } -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("PatQualifiedPath", 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, $2, $3, $6), $7, $10); -} -; - -pats_or -: pat { $$ = mk_node("Pats", 1, $1); } -| pats_or '|' pat { $$ = ext_node($1, 1, $3); } -; - -binding_mode -: REF { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); } -| REF MUT { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); } -| MUT { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); } -; - -lit_or_path -: path_expr { $$ = mk_node("PatLit", 1, $1); } -| lit { $$ = mk_node("PatLit", 1, $1); } -| '-' lit { $$ = mk_node("PatLit", 1, $2); } -; - -pat_field -: ident { $$ = mk_node("PatField", 1, $1); } -| binding_mode ident { $$ = mk_node("PatField", 2, $1, $2); } -| BOX ident { $$ = mk_node("PatField", 2, mk_atom("box"), $2); } -| BOX binding_mode ident { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); } -| ident ':' pat { $$ = mk_node("PatField", 2, $1, $3); } -| binding_mode ident ':' pat { $$ = mk_node("PatField", 3, $1, $2, $4); } -| LIT_INTEGER ':' pat { $$ = mk_node("PatField", 2, mk_atom(yytext), $3); } -; - -pat_fields -: pat_field { $$ = mk_node("PatFields", 1, $1); } -| pat_fields ',' pat_field { $$ = ext_node($1, 1, $3); } -; - -pat_struct -: pat_fields { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } -| pat_fields ',' { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } -| pat_fields ',' DOTDOT { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); } -| DOTDOT { $$ = mk_node("PatStruct", 1, mk_atom("true")); } -| %empty { $$ = mk_node("PatStruct", 1, mk_none()); } -; - -pat_tup -: pat_tup_elts { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts ',' DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $4); } -| pat_tup_elts DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $4); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $5); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $5); } -| DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, mk_none(), $3); } -| DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node("PatTup", 2, mk_none(), mk_none()); } -; - -pat_tup_elts -: pat { $$ = mk_node("PatTupElts", 1, $1); } -| pat_tup_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -pat_vec -: pat_vec_elts { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts ',' DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $4); } -| pat_vec_elts DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $4); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $5); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $5); } -| DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, mk_none(), $3); } -| DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } -| %empty { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } -; - -pat_vec_elts -: pat { $$ = mk_node("PatVecElts", 1, $1); } -| pat_vec_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 3: Types -//////////////////////////////////////////////////////////////////////// - -ty -: ty_prim -| ty_closure -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $3, $6), $7, $10); } -| '(' ty_sums ')' { $$ = mk_node("TyTup", 1, $2); } -| '(' ty_sums ',' ')' { $$ = mk_node("TyTup", 1, $2); } -| '(' ')' { $$ = mk_atom("TyNil"); } -; - -ty_prim -: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); } -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); } -| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); } -| %prec IDENT path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $1, $3, $4); } -| %prec IDENT MOD_SEP path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $2, $4, $5); } -| BOX ty { $$ = mk_node("TyBox", 1, $2); } -| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); } -| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); } -| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); } -| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); } -| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); } -| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); } -| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); } -| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); } -| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); } -| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); } -| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); } -| UNDERSCORE { $$ = mk_atom("TyInfer"); } -| ty_bare_fn -| for_in_type -; - -ty_bare_fn -: FN ty_fn_decl { $$ = $2; } -| UNSAFE FN ty_fn_decl { $$ = $3; } -| EXTERN maybe_abi FN ty_fn_decl { $$ = $4; } -| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; } -; - -ty_fn_decl -: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); } -; - -ty_closure -: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); } -| '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); } -| UNSAFE OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $3, $4); } -| OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $2, $3); } -; - -for_in_type -: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); } -; - -for_in_type_suffix -: ty_bare_fn -| trait_ref -| ty_closure -; - -maybe_mut -: MUT { $$ = mk_atom("MutMutable"); } -| %prec MUT %empty { $$ = mk_atom("MutImmutable"); } -; - -maybe_mut_or_const -: MUT { $$ = mk_atom("MutMutable"); } -| CONST { $$ = mk_atom("MutImmutable"); } -| %empty { $$ = mk_atom("MutImmutable"); } -; - -ty_qualified_path_and_generic_values -: ty_qualified_path maybe_bindings -{ - $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2); -} -| ty_qualified_path ',' ty_sums maybe_bindings -{ - $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, $1, $3), $4); -} -; - -ty_qualified_path -: ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } -| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } -; - -maybe_ty_sums -: ty_sums -| ty_sums ',' -| %empty { $$ = mk_none(); } -; - -ty_sums -: ty_sum { $$ = mk_node("TySums", 1, $1); } -| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); } -; - -ty_sum -: ty_sum_elt { $$ = mk_node("TySum", 1, $1); } -| ty_sum '+' ty_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_sum_elt -: ty -| lifetime -; - -ty_prim_sum -: ty_prim_sum_elt { $$ = mk_node("TySum", 1, $1); } -| ty_prim_sum '+' ty_prim_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_prim_sum_elt -: ty_prim -| lifetime -; - -maybe_ty_param_bounds -: ':' ty_param_bounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ty_param_bounds -: boundseq -| %empty { $$ = mk_none(); } -; - -boundseq -: polybound -| boundseq '+' polybound { $$ = ext_node($1, 1, $3); } -; - -polybound -: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); } -| bound -| '?' FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $4, $6); } -| '?' bound { $$ = $2; } -; - -bindings -: binding { $$ = mk_node("Bindings", 1, $1); } -| bindings ',' binding { $$ = ext_node($1, 1, $3); } -; - -binding -: ident '=' ty { mk_node("Binding", 2, $1, $3); } -; - -ty_param -: ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 3, $1, $2, $3); } -| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); } -; - -maybe_bounds -: %prec SHIFTPLUS - ':' bounds { $$ = $2; } -| %prec SHIFTPLUS %empty { $$ = mk_none(); } -; - -bounds -: bound { $$ = mk_node("bounds", 1, $1); } -| bounds '+' bound { $$ = ext_node($1, 1, $3); } -; - -bound -: lifetime -| trait_ref -; - -maybe_ltbounds -: %prec SHIFTPLUS - ':' ltbounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ltbounds -: lifetime { $$ = mk_node("ltbounds", 1, $1); } -| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); } -; - -maybe_ty_default -: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_lifetimes -: lifetimes -| lifetimes ',' -| %empty { $$ = mk_none(); } -; - -lifetimes -: lifetime_and_bounds { $$ = mk_node("Lifetimes", 1, $1); } -| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); } -; - -lifetime_and_bounds -: LIFETIME maybe_ltbounds { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); } -| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } -; - -lifetime -: LIFETIME { $$ = mk_node("lifetime", 1, mk_atom(yytext)); } -| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } -; - -trait_ref -: %prec IDENT path_generic_args_without_colons -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; } -; - -//////////////////////////////////////////////////////////////////////// -// Part 4: Blocks, statements, and expressions -//////////////////////////////////////////////////////////////////////// - -inner_attrs_and_block -: '{' maybe_inner_attrs maybe_stmts '}' { $$ = mk_node("ExprBlock", 2, $2, $3); } -; - -block -: '{' maybe_stmts '}' { $$ = mk_node("ExprBlock", 1, $2); } -; - -maybe_stmts -: stmts -| stmts nonblock_expr { $$ = ext_node($1, 1, $2); } -| nonblock_expr -| %empty { $$ = mk_none(); } -; - -// There are two sub-grammars within a "stmts: exprs" derivation -// depending on whether each stmt-expr is a block-expr form; this is to -// handle the "semicolon rule" for stmt sequencing that permits -// writing -// -// if foo { bar } 10 -// -// as a sequence of two stmts (one if-expr stmt, one lit-10-expr -// stmt). Unfortunately by permitting juxtaposition of exprs in -// sequence like that, the non-block expr grammar has to have a -// second limited sub-grammar that excludes the prefix exprs that -// are ambiguous with binops. That is to say: -// -// {10} - 1 -// -// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that -// is to say, two statements rather than one, at least according to -// the mainline rust parser. -// -// So we wind up with a 3-way split in exprs that occur in stmt lists: -// block, nonblock-prefix, and nonblock-nonprefix. -// -// In non-stmts contexts, expr can relax this trichotomy. - -stmts -: stmt { $$ = mk_node("stmts", 1, $1); } -| stmts stmt { $$ = ext_node($1, 1, $2); } -; - -stmt -: maybe_outer_attrs let { $$ = $2; } -| stmt_item -| PUB stmt_item { $$ = $2; } -| outer_attrs stmt_item { $$ = $2; } -| outer_attrs PUB stmt_item { $$ = $3; } -| full_block_expr -| maybe_outer_attrs block { $$ = $2; } -| nonblock_expr ';' -| outer_attrs nonblock_expr ';' { $$ = $2; } -| ';' { $$ = mk_none(); } -; - -maybe_exprs -: exprs -| exprs ',' -| %empty { $$ = mk_none(); } -; - -maybe_expr -: expr -| %empty { $$ = mk_none(); } -; - -exprs -: expr { $$ = mk_node("exprs", 1, $1); } -| exprs ',' expr { $$ = ext_node($1, 1, $3); } -; - -path_expr -: path_generic_args_with_colons -| MOD_SEP path_generic_args_with_colons { $$ = $2; } -| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); } -; - -// A path with a lifetime and type parameters with double colons before -// the type parameters; e.g. `foo::bar::<'a>::Baz::` -// -// These show up in expr context, in order to disambiguate from "less-than" -// expressions. -path_generic_args_with_colons -: ident { $$ = mk_node("components", 1, $1); } -| SUPER { $$ = mk_atom("Super"); } -| path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| path_generic_args_with_colons MOD_SEP SUPER { $$ = ext_node($1, 1, mk_atom("Super")); } -| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); } -; - -// the braces-delimited macro is a block_expr so it doesn't appear here -macro_expr -: path_expr '!' maybe_ident parens_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } -; - -nonblock_expr -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } -| nonblock_expr '?' { $$ = mk_node("ExprTry", 1, $1); } -| nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| nonblock_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| nonblock_expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| nonblock_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE lifetime { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } -| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| nonblock_expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| nonblock_expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| nonblock_expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| nonblock_expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| nonblock_expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| nonblock_expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| nonblock_expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| nonblock_expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| nonblock_expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| nonblock_expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| nonblock_expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| nonblock_expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| nonblock_expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| nonblock_expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| nonblock_expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| nonblock_expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| nonblock_expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| nonblock_expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| nonblock_expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| nonblock_expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| nonblock_expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| nonblock_expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| nonblock_expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| nonblock_expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| nonblock_expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| nonblock_expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| nonblock_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| nonblock_expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| nonblock_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| nonblock_expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| nonblock_prefix_expr -; - -expr -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } -| expr '?' { $$ = mk_node("ExprTry", 1, $1); } -| expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } -| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr -; - -expr_nostruct -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| expr_nostruct '?' { $$ = mk_node("ExprTry", 1, $1); } -| expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| expr_nostruct '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| expr_nostruct '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| expr_nostruct '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); } -| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| expr_nostruct MINUSEQ expr_nostruct { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| expr_nostruct ANDEQ expr_nostruct { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| expr_nostruct OREQ expr_nostruct { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| expr_nostruct PLUSEQ expr_nostruct { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| expr_nostruct STAREQ expr_nostruct { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| expr_nostruct SLASHEQ expr_nostruct { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| expr_nostruct CARETEQ expr_nostruct { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| expr_nostruct PERCENTEQ expr_nostruct { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| expr_nostruct OROR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| expr_nostruct ANDAND expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| expr_nostruct EQEQ expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| expr_nostruct NE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| expr_nostruct '<' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| expr_nostruct '>' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| expr_nostruct LE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| expr_nostruct GE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| expr_nostruct '|' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| expr_nostruct '^' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| expr_nostruct '&' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| expr_nostruct SHL expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| expr_nostruct SHR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| expr_nostruct '+' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| expr_nostruct '-' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| expr_nostruct '*' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| expr_nostruct '/' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| expr_nostruct '%' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| expr_nostruct DOTDOT %prec RANGE { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| expr_nostruct DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| expr_nostruct AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| expr_nostruct ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr_nostruct -; - -nonblock_prefix_expr_nostruct -: '-' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } -| '!' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } -| '*' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } -| '&' maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 2, $2, $3); } -| ANDAND maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } -| lambda_expr_nostruct -| MOVE lambda_expr_nostruct { $$ = $2; } -; - -nonblock_prefix_expr -: '-' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } -| '!' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } -| '*' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } -| '&' maybe_mut expr { $$ = mk_node("ExprAddrOf", 2, $2, $3); } -| ANDAND maybe_mut expr { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } -| lambda_expr -| MOVE lambda_expr { $$ = $2; } -; - -expr_qualified_path -: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params -{ - $$ = mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11, $12); -} - -maybe_qpath_params -: MOD_SEP generic_args { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_as_trait_ref -: AS trait_ref { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -lambda_expr -: %prec LAMBDA - OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - '|' '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } -; - -lambda_expr_no_first_bar -: %prec LAMBDA - '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } -; - -lambda_expr_nostruct -: %prec LAMBDA - OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); } -| %prec LAMBDA - '|' '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } -; - -lambda_expr_nostruct_no_first_bar -: %prec LAMBDA - '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } -; - -vec_expr -: maybe_exprs -| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); } -; - -struct_expr_fields -: field_inits -| field_inits ',' -| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_field_inits -: field_inits -| field_inits ',' -| %empty { $$ = mk_none(); } -; - -field_inits -: field_init { $$ = mk_node("FieldInits", 1, $1); } -| field_inits ',' field_init { $$ = ext_node($1, 1, $3); } -; - -field_init -: ident { $$ = mk_node("FieldInit", 1, $1); } -| ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); } -| LIT_INTEGER ':' expr { $$ = mk_node("FieldInit", 2, mk_atom(yytext), $3); } -; - -default_field_init -: DOTDOT expr { $$ = mk_node("DefaultFieldInit", 1, $2); } -; - -block_expr -: expr_match -| expr_if -| expr_if_let -| expr_while -| expr_while_let -| expr_loop -| expr_for -| UNSAFE block { $$ = mk_node("UnsafeBlock", 1, $2); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); } -; - -full_block_expr -: block_expr -| block_expr_dot -; - -block_expr_dot -: block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } -| block_expr_dot '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } -| block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } -| block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } -| block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| block_expr_dot '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -; - -expr_match -: MATCH expr_nostruct '{' '}' { $$ = mk_node("ExprMatch", 1, $2); } -| MATCH expr_nostruct '{' match_clauses '}' { $$ = mk_node("ExprMatch", 2, $2, $4); } -| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); } -| MATCH expr_nostruct '{' nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); } -; - -match_clauses -: match_clause { $$ = mk_node("Arms", 1, $1); } -| match_clauses match_clause { $$ = ext_node($1, 1, $2); } -; - -match_clause -: nonblock_match_clause ',' -| block_match_clause -| block_match_clause ',' -; - -nonblock_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } -; - -block_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } -; - -maybe_guard -: IF expr_nostruct { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -expr_if -: IF expr_nostruct block { $$ = mk_node("ExprIf", 2, $2, $3); } -| IF expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIf", 3, $2, $3, $5); } -; - -expr_if_let -: IF LET pat '=' expr_nostruct block { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); } -| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); } -; - -block_or_if -: block -| expr_if -| expr_if_let -; - -expr_while -: maybe_label WHILE expr_nostruct block { $$ = mk_node("ExprWhile", 3, $1, $3, $4); } -; - -expr_while_let -: maybe_label WHILE LET pat '=' expr_nostruct block { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); } -; - -expr_loop -: maybe_label LOOP block { $$ = mk_node("ExprLoop", 2, $1, $3); } -; - -expr_for -: maybe_label FOR pat IN expr_nostruct block { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); } -; - -maybe_label -: lifetime ':' -| %empty { $$ = mk_none(); } -; - -let -: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 5: Macros and misc. rules -//////////////////////////////////////////////////////////////////////// - -lit -: LIT_BYTE { $$ = mk_node("LitByte", 1, mk_atom(yytext)); } -| LIT_CHAR { $$ = mk_node("LitChar", 1, mk_atom(yytext)); } -| LIT_INTEGER { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); } -| LIT_FLOAT { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); } -| TRUE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } -| FALSE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } -| str -; - -str -: LIT_STR { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); } -| LIT_STR_RAW { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); } -| LIT_BYTE_STR { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); } -| LIT_BYTE_STR_RAW { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); } -; - -maybe_ident -: %empty { $$ = mk_none(); } -| ident -; - -ident -: IDENT { $$ = mk_node("ident", 1, mk_atom(yytext)); } -// Weak keywords that can be used as identifiers -| CATCH { $$ = mk_node("ident", 1, mk_atom(yytext)); } -| DEFAULT { $$ = mk_node("ident", 1, mk_atom(yytext)); } -| UNION { $$ = mk_node("ident", 1, mk_atom(yytext)); } -; - -unpaired_token -: SHL { $$ = mk_atom(yytext); } -| SHR { $$ = mk_atom(yytext); } -| LE { $$ = mk_atom(yytext); } -| EQEQ { $$ = mk_atom(yytext); } -| NE { $$ = mk_atom(yytext); } -| GE { $$ = mk_atom(yytext); } -| ANDAND { $$ = mk_atom(yytext); } -| OROR { $$ = mk_atom(yytext); } -| LARROW { $$ = mk_atom(yytext); } -| SHLEQ { $$ = mk_atom(yytext); } -| SHREQ { $$ = mk_atom(yytext); } -| MINUSEQ { $$ = mk_atom(yytext); } -| ANDEQ { $$ = mk_atom(yytext); } -| OREQ { $$ = mk_atom(yytext); } -| PLUSEQ { $$ = mk_atom(yytext); } -| STAREQ { $$ = mk_atom(yytext); } -| SLASHEQ { $$ = mk_atom(yytext); } -| CARETEQ { $$ = mk_atom(yytext); } -| PERCENTEQ { $$ = mk_atom(yytext); } -| DOTDOT { $$ = mk_atom(yytext); } -| DOTDOTDOT { $$ = mk_atom(yytext); } -| MOD_SEP { $$ = mk_atom(yytext); } -| RARROW { $$ = mk_atom(yytext); } -| FAT_ARROW { $$ = mk_atom(yytext); } -| LIT_BYTE { $$ = mk_atom(yytext); } -| LIT_CHAR { $$ = mk_atom(yytext); } -| LIT_INTEGER { $$ = mk_atom(yytext); } -| LIT_FLOAT { $$ = mk_atom(yytext); } -| LIT_STR { $$ = mk_atom(yytext); } -| LIT_STR_RAW { $$ = mk_atom(yytext); } -| LIT_BYTE_STR { $$ = mk_atom(yytext); } -| LIT_BYTE_STR_RAW { $$ = mk_atom(yytext); } -| IDENT { $$ = mk_atom(yytext); } -| UNDERSCORE { $$ = mk_atom(yytext); } -| LIFETIME { $$ = mk_atom(yytext); } -| SELF { $$ = mk_atom(yytext); } -| STATIC { $$ = mk_atom(yytext); } -| ABSTRACT { $$ = mk_atom(yytext); } -| ALIGNOF { $$ = mk_atom(yytext); } -| AS { $$ = mk_atom(yytext); } -| BECOME { $$ = mk_atom(yytext); } -| BREAK { $$ = mk_atom(yytext); } -| CATCH { $$ = mk_atom(yytext); } -| CRATE { $$ = mk_atom(yytext); } -| DEFAULT { $$ = mk_atom(yytext); } -| DO { $$ = mk_atom(yytext); } -| ELSE { $$ = mk_atom(yytext); } -| ENUM { $$ = mk_atom(yytext); } -| EXTERN { $$ = mk_atom(yytext); } -| FALSE { $$ = mk_atom(yytext); } -| FINAL { $$ = mk_atom(yytext); } -| FN { $$ = mk_atom(yytext); } -| FOR { $$ = mk_atom(yytext); } -| IF { $$ = mk_atom(yytext); } -| IMPL { $$ = mk_atom(yytext); } -| IN { $$ = mk_atom(yytext); } -| LET { $$ = mk_atom(yytext); } -| LOOP { $$ = mk_atom(yytext); } -| MACRO { $$ = mk_atom(yytext); } -| MATCH { $$ = mk_atom(yytext); } -| MOD { $$ = mk_atom(yytext); } -| MOVE { $$ = mk_atom(yytext); } -| MUT { $$ = mk_atom(yytext); } -| OFFSETOF { $$ = mk_atom(yytext); } -| OVERRIDE { $$ = mk_atom(yytext); } -| PRIV { $$ = mk_atom(yytext); } -| PUB { $$ = mk_atom(yytext); } -| PURE { $$ = mk_atom(yytext); } -| REF { $$ = mk_atom(yytext); } -| RETURN { $$ = mk_atom(yytext); } -| STRUCT { $$ = mk_atom(yytext); } -| SIZEOF { $$ = mk_atom(yytext); } -| SUPER { $$ = mk_atom(yytext); } -| TRUE { $$ = mk_atom(yytext); } -| TRAIT { $$ = mk_atom(yytext); } -| TYPE { $$ = mk_atom(yytext); } -| UNION { $$ = mk_atom(yytext); } -| UNSAFE { $$ = mk_atom(yytext); } -| UNSIZED { $$ = mk_atom(yytext); } -| USE { $$ = mk_atom(yytext); } -| VIRTUAL { $$ = mk_atom(yytext); } -| WHILE { $$ = mk_atom(yytext); } -| YIELD { $$ = mk_atom(yytext); } -| CONTINUE { $$ = mk_atom(yytext); } -| PROC { $$ = mk_atom(yytext); } -| BOX { $$ = mk_atom(yytext); } -| CONST { $$ = mk_atom(yytext); } -| WHERE { $$ = mk_atom(yytext); } -| TYPEOF { $$ = mk_atom(yytext); } -| INNER_DOC_COMMENT { $$ = mk_atom(yytext); } -| OUTER_DOC_COMMENT { $$ = mk_atom(yytext); } -| SHEBANG { $$ = mk_atom(yytext); } -| STATIC_LIFETIME { $$ = mk_atom(yytext); } -| ';' { $$ = mk_atom(yytext); } -| ',' { $$ = mk_atom(yytext); } -| '.' { $$ = mk_atom(yytext); } -| '@' { $$ = mk_atom(yytext); } -| '#' { $$ = mk_atom(yytext); } -| '~' { $$ = mk_atom(yytext); } -| ':' { $$ = mk_atom(yytext); } -| '$' { $$ = mk_atom(yytext); } -| '=' { $$ = mk_atom(yytext); } -| '?' { $$ = mk_atom(yytext); } -| '!' { $$ = mk_atom(yytext); } -| '<' { $$ = mk_atom(yytext); } -| '>' { $$ = mk_atom(yytext); } -| '-' { $$ = mk_atom(yytext); } -| '&' { $$ = mk_atom(yytext); } -| '|' { $$ = mk_atom(yytext); } -| '+' { $$ = mk_atom(yytext); } -| '*' { $$ = mk_atom(yytext); } -| '/' { $$ = mk_atom(yytext); } -| '^' { $$ = mk_atom(yytext); } -| '%' { $$ = mk_atom(yytext); } -; - -token_trees -: %empty { $$ = mk_node("TokenTrees", 0); } -| token_trees token_tree { $$ = ext_node($1, 1, $2); } -; - -token_tree -: delimited_token_trees -| unpaired_token { $$ = mk_node("TTTok", 1, $1); } -; - -delimited_token_trees -: parens_delimited_token_trees -| braces_delimited_token_trees -| brackets_delimited_token_trees -; - -parens_delimited_token_trees -: '(' token_trees ')' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("(")), - $2, - mk_node("TTTok", 1, mk_atom(")"))); -} -; - -braces_delimited_token_trees -: '{' token_trees '}' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("{")), - $2, - mk_node("TTTok", 1, mk_atom("}"))); -} -; - -brackets_delimited_token_trees -: '[' token_trees ']' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("[")), - $2, - mk_node("TTTok", 1, mk_atom("]"))); -} -; diff --git a/gcc/rust/rustc_parser/grammar/raw-string-literal-ambiguity.md b/gcc/rust/rustc_parser/grammar/raw-string-literal-ambiguity.md deleted file mode 100644 index c909f23..0000000 --- a/gcc/rust/rustc_parser/grammar/raw-string-literal-ambiguity.md +++ /dev/null @@ -1,64 +0,0 @@ -Rust's lexical grammar is not context-free. Raw string literals are the source -of the problem. Informally, a raw string literal is an `r`, followed by `N` -hashes (where N can be zero), a quote, any characters, then a quote followed -by `N` hashes. Critically, once inside the first pair of quotes, -another quote cannot be followed by `N` consecutive hashes. e.g. -`r###""###"###` is invalid. - -This grammar describes this as best possible: - - R -> 'r' S - S -> '"' B '"' - S -> '#' S '#' - B -> . B - B -> ε - -Where `.` represents any character, and `ε` the empty string. Consider the -string `r#""#"#`. This string is not a valid raw string literal, but can be -accepted as one by the above grammar, using the derivation: - - R : #""#"# - S : ""#" - S : "# - B : # - B : ε - -(Where `T : U` means the rule `T` is applied, and `U` is the remainder of the -string.) The difficulty arises from the fact that it is fundamentally -context-sensitive. In particular, the context needed is the number of hashes. - -To prove that Rust's string literals are not context-free, we will use -the fact that context-free languages are closed under intersection with -regular languages, and the -[pumping lemma for context-free languages](https://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages). - -Consider the regular language `R = r#+""#*"#+`. If Rust's raw string literals are -context-free, then their intersection with `R`, `R'`, should also be context-free. -Therefore, to prove that raw string literals are not context-free, -it is sufficient to prove that `R'` is not context-free. - -The language `R'` is `{r#^n""#^m"#^n | m < n}`. - -Assume `R'` *is* context-free. Then `R'` has some pumping length `p > 0` for which -the pumping lemma applies. Consider the following string `s` in `R'`: - -`r#^p""#^{p-1}"#^p` - -e.g. for `p = 2`: `s = r##""#"##` - -Then `s = uvwxy` for some choice of `uvwxy` such that `vx` is non-empty, -`|vwx| < p+1`, and `uv^iwx^iy` is in `R'` for all `i >= 0`. - -Neither `v` nor `x` can contain a `"` or `r`, as the number of these characters -in any string in `R'` is fixed. So `v` and `x` contain only hashes. -Consequently, of the three sequences of hashes, `v` and `x` combined -can only pump two of them. -If we ever choose the central sequence of hashes, then one of the outer sequences -will not grow when we pump, leading to an imbalance between the outer sequences. -Therefore, we must pump both outer sequences of hashes. However, -there are `p+2` characters between these two sequences of hashes, and `|vwx|` must -be less than `p+1`. Therefore we have a contradiction, and `R'` must not be -context-free. - -Since `R'` is not context-free, it follows that the Rust's raw string literals -must not be context-free. diff --git a/gcc/rust/rustc_parser/grammar/testparser.py b/gcc/rust/rustc_parser/grammar/testparser.py deleted file mode 100755 index 4b5a7fb..0000000 --- a/gcc/rust/rustc_parser/grammar/testparser.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -# ignore-tidy-linelength - -import sys - -import os -import subprocess -import argparse - -# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR - -# Parsers should read from stdin and return exit status 0 for a -# successful parse, and nonzero for an unsuccessful parse - -parser = argparse.ArgumentParser() -parser.add_argument('-p', '--parser', nargs='+') -parser.add_argument('-s', '--source-dir', nargs=1, required=True) -args = parser.parse_args(sys.argv[1:]) - -total = 0 -ok = {} -bad = {} -for parser in args.parser: - ok[parser] = 0 - bad[parser] = [] -devnull = open(os.devnull, 'w') -print("\n") - -for base, dirs, files in os.walk(args.source_dir[0]): - for f in filter(lambda p: p.endswith('.rs'), files): - p = os.path.join(base, f) - parse_fail = 'parse-fail' in p - if sys.version_info.major == 3: - lines = open(p, encoding='utf-8').readlines() - else: - lines = open(p).readlines() - if any('ignore-test' in line or 'ignore-lexer-test' in line for line in lines): - continue - total += 1 - for parser in args.parser: - if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0: - if parse_fail: - bad[parser].append(p) - else: - ok[parser] += 1 - else: - if parse_fail: - ok[parser] += 1 - else: - bad[parser].append(p) - parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser]) - sys.stdout.write("\033[K\r total: {}, {}, scanned {}" - .format(total, os.path.relpath(parser_stats), os.path.relpath(p))) - -devnull.close() - -print("\n") - -for parser in args.parser: - filename = os.path.basename(parser) + '.bad' - print("writing {} files that did not yield the correct result with {} to {}".format(len(bad[parser]), parser, filename)) - with open(filename, "w") as f: - for p in bad[parser]: - f.write(p) - f.write("\n") diff --git a/gcc/rust/rustc_parser/grammar/tokens.h b/gcc/rust/rustc_parser/grammar/tokens.h deleted file mode 100644 index 297e3dc..0000000 --- a/gcc/rust/rustc_parser/grammar/tokens.h +++ /dev/null @@ -1,99 +0,0 @@ -enum Token { - SHL = 257, // Parser generators reserve 0-256 for char literals - SHR, - LE, - EQEQ, - NE, - GE, - ANDAND, - OROR, - SHLEQ, - SHREQ, - MINUSEQ, - ANDEQ, - OREQ, - PLUSEQ, - STAREQ, - SLASHEQ, - CARETEQ, - PERCENTEQ, - DOTDOT, - DOTDOTDOT, - MOD_SEP, - LARROW, - RARROW, - FAT_ARROW, - LIT_BYTE, - LIT_CHAR, - LIT_INTEGER, - LIT_FLOAT, - LIT_STR, - LIT_STR_RAW, - LIT_BYTE_STR, - LIT_BYTE_STR_RAW, - IDENT, - UNDERSCORE, - LIFETIME, - - // keywords - SELF, - STATIC, - ABSTRACT, - ALIGNOF, - AS, - BECOME, - BREAK, - CATCH, - CRATE, - DEFAULT, - DO, - ELSE, - ENUM, - EXTERN, - FALSE, - FINAL, - FN, - FOR, - IF, - IMPL, - IN, - LET, - LOOP, - MACRO, - MATCH, - MOD, - MOVE, - MUT, - OFFSETOF, - OVERRIDE, - PRIV, - PUB, - PURE, - REF, - RETURN, - SIZEOF, - STRUCT, - SUPER, - UNION, - TRUE, - TRAIT, - TYPE, - UNSAFE, - UNSIZED, - USE, - VIRTUAL, - WHILE, - YIELD, - CONTINUE, - PROC, - BOX, - CONST, - WHERE, - TYPEOF, - INNER_DOC_COMMENT, - OUTER_DOC_COMMENT, - - SHEBANG, - SHEBANG_LINE, - STATIC_LIFETIME -}; diff --git a/gcc/rust/rustc_parser/libsyntax/Cargo.toml b/gcc/rust/rustc_parser/libsyntax/Cargo.toml deleted file mode 100644 index c5daa65..0000000 --- a/gcc/rust/rustc_parser/libsyntax/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "syntax" -version = "0.0.0" -edition = "2018" - -[lib] -name = "syntax" -path = "lib.rs" -doctest = false - -[dependencies] -bitflags = "1.0" -serialize = { path = "../libserialize" } -log = "0.4" -scoped-tls = "1.0" -lazy_static = "1.0.0" -syntax_pos = { path = "../libsyntax_pos" } -errors = { path = "../librustc_errors", package = "rustc_errors" } -rustc_data_structures = { path = "../librustc_data_structures" } -rustc_macros = { path = "../librustc_macros" } -rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/gcc/rust/rustc_parser/libsyntax/README.md b/gcc/rust/rustc_parser/libsyntax/README.md deleted file mode 100644 index daa252e..0000000 --- a/gcc/rust/rustc_parser/libsyntax/README.md +++ /dev/null @@ -1,9 +0,0 @@ -The `syntax` crate contains those things concerned purely with syntax -– that is, the AST ("abstract syntax tree"), parser, pretty-printer, -lexer, macro expander, and utilities for traversing ASTs. - -For more information about how these things work in rustc, see the -rustc guide: - -- [Parsing](https://rust-lang.github.io/rustc-guide/the-parser.html) -- [Macro Expansion](https://rust-lang.github.io/rustc-guide/macro-expansion.html) diff --git a/gcc/rust/rustc_parser/libsyntax/ast.rs b/gcc/rust/rustc_parser/libsyntax/ast.rs deleted file mode 100644 index c627596..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ast.rs +++ /dev/null @@ -1,2409 +0,0 @@ -// The Rust abstract syntax tree. - -pub use GenericArgs::*; -pub use UnsafeSource::*; -pub use crate::symbol::{Ident, Symbol as Name}; -pub use crate::util::parser::ExprPrecedence; - -use crate::ext::hygiene::{Mark, SyntaxContext}; -use crate::parse::token; -use crate::print::pprust; -use crate::ptr::P; -use crate::source_map::{dummy_spanned, respan, Spanned}; -use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::TokenStream; -use crate::ThinVec; - -use rustc_data_structures::indexed_vec::Idx; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; -use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP}; - -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; -use serialize::{self, Decoder, Encoder}; -use std::fmt; - -pub use rustc_target::abi::FloatTy; - -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] -pub struct Label { - pub ident: Ident, -} - -impl fmt::Debug for Label { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "label({:?})", self.ident) - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] -pub struct Lifetime { - pub id: NodeId, - pub ident: Ident, -} - -impl fmt::Debug for Lifetime { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "lifetime({}: {})", - self.id, - pprust::lifetime_to_string(self) - ) - } -} - -/// A "Path" is essentially Rust's notion of a name. -/// -/// It's represented as a sequence of identifiers, -/// along with a bunch of supporting information. -/// -/// E.g., `std::cmp::PartialEq`. -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct Path { - pub span: Span, - /// The segments in the path: the things separated by `::`. - /// Global paths begin with `kw::PathRoot`. - pub segments: Vec, -} - -impl PartialEq for Path { - fn eq(&self, symbol: &Symbol) -> bool { - self.segments.len() == 1 && { - self.segments[0].ident.name == *symbol - } - } -} - -impl fmt::Debug for Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "path({})", pprust::path_to_string(self)) - } -} - -impl fmt::Display for Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", pprust::path_to_string(self)) - } -} - -impl Path { - // Convert a span and an identifier to the corresponding - // one-segment path. - pub fn from_ident(ident: Ident) -> Path { - Path { - segments: vec![PathSegment::from_ident(ident)], - span: ident.span, - } - } - - pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot - } -} - -/// A segment of a path: an identifier, an optional lifetime, and a set of types. -/// -/// E.g., `std`, `String` or `Box`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct PathSegment { - /// The identifier portion of this path segment. - pub ident: Ident, - - pub id: NodeId, - - /// Type/lifetime parameters attached to this path. They come in - /// two flavors: `Path` and `Path(A,B) -> C`. - /// `None` means that no parameter list is supplied (`Path`), - /// `Some` means that parameter list is supplied (`Path`) - /// but it can be empty (`Path<>`). - /// `P` is used as a size optimization for the common case with no parameters. - pub args: Option>, -} - -impl PathSegment { - pub fn from_ident(ident: Ident) -> Self { - PathSegment { ident, id: DUMMY_NODE_ID, args: None } - } - pub fn path_root(span: Span) -> Self { - PathSegment::from_ident(Ident::new(kw::PathRoot, span)) - } -} - -/// The arguments of a path segment. -/// -/// E.g., `` as in `Foo` or `(A, B)` as in `Foo(A, B)`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum GenericArgs { - /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`. - AngleBracketed(AngleBracketedArgs), - /// The `(A, B)` and `C` in `Foo(A, B) -> C`. - Parenthesized(ParenthesizedArgs), -} - -impl GenericArgs { - pub fn is_parenthesized(&self) -> bool { - match *self { - Parenthesized(..) => true, - _ => false, - } - } - - pub fn is_angle_bracketed(&self) -> bool { - match *self { - AngleBracketed(..) => true, - _ => false, - } - } - - pub fn span(&self) -> Span { - match *self { - AngleBracketed(ref data) => data.span, - Parenthesized(ref data) => data.span, - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum GenericArg { - Lifetime(Lifetime), - Type(P), - Const(AnonConst), -} - -impl GenericArg { - pub fn span(&self) -> Span { - match self { - GenericArg::Lifetime(lt) => lt.ident.span, - GenericArg::Type(ty) => ty.span, - GenericArg::Const(ct) => ct.value.span, - } - } -} - -/// A path like `Foo<'a, T>`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] -pub struct AngleBracketedArgs { - /// The overall span. - pub span: Span, - /// The arguments for this path segment. - pub args: Vec, - /// Constraints on associated types, if any. - /// E.g., `Foo`. - pub constraints: Vec, -} - -impl Into>> for AngleBracketedArgs { - fn into(self) -> Option> { - Some(P(GenericArgs::AngleBracketed(self))) - } -} - -impl Into>> for ParenthesizedArgs { - fn into(self) -> Option> { - Some(P(GenericArgs::Parenthesized(self))) - } -} - -/// A path like `Foo(A, B) -> C`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ParenthesizedArgs { - /// Overall span - pub span: Span, - - /// `(A, B)` - pub inputs: Vec>, - - /// `C` - pub output: Option>, -} - -impl ParenthesizedArgs { - pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs { - AngleBracketedArgs { - span: self.span, - args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(), - constraints: vec![], - } - } -} - -// hack to ensure that we don't try to access the private parts of `NodeId` in this module -mod node_id_inner { - use rustc_data_structures::indexed_vec::Idx; - use rustc_data_structures::newtype_index; - newtype_index! { - pub struct NodeId { - ENCODABLE = custom - DEBUG_FORMAT = "NodeId({})" - } - } -} - -pub use node_id_inner::NodeId; - -impl NodeId { - pub fn placeholder_from_mark(mark: Mark) -> Self { - NodeId::from_u32(mark.as_u32()) - } - - pub fn placeholder_to_mark(self) -> Mark { - Mark::from_u32(self.as_u32()) - } -} - -impl fmt::Display for NodeId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_u32(), f) - } -} - -impl serialize::UseSpecializedEncodable for NodeId { - fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_u32(self.as_u32()) - } -} - -impl serialize::UseSpecializedDecodable for NodeId { - fn default_decode(d: &mut D) -> Result { - d.read_u32().map(NodeId::from_u32) - } -} - -/// `NodeId` used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); - -/// When parsing and doing expansions, we initially give all AST nodes this AST -/// node value. Then later, in the renumber pass, we renumber them to have -/// small, positive ids. -pub const DUMMY_NODE_ID: NodeId = NodeId::MAX; - -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] -pub enum TraitBoundModifier { - None, - Maybe, -} - -/// The AST represents all type param bounds as types. -/// `typeck::collect::compute_bounds` matches these against -/// the "special" built-in traits (see `middle::lang_items`) and -/// detects `Copy`, `Send` and `Sync`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum GenericBound { - Trait(PolyTraitRef, TraitBoundModifier), - Outlives(Lifetime), -} - -impl GenericBound { - pub fn span(&self) -> Span { - match self { - &GenericBound::Trait(ref t, ..) => t.span, - &GenericBound::Outlives(ref l) => l.ident.span, - } - } -} - -pub type GenericBounds = Vec; - -/// Specifies the enforced ordering for generic parameters. In the future, -/// if we wanted to relax this order, we could override `PartialEq` and -/// `PartialOrd`, to allow the kinds to be unordered. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] -pub enum ParamKindOrd { - Lifetime, - Type, - Const, -} - -impl fmt::Display for ParamKindOrd { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ParamKindOrd::Lifetime => "lifetime".fmt(f), - ParamKindOrd::Type => "type".fmt(f), - ParamKindOrd::Const => "const".fmt(f), - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum GenericParamKind { - /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). - Lifetime, - Type { default: Option> }, - Const { ty: P }, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct GenericParam { - pub id: NodeId, - pub ident: Ident, - pub attrs: ThinVec, - pub bounds: GenericBounds, - - pub kind: GenericParamKind, -} - -/// Represents lifetime, type and const parameters attached to a declaration of -/// a function, enum, trait, etc. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Generics { - pub params: Vec, - pub where_clause: WhereClause, - pub span: Span, -} - -impl Default for Generics { - /// Creates an instance of `Generics`. - fn default() -> Generics { - Generics { - params: Vec::new(), - where_clause: WhereClause { - predicates: Vec::new(), - span: DUMMY_SP, - }, - span: DUMMY_SP, - } - } -} - -/// A where-clause in a definition. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct WhereClause { - pub predicates: Vec, - pub span: Span, -} - -/// A single predicate in a where-clause. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum WherePredicate { - /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). - BoundPredicate(WhereBoundPredicate), - /// A lifetime predicate (e.g., `'a: 'b + 'c`). - RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported). - EqPredicate(WhereEqPredicate), -} - -impl WherePredicate { - pub fn span(&self) -> Span { - match self { - &WherePredicate::BoundPredicate(ref p) => p.span, - &WherePredicate::RegionPredicate(ref p) => p.span, - &WherePredicate::EqPredicate(ref p) => p.span, - } - } -} - -/// A type bound. -/// -/// E.g., `for<'c> Foo: Send + Clone + 'c`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct WhereBoundPredicate { - pub span: Span, - /// Any generics from a `for` binding - pub bound_generic_params: Vec, - /// The type being bounded - pub bounded_ty: P, - /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: GenericBounds, -} - -/// A lifetime predicate. -/// -/// E.g., `'a: 'b + 'c`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct WhereRegionPredicate { - pub span: Span, - pub lifetime: Lifetime, - pub bounds: GenericBounds, -} - -/// An equality predicate (unsupported). -/// -/// E.g., `T = int`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct WhereEqPredicate { - pub id: NodeId, - pub span: Span, - pub lhs_ty: P, - pub rhs_ty: P, -} - -/// The set of `MetaItem`s that define the compilation environment of the crate, -/// used to drive conditional compilation. -pub type CrateConfig = FxHashSet<(Name, Option)>; - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Crate { - pub module: Mod, - pub attrs: Vec, - pub span: Span, -} - -/// Possible values inside of compile-time attribute lists. -/// -/// E.g., the '..' in `#[name(..)]`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum NestedMetaItem { - /// A full MetaItem, for recursive meta items. - MetaItem(MetaItem), - /// A literal. - /// - /// E.g., `"foo"`, `64`, `true`. - Literal(Lit), -} - -/// A spanned compile-time attribute item. -/// -/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct MetaItem { - pub path: Path, - pub node: MetaItemKind, - pub span: Span, -} - -/// A compile-time attribute item. -/// -/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum MetaItemKind { - /// Word meta item. - /// - /// E.g., `test` as in `#[test]`. - Word, - /// List meta item. - /// - /// E.g., `derive(..)` as in `#[derive(..)]`. - List(Vec), - /// Name value meta item. - /// - /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. - NameValue(Lit), -} - -/// A Block (`{ .. }`). -/// -/// E.g., `{ .. }` as in `fn foo() { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Block { - /// Statements in a block - pub stmts: Vec, - pub id: NodeId, - /// Distinguishes between `unsafe { ... }` and `{ ... }` - pub rules: BlockCheckMode, - pub span: Span, -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct Pat { - pub id: NodeId, - pub node: PatKind, - pub span: Span, -} - -impl fmt::Debug for Pat { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self)) - } -} - -impl Pat { - pub(super) fn to_ty(&self) -> Option> { - let node = match &self.node { - PatKind::Wild => TyKind::Infer, - PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => { - TyKind::Path(None, Path::from_ident(*ident)) - } - PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), - PatKind::Mac(mac) => TyKind::Mac(mac.clone()), - PatKind::Ref(pat, mutbl) => pat - .to_ty() - .map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?, - PatKind::Slice(pats, None, _) if pats.len() == 1 => { - pats[0].to_ty().map(TyKind::Slice)? - } - PatKind::Tuple(pats, None) => { - let mut tys = Vec::with_capacity(pats.len()); - // FIXME(#48994) - could just be collected into an Option - for pat in pats { - tys.push(pat.to_ty()?); - } - TyKind::Tup(tys) - } - _ => return None, - }; - - Some(P(Ty { - node, - id: self.id, - span: self.span, - })) - } - - pub fn walk(&self, it: &mut F) -> bool - where - F: FnMut(&Pat) -> bool, - { - if !it(self) { - return false; - } - - match self.node { - PatKind::Ident(_, _, Some(ref p)) => p.walk(it), - PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)), - PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { - s.iter().all(|p| p.walk(it)) - } - PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it), - PatKind::Slice(ref before, ref slice, ref after) => { - before.iter().all(|p| p.walk(it)) - && slice.iter().all(|p| p.walk(it)) - && after.iter().all(|p| p.walk(it)) - } - PatKind::Wild - | PatKind::Lit(_) - | PatKind::Range(..) - | PatKind::Ident(..) - | PatKind::Path(..) - | PatKind::Mac(_) => true, - } - } -} - -/// A single field in a struct pattern -/// -/// Patterns like the fields of Foo `{ x, ref y, ref mut z }` -/// are treated the same as` x: x, y: ref y, z: ref mut z`, -/// except is_shorthand is true -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct FieldPat { - /// The identifier for the field - pub ident: Ident, - /// The pattern the field is destructured to - pub pat: P, - pub is_shorthand: bool, - pub attrs: ThinVec, -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum BindingMode { - ByRef(Mutability), - ByValue(Mutability), -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum RangeEnd { - Included(RangeSyntax), - Excluded, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum RangeSyntax { - DotDotDot, - DotDotEq, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum PatKind { - /// Represents a wildcard pattern (`_`). - Wild, - - /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), - /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third - /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens - /// during name resolution. - Ident(BindingMode, Ident, Option>), - - /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). - /// The `bool` is `true` in the presence of a `..`. - Struct(Path, Vec>, /* recovered */ bool), - - /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). - /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// `0 <= position <= subpats.len()`. - TupleStruct(Path, Vec>, Option), - - /// A possibly qualified path pattern. - /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants - /// or associated constants. Qualified path patterns `::B::C`/`::B::C` can - /// only legally refer to associated constants. - Path(Option, Path), - - /// A tuple pattern (`(a, b)`). - /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// `0 <= position <= subpats.len()`. - Tuple(Vec>, Option), - - /// A `box` pattern. - Box(P), - - /// A reference pattern (e.g., `&mut (a, b)`). - Ref(P, Mutability), - - /// A literal. - Lit(P), - - /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). - Range(P, P, Spanned), - - /// `[a, b, ..i, y, z]` is represented as: - /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` - Slice(Vec>, Option>, Vec>), - - /// Parentheses in patterns used for grouping (i.e., `(PAT)`). - Paren(P), - - /// A macro pattern; pre-expansion. - Mac(Mac), -} - -#[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy, -)] -pub enum Mutability { - Mutable, - Immutable, -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum BinOpKind { - /// The `+` operator (addition) - Add, - /// The `-` operator (subtraction) - Sub, - /// The `*` operator (multiplication) - Mul, - /// The `/` operator (division) - Div, - /// The `%` operator (modulus) - Rem, - /// The `&&` operator (logical and) - And, - /// The `||` operator (logical or) - Or, - /// The `^` operator (bitwise xor) - BitXor, - /// The `&` operator (bitwise and) - BitAnd, - /// The `|` operator (bitwise or) - BitOr, - /// The `<<` operator (shift left) - Shl, - /// The `>>` operator (shift right) - Shr, - /// The `==` operator (equality) - Eq, - /// The `<` operator (less than) - Lt, - /// The `<=` operator (less than or equal to) - Le, - /// The `!=` operator (not equal to) - Ne, - /// The `>=` operator (greater than or equal to) - Ge, - /// The `>` operator (greater than) - Gt, -} - -impl BinOpKind { - pub fn to_string(&self) -> &'static str { - use BinOpKind::*; - match *self { - Add => "+", - Sub => "-", - Mul => "*", - Div => "/", - Rem => "%", - And => "&&", - Or => "||", - BitXor => "^", - BitAnd => "&", - BitOr => "|", - Shl => "<<", - Shr => ">>", - Eq => "==", - Lt => "<", - Le => "<=", - Ne => "!=", - Ge => ">=", - Gt => ">", - } - } - pub fn lazy(&self) -> bool { - match *self { - BinOpKind::And | BinOpKind::Or => true, - _ => false, - } - } - - pub fn is_shift(&self) -> bool { - match *self { - BinOpKind::Shl | BinOpKind::Shr => true, - _ => false, - } - } - - pub fn is_comparison(&self) -> bool { - use BinOpKind::*; - match *self { - Eq | Lt | Le | Ne | Gt | Ge => true, - And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false, - } - } - - /// Returns `true` if the binary operator takes its arguments by value - pub fn is_by_value(&self) -> bool { - !self.is_comparison() - } -} - -pub type BinOp = Spanned; - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum UnOp { - /// The `*` operator for dereferencing - Deref, - /// The `!` operator for logical inversion - Not, - /// The `-` operator for negation - Neg, -} - -impl UnOp { - /// Returns `true` if the unary operator takes its argument by value - pub fn is_by_value(u: UnOp) -> bool { - match u { - UnOp::Neg | UnOp::Not => true, - _ => false, - } - } - - pub fn to_string(op: UnOp) -> &'static str { - match op { - UnOp::Deref => "*", - UnOp::Not => "!", - UnOp::Neg => "-", - } - } -} - -/// A statement -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct Stmt { - pub id: NodeId, - pub node: StmtKind, - pub span: Span, -} - -impl Stmt { - pub fn add_trailing_semicolon(mut self) -> Self { - self.node = match self.node { - StmtKind::Expr(expr) => StmtKind::Semi(expr), - StmtKind::Mac(mac) => { - StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs))) - } - node => node, - }; - self - } - - pub fn is_item(&self) -> bool { - match self.node { - StmtKind::Item(_) => true, - _ => false, - } - } - - pub fn is_expr(&self) -> bool { - match self.node { - StmtKind::Expr(_) => true, - _ => false, - } - } -} - -impl fmt::Debug for Stmt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "stmt({}: {})", - self.id.to_string(), - pprust::stmt_to_string(self) - ) - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub enum StmtKind { - /// A local (let) binding. - Local(P), - - /// An item definition. - Item(P), - - /// Expr without trailing semi-colon. - Expr(P), - /// Expr with a trailing semi-colon. - Semi(P), - /// Macro. - Mac(P<(Mac, MacStmtStyle, ThinVec)>), -} - -#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum MacStmtStyle { - /// The macro statement had a trailing semicolon (e.g., `foo! { ... };` - /// `foo!(...);`, `foo![...];`). - Semicolon, - /// The macro statement had braces (e.g., `foo! { ... }`). - Braces, - /// The macro statement had parentheses or brackets and no semicolon (e.g., - /// `foo!(...)`). All of these will end up being converted into macro - /// expressions. - NoBraces, -} - -/// Local represents a `let` statement, e.g., `let : = ;`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Local { - pub pat: P, - pub ty: Option>, - /// Initializer expression to set the value, if any. - pub init: Option>, - pub id: NodeId, - pub span: Span, - pub attrs: ThinVec, -} - -/// An arm of a 'match'. -/// -/// E.g., `0..=10 => { println!("match!") }` as in -/// -/// ``` -/// match 123 { -/// 0..=10 => { println!("match!") }, -/// _ => { println!("no match!") }, -/// } -/// ``` -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Arm { - pub attrs: Vec, - pub pats: Vec>, - pub guard: Option>, - pub body: P, - pub span: Span, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Field { - pub ident: Ident, - pub expr: P, - pub span: Span, - pub is_shorthand: bool, - pub attrs: ThinVec, -} - -pub type SpannedIdent = Spanned; - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum BlockCheckMode { - Default, - Unsafe(UnsafeSource), -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum UnsafeSource { - CompilerGenerated, - UserProvided, -} - -/// A constant (expression) that's not an item or associated item, -/// but needs its own `DefId` for type-checking, const-eval, etc. -/// These are usually found nested inside types (e.g., array lengths) -/// or expressions (e.g., repeat counts), and also used to define -/// explicit discriminant values for enum variants. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AnonConst { - pub id: NodeId, - pub value: P, -} - -/// An expression -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct Expr { - pub id: NodeId, - pub node: ExprKind, - pub span: Span, - pub attrs: ThinVec, -} - -// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] -static_assert_size!(Expr, 96); - -impl Expr { - /// Whether this expression would be valid somewhere that expects a value; for example, an `if` - /// condition. - pub fn returns(&self) -> bool { - if let ExprKind::Block(ref block, _) = self.node { - match block.stmts.last().map(|last_stmt| &last_stmt.node) { - // implicit return - Some(&StmtKind::Expr(_)) => true, - Some(&StmtKind::Semi(ref expr)) => { - if let ExprKind::Ret(_) = expr.node { - // last statement is explicit return - true - } else { - false - } - } - // This is a block that doesn't end in either an implicit or explicit return - _ => false, - } - } else { - // This is not a block, it is a value - true - } - } - - fn to_bound(&self) -> Option { - match &self.node { - ExprKind::Path(None, path) => Some(GenericBound::Trait( - PolyTraitRef::new(Vec::new(), path.clone(), self.span), - TraitBoundModifier::None, - )), - _ => None, - } - } - - pub(super) fn to_ty(&self) -> Option> { - let node = match &self.node { - ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), - ExprKind::Mac(mac) => TyKind::Mac(mac.clone()), - ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, - ExprKind::AddrOf(mutbl, expr) => expr - .to_ty() - .map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?, - ExprKind::Repeat(expr, expr_len) => { - expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))? - } - ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?, - ExprKind::Tup(exprs) => { - let tys = exprs - .iter() - .map(|expr| expr.to_ty()) - .collect::>>()?; - TyKind::Tup(tys) - } - ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => { - if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) { - TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None) - } else { - return None; - } - } - _ => return None, - }; - - Some(P(Ty { - node, - id: self.id, - span: self.span, - })) - } - - pub fn precedence(&self) -> ExprPrecedence { - match self.node { - ExprKind::Box(_) => ExprPrecedence::Box, - ExprKind::Array(_) => ExprPrecedence::Array, - ExprKind::Call(..) => ExprPrecedence::Call, - ExprKind::MethodCall(..) => ExprPrecedence::MethodCall, - ExprKind::Tup(_) => ExprPrecedence::Tup, - ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node), - ExprKind::Unary(..) => ExprPrecedence::Unary, - ExprKind::Lit(_) => ExprPrecedence::Lit, - ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, - ExprKind::Let(..) => ExprPrecedence::Let, - ExprKind::If(..) => ExprPrecedence::If, - ExprKind::While(..) => ExprPrecedence::While, - ExprKind::ForLoop(..) => ExprPrecedence::ForLoop, - ExprKind::Loop(..) => ExprPrecedence::Loop, - ExprKind::Match(..) => ExprPrecedence::Match, - ExprKind::Closure(..) => ExprPrecedence::Closure, - ExprKind::Block(..) => ExprPrecedence::Block, - ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, - ExprKind::Async(..) => ExprPrecedence::Async, - ExprKind::Await(..) => ExprPrecedence::Await, - ExprKind::Assign(..) => ExprPrecedence::Assign, - ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, - ExprKind::Field(..) => ExprPrecedence::Field, - ExprKind::Index(..) => ExprPrecedence::Index, - ExprKind::Range(..) => ExprPrecedence::Range, - ExprKind::Path(..) => ExprPrecedence::Path, - ExprKind::AddrOf(..) => ExprPrecedence::AddrOf, - ExprKind::Break(..) => ExprPrecedence::Break, - ExprKind::Continue(..) => ExprPrecedence::Continue, - ExprKind::Ret(..) => ExprPrecedence::Ret, - ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, - ExprKind::Mac(..) => ExprPrecedence::Mac, - ExprKind::Struct(..) => ExprPrecedence::Struct, - ExprKind::Repeat(..) => ExprPrecedence::Repeat, - ExprKind::Paren(..) => ExprPrecedence::Paren, - ExprKind::Try(..) => ExprPrecedence::Try, - ExprKind::Yield(..) => ExprPrecedence::Yield, - ExprKind::Err => ExprPrecedence::Err, - } - } -} - -impl fmt::Debug for Expr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self)) - } -} - -/// Limit types of a range (inclusive or exclusive) -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum RangeLimits { - /// Inclusive at the beginning, exclusive at the end - HalfOpen, - /// Inclusive at the beginning and end - Closed, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ExprKind { - /// A `box x` expression. - Box(P), - /// An array (`[a, b, c, d]`) - Array(Vec>), - /// A function call - /// - /// The first field resolves to the function itself, - /// and the second field is the list of arguments. - /// This also represents calling the constructor of - /// tuple-like ADTs such as tuple structs and enum variants. - Call(P, Vec>), - /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) - /// - /// The `PathSegment` represents the method name and its generic arguments - /// (within the angle brackets). - /// The first element of the vector of an `Expr` is the expression that evaluates - /// to the object on which the method is being called on (the receiver), - /// and the remaining elements are the rest of the arguments. - /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. - MethodCall(PathSegment, Vec>), - /// A tuple (e.g., `(a, b, c, d)`). - Tup(Vec>), - /// A binary operation (e.g., `a + b`, `a * b`). - Binary(BinOp, P, P), - /// A unary operation (e.g., `!x`, `*x`). - Unary(UnOp, P), - /// A literal (e.g., `1`, `"foo"`). - Lit(Lit), - /// A cast (e.g., `foo as f64`). - Cast(P, P), - /// A type ascription (e.g., `42: usize`). - Type(P, P), - /// A `let pats = expr` expression that is only semantically allowed in the condition - /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`). - /// - /// The `Vec>` is for or-patterns at the top level. - /// FIXME(54883): Change this to just `P`. - Let(Vec>, P), - /// An `if` block, with an optional `else` block. - /// - /// `if expr { block } else { expr }` - If(P, P, Option>), - /// A while loop, with an optional label. - /// - /// `'label: while expr { block }` - While(P, P, Option` or -/// `A: TraitA + TraitB` in `Foo`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AssocTyConstraint { - pub id: NodeId, - pub ident: Ident, - pub kind: AssocTyConstraintKind, - pub span: Span, -} - -/// The kinds of an `AssocTyConstraint`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum AssocTyConstraintKind { - /// E.g., `A = Bar` in `Foo`. - Equality { - ty: P, - }, - /// E.g. `A: TraitA + TraitB` in `Foo`. - Bound { - bounds: GenericBounds, - }, -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct Ty { - pub id: NodeId, - pub node: TyKind, - pub span: Span, -} - -impl fmt::Debug for Ty { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "type({})", pprust::ty_to_string(self)) - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct BareFnTy { - pub unsafety: Unsafety, - pub abi: Abi, - pub generic_params: Vec, - pub decl: P, -} - -/// The various kinds of type recognized by the compiler. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum TyKind { - /// A variable-length slice (`[T]`). - Slice(P), - /// A fixed length array (`[T; n]`). - Array(P, AnonConst), - /// A raw pointer (`*const T` or `*mut T`). - Ptr(MutTy), - /// A reference (`&'a T` or `&'a mut T`). - Rptr(Option, MutTy), - /// A bare function (e.g., `fn(usize) -> bool`). - BareFn(P), - /// The never type (`!`). - Never, - /// A tuple (`(A, B, C, D,...)`). - Tup(Vec>), - /// A path (`module::module::...::Type`), optionally - /// "qualified", e.g., ` as SomeTrait>::SomeType`. - /// - /// Type parameters are stored in the `Path` itself. - Path(Option, Path), - /// A trait object type `Bound1 + Bound2 + Bound3` - /// where `Bound` is a trait or a lifetime. - TraitObject(GenericBounds, TraitObjectSyntax), - /// An `impl Bound1 + Bound2 + Bound3` type - /// where `Bound` is a trait or a lifetime. - /// - /// The `NodeId` exists to prevent lowering from having to - /// generate `NodeId`s on the fly, which would complicate - /// the generation of `existential type` items significantly. - ImplTrait(NodeId, GenericBounds), - /// No-op; kept solely so that we can pretty-print faithfully. - Paren(P), - /// Unused for now. - Typeof(AnonConst), - /// This means the type should be inferred instead of it having been - /// specified. This can appear anywhere in a type. - Infer, - /// Inferred type of a `self` or `&self` argument in a method. - ImplicitSelf, - /// A macro in the type position. - Mac(Mac), - /// Placeholder for a kind that has failed to be defined. - Err, - /// Placeholder for a `va_list`. - CVarArgs, -} - -impl TyKind { - pub fn is_implicit_self(&self) -> bool { - if let TyKind::ImplicitSelf = *self { - true - } else { - false - } - } - - pub fn is_unit(&self) -> bool { - if let TyKind::Tup(ref tys) = *self { - tys.is_empty() - } else { - false - } - } -} - -/// Syntax used to declare a trait object. -#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum TraitObjectSyntax { - Dyn, - None, -} - -/// Inline assembly dialect. -/// -/// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum AsmDialect { - Att, - Intel, -} - -/// Inline assembly. -/// -/// E.g., `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct InlineAsmOutput { - pub constraint: Symbol, - pub expr: P, - pub is_rw: bool, - pub is_indirect: bool, -} - -/// Inline assembly. -/// -/// E.g., `asm!("NOP");`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct InlineAsm { - pub asm: Symbol, - pub asm_str_style: StrStyle, - pub outputs: Vec, - pub inputs: Vec<(Symbol, P)>, - pub clobbers: Vec, - pub volatile: bool, - pub alignstack: bool, - pub dialect: AsmDialect, - pub ctxt: SyntaxContext, -} - -/// An argument in a function header. -/// -/// E.g., `bar: usize` as in `fn foo(bar: usize)`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Arg { - pub attrs: ThinVec, - pub ty: P, - pub pat: P, - pub id: NodeId, -} - -/// Alternative representation for `Arg`s describing `self` parameter of methods. -/// -/// E.g., `&mut self` as in `fn foo(&mut self)`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum SelfKind { - /// `self`, `mut self` - Value(Mutability), - /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability), - /// `self: TYPE`, `mut self: TYPE` - Explicit(P, Mutability), -} - -pub type ExplicitSelf = Spanned; - -impl Arg { - pub fn to_self(&self) -> Option { - if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { - if ident.name == kw::SelfLower { - return match self.ty.node { - TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.node.is_implicit_self() => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) - } - _ => Some(respan( - self.pat.span.to(self.ty.span), - SelfKind::Explicit(self.ty.clone(), mutbl), - )), - }; - } - } - None - } - - pub fn is_self(&self) -> bool { - if let PatKind::Ident(_, ident, _) = self.pat.node { - ident.name == kw::SelfLower - } else { - false - } - } - - pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Arg { - let span = eself.span.to(eself_ident.span); - let infer_ty = P(Ty { - id: DUMMY_NODE_ID, - node: TyKind::ImplicitSelf, - span, - }); - let arg = |mutbl, ty| Arg { - attrs, - pat: P(Pat { - id: DUMMY_NODE_ID, - node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), - span, - }), - ty, - id: DUMMY_NODE_ID, - }; - match eself.node { - SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), - SelfKind::Value(mutbl) => arg(mutbl, infer_ty), - SelfKind::Region(lt, mutbl) => arg( - Mutability::Immutable, - P(Ty { - id: DUMMY_NODE_ID, - node: TyKind::Rptr( - lt, - MutTy { - ty: infer_ty, - mutbl, - }, - ), - span, - }), - ), - } - } -} - -/// A header (not the body) of a function declaration. -/// -/// E.g., `fn foo(bar: baz)`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct FnDecl { - pub inputs: Vec, - pub output: FunctionRetTy, - pub c_variadic: bool, -} - -impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) - } - pub fn has_self(&self) -> bool { - self.inputs.get(0).map(Arg::is_self).unwrap_or(false) - } -} - -/// Is the trait definition an auto trait? -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum IsAuto { - Yes, - No, -} - -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum Unsafety { - Unsafe, - Normal, -} - -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum IsAsync { - Async { - closure_id: NodeId, - return_impl_trait_id: NodeId, - }, - NotAsync, -} - -impl IsAsync { - pub fn is_async(self) -> bool { - if let IsAsync::Async { .. } = self { - true - } else { - false - } - } - - /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(self) -> Option { - match self { - IsAsync::Async { - return_impl_trait_id, - .. - } => Some(return_impl_trait_id), - IsAsync::NotAsync => None, - } - } -} - -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum Constness { - Const, - NotConst, -} - -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub enum Defaultness { - Default, - Final, -} - -impl fmt::Display for Unsafety { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt( - match *self { - Unsafety::Normal => "normal", - Unsafety::Unsafe => "unsafe", - }, - f, - ) - } -} - -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] -pub enum ImplPolarity { - /// `impl Trait for Type` - Positive, - /// `impl !Trait for Type` - Negative, -} - -impl fmt::Debug for ImplPolarity { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ImplPolarity::Positive => "positive".fmt(f), - ImplPolarity::Negative => "negative".fmt(f), - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum FunctionRetTy { - /// Returns type is not specified. - /// - /// Functions default to `()` and closures default to inference. - /// Span points to where return type would be inserted. - Default(Span), - /// Everything else. - Ty(P), -} - -impl FunctionRetTy { - pub fn span(&self) -> Span { - match *self { - FunctionRetTy::Default(span) => span, - FunctionRetTy::Ty(ref ty) => ty.span, - } - } -} - -/// Module declaration. -/// -/// E.g., `mod foo;` or `mod foo { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Mod { - /// A span from the first token past `{` to the last token until `}`. - /// For `mod foo;`, the inner span ranges from the first token - /// to the last token in the external file. - pub inner: Span, - pub items: Vec>, - /// `true` for `mod foo { .. }`; `false` for `mod foo;`. - pub inline: bool, -} - -/// Foreign module declaration. -/// -/// E.g., `extern { .. }` or `extern C { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ForeignMod { - pub abi: Abi, - pub items: Vec, -} - -/// Global inline assembly. -/// -/// Also known as "module-level assembly" or "file-scoped assembly". -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] -pub struct GlobalAsm { - pub asm: Symbol, - pub ctxt: SyntaxContext, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct EnumDef { - pub variants: Vec, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Variant_ { - /// Name of the variant. - pub ident: Ident, - /// Attributes of the variant. - pub attrs: Vec, - /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). - pub id: NodeId, - /// Fields and constructor id of the variant. - pub data: VariantData, - /// Explicit discriminant, e.g., `Foo = 1`. - pub disr_expr: Option, -} - -pub type Variant = Spanned; - -/// Part of `use` item to the right of its prefix. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum UseTreeKind { - /// `use prefix` or `use prefix as rename` - /// - /// The extra `NodeId`s are for HIR lowering, when additional statements are created for each - /// namespace. - Simple(Option, NodeId, NodeId), - /// `use prefix::{...}` - Nested(Vec<(UseTree, NodeId)>), - /// `use prefix::*` - Glob, -} - -/// A tree of paths sharing common prefixes. -/// Used in `use` items both at top-level and inside of braces in import groups. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct UseTree { - pub prefix: Path, - pub kind: UseTreeKind, - pub span: Span, -} - -impl UseTree { - pub fn ident(&self) -> Ident { - match self.kind { - UseTreeKind::Simple(Some(rename), ..) => rename, - UseTreeKind::Simple(None, ..) => { - self.prefix - .segments - .last() - .expect("empty prefix in a simple import") - .ident - } - _ => panic!("`UseTree::ident` can only be used on a simple import"), - } - } -} - -/// Distinguishes between `Attribute`s that decorate items and Attributes that -/// are contained as statements within items. These two cases need to be -/// distinguished for pretty-printing. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum AttrStyle { - Outer, - Inner, -} - -#[derive( - Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy, -)] -pub struct AttrId(pub usize); - -impl Idx for AttrId { - fn new(idx: usize) -> Self { - AttrId(idx) - } - fn index(self) -> usize { - self.0 - } -} - -/// Metadata associated with an item. -/// Doc-comments are promoted to attributes that have `is_sugared_doc = true`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Attribute { - pub id: AttrId, - pub style: AttrStyle, - pub path: Path, - pub tokens: TokenStream, - pub is_sugared_doc: bool, - pub span: Span, -} - -/// `TraitRef`s appear in impls. -/// -/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all -/// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl. -/// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the -/// same as the impl's `NodeId`). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct TraitRef { - pub path: Path, - pub ref_id: NodeId, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct PolyTraitRef { - /// The `'a` in `<'a> Foo<&'a T>`. - pub bound_generic_params: Vec, - - /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. - pub trait_ref: TraitRef, - - pub span: Span, -} - -impl PolyTraitRef { - pub fn new(generic_params: Vec, path: Path, span: Span) -> Self { - PolyTraitRef { - bound_generic_params: generic_params, - trait_ref: TraitRef { - path, - ref_id: DUMMY_NODE_ID, - }, - span, - } - } -} - -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum CrateSugar { - /// Source is `pub(crate)`. - PubCrate, - - /// Source is (just) `crate`. - JustCrate, -} - -pub type Visibility = Spanned; - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum VisibilityKind { - Public, - Crate(CrateSugar), - Restricted { path: P, id: NodeId }, - Inherited, -} - -impl VisibilityKind { - pub fn is_pub(&self) -> bool { - if let VisibilityKind::Public = *self { - true - } else { - false - } - } -} - -/// Field of a struct. -/// -/// E.g., `bar: usize` as in `struct Foo { bar: usize }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct StructField { - pub span: Span, - pub ident: Option, - pub vis: Visibility, - pub id: NodeId, - pub ty: P, - pub attrs: Vec, -} - -/// Fields and constructor ids of enum variants and structs. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum VariantData { - /// Struct variant. - /// - /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. - Struct(Vec, bool), - /// Tuple variant. - /// - /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. - Tuple(Vec, NodeId), - /// Unit variant. - /// - /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. - Unit(NodeId), -} - -impl VariantData { - /// Return the fields of this variant. - pub fn fields(&self) -> &[StructField] { - match *self { - VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, - _ => &[], - } - } - - /// Return the `NodeId` of this variant's constructor, if it has one. - pub fn ctor_id(&self) -> Option { - match *self { - VariantData::Struct(..) => None, - VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), - } - } -} - -/// An item. -/// -/// The name might be a dummy name in case of anonymous items. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Item { - pub ident: Ident, - pub attrs: Vec, - pub id: NodeId, - pub node: ItemKind, - pub vis: Visibility, - pub span: Span, - - /// Original tokens this item was parsed from. This isn't necessarily - /// available for all items, although over time more and more items should - /// have this be `Some`. Right now this is primarily used for procedural - /// macros, notably custom attributes. - /// - /// Note that the tokens here do not include the outer attributes, but will - /// include inner attributes. - pub tokens: Option, -} - -impl Item { - /// Return the span that encompasses the attributes. - pub fn span_with_attributes(&self) -> Span { - self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span)) - } -} - -/// A function header. -/// -/// All the information between the visibility and the name of the function is -/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] -pub struct FnHeader { - pub unsafety: Unsafety, - pub asyncness: Spanned, - pub constness: Spanned, - pub abi: Abi, -} - -impl Default for FnHeader { - fn default() -> FnHeader { - FnHeader { - unsafety: Unsafety::Normal, - asyncness: dummy_spanned(IsAsync::NotAsync), - constness: dummy_spanned(Constness::NotConst), - abi: Abi::Rust, - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ItemKind { - /// An `extern crate` item, with optional *original* crate name if the crate was renamed. - /// - /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. - ExternCrate(Option), - /// A use declaration (`use` or `pub use`) item. - /// - /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. - Use(P), - /// A static item (`static` or `pub static`). - /// - /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(P, Mutability, P), - /// A constant item (`const` or `pub const`). - /// - /// E.g., `const FOO: i32 = 42;`. - Const(P, P), - /// A function declaration (`fn` or `pub fn`). - /// - /// E.g., `fn foo(bar: usize) -> usize { .. }`. - Fn(P, FnHeader, Generics, P), - /// A module declaration (`mod` or `pub mod`). - /// - /// E.g., `mod foo;` or `mod foo { .. }`. - Mod(Mod), - /// An external module (`extern` or `pub extern`). - /// - /// E.g., `extern {}` or `extern "C" {}`. - ForeignMod(ForeignMod), - /// Module-level inline assembly (from `global_asm!()`). - GlobalAsm(P), - /// A type alias (`type` or `pub type`). - /// - /// E.g., `type Foo = Bar;`. - Ty(P, Generics), - /// An existential type declaration (`existential type`). - /// - /// E.g., `existential type Foo: Bar + Boo;`. - Existential(GenericBounds, Generics), - /// An enum definition (`enum` or `pub enum`). - /// - /// E.g., `enum Foo { C, D }`. - Enum(EnumDef, Generics), - /// A struct definition (`struct` or `pub struct`). - /// - /// E.g., `struct Foo { x: A }`. - Struct(VariantData, Generics), - /// A union definition (`union` or `pub union`). - /// - /// E.g., `union Foo { x: A, y: B }`. - Union(VariantData, Generics), - /// A Trait declaration (`trait` or `pub trait`). - /// - /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. - Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), - /// Trait alias - /// - /// E.g., `trait Foo = Bar + Quux;`. - TraitAlias(Generics, GenericBounds), - /// An implementation. - /// - /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. - Impl( - Unsafety, - ImplPolarity, - Defaultness, - Generics, - Option, // (optional) trait this impl implements - P, // self - Vec, - ), - /// A macro invocation. - /// - /// E.g., `macro_rules! foo { .. }` or `foo!(..)`. - Mac(Mac), - - /// A macro definition. - MacroDef(MacroDef), -} - -impl ItemKind { - pub fn descriptive_variant(&self) -> &str { - match *self { - ItemKind::ExternCrate(..) => "extern crate", - ItemKind::Use(..) => "use", - ItemKind::Static(..) => "static item", - ItemKind::Const(..) => "constant item", - ItemKind::Fn(..) => "function", - ItemKind::Mod(..) => "module", - ItemKind::ForeignMod(..) => "foreign module", - ItemKind::GlobalAsm(..) => "global asm", - ItemKind::Ty(..) => "type alias", - ItemKind::Existential(..) => "existential type", - ItemKind::Enum(..) => "enum", - ItemKind::Struct(..) => "struct", - ItemKind::Union(..) => "union", - ItemKind::Trait(..) => "trait", - ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) => "item", - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ForeignItem { - pub ident: Ident, - pub attrs: Vec, - pub node: ForeignItemKind, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, -} - -/// An item within an `extern` block. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ForeignItemKind { - /// A foreign function. - Fn(P, Generics), - /// A foreign static item (`static ext: u8`). - Static(P, Mutability), - /// A foreign type. - Ty, - /// A macro invocation. - Macro(Mac), -} - -impl ForeignItemKind { - pub fn descriptive_variant(&self) -> &str { - match *self { - ForeignItemKind::Fn(..) => "foreign function", - ForeignItemKind::Static(..) => "foreign static item", - ForeignItemKind::Ty => "foreign type", - ForeignItemKind::Macro(..) => "macro in foreign module", - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use serialize; - - // Are ASTs encodable? - #[test] - fn check_asts_encodable() { - fn assert_encodable() {} - assert_encodable::(); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/attr/builtin.rs b/gcc/rust/rustc_parser/libsyntax/attr/builtin.rs deleted file mode 100644 index b41f104..0000000 --- a/gcc/rust/rustc_parser/libsyntax/attr/builtin.rs +++ /dev/null @@ -1,903 +0,0 @@ -//! Parsing and validation of builtin attributes - -use crate::ast::{self, Attribute, MetaItem, NestedMetaItem}; -use crate::feature_gate::{Features, GatedCfg}; -use crate::parse::ParseSess; - -use errors::{Applicability, Handler}; -use syntax_pos::hygiene::Transparency; -use syntax_pos::{symbol::Symbol, symbol::sym, Span}; - -use super::{mark_used, MetaItemKind}; - -enum AttrError { - MultipleItem(String), - UnknownMetaItem(String, &'static [&'static str]), - MissingSince, - MissingFeature, - MultipleStabilityLevels, - UnsupportedLiteral(&'static str, /* is_bytestr */ bool), -} - -fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { - let diag = &sess.span_diagnostic; - match error { - AttrError::MultipleItem(item) => span_err!(diag, span, E0538, - "multiple '{}' items", item), - AttrError::UnknownMetaItem(item, expected) => { - let expected = expected - .iter() - .map(|name| format!("`{}`", name)) - .collect::>(); - struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item) - .span_label(span, format!("expected one of {}", expected.join(", "))) - .emit(); - } - AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"), - AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"), - AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544, - "multiple stability levels"), - AttrError::UnsupportedLiteral( - msg, - is_bytestr, - ) => { - let mut err = struct_span_err!(diag, span, E0565, "{}", msg); - if is_bytestr { - if let Ok(lint_str) = sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "consider removing the prefix", - format!("{}", &lint_str[1..]), - Applicability::MaybeIncorrect, - ); - } - } - err.emit(); - } - } -} - -#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] -pub enum InlineAttr { - None, - Hint, - Always, - Never, -} - -#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] -pub enum OptimizeAttr { - None, - Speed, - Size, -} - -#[derive(Copy, Clone, PartialEq)] -pub enum UnwindAttr { - Allowed, - Aborts, -} - -/// Determine what `#[unwind]` attribute is present in `attrs`, if any. -pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option { - attrs.iter().fold(None, |ia, attr| { - if attr.check_name(sym::unwind) { - if let Some(meta) = attr.meta() { - if let MetaItemKind::List(items) = meta.node { - if items.len() == 1 { - if items[0].check_name(sym::allowed) { - return Some(UnwindAttr::Allowed); - } else if items[0].check_name(sym::aborts) { - return Some(UnwindAttr::Aborts); - } - } - - diagnostic.map(|d| { - struct_span_err!(d, attr.span, E0633, "malformed `unwind` attribute input") - .span_label(attr.span, "invalid argument") - .span_suggestions( - attr.span, - "the allowed arguments are `allowed` and `aborts`", - (vec!["allowed", "aborts"]).into_iter() - .map(|s| format!("#[unwind({})]", s)), - Applicability::MachineApplicable, - ).emit(); - }); - } - } - } - - ia - }) -} - -/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes. -#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct Stability { - pub level: StabilityLevel, - pub feature: Symbol, - pub rustc_depr: Option, - /// `None` means the function is stable but needs to be a stable const fn, too - /// `Some` contains the feature gate required to be able to use the function - /// as const fn - pub const_stability: Option, - /// whether the function has a `#[rustc_promotable]` attribute - pub promotable: bool, - /// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute - pub allow_const_fn_ptr: bool, -} - -/// The available stability levels. -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] -pub enum StabilityLevel { - // Reason for the current stability level and the relevant rust-lang issue - Unstable { reason: Option, issue: u32 }, - Stable { since: Symbol }, -} - -impl Stability { - pub fn unstable(feature: Symbol, reason: Option, issue: u32) -> Stability { - Stability { - level: StabilityLevel::Unstable { reason, issue }, - feature, - rustc_depr: None, - const_stability: None, - promotable: false, - allow_const_fn_ptr: false, - } - } -} - -impl StabilityLevel { - pub fn is_unstable(&self) -> bool { - if let StabilityLevel::Unstable {..} = *self { - true - } else { - false - } - } - pub fn is_stable(&self) -> bool { - if let StabilityLevel::Stable {..} = *self { - true - } else { - false - } - } -} - -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] -pub struct RustcDeprecation { - pub since: Symbol, - pub reason: Symbol, - /// A text snippet used to completely replace any use of the deprecated item in an expression. - pub suggestion: Option, -} - -/// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`. -/// This will not perform any "sanity checks" on the form of the attributes. -pub fn contains_feature_attr(attrs: &[Attribute], feature_name: Symbol) -> bool { - attrs.iter().any(|item| { - item.check_name(sym::feature) && - item.meta_item_list().map(|list| { - list.iter().any(|mi| mi.is_word() && mi.check_name(feature_name)) - }).unwrap_or(false) - }) -} - -/// Collects stability info from all stability attributes in `attrs`. -/// Returns `None` if no stability attributes are found. -pub fn find_stability(sess: &ParseSess, attrs: &[Attribute], - item_sp: Span) -> Option { - find_stability_generic(sess, attrs.iter(), item_sp) -} - -fn find_stability_generic<'a, I>(sess: &ParseSess, - attrs_iter: I, - item_sp: Span) - -> Option - where I: Iterator -{ - use StabilityLevel::*; - - let mut stab: Option = None; - let mut rustc_depr: Option = None; - let mut rustc_const_unstable: Option = None; - let mut promotable = false; - let mut allow_const_fn_ptr = false; - let diagnostic = &sess.span_diagnostic; - - 'outer: for attr in attrs_iter { - if ![ - sym::rustc_deprecated, - sym::rustc_const_unstable, - sym::unstable, - sym::stable, - sym::rustc_promotable, - sym::rustc_allow_const_fn_ptr, - ].iter().any(|&s| attr.path == s) { - continue // not a stability level - } - - mark_used(attr); - - let meta = attr.meta(); - - if attr.path == sym::rustc_promotable { - promotable = true; - } - if attr.path == sym::rustc_allow_const_fn_ptr { - allow_const_fn_ptr = true; - } - // attributes with data - else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta { - let meta = meta.as_ref().unwrap(); - let get = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string())); - return false - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - span_err!(diagnostic, meta.span, E0539, "incorrect meta item"); - false - } - }; - - macro_rules! get_meta { - ($($name:ident),+) => { - $( - let mut $name = None; - )+ - for meta in metas { - if let Some(mi) = meta.meta_item() { - match mi.name_or_empty() { - $( - sym::$name => if !get(mi, &mut $name) { continue 'outer }, - )+ - _ => { - let expected = &[ $( stringify!($name) ),+ ]; - handle_errors( - sess, - mi.span, - AttrError::UnknownMetaItem(mi.path.to_string(), expected), - ); - continue 'outer - } - } - } else { - handle_errors( - sess, - meta.span(), - AttrError::UnsupportedLiteral( - "unsupported literal", - false, - ), - ); - continue 'outer - } - } - } - } - - match meta.name_or_empty() { - sym::rustc_deprecated => { - if rustc_depr.is_some() { - span_err!(diagnostic, item_sp, E0540, - "multiple rustc_deprecated attributes"); - continue 'outer - } - - get_meta!(since, reason, suggestion); - - match (since, reason) { - (Some(since), Some(reason)) => { - rustc_depr = Some(RustcDeprecation { - since, - reason, - suggestion, - }) - } - (None, _) => { - handle_errors(sess, attr.span, AttrError::MissingSince); - continue - } - _ => { - span_err!(diagnostic, attr.span, E0543, "missing 'reason'"); - continue - } - } - } - sym::rustc_const_unstable => { - if rustc_const_unstable.is_some() { - span_err!(diagnostic, item_sp, E0553, - "multiple rustc_const_unstable attributes"); - continue 'outer - } - - get_meta!(feature); - if let Some(feature) = feature { - rustc_const_unstable = Some(feature); - } else { - span_err!(diagnostic, attr.span, E0629, "missing 'feature'"); - continue - } - } - sym::unstable => { - if stab.is_some() { - handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); - break - } - - let mut feature = None; - let mut reason = None; - let mut issue = None; - for meta in metas { - if let Some(mi) = meta.meta_item() { - match mi.name_or_empty() { - sym::feature => if !get(mi, &mut feature) { continue 'outer }, - sym::reason => if !get(mi, &mut reason) { continue 'outer }, - sym::issue => if !get(mi, &mut issue) { continue 'outer }, - _ => { - handle_errors( - sess, - meta.span(), - AttrError::UnknownMetaItem( - mi.path.to_string(), - &["feature", "reason", "issue"] - ), - ); - continue 'outer - } - } - } else { - handle_errors( - sess, - meta.span(), - AttrError::UnsupportedLiteral( - "unsupported literal", - false, - ), - ); - continue 'outer - } - } - - match (feature, reason, issue) { - (Some(feature), reason, Some(issue)) => { - stab = Some(Stability { - level: Unstable { - reason, - issue: { - if let Ok(issue) = issue.as_str().parse() { - issue - } else { - span_err!(diagnostic, attr.span, E0545, - "incorrect 'issue'"); - continue - } - } - }, - feature, - rustc_depr: None, - const_stability: None, - promotable: false, - allow_const_fn_ptr: false, - }) - } - (None, _, _) => { - handle_errors(sess, attr.span, AttrError::MissingFeature); - continue - } - _ => { - span_err!(diagnostic, attr.span, E0547, "missing 'issue'"); - continue - } - } - } - sym::stable => { - if stab.is_some() { - handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); - break - } - - let mut feature = None; - let mut since = None; - for meta in metas { - match meta { - NestedMetaItem::MetaItem(mi) => { - match mi.name_or_empty() { - sym::feature => if !get(mi, &mut feature) { continue 'outer }, - sym::since => if !get(mi, &mut since) { continue 'outer }, - _ => { - handle_errors( - sess, - meta.span(), - AttrError::UnknownMetaItem( - mi.path.to_string(), &["since", "note"], - ), - ); - continue 'outer - } - } - }, - NestedMetaItem::Literal(lit) => { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "unsupported literal", - false, - ), - ); - continue 'outer - } - } - } - - match (feature, since) { - (Some(feature), Some(since)) => { - stab = Some(Stability { - level: Stable { - since, - }, - feature, - rustc_depr: None, - const_stability: None, - promotable: false, - allow_const_fn_ptr: false, - }) - } - (None, _) => { - handle_errors(sess, attr.span, AttrError::MissingFeature); - continue - } - _ => { - handle_errors(sess, attr.span, AttrError::MissingSince); - continue - } - } - } - _ => unreachable!() - } - } - } - - // Merge the deprecation info into the stability info - if let Some(rustc_depr) = rustc_depr { - if let Some(ref mut stab) = stab { - stab.rustc_depr = Some(rustc_depr); - } else { - span_err!(diagnostic, item_sp, E0549, - "rustc_deprecated attribute must be paired with \ - either stable or unstable attribute"); - } - } - - // Merge the const-unstable info into the stability info - if let Some(feature) = rustc_const_unstable { - if let Some(ref mut stab) = stab { - stab.const_stability = Some(feature); - } else { - span_err!(diagnostic, item_sp, E0630, - "rustc_const_unstable attribute must be paired with \ - either stable or unstable attribute"); - } - } - - // Merge the const-unstable info into the stability info - if promotable || allow_const_fn_ptr { - if let Some(ref mut stab) = stab { - stab.promotable = promotable; - stab.allow_const_fn_ptr = allow_const_fn_ptr; - } else { - span_err!(diagnostic, item_sp, E0717, - "rustc_promotable and rustc_allow_const_fn_ptr attributes \ - must be paired with either stable or unstable attribute"); - } - } - - stab -} - -pub fn find_crate_name(attrs: &[Attribute]) -> Option { - super::first_attr_value_str_by_name(attrs, sym::crate_name) -} - -/// Tests if a cfg-pattern matches the cfg set -pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool { - eval_condition(cfg, sess, &mut |cfg| { - if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) { - gated_cfg.check_and_emit(sess, feats); - } - let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true }; - if cfg.path.segments.len() != 1 { - return error(cfg.path.span, "`cfg` predicate key must be an identifier"); - } - match &cfg.node { - MetaItemKind::List(..) => { - error(cfg.span, "unexpected parentheses after `cfg` predicate key") - } - MetaItemKind::NameValue(lit) if !lit.node.is_str() => { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "literal in `cfg` predicate value must be a string", - lit.node.is_bytestr() - ), - ); - true - } - MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let ident = cfg.ident().expect("multi-segment cfg predicate"); - sess.config.contains(&(ident.name, cfg.value_str())) - } - } - }) -} - -/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to -/// evaluate individual items. -pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) - -> bool - where F: FnMut(&ast::MetaItem) -> bool -{ - match cfg.node { - ast::MetaItemKind::List(ref mis) => { - for mi in mis.iter() { - if !mi.is_meta_item() { - handle_errors( - sess, - mi.span(), - AttrError::UnsupportedLiteral( - "unsupported literal", - false - ), - ); - return false; - } - } - - // The unwraps below may look dangerous, but we've already asserted - // that they won't fail with the loop above. - match cfg.name_or_empty() { - sym::any => mis.iter().any(|mi| { - eval_condition(mi.meta_item().unwrap(), sess, eval) - }), - sym::all => mis.iter().all(|mi| { - eval_condition(mi.meta_item().unwrap(), sess, eval) - }), - sym::not => { - if mis.len() != 1 { - span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern"); - return false; - } - - !eval_condition(mis[0].meta_item().unwrap(), sess, eval) - }, - _ => { - span_err!(sess.span_diagnostic, cfg.span, E0537, - "invalid predicate `{}`", cfg.path); - false - } - } - }, - ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => { - eval(cfg) - } - } -} - - -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] -pub struct Deprecation { - pub since: Option, - pub note: Option, -} - -/// Finds the deprecation attribute. `None` if none exists. -pub fn find_deprecation(sess: &ParseSess, attrs: &[Attribute], - item_sp: Span) -> Option { - find_deprecation_generic(sess, attrs.iter(), item_sp) -} - -fn find_deprecation_generic<'a, I>(sess: &ParseSess, - attrs_iter: I, - item_sp: Span) - -> Option - where I: Iterator -{ - let mut depr: Option = None; - let diagnostic = &sess.span_diagnostic; - - 'outer: for attr in attrs_iter { - if !attr.check_name(sym::deprecated) { - continue; - } - - if depr.is_some() { - span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes"); - break - } - - let meta = attr.meta().unwrap(); - depr = match &meta.node { - MetaItemKind::Word => Some(Deprecation { since: None, note: None }), - MetaItemKind::NameValue(..) => { - meta.value_str().map(|note| { - Deprecation { since: None, note: Some(note) } - }) - } - MetaItemKind::List(list) => { - let get = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors( - sess, meta.span, AttrError::MultipleItem(meta.path.to_string()) - ); - return false - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - if let Some(lit) = meta.name_value_literal() { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "literal in `deprecated` \ - value must be a string", - lit.node.is_bytestr() - ), - ); - } else { - span_err!(diagnostic, meta.span, E0551, "incorrect meta item"); - } - - false - } - }; - - let mut since = None; - let mut note = None; - for meta in list { - match meta { - NestedMetaItem::MetaItem(mi) => { - match mi.name_or_empty() { - sym::since => if !get(mi, &mut since) { continue 'outer }, - sym::note => if !get(mi, &mut note) { continue 'outer }, - _ => { - handle_errors( - sess, - meta.span(), - AttrError::UnknownMetaItem(mi.path.to_string(), - &["since", "note"]), - ); - continue 'outer - } - } - } - NestedMetaItem::Literal(lit) => { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "item in `deprecated` must be a key/value pair", - false, - ), - ); - continue 'outer - } - } - } - - Some(Deprecation { since, note }) - } - }; - } - - depr -} - -#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] -pub enum ReprAttr { - ReprInt(IntType), - ReprC, - ReprPacked(u32), - ReprSimd, - ReprTransparent, - ReprAlign(u32), -} - -#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] -pub enum IntType { - SignedInt(ast::IntTy), - UnsignedInt(ast::UintTy) -} - -impl IntType { - #[inline] - pub fn is_signed(self) -> bool { - use IntType::*; - - match self { - SignedInt(..) => true, - UnsignedInt(..) => false - } - } -} - -/// Parse #[repr(...)] forms. -/// -/// Valid repr contents: any of the primitive integral type names (see -/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use -/// the same discriminant size that the corresponding C enum would or C -/// structure layout, `packed` to remove padding, and `transparent` to elegate representation -/// concerns to the only non-ZST field. -pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { - use ReprAttr::*; - - let mut acc = Vec::new(); - let diagnostic = &sess.span_diagnostic; - if attr.path == sym::repr { - if let Some(items) = attr.meta_item_list() { - mark_used(attr); - for item in items { - if !item.is_meta_item() { - handle_errors( - sess, - item.span(), - AttrError::UnsupportedLiteral( - "meta item in `repr` must be an identifier", - false, - ), - ); - continue - } - - let mut recognised = false; - if item.is_word() { - let hint = match item.name_or_empty() { - sym::C => Some(ReprC), - sym::packed => Some(ReprPacked(1)), - sym::simd => Some(ReprSimd), - sym::transparent => Some(ReprTransparent), - name => int_type_of_word(name).map(ReprInt), - }; - - if let Some(h) = hint { - recognised = true; - acc.push(h); - } - } else if let Some((name, value)) = item.name_value_literal() { - let parse_alignment = |node: &ast::LitKind| -> Result { - if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { - if literal.is_power_of_two() { - // rustc::ty::layout::Align restricts align to <= 2^29 - if *literal <= 1 << 29 { - Ok(*literal as u32) - } else { - Err("larger than 2^29") - } - } else { - Err("not a power of two") - } - } else { - Err("not an unsuffixed integer") - } - }; - - let mut literal_error = None; - if name == sym::align { - recognised = true; - match parse_alignment(&value.node) { - Ok(literal) => acc.push(ReprAlign(literal)), - Err(message) => literal_error = Some(message) - }; - } - else if name == sym::packed { - recognised = true; - match parse_alignment(&value.node) { - Ok(literal) => acc.push(ReprPacked(literal)), - Err(message) => literal_error = Some(message) - }; - } - if let Some(literal_error) = literal_error { - span_err!(diagnostic, item.span(), E0589, - "invalid `repr(align)` attribute: {}", literal_error); - } - } else { - if let Some(meta_item) = item.meta_item() { - if meta_item.check_name(sym::align) { - if let MetaItemKind::NameValue(ref value) = meta_item.node { - recognised = true; - let mut err = struct_span_err!(diagnostic, item.span(), E0693, - "incorrect `repr(align)` attribute format"); - match value.node { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("align({})", int), - Applicability::MachineApplicable - ); - } - ast::LitKind::Str(s, _) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("align({})", s), - Applicability::MachineApplicable - ); - } - _ => {} - } - err.emit(); - } - } - } - } - if !recognised { - // Not a word we recognize - span_err!(diagnostic, item.span(), E0552, - "unrecognized representation hint"); - } - } - } - } - acc -} - -fn int_type_of_word(s: Symbol) -> Option { - use IntType::*; - - match s { - sym::i8 => Some(SignedInt(ast::IntTy::I8)), - sym::u8 => Some(UnsignedInt(ast::UintTy::U8)), - sym::i16 => Some(SignedInt(ast::IntTy::I16)), - sym::u16 => Some(UnsignedInt(ast::UintTy::U16)), - sym::i32 => Some(SignedInt(ast::IntTy::I32)), - sym::u32 => Some(UnsignedInt(ast::UintTy::U32)), - sym::i64 => Some(SignedInt(ast::IntTy::I64)), - sym::u64 => Some(UnsignedInt(ast::UintTy::U64)), - sym::i128 => Some(SignedInt(ast::IntTy::I128)), - sym::u128 => Some(UnsignedInt(ast::UintTy::U128)), - sym::isize => Some(SignedInt(ast::IntTy::Isize)), - sym::usize => Some(UnsignedInt(ast::UintTy::Usize)), - _ => None - } -} - -pub enum TransparencyError { - UnknownTransparency(Symbol, Span), - MultipleTransparencyAttrs(Span, Span), -} - -pub fn find_transparency( - attrs: &[Attribute], is_legacy: bool -) -> (Transparency, Option) { - let mut transparency = None; - let mut error = None; - for attr in attrs { - if attr.check_name(sym::rustc_macro_transparency) { - if let Some((_, old_span)) = transparency { - error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span)); - break; - } else if let Some(value) = attr.value_str() { - transparency = Some((match &*value.as_str() { - "transparent" => Transparency::Transparent, - "semitransparent" => Transparency::SemiTransparent, - "opaque" => Transparency::Opaque, - _ => { - error = Some(TransparencyError::UnknownTransparency(value, attr.span)); - continue; - } - }, attr.span)); - } - } - } - let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque }; - (transparency.map_or(fallback, |t| t.0), error) -} diff --git a/gcc/rust/rustc_parser/libsyntax/attr/mod.rs b/gcc/rust/rustc_parser/libsyntax/attr/mod.rs deleted file mode 100644 index a9f2429..0000000 --- a/gcc/rust/rustc_parser/libsyntax/attr/mod.rs +++ /dev/null @@ -1,753 +0,0 @@ -//! Functions dealing with attributes and meta items - -mod builtin; - -pub use builtin::*; -pub use IntType::*; -pub use ReprAttr::*; -pub use StabilityLevel::*; - -use crate::ast; -use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment}; -use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; -use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam}; -use crate::mut_visit::visit_clobber; -use crate::source_map::{BytePos, Spanned, dummy_spanned}; -use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use crate::parse::parser::Parser; -use crate::parse::{self, ParseSess, PResult}; -use crate::parse::token::{self, Token}; -use crate::ptr::P; -use crate::symbol::{sym, Symbol}; -use crate::ThinVec; -use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; -use crate::GLOBALS; - -use log::debug; -use syntax_pos::{FileName, Span}; - -use std::iter; -use std::ops::DerefMut; - -pub fn mark_used(attr: &Attribute) { - debug!("Marking {:?} as used.", attr); - GLOBALS.with(|globals| { - globals.used_attrs.lock().insert(attr.id); - }); -} - -pub fn is_used(attr: &Attribute) -> bool { - GLOBALS.with(|globals| { - globals.used_attrs.lock().contains(attr.id) - }) -} - -pub fn mark_known(attr: &Attribute) { - debug!("Marking {:?} as known.", attr); - GLOBALS.with(|globals| { - globals.known_attrs.lock().insert(attr.id); - }); -} - -pub fn is_known(attr: &Attribute) -> bool { - GLOBALS.with(|globals| { - globals.known_attrs.lock().contains(attr.id) - }) -} - -pub fn is_known_lint_tool(m_item: Ident) -> bool { - [sym::clippy, sym::rustc].contains(&m_item.name) -} - -impl NestedMetaItem { - /// Returns the MetaItem if self is a NestedMetaItem::MetaItem. - pub fn meta_item(&self) -> Option<&MetaItem> { - match *self { - NestedMetaItem::MetaItem(ref item) => Some(item), - _ => None - } - } - - /// Returns the Lit if self is a NestedMetaItem::Literal. - pub fn literal(&self) -> Option<&Lit> { - match *self { - NestedMetaItem::Literal(ref lit) => Some(lit), - _ => None - } - } - - /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name(&self, name: Symbol) -> bool { - self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) - } - - /// For a single-segment meta-item returns its name, otherwise returns `None`. - pub fn ident(&self) -> Option { - self.meta_item().and_then(|meta_item| meta_item.ident()) - } - pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name - } - - /// Gets the string value if self is a MetaItem and the MetaItem is a - /// MetaItemKind::NameValue variant containing a string, otherwise None. - pub fn value_str(&self) -> Option { - self.meta_item().and_then(|meta_item| meta_item.value_str()) - } - - /// Returns a name and single literal value tuple of the MetaItem. - pub fn name_value_literal(&self) -> Option<(Name, &Lit)> { - self.meta_item().and_then( - |meta_item| meta_item.meta_item_list().and_then( - |meta_item_list| { - if meta_item_list.len() == 1 { - if let Some(ident) = meta_item.ident() { - if let Some(lit) = meta_item_list[0].literal() { - return Some((ident.name, lit)); - } - } - } - None - })) - } - - /// Gets a list of inner meta items from a list MetaItem type. - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { - self.meta_item().and_then(|meta_item| meta_item.meta_item_list()) - } - - /// Returns `true` if the variant is MetaItem. - pub fn is_meta_item(&self) -> bool { - self.meta_item().is_some() - } - - /// Returns `true` if the variant is Literal. - pub fn is_literal(&self) -> bool { - self.literal().is_some() - } - - /// Returns `true` if self is a MetaItem and the meta item is a word. - pub fn is_word(&self) -> bool { - self.meta_item().map_or(false, |meta_item| meta_item.is_word()) - } - - /// Returns `true` if self is a MetaItem and the meta item is a ValueString. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - /// Returns `true` if self is a MetaItem and the meta item is a list. - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } -} - -impl Attribute { - /// Returns `true` if the attribute's path matches the argument. If it matches, then the - /// attribute is marked as used. - /// - /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name(&self, name: Symbol) -> bool { - let matches = self.path == name; - if matches { - mark_used(self); - } - matches - } - - /// For a single-segment attribute returns its name, otherwise returns `None`. - pub fn ident(&self) -> Option { - if self.path.segments.len() == 1 { - Some(self.path.segments[0].ident) - } else { - None - } - } - pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name - } - - pub fn value_str(&self) -> Option { - self.meta().and_then(|meta| meta.value_str()) - } - - pub fn meta_item_list(&self) -> Option> { - match self.meta() { - Some(MetaItem { node: MetaItemKind::List(list), .. }) => Some(list), - _ => None - } - } - - pub fn is_word(&self) -> bool { - self.tokens.is_empty() - } - - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } - - /// Indicates if the attribute is a Value String. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } -} - -impl MetaItem { - /// For a single-segment meta-item returns its name, otherwise returns `None`. - pub fn ident(&self) -> Option { - if self.path.segments.len() == 1 { - Some(self.path.segments[0].ident) - } else { - None - } - } - pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(Ident::invalid()).name - } - - // #[attribute(name = "value")] - // ^^^^^^^^^^^^^^ - pub fn name_value_literal(&self) -> Option<&Lit> { - match &self.node { - MetaItemKind::NameValue(v) => Some(v), - _ => None, - } - } - - pub fn value_str(&self) -> Option { - match self.node { - MetaItemKind::NameValue(ref v) => { - match v.node { - LitKind::Str(ref s, _) => Some(*s), - _ => None, - } - }, - _ => None - } - } - - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { - match self.node { - MetaItemKind::List(ref l) => Some(&l[..]), - _ => None - } - } - - pub fn is_word(&self) -> bool { - match self.node { - MetaItemKind::Word => true, - _ => false, - } - } - - pub fn check_name(&self, name: Symbol) -> bool { - self.path == name - } - - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } -} - -impl Attribute { - /// Extracts the MetaItem from inside this Attribute. - pub fn meta(&self) -> Option { - let mut tokens = self.tokens.trees().peekable(); - Some(MetaItem { - path: self.path.clone(), - node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { - if tokens.peek().is_some() { - return None; - } - node - } else { - return None; - }, - span: self.span, - }) - } - - pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let mut parser = Parser::new( - sess, - self.tokens.clone(), - None, - false, - false, - Some("attribute"), - ); - let result = f(&mut parser)?; - if parser.token != token::Eof { - parser.unexpected()?; - } - Ok(result) - } - - pub fn parse_list<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, Vec> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - if self.tokens.is_empty() { - return Ok(Vec::new()); - } - self.parse(sess, |parser| { - parser.expect(&token::OpenDelim(token::Paren))?; - let mut list = Vec::new(); - while !parser.eat(&token::CloseDelim(token::Paren)) { - list.push(f(parser)?); - if !parser.eat(&token::Comma) { - parser.expect(&token::CloseDelim(token::Paren))?; - break - } - } - Ok(list) - }) - } - - pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { - Ok(MetaItem { - path: self.path.clone(), - node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, - span: self.span, - }) - } - - /// Converts self to a normal #[doc="foo"] comment, if it is a - /// comment like `///` or `/** */`. (Returns self unchanged for - /// non-sugared doc attributes.) - pub fn with_desugared_doc(&self, f: F) -> T where - F: FnOnce(&Attribute) -> T, - { - if self.is_sugared_doc { - let comment = self.value_str().unwrap(); - let meta = mk_name_value_item_str( - Ident::with_empty_ctxt(sym::doc), - dummy_spanned(Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())))); - let mut attr = if self.style == ast::AttrStyle::Outer { - mk_attr_outer(self.span, self.id, meta) - } else { - mk_attr_inner(self.span, self.id, meta) - }; - attr.is_sugared_doc = true; - f(&attr) - } else { - f(self) - } - } -} - -/* Constructors */ - -pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { - let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked); - mk_name_value_item(ident.span.to(value.span), ident, lit_kind, value.span) -} - -pub fn mk_name_value_item(span: Span, ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { - let lit = Lit::from_lit_kind(lit_kind, lit_span); - MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(lit) } -} - -pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::List(items) } -} - -pub fn mk_word_item(ident: Ident) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } -} - -pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { - NestedMetaItem::MetaItem(mk_word_item(ident)) -} - -pub fn mk_attr_id() -> AttrId { - use std::sync::atomic::AtomicUsize; - use std::sync::atomic::Ordering; - - static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0); - - let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst); - assert!(id != ::std::usize::MAX); - AttrId(id) -} - -/// Returns an inner attribute with the given value. -pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute { - mk_spanned_attr_inner(span, id, item) -} - -/// Returns an inner attribute with the given value and span. -pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute { - Attribute { - id, - style: ast::AttrStyle::Inner, - path: item.path, - tokens: item.node.tokens(item.span), - is_sugared_doc: false, - span: sp, - } -} - -/// Returns an outer attribute with the given value. -pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute { - mk_spanned_attr_outer(span, id, item) -} - -/// Returns an outer attribute with the given value and span. -pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute { - Attribute { - id, - style: ast::AttrStyle::Outer, - path: item.path, - tokens: item.node.tokens(item.span), - is_sugared_doc: false, - span: sp, - } -} - -pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { - let style = doc_comment_style(&text.as_str()); - let lit_kind = LitKind::Str(text, ast::StrStyle::Cooked); - let lit = Lit::from_lit_kind(lit_kind, span); - Attribute { - id, - style, - path: Path::from_ident(Ident::with_empty_ctxt(sym::doc).with_span_pos(span)), - tokens: MetaItemKind::NameValue(lit).tokens(span), - is_sugared_doc: true, - span, - } -} - -pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { - items.iter().any(|item| { - item.check_name(name) - }) -} - -pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool { - attrs.iter().any(|item| { - item.check_name(name) - }) -} - -pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> { - attrs.iter().find(|attr| attr.check_name(name)) -} - -pub fn filter_by_name(attrs: &[Attribute], name: Symbol) - -> impl Iterator { - attrs.iter().filter(move |attr| attr.check_name(name)) -} - -pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option { - attrs.iter() - .find(|at| at.check_name(name)) - .and_then(|at| at.value_str()) -} - -impl MetaItem { - fn tokens(&self) -> TokenStream { - let mut idents = vec![]; - let mut last_pos = BytePos(0 as u32); - for (i, segment) in self.path.segments.iter().enumerate() { - let is_first = i == 0; - if !is_first { - let mod_sep_span = Span::new(last_pos, - segment.ident.span.lo(), - segment.ident.span.ctxt()); - idents.push(TokenTree::token(token::ModSep, mod_sep_span).into()); - } - idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into()); - last_pos = segment.ident.span.hi(); - } - self.node.tokens(self.span).append_to_tree_and_joint_vec(&mut idents); - TokenStream::new(idents) - } - - fn from_tokens(tokens: &mut iter::Peekable) -> Option - where I: Iterator, - { - // FIXME: Share code with `parse_path`. - let path = match tokens.next() { - Some(TokenTree::Token(Token { kind: kind @ token::Ident(..), span })) | - Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: { - let mut segments = if let token::Ident(name, _) = kind { - if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) - = tokens.peek() { - tokens.next(); - vec![PathSegment::from_ident(Ident::new(name, span))] - } else { - break 'arm Path::from_ident(Ident::new(name, span)); - } - } else { - vec![PathSegment::path_root(span)] - }; - loop { - if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) - = tokens.next() { - segments.push(PathSegment::from_ident(Ident::new(name, span))); - } else { - return None; - } - if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) - = tokens.peek() { - tokens.next(); - } else { - break; - } - } - let span = span.with_hi(segments.last().unwrap().ident.span.hi()); - Path { span, segments } - } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { - token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident), - token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), - token::Nonterminal::NtPath(ref path) => path.clone(), - _ => return None, - }, - _ => return None, - }; - let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi()); - let node = MetaItemKind::from_tokens(tokens)?; - let hi = match node { - MetaItemKind::NameValue(ref lit) => lit.span.hi(), - MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()), - _ => path.span.hi(), - }; - let span = path.span.with_hi(hi); - Some(MetaItem { path, node, span }) - } -} - -impl MetaItemKind { - pub fn tokens(&self, span: Span) -> TokenStream { - match *self { - MetaItemKind::Word => TokenStream::empty(), - MetaItemKind::NameValue(ref lit) => { - let mut vec = vec![TokenTree::token(token::Eq, span).into()]; - lit.tokens().append_to_tree_and_joint_vec(&mut vec); - TokenStream::new(vec) - } - MetaItemKind::List(ref list) => { - let mut tokens = Vec::new(); - for (i, item) in list.iter().enumerate() { - if i > 0 { - tokens.push(TokenTree::token(token::Comma, span).into()); - } - item.tokens().append_to_tree_and_joint_vec(&mut tokens); - } - TokenTree::Delimited( - DelimSpan::from_single(span), - token::Paren, - TokenStream::new(tokens).into(), - ).into() - } - } - } - - fn from_tokens(tokens: &mut iter::Peekable) -> Option - where I: Iterator, - { - let delimited = match tokens.peek().cloned() { - Some(TokenTree::Token(token)) if token == token::Eq => { - tokens.next(); - return if let Some(TokenTree::Token(token)) = tokens.next() { - Lit::from_token(&token).ok().map(MetaItemKind::NameValue) - } else { - None - }; - } - Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => { - tokens.next(); - tts.clone() - } - _ => return Some(MetaItemKind::Word), - }; - - let mut tokens = delimited.into_trees().peekable(); - let mut result = Vec::new(); - while let Some(..) = tokens.peek() { - let item = NestedMetaItem::from_tokens(&mut tokens)?; - result.push(item); - match tokens.next() { - None | Some(TokenTree::Token(Token { kind: token::Comma, .. })) => {} - _ => return None, - } - } - Some(MetaItemKind::List(result)) - } -} - -impl NestedMetaItem { - pub fn span(&self) -> Span { - match *self { - NestedMetaItem::MetaItem(ref item) => item.span, - NestedMetaItem::Literal(ref lit) => lit.span, - } - } - - fn tokens(&self) -> TokenStream { - match *self { - NestedMetaItem::MetaItem(ref item) => item.tokens(), - NestedMetaItem::Literal(ref lit) => lit.tokens(), - } - } - - fn from_tokens(tokens: &mut iter::Peekable) -> Option - where I: Iterator, - { - if let Some(TokenTree::Token(token)) = tokens.peek() { - if let Ok(lit) = Lit::from_token(token) { - tokens.next(); - return Some(NestedMetaItem::Literal(lit)); - } - } - - MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem) - } -} - -pub trait HasAttrs: Sized { - fn attrs(&self) -> &[ast::Attribute]; - fn visit_attrs)>(&mut self, f: F); -} - -impl HasAttrs for Spanned { - fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } - fn visit_attrs)>(&mut self, f: F) { - self.node.visit_attrs(f); - } -} - -impl HasAttrs for Vec { - fn attrs(&self) -> &[Attribute] { - self - } - fn visit_attrs)>(&mut self, f: F) { - f(self) - } -} - -impl HasAttrs for ThinVec { - fn attrs(&self) -> &[Attribute] { - self - } - fn visit_attrs)>(&mut self, f: F) { - visit_clobber(self, |this| { - let mut vec = this.into(); - f(&mut vec); - vec.into() - }); - } -} - -impl HasAttrs for P { - fn attrs(&self) -> &[Attribute] { - (**self).attrs() - } - fn visit_attrs)>(&mut self, f: F) { - (**self).visit_attrs(f); - } -} - -impl HasAttrs for StmtKind { - fn attrs(&self) -> &[Attribute] { - match *self { - StmtKind::Local(ref local) => local.attrs(), - StmtKind::Item(..) => &[], - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), - StmtKind::Mac(ref mac) => { - let (_, _, ref attrs) = **mac; - attrs.attrs() - } - } - } - - fn visit_attrs)>(&mut self, f: F) { - match self { - StmtKind::Local(local) => local.visit_attrs(f), - StmtKind::Item(..) => {} - StmtKind::Expr(expr) => expr.visit_attrs(f), - StmtKind::Semi(expr) => expr.visit_attrs(f), - StmtKind::Mac(mac) => { - let (_mac, _style, attrs) = mac.deref_mut(); - attrs.visit_attrs(f); - } - } - } -} - -impl HasAttrs for Stmt { - fn attrs(&self) -> &[ast::Attribute] { - self.node.attrs() - } - - fn visit_attrs)>(&mut self, f: F) { - self.node.visit_attrs(f); - } -} - -impl HasAttrs for GenericParam { - fn attrs(&self) -> &[ast::Attribute] { - &self.attrs - } - - fn visit_attrs)>(&mut self, f: F) { - self.attrs.visit_attrs(f); - } -} - -macro_rules! derive_has_attrs { - ($($ty:path),*) => { $( - impl HasAttrs for $ty { - fn attrs(&self) -> &[Attribute] { - &self.attrs - } - - fn visit_attrs)>(&mut self, f: F) { - self.attrs.visit_attrs(f); - } - } - )* } -} - -derive_has_attrs! { - Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_, ast::Arg -} - -pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { - for raw_attr in attrs { - let mut parser = parse::new_parser_from_source_str( - parse_sess, - FileName::cli_crate_attr_source_code(&raw_attr), - raw_attr.clone(), - ); - - let start_span = parser.token.span; - let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted()); - let end_span = parser.token.span; - if parser.token != token::Eof { - parse_sess.span_diagnostic - .span_err(start_span.to(end_span), "invalid crate attribute"); - continue; - } - - krate.attrs.push(Attribute { - id: mk_attr_id(), - style: AttrStyle::Inner, - path, - tokens, - is_sugared_doc: false, - span: start_span.to(end_span), - }); - } - - krate -} diff --git a/gcc/rust/rustc_parser/libsyntax/build.rs b/gcc/rust/rustc_parser/libsyntax/build.rs deleted file mode 100644 index 9b861f9..0000000 --- a/gcc/rust/rustc_parser/libsyntax/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL"); - println!("cargo:rerun-if-env-changed=CFG_DISABLE_UNSTABLE_FEATURES"); -} diff --git a/gcc/rust/rustc_parser/libsyntax/config.rs b/gcc/rust/rustc_parser/libsyntax/config.rs deleted file mode 100644 index 1ab367f..0000000 --- a/gcc/rust/rustc_parser/libsyntax/config.rs +++ /dev/null @@ -1,369 +0,0 @@ -use crate::attr::HasAttrs; -use crate::feature_gate::{ - feature_err, - EXPLAIN_STMT_ATTR_SYNTAX, - Features, - get_features, - GateIssue, -}; -use crate::attr; -use crate::ast; -use crate::edition::Edition; -use crate::mut_visit::*; -use crate::parse::{token, ParseSess}; -use crate::ptr::P; -use crate::symbol::sym; -use crate::util::map_in_place::MapInPlace; - -use errors::Applicability; -use smallvec::SmallVec; - -/// A folder that strips out items that do not belong in the current configuration. -pub struct StripUnconfigured<'a> { - pub sess: &'a ParseSess, - pub features: Option<&'a Features>, -} - -// `cfg_attr`-process the crate's attributes and compute the crate's features. -pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition, - allow_features: &Option>) -> (ast::Crate, Features) { - let features; - { - let mut strip_unconfigured = StripUnconfigured { - sess, - features: None, - }; - - let unconfigured_attrs = krate.attrs.clone(); - let err_count = sess.span_diagnostic.err_count(); - if let Some(attrs) = strip_unconfigured.configure(krate.attrs) { - krate.attrs = attrs; - } else { // the entire crate is unconfigured - krate.attrs = Vec::new(); - krate.module.items = Vec::new(); - return (krate, Features::new()); - } - - features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features); - - // Avoid reconfiguring malformed `cfg_attr`s - if err_count == sess.span_diagnostic.err_count() { - strip_unconfigured.features = Some(&features); - strip_unconfigured.configure(unconfigured_attrs); - } - } - - (krate, features) -} - -macro_rules! configure { - ($this:ident, $node:ident) => { - match $this.configure($node) { - Some(node) => node, - None => return Default::default(), - } - } -} - -impl<'a> StripUnconfigured<'a> { - pub fn configure(&mut self, mut node: T) -> Option { - self.process_cfg_attrs(&mut node); - if self.in_cfg(node.attrs()) { Some(node) } else { None } - } - - /// Parse and expand all `cfg_attr` attributes into a list of attributes - /// that are within each `cfg_attr` that has a true configuration predicate. - /// - /// Gives compiler warnigns if any `cfg_attr` does not contain any - /// attributes and is in the original source code. Gives compiler errors if - /// the syntax of any `cfg_attr` is incorrect. - pub fn process_cfg_attrs(&mut self, node: &mut T) { - node.visit_attrs(|attrs| { - attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - }); - } - - /// Parse and expand a single `cfg_attr` attribute into a list of attributes - /// when the configuration predicate is true, or otherwise expand into an - /// empty list of attributes. - /// - /// Gives a compiler warning when the `cfg_attr` contains no attributes and - /// is in the original source file. Gives a compiler error if the syntax of - /// the attribute is incorrect. - fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { - if attr.path != sym::cfg_attr { - return vec![attr]; - } - if attr.tokens.is_empty() { - self.sess.span_diagnostic - .struct_span_err( - attr.span, - "malformed `cfg_attr` attribute input", - ).span_suggestion( - attr.span, - "missing condition and attribute", - "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(), - Applicability::HasPlaceholders, - ).note("for more information, visit \ - ") - .emit(); - return vec![]; - } - - let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { - parser.expect(&token::OpenDelim(token::Paren))?; - - let cfg_predicate = parser.parse_meta_item()?; - parser.expect(&token::Comma)?; - - // Presumably, the majority of the time there will only be one attr. - let mut expanded_attrs = Vec::with_capacity(1); - - while !parser.check(&token::CloseDelim(token::Paren)) { - let lo = parser.token.span.lo(); - let (path, tokens) = parser.parse_meta_item_unrestricted()?; - expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo))); - parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; - } - - parser.expect(&token::CloseDelim(token::Paren))?; - Ok((cfg_predicate, expanded_attrs)) - }) { - Ok(result) => result, - Err(mut e) => { - e.emit(); - return vec![]; - } - }; - - // Lint on zero attributes in source. - if expanded_attrs.is_empty() { - return vec![attr]; - } - - // At this point we know the attribute is considered used. - attr::mark_used(&attr); - - if attr::cfg_matches(&cfg_predicate, self.sess, self.features) { - // We call `process_cfg_attr` recursively in case there's a - // `cfg_attr` inside of another `cfg_attr`. E.g. - // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. - expanded_attrs.into_iter() - .flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute { - id: attr::mk_attr_id(), - style: attr.style, - path, - tokens, - is_sugared_doc: false, - span, - })) - .collect() - } else { - vec![] - } - } - - /// Determines if a node with the given attributes should be included in this configuration. - pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { - attrs.iter().all(|attr| { - if !is_cfg(attr) { - return true; - } - - let error = |span, msg, suggestion: &str| { - let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); - if !suggestion.is_empty() { - err.span_suggestion( - span, - "expected syntax is", - suggestion.into(), - Applicability::MaybeIncorrect, - ); - } - err.emit(); - true - }; - - let meta_item = match attr.parse_meta(self.sess) { - Ok(meta_item) => meta_item, - Err(mut err) => { err.emit(); return true; } - }; - let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() { - nested_meta_items - } else { - return error(meta_item.span, "`cfg` is not followed by parentheses", - "cfg(/* predicate */)"); - }; - - if nested_meta_items.is_empty() { - return error(meta_item.span, "`cfg` predicate is not specified", ""); - } else if nested_meta_items.len() > 1 { - return error(nested_meta_items.last().unwrap().span(), - "multiple `cfg` predicates are specified", ""); - } - - match nested_meta_items[0].meta_item() { - Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), - None => error(nested_meta_items[0].span(), - "`cfg` predicate key cannot be a literal", ""), - } - }) - } - - /// Visit attributes on expression and statements (but not attributes on items in blocks). - fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { - // flag the offending attributes - for attr in attrs.iter() { - self.maybe_emit_expr_attr_err(attr); - } - } - - /// If attributes are not allowed on expressions, emit an error for `attr` - pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) { - if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { - let mut err = feature_err(self.sess, - sym::stmt_expr_attributes, - attr.span, - GateIssue::Language, - EXPLAIN_STMT_ATTR_SYNTAX); - - if attr.is_sugared_doc { - err.help("`///` is for documentation comments. For a plain comment, use `//`."); - } - - err.emit(); - } - } - - pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - let ast::ForeignMod { abi: _, items } = foreign_mod; - items.flat_map_in_place(|item| self.configure(item)); - } - - pub fn configure_generic_params(&mut self, params: &mut Vec) { - params.flat_map_in_place(|param| self.configure(param)); - } - - fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { - match vdata { - ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => - fields.flat_map_in_place(|field| self.configure(field)), - ast::VariantData::Unit(_) => {} - } - } - - pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) { - match item { - ast::ItemKind::Struct(def, _generics) | - ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def), - ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => { - variants.flat_map_in_place(|variant| self.configure(variant)); - for variant in variants { - self.configure_variant_data(&mut variant.node.data); - } - } - _ => {} - } - } - - pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) { - match expr_kind { - ast::ExprKind::Match(_m, arms) => { - arms.flat_map_in_place(|arm| self.configure(arm)); - } - ast::ExprKind::Struct(_path, fields, _base) => { - fields.flat_map_in_place(|field| self.configure(field)); - } - _ => {} - } - } - - pub fn configure_expr(&mut self, expr: &mut P) { - self.visit_expr_attrs(expr.attrs()); - - // If an expr is valid to cfg away it will have been removed by the - // outer stmt or expression folder before descending in here. - // Anything else is always required, and thus has to error out - // in case of a cfg attr. - // - // N.B., this is intentionally not part of the visit_expr() function - // in order for filter_map_expr() to be able to avoid this check - if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { - let msg = "removing an expression is not supported in this position"; - self.sess.span_diagnostic.span_err(attr.span, msg); - } - - self.process_cfg_attrs(expr) - } - - pub fn configure_pat(&mut self, pat: &mut P) { - if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.node { - fields.flat_map_in_place(|field| self.configure(field)); - } - } - - pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { - fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); - } -} - -impl<'a> MutVisitor for StripUnconfigured<'a> { - fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - self.configure_foreign_mod(foreign_mod); - noop_visit_foreign_mod(foreign_mod, self); - } - - fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { - self.configure_item_kind(item); - noop_visit_item_kind(item, self); - } - - fn visit_expr(&mut self, expr: &mut P) { - self.configure_expr(expr); - self.configure_expr_kind(&mut expr.node); - noop_visit_expr(expr, self); - } - - fn filter_map_expr(&mut self, expr: P) -> Option> { - let mut expr = configure!(self, expr); - self.configure_expr_kind(&mut expr.node); - noop_visit_expr(&mut expr, self); - Some(expr) - } - - fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { - noop_flat_map_stmt(configure!(self, stmt), self) - } - - fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { - noop_flat_map_item(configure!(self, item), self) - } - - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - noop_flat_map_impl_item(configure!(self, item), self) - } - - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { - noop_flat_map_trait_item(configure!(self, item), self) - } - - fn visit_mac(&mut self, _mac: &mut ast::Mac) { - // Don't configure interpolated AST (cf. issue #34171). - // Interpolated AST will get configured once the surrounding tokens are parsed. - } - - fn visit_pat(&mut self, pat: &mut P) { - self.configure_pat(pat); - noop_visit_pat(pat, self) - } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } -} - -fn is_cfg(attr: &ast::Attribute) -> bool { - attr.check_name(sym::cfg) -} diff --git a/gcc/rust/rustc_parser/libsyntax/diagnostics/macros.rs b/gcc/rust/rustc_parser/libsyntax/diagnostics/macros.rs deleted file mode 100644 index 6f7493a..0000000 --- a/gcc/rust/rustc_parser/libsyntax/diagnostics/macros.rs +++ /dev/null @@ -1,188 +0,0 @@ -#[macro_export] -macro_rules! register_diagnostic { - ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); - ($code:tt) => (__register_diagnostic! { $code }) -} - -#[macro_export] -macro_rules! span_fatal { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.span_fatal_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! span_err { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.span_err_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! span_warn { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.span_warn_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! struct_err { - ($session:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.struct_err_with_code( - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! span_err_or_warn { - ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - if $is_warning { - $session.span_warn_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - } else { - $session.span_err_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - } - }) -} - -#[macro_export] -macro_rules! struct_span_fatal { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.struct_span_fatal_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! struct_span_err { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.struct_span_err_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! stringify_error_code { - ($code:ident) => ({ - __diagnostic_used!($code); - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()) - }) -} - -#[macro_export] -macro_rules! type_error_struct { - ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ - if $typ.references_error() { - $session.diagnostic().struct_dummy() - } else { - struct_span_err!($session, $span, $code, $($message)*) - } - }) -} - -#[macro_export] -macro_rules! struct_span_warn { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.struct_span_warn_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - }) -} - -#[macro_export] -macro_rules! struct_span_err_or_warn { - ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - if $is_warning { - $session.struct_span_warn_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - } else { - $session.struct_span_err_with_code( - $span, - &format!($($message)*), - $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()), - ) - } - }) -} - -#[macro_export] -macro_rules! span_note { - ($err:expr, $span:expr, $($message:tt)*) => ({ - ($err).span_note($span, &format!($($message)*)); - }) -} - -#[macro_export] -macro_rules! span_help { - ($err:expr, $span:expr, $($message:tt)*) => ({ - ($err).span_help($span, &format!($($message)*)); - }) -} - -#[macro_export] -macro_rules! help { - ($err:expr, $($message:tt)*) => ({ - ($err).help(&format!($($message)*)); - }) -} - -#[macro_export] -macro_rules! register_diagnostics { - ($($code:tt),*) => ( - $(register_diagnostic! { $code })* - ); - ($($code:tt),*,) => ( - $(register_diagnostic! { $code })* - ) -} - -#[macro_export] -macro_rules! register_long_diagnostics { - ($($code:tt: $description:tt),*) => ( - $(register_diagnostic! { $code, $description })* - ); - ($($code:tt: $description:tt),*,) => ( - $(register_diagnostic! { $code, $description })* - ) -} diff --git a/gcc/rust/rustc_parser/libsyntax/diagnostics/metadata.rs b/gcc/rust/rustc_parser/libsyntax/diagnostics/metadata.rs deleted file mode 100644 index 53f37bb..0000000 --- a/gcc/rust/rustc_parser/libsyntax/diagnostics/metadata.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! This module contains utilities for outputting metadata for diagnostic errors. -//! -//! Each set of errors is mapped to a metadata file by a name, which is -//! currently always a crate name. - -use std::collections::BTreeMap; -use std::env; -use std::fs::{remove_file, create_dir_all, File}; -use std::io::Write; -use std::path::PathBuf; -use std::error::Error; -use rustc_serialize::json::as_json; - -use syntax_pos::{Span, FileName}; - -use crate::ext::base::ExtCtxt; -use crate::diagnostics::plugin::{ErrorMap, ErrorInfo}; - -/// JSON encodable/decodable version of `ErrorInfo`. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorMetadata { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata that can be (de)serialized. -pub type ErrorMetadataMap = BTreeMap; - -/// JSON encodable error location type with filename and line number. -#[derive(PartialEq, RustcDecodable, RustcEncodable)] -pub struct ErrorLocation { - pub filename: FileName, - pub line: usize -} - -impl ErrorLocation { - /// Creates an error location from a span. - pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation { - let loc = ecx.source_map().lookup_char_pos(sp.lo()); - ErrorLocation { - filename: loc.file.name.clone(), - line: loc.line - } - } -} - -/// Gets the directory where metadata for a given `prefix` should be stored. -/// -/// See `output_metadata`. -pub fn get_metadata_dir(prefix: &str) -> PathBuf { - env::var_os("RUSTC_ERROR_METADATA_DST") - .map(PathBuf::from) - .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set") - .join(prefix) -} - -/// Map `name` to a path in the given directory: /.json -fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf { - directory.join(format!("{}.json", name)) -} - -/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`. -/// -/// For our current purposes the prefix is the target architecture and the name is a crate name. -/// If an error occurs steps will be taken to ensure that no file is created. -pub fn output_metadata(ecx: &ExtCtxt<'_>, prefix: &str, name: &str, err_map: &ErrorMap) - -> Result<(), Box> -{ - // Create the directory to place the file in. - let metadata_dir = get_metadata_dir(prefix); - create_dir_all(&metadata_dir)?; - - // Open the metadata file. - let metadata_path = get_metadata_path(metadata_dir, name); - let mut metadata_file = File::create(&metadata_path)?; - - // Construct a serializable map. - let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| { - let key = k.as_str().to_string(); - let value = ErrorMetadata { - description: description.map(|n| n.as_str().to_string()), - use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp)) - }; - (key, value) - }).collect::(); - - // Write the data to the file, deleting it if the write fails. - let result = write!(&mut metadata_file, "{}", as_json(&json_map)); - if result.is_err() { - remove_file(&metadata_path)?; - } - Ok(result?) -} diff --git a/gcc/rust/rustc_parser/libsyntax/diagnostics/plugin.rs b/gcc/rust/rustc_parser/libsyntax/diagnostics/plugin.rs deleted file mode 100644 index ee640a1..0000000 --- a/gcc/rust/rustc_parser/libsyntax/diagnostics/plugin.rs +++ /dev/null @@ -1,213 +0,0 @@ -use std::collections::BTreeMap; -use std::env; - -use crate::ast::{self, Ident, Name}; -use crate::source_map; -use crate::ext::base::{ExtCtxt, MacEager, MacResult}; -use crate::ext::build::AstBuilder; -use crate::parse::token::{self, Token}; -use crate::ptr::P; -use crate::symbol::kw; -use crate::tokenstream::{TokenTree}; - -use smallvec::smallvec; -use syntax_pos::Span; - -use crate::diagnostics::metadata::output_metadata; - -pub use errors::*; - -// Maximum width of any line in an extended error description (inclusive). -const MAX_DESCRIPTION_WIDTH: usize = 80; - -/// Error information type. -pub struct ErrorInfo { - pub description: Option, - pub use_site: Option -} - -/// Mapping from error codes to metadata. -pub type ErrorMap = BTreeMap; - -pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - let code = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => code, - _ => unreachable!() - }; - - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - match diagnostics.get_mut(&code) { - // Previously used errors. - Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => { - ecx.struct_span_warn(span, &format!( - "diagnostic code {} already used", code - )).span_note(previous_span, "previous invocation") - .emit(); - } - // Newly used errors. - Some(ref mut info) => { - info.use_site = Some(span); - } - // Unregistered errors. - None => { - ecx.span_err(span, &format!( - "used diagnostic code {} not registered", code - )); - } - } - }); - MacEager::expr(ecx.expr_tuple(span, Vec::new())) -} - -pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - let (code, description) = match token_tree { - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }) - ] => { - (*code, None) - }, - [ - TokenTree::Token(Token { kind: token::Ident(code, _), .. }), - TokenTree::Token(Token { kind: token::Comma, .. }), - TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..}) - ] => { - (*code, Some(*symbol)) - }, - _ => unreachable!() - }; - - // Check that the description starts and ends with a newline and doesn't - // overflow the maximum line width. - description.map(|raw_msg| { - let msg = raw_msg.as_str(); - if !msg.starts_with("\n") || !msg.ends_with("\n") { - ecx.span_err(span, &format!( - "description for error code {} doesn't start and end with a newline", - code - )); - } - - // URLs can be unavoidably longer than the line limit, so we allow them. - // Allowed format is: `[name]: https://www.rust-lang.org/` - let is_url = |l: &str| l.starts_with("[") && l.contains("]:") && l.contains("http"); - - if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) { - ecx.span_err(span, &format!( - "description for error code {} contains a line longer than {} characters.\n\ - if you're inserting a long URL use the footnote style to bypass this check.", - code, MAX_DESCRIPTION_WIDTH - )); - } - }); - // Add the error to the map. - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let info = ErrorInfo { - description, - use_site: None - }; - if diagnostics.insert(code, info).is_some() { - ecx.span_err(span, &format!( - "diagnostic code {} already registered", code - )); - } - }); - - MacEager::items(smallvec![]) -} - -#[allow(deprecated)] -pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, - span: Span, - token_tree: &[TokenTree]) - -> Box { - assert_eq!(token_tree.len(), 3); - let (crate_name, ident) = match (&token_tree[0], &token_tree[2]) { - ( - // Crate name. - &TokenTree::Token(Token { kind: token::Ident(crate_name, _), .. }), - // DIAGNOSTICS ident. - &TokenTree::Token(Token { kind: token::Ident(name, _), span }) - ) => (crate_name, Ident::new(name, span)), - _ => unreachable!() - }; - - // Output error metadata to `tmp/extended-errors//.json` - if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") { - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - if let Err(e) = output_metadata(ecx, - &target_triple, - &crate_name.as_str(), - diagnostics) { - ecx.span_bug(span, &format!( - "error writing metadata for triple `{}` and crate `{}`, error: {}, \ - cause: {:?}", - target_triple, crate_name, e.description(), e.cause() - )); - } - }); - } else { - ecx.span_err(span, &format!( - "failed to write metadata for crate `{}` because $CFG_COMPILER_HOST_TRIPLE is not set", - crate_name)); - } - - // Construct the output expression. - let (count, expr) = - ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { - let descriptions: Vec> = - diagnostics.iter().filter_map(|(&code, info)| { - info.description.map(|description| { - ecx.expr_tuple(span, vec![ - ecx.expr_str(span, code), - ecx.expr_str(span, description) - ]) - }) - }).collect(); - (descriptions.len(), ecx.expr_vec(span, descriptions)) - }); - - let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime)); - let ty_str = ecx.ty_rptr( - span, - ecx.ty_ident(span, ecx.ident_of("str")), - Some(static_), - ast::Mutability::Immutable, - ); - - let ty = ecx.ty( - span, - ast::TyKind::Array( - ecx.ty( - span, - ast::TyKind::Tup(vec![ty_str.clone(), ty_str]) - ), - ast::AnonConst { - id: ast::DUMMY_NODE_ID, - value: ecx.expr_usize(span, count), - }, - ), - ); - - MacEager::items(smallvec![ - P(ast::Item { - ident, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Const( - ty, - expr, - ), - vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Public), - span, - tokens: None, - }) - ]) -} diff --git a/gcc/rust/rustc_parser/libsyntax/early_buffered_lints.rs b/gcc/rust/rustc_parser/libsyntax/early_buffered_lints.rs deleted file mode 100644 index b26a116..0000000 --- a/gcc/rust/rustc_parser/libsyntax/early_buffered_lints.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! Allows the buffering of lints for later. -//! -//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat -//! redundant. Later, these types can be converted to types for use by the rest of the compiler. - -use crate::ast::NodeId; -use syntax_pos::MultiSpan; - -/// Since we cannot import `LintId`s from `rustc::lint`, we define some Ids here which can later be -/// passed to `rustc::lint::Lint::from_parser_lint_id` to get a `rustc::lint::Lint`. -pub enum BufferedEarlyLintId { - IllFormedAttributeInput, -} - -/// Stores buffered lint info which can later be passed to `librustc`. -pub struct BufferedEarlyLint { - /// The span of code that we are linting on. - pub span: MultiSpan, - - /// The lint message. - pub msg: String, - - /// The `NodeId` of the AST node that generated the lint. - pub id: NodeId, - - /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`. - pub lint_id: BufferedEarlyLintId, -} diff --git a/gcc/rust/rustc_parser/libsyntax/entry.rs b/gcc/rust/rustc_parser/libsyntax/entry.rs deleted file mode 100644 index 0b6cf30b..0000000 --- a/gcc/rust/rustc_parser/libsyntax/entry.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::attr; -use crate::ast::{Item, ItemKind}; -use crate::symbol::sym; - -pub enum EntryPointType { - None, - MainNamed, - MainAttr, - Start, - OtherMain, // Not an entry point, but some other function named main -} - -// Beware, this is duplicated in librustc/middle/entry.rs, make sure to keep -// them in sync. -pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType { - match item.node { - ItemKind::Fn(..) => { - if attr::contains_name(&item.attrs, sym::start) { - EntryPointType::Start - } else if attr::contains_name(&item.attrs, sym::main) { - EntryPointType::MainAttr - } else if item.ident.name == sym::main { - if depth == 1 { - // This is a top-level function so can be 'main' - EntryPointType::MainNamed - } else { - EntryPointType::OtherMain - } - } else { - EntryPointType::None - } - } - _ => EntryPointType::None, - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/error_codes.rs b/gcc/rust/rustc_parser/libsyntax/error_codes.rs deleted file mode 100644 index e2d212e..0000000 --- a/gcc/rust/rustc_parser/libsyntax/error_codes.rs +++ /dev/null @@ -1,450 +0,0 @@ -#![allow(non_snake_case)] - -// Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { - -E0178: r##" -In types, the `+` type operator has low precedence, so it is often necessary -to use parentheses. - -For example: - -```compile_fail,E0178 -trait Foo {} - -struct Bar<'a> { - w: &'a Foo + Copy, // error, use &'a (Foo + Copy) - x: &'a Foo + 'a, // error, use &'a (Foo + 'a) - y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a) - z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a) -} -``` - -More details can be found in [RFC 438]. - -[RFC 438]: https://github.com/rust-lang/rfcs/pull/438 -"##, - -E0536: r##" -The `not` cfg-predicate was malformed. - -Erroneous code example: - -```compile_fail,E0536 -#[cfg(not())] // error: expected 1 cfg-pattern -pub fn something() {} - -pub fn main() {} -``` - -The `not` predicate expects one cfg-pattern. Example: - -``` -#[cfg(not(target_os = "linux"))] // ok! -pub fn something() {} - -pub fn main() {} -``` - -For more information about the cfg attribute, read: -https://doc.rust-lang.org/reference.html#conditional-compilation -"##, - -E0537: r##" -An unknown predicate was used inside the `cfg` attribute. - -Erroneous code example: - -```compile_fail,E0537 -#[cfg(unknown())] // error: invalid predicate `unknown` -pub fn something() {} - -pub fn main() {} -``` - -The `cfg` attribute supports only three kinds of predicates: - - * any - * all - * not - -Example: - -``` -#[cfg(not(target_os = "linux"))] // ok! -pub fn something() {} - -pub fn main() {} -``` - -For more information about the cfg attribute, read: -https://doc.rust-lang.org/reference.html#conditional-compilation -"##, - -E0538: r##" -Attribute contains same meta item more than once. - -Erroneous code example: - -```compile_fail,E0538 -#[deprecated( - since="1.0.0", - note="First deprecation note.", - note="Second deprecation note." // error: multiple same meta item -)] -fn deprecated_function() {} -``` - -Meta items are the key-value pairs inside of an attribute. Each key may only be -used once in each attribute. - -To fix the problem, remove all but one of the meta items with the same key. - -Example: - -``` -#[deprecated( - since="1.0.0", - note="First deprecation note." -)] -fn deprecated_function() {} -``` -"##, - -E0541: r##" -An unknown meta item was used. - -Erroneous code example: - -```compile_fail,E0541 -#[deprecated( - since="1.0.0", - // error: unknown meta item - reason="Example invalid meta item. Should be 'note'") -] -fn deprecated_function() {} -``` - -Meta items are the key-value pairs inside of an attribute. The keys provided -must be one of the valid keys for the specified attribute. - -To fix the problem, either remove the unknown meta item, or rename it if you -provided the wrong name. - -In the erroneous code example above, the wrong name was provided, so changing -to a correct one it will fix the error. Example: - -``` -#[deprecated( - since="1.0.0", - note="This is a valid meta item for the deprecated attribute." -)] -fn deprecated_function() {} -``` -"##, - -E0552: r##" -A unrecognized representation attribute was used. - -Erroneous code example: - -```compile_fail,E0552 -#[repr(D)] // error: unrecognized representation hint -struct MyStruct { - my_field: usize -} -``` - -You can use a `repr` attribute to tell the compiler how you want a struct or -enum to be laid out in memory. - -Make sure you're using one of the supported options: - -``` -#[repr(C)] // ok! -struct MyStruct { - my_field: usize -} -``` - -For more information about specifying representations, see the ["Alternative -Representations" section] of the Rustonomicon. - -["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html -"##, - -E0554: r##" -Feature attributes are only allowed on the nightly release channel. Stable or -beta compilers will not comply. - -Example of erroneous code (on a stable compiler): - -```ignore (depends on release channel) -#![feature(non_ascii_idents)] // error: #![feature] may not be used on the - // stable release channel -``` - -If you need the feature, make sure to use a nightly release of the compiler -(but be warned that the feature may be removed or altered in the future). -"##, - -E0557: r##" -A feature attribute named a feature that has been removed. - -Erroneous code example: - -```compile_fail,E0557 -#![feature(managed_boxes)] // error: feature has been removed -``` - -Delete the offending feature attribute. -"##, - -E0565: r##" -A literal was used in a built-in attribute that doesn't support literals. - -Erroneous code example: - -```ignore (compile_fail not working here; see Issue #43707) -#[inline("always")] // error: unsupported literal -pub fn something() {} -``` - -Literals in attributes are new and largely unsupported in built-in attributes. -Work to support literals where appropriate is ongoing. Try using an unquoted -name instead: - -``` -#[inline(always)] -pub fn something() {} -``` -"##, - -E0583: r##" -A file wasn't found for an out-of-line module. - -Erroneous code example: - -```ignore (compile_fail not working here; see Issue #43707) -mod file_that_doesnt_exist; // error: file not found for module - -fn main() {} -``` - -Please be sure that a file corresponding to the module exists. If you -want to use a module named `file_that_doesnt_exist`, you need to have a file -named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the -same directory. -"##, - -E0585: r##" -A documentation comment that doesn't document anything was found. - -Erroneous code example: - -```compile_fail,E0585 -fn main() { - // The following doc comment will fail: - /// This is a useless doc comment! -} -``` - -Documentation comments need to be followed by items, including functions, -types, modules, etc. Examples: - -``` -/// I'm documenting the following struct: -struct Foo; - -/// I'm documenting the following function: -fn foo() {} -``` -"##, - -E0586: r##" -An inclusive range was used with no end. - -Erroneous code example: - -```compile_fail,E0586 -fn main() { - let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1..=]; // error: inclusive range was used with no end -} -``` - -An inclusive range needs an end in order to *include* it. If you just need a -start and no end, use a non-inclusive range (with `..`): - -``` -fn main() { - let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1..]; // ok! -} -``` - -Or put an end to your inclusive range: - -``` -fn main() { - let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1..=3]; // ok! -} -``` -"##, - -E0589: r##" -The value of `N` that was specified for `repr(align(N))` was not a power -of two, or was greater than 2^29. - -```compile_fail,E0589 -#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two -enum Foo { - Bar(u64), -} -``` -"##, - -E0658: r##" -An unstable feature was used. - -Erroneous code example: - -```compile_fail,E658 -#[repr(u128)] // error: use of unstable library feature 'repr128' -enum Foo { - Bar(u64), -} -``` - -If you're using a stable or a beta version of rustc, you won't be able to use -any unstable features. In order to do so, please switch to a nightly version of -rustc (by using rustup). - -If you're using a nightly version of rustc, just add the corresponding feature -to be able to use it: - -``` -#![feature(repr128)] - -#[repr(u128)] // ok! -enum Foo { - Bar(u64), -} -``` -"##, - -E0633: r##" -The `unwind` attribute was malformed. - -Erroneous code example: - -```ignore (compile_fail not working here; see Issue #43707) -#[unwind()] // error: expected one argument -pub extern fn something() {} - -fn main() {} -``` - -The `#[unwind]` attribute should be used as follows: - -- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function - should abort the process if it attempts to unwind. This is the safer - and preferred option. - -- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function - should be allowed to unwind. This can easily result in Undefined - Behavior (UB), so be careful. - -NB. The default behavior here is "allowed", but this is unspecified -and likely to change in the future. - -"##, - -E0704: r##" -This error indicates that a incorrect visibility restriction was specified. - -Example of erroneous code: - -```compile_fail,E0704 -mod foo { - pub(foo) struct Bar { - x: i32 - } -} -``` - -To make struct `Bar` only visible in module `foo` the `in` keyword should be -used: -``` -mod foo { - pub(in crate::foo) struct Bar { - x: i32 - } -} -# fn main() {} -``` - -For more information see the Rust Reference on [Visibility]. - -[Visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html -"##, - -E0705: r##" -A `#![feature]` attribute was declared for a feature that is stable in -the current edition, but not in all editions. - -Erroneous code example: - -```ignore (limited to a warning during 2018 edition development) -#![feature(rust_2018_preview)] -#![feature(test_2018_feature)] // error: the feature - // `test_2018_feature` is - // included in the Rust 2018 edition -``` - -"##, - -E0725: r##" -A feature attribute named a feature that was disallowed in the compiler -command line flags. - -Erroneous code example: - -```ignore (can't specify compiler flags from doctests) -#![feature(never_type)] // error: the feature `never_type` is not in - // the list of allowed features -``` - -Delete the offending feature attribute, or add it to the list of allowed -features in the `-Z allow_features` flag. -"##, - -} - -register_diagnostics! { - E0539, // incorrect meta item - E0540, // multiple rustc_deprecated attributes - E0542, // missing 'since' - E0543, // missing 'reason' - E0544, // multiple stability levels - E0545, // incorrect 'issue' - E0546, // missing 'feature' - E0547, // missing 'issue' -// E0548, // replaced with a generic attribute input check - E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute - E0550, // multiple deprecated attributes - E0551, // incorrect meta item - E0553, // multiple rustc_const_unstable attributes -// E0555, // replaced with a generic attribute input check - E0556, // malformed feature, expected just one word - E0584, // file for module `..` found at both .. and .. - E0629, // missing 'feature' (rustc_const_unstable) - E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute - E0693, // incorrect `repr(align)` attribute format - E0694, // an unknown tool name found in scoped attributes - E0703, // invalid ABI - E0717, // rustc_promotable without stability attribute -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/base.rs b/gcc/rust/rustc_parser/libsyntax/ext/base.rs deleted file mode 100644 index 15c0b6c..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/base.rs +++ /dev/null @@ -1,1013 +0,0 @@ -use crate::ast::{self, Attribute, Name, PatKind}; -use crate::attr::{HasAttrs, Stability, Deprecation}; -use crate::source_map::{SourceMap, Spanned, respan}; -use crate::edition::Edition; -use crate::ext::expand::{self, AstFragment, Invocation}; -use crate::ext::hygiene::{Mark, SyntaxContext, Transparency}; -use crate::mut_visit::{self, MutVisitor}; -use crate::parse::{self, parser, DirectoryOwnership}; -use crate::parse::token; -use crate::ptr::P; -use crate::symbol::{kw, sym, Ident, Symbol}; -use crate::{ThinVec, MACRO_ARGUMENTS}; -use crate::tokenstream::{self, TokenStream}; - -use errors::{DiagnosticBuilder, DiagnosticId}; -use smallvec::{smallvec, SmallVec}; -use syntax_pos::{Span, MultiSpan, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnInfo, ExpnFormat}; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::{self, Lrc}; -use std::iter; -use std::path::PathBuf; -use std::rc::Rc; -use std::default::Default; - - -#[derive(Debug,Clone)] -pub enum Annotatable { - Item(P), - TraitItem(P), - ImplItem(P), - ForeignItem(P), - Stmt(P), - Expr(P), -} - -impl HasAttrs for Annotatable { - fn attrs(&self) -> &[Attribute] { - match *self { - Annotatable::Item(ref item) => &item.attrs, - Annotatable::TraitItem(ref trait_item) => &trait_item.attrs, - Annotatable::ImplItem(ref impl_item) => &impl_item.attrs, - Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs, - Annotatable::Stmt(ref stmt) => stmt.attrs(), - Annotatable::Expr(ref expr) => &expr.attrs, - } - } - - fn visit_attrs)>(&mut self, f: F) { - match self { - Annotatable::Item(item) => item.visit_attrs(f), - Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f), - Annotatable::ImplItem(impl_item) => impl_item.visit_attrs(f), - Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f), - Annotatable::Stmt(stmt) => stmt.visit_attrs(f), - Annotatable::Expr(expr) => expr.visit_attrs(f), - } - } -} - -impl Annotatable { - pub fn span(&self) -> Span { - match *self { - Annotatable::Item(ref item) => item.span, - Annotatable::TraitItem(ref trait_item) => trait_item.span, - Annotatable::ImplItem(ref impl_item) => impl_item.span, - Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, - Annotatable::Stmt(ref stmt) => stmt.span, - Annotatable::Expr(ref expr) => expr.span, - } - } - - pub fn expect_item(self) -> P { - match self { - Annotatable::Item(i) => i, - _ => panic!("expected Item") - } - } - - pub fn map_item_or(self, mut f: F, mut or: G) -> Annotatable - where F: FnMut(P) -> P, - G: FnMut(Annotatable) -> Annotatable - { - match self { - Annotatable::Item(i) => Annotatable::Item(f(i)), - _ => or(self) - } - } - - pub fn expect_trait_item(self) -> ast::TraitItem { - match self { - Annotatable::TraitItem(i) => i.into_inner(), - _ => panic!("expected Item") - } - } - - pub fn expect_impl_item(self) -> ast::ImplItem { - match self { - Annotatable::ImplItem(i) => i.into_inner(), - _ => panic!("expected Item") - } - } - - pub fn expect_foreign_item(self) -> ast::ForeignItem { - match self { - Annotatable::ForeignItem(i) => i.into_inner(), - _ => panic!("expected foreign item") - } - } - - pub fn expect_stmt(self) -> ast::Stmt { - match self { - Annotatable::Stmt(stmt) => stmt.into_inner(), - _ => panic!("expected statement"), - } - } - - pub fn expect_expr(self) -> P { - match self { - Annotatable::Expr(expr) => expr, - _ => panic!("expected expression"), - } - } - - pub fn derive_allowed(&self) -> bool { - match *self { - Annotatable::Item(ref item) => match item.node { - ast::ItemKind::Struct(..) | - ast::ItemKind::Enum(..) | - ast::ItemKind::Union(..) => true, - _ => false, - }, - _ => false, - } - } -} - -// `meta_item` is the annotation, and `item` is the item being modified. -// FIXME Decorators should follow the same pattern too. -pub trait MultiItemModifier { - fn expand(&self, - ecx: &mut ExtCtxt<'_>, - span: Span, - meta_item: &ast::MetaItem, - item: Annotatable) - -> Vec; -} - -impl MultiItemModifier for F - where F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T, - T: Into>, -{ - fn expand(&self, - ecx: &mut ExtCtxt<'_>, - span: Span, - meta_item: &ast::MetaItem, - item: Annotatable) - -> Vec { - (*self)(ecx, span, meta_item, item).into() - } -} - -impl Into> for Annotatable { - fn into(self) -> Vec { - vec![self] - } -} - -pub trait ProcMacro { - fn expand<'cx>(&self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - ts: TokenStream) - -> TokenStream; -} - -impl ProcMacro for F - where F: Fn(TokenStream) -> TokenStream -{ - fn expand<'cx>(&self, - _ecx: &'cx mut ExtCtxt<'_>, - _span: Span, - ts: TokenStream) - -> TokenStream { - // FIXME setup implicit context in TLS before calling self. - (*self)(ts) - } -} - -pub trait AttrProcMacro { - fn expand<'cx>(&self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - annotation: TokenStream, - annotated: TokenStream) - -> TokenStream; -} - -impl AttrProcMacro for F - where F: Fn(TokenStream, TokenStream) -> TokenStream -{ - fn expand<'cx>(&self, - _ecx: &'cx mut ExtCtxt<'_>, - _span: Span, - annotation: TokenStream, - annotated: TokenStream) - -> TokenStream { - // FIXME setup implicit context in TLS before calling self. - (*self)(annotation, annotated) - } -} - -/// Represents a thing that maps token trees to Macro Results -pub trait TTMacroExpander { - fn expand<'cx>( - &self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - input: TokenStream, - def_span: Option, - ) -> Box; -} - -pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) - -> Box; - -impl TTMacroExpander for F - where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree]) - -> Box -{ - fn expand<'cx>( - &self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - input: TokenStream, - _def_span: Option, - ) -> Box { - struct AvoidInterpolatedIdents; - - impl MutVisitor for AvoidInterpolatedIdents { - fn visit_tt(&mut self, tt: &mut tokenstream::TokenTree) { - if let tokenstream::TokenTree::Token(token) = tt { - if let token::Interpolated(nt) = &token.kind { - if let token::NtIdent(ident, is_raw) = **nt { - *tt = tokenstream::TokenTree::token( - token::Ident(ident.name, is_raw), ident.span - ); - } - } - } - mut_visit::noop_visit_tt(tt, self) - } - - fn visit_mac(&mut self, mac: &mut ast::Mac) { - mut_visit::noop_visit_mac(mac, self) - } - } - - let input: Vec<_> = - input.trees().map(|mut tt| { AvoidInterpolatedIdents.visit_tt(&mut tt); tt }).collect(); - (*self)(ecx, span, &input) - } -} - -// Use a macro because forwarding to a simple function has type system issues -macro_rules! make_stmts_default { - ($me:expr) => { - $me.make_expr().map(|e| smallvec![ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: e.span, - node: ast::StmtKind::Expr(e), - }]) - } -} - -/// The result of a macro expansion. The return values of the various -/// methods are spliced into the AST at the callsite of the macro. -pub trait MacResult { - /// Creates an expression. - fn make_expr(self: Box) -> Option> { - None - } - /// Creates zero or more items. - fn make_items(self: Box) -> Option; 1]>> { - None - } - - /// Creates zero or more impl items. - fn make_impl_items(self: Box) -> Option> { - None - } - - /// Creates zero or more trait items. - fn make_trait_items(self: Box) -> Option> { - None - } - - /// Creates zero or more items in an `extern {}` block - fn make_foreign_items(self: Box) -> Option> { None } - - /// Creates a pattern. - fn make_pat(self: Box) -> Option> { - None - } - - /// Creates zero or more statements. - /// - /// By default this attempts to create an expression statement, - /// returning None if that fails. - fn make_stmts(self: Box) -> Option> { - make_stmts_default!(self) - } - - fn make_ty(self: Box) -> Option> { - None - } -} - -macro_rules! make_MacEager { - ( $( $fld:ident: $t:ty, )* ) => { - /// `MacResult` implementation for the common case where you've already - /// built each form of AST that you might return. - #[derive(Default)] - pub struct MacEager { - $( - pub $fld: Option<$t>, - )* - } - - impl MacEager { - $( - pub fn $fld(v: $t) -> Box { - Box::new(MacEager { - $fld: Some(v), - ..Default::default() - }) - } - )* - } - } -} - -make_MacEager! { - expr: P, - pat: P, - items: SmallVec<[P; 1]>, - impl_items: SmallVec<[ast::ImplItem; 1]>, - trait_items: SmallVec<[ast::TraitItem; 1]>, - foreign_items: SmallVec<[ast::ForeignItem; 1]>, - stmts: SmallVec<[ast::Stmt; 1]>, - ty: P, -} - -impl MacResult for MacEager { - fn make_expr(self: Box) -> Option> { - self.expr - } - - fn make_items(self: Box) -> Option; 1]>> { - self.items - } - - fn make_impl_items(self: Box) -> Option> { - self.impl_items - } - - fn make_trait_items(self: Box) -> Option> { - self.trait_items - } - - fn make_foreign_items(self: Box) -> Option> { - self.foreign_items - } - - fn make_stmts(self: Box) -> Option> { - match self.stmts.as_ref().map_or(0, |s| s.len()) { - 0 => make_stmts_default!(self), - _ => self.stmts, - } - } - - fn make_pat(self: Box) -> Option> { - if let Some(p) = self.pat { - return Some(p); - } - if let Some(e) = self.expr { - if let ast::ExprKind::Lit(_) = e.node { - return Some(P(ast::Pat { - id: ast::DUMMY_NODE_ID, - span: e.span, - node: PatKind::Lit(e), - })); - } - } - None - } - - fn make_ty(self: Box) -> Option> { - self.ty - } -} - -/// Fill-in macro expansion result, to allow compilation to continue -/// after hitting errors. -#[derive(Copy, Clone)] -pub struct DummyResult { - expr_only: bool, - is_error: bool, - span: Span, -} - -impl DummyResult { - /// Creates a default MacResult that can be anything. - /// - /// Use this as a return value after hitting any errors and - /// calling `span_err`. - pub fn any(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: true, span }) - } - - /// Same as `any`, but must be a valid fragment, not error. - pub fn any_valid(span: Span) -> Box { - Box::new(DummyResult { expr_only: false, is_error: false, span }) - } - - /// Creates a default MacResult that can only be an expression. - /// - /// Use this for macros that must expand to an expression, so even - /// if an error is encountered internally, the user will receive - /// an error that they also used it in the wrong place. - pub fn expr(span: Span) -> Box { - Box::new(DummyResult { expr_only: true, is_error: true, span }) - } - - /// A plain dummy expression. - pub fn raw_expr(sp: Span, is_error: bool) -> P { - P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) }, - span: sp, - attrs: ThinVec::new(), - }) - } - - /// A plain dummy pattern. - pub fn raw_pat(sp: Span) -> ast::Pat { - ast::Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Wild, - span: sp, - } - } - - /// A plain dummy type. - pub fn raw_ty(sp: Span, is_error: bool) -> P { - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(Vec::new()) }, - span: sp - }) - } -} - -impl MacResult for DummyResult { - fn make_expr(self: Box) -> Option> { - Some(DummyResult::raw_expr(self.span, self.is_error)) - } - - fn make_pat(self: Box) -> Option> { - Some(P(DummyResult::raw_pat(self.span))) - } - - fn make_items(self: Box) -> Option; 1]>> { - // this code needs a comment... why not always just return the Some() ? - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } - } - - fn make_impl_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } - } - - fn make_trait_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } - } - - fn make_foreign_items(self: Box) -> Option> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } - } - - fn make_stmts(self: Box) -> Option> { - Some(smallvec![ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.is_error)), - span: self.span, - }]) - } - - fn make_ty(self: Box) -> Option> { - Some(DummyResult::raw_ty(self.span, self.is_error)) - } -} - -/// Represents different kinds of macro invocations that can be resolved. -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum MacroKind { - /// A bang macro - foo!() - Bang, - /// An attribute macro - #[foo] - Attr, - /// A derive attribute macro - #[derive(Foo)] - Derive, - /// A view of a procedural macro from the same crate that defines it. - ProcMacroStub, -} - -impl MacroKind { - pub fn descr(self) -> &'static str { - match self { - MacroKind::Bang => "macro", - MacroKind::Attr => "attribute macro", - MacroKind::Derive => "derive macro", - MacroKind::ProcMacroStub => "crate-local procedural macro", - } - } - - pub fn article(self) -> &'static str { - match self { - MacroKind::Attr => "an", - _ => "a", - } - } -} - -/// A syntax extension kind. -pub enum SyntaxExtensionKind { - /// A token-based function-like macro. - Bang( - /// An expander with signature TokenStream -> TokenStream. - Box, - ), - - /// An AST-based function-like macro. - LegacyBang( - /// An expander with signature TokenStream -> AST. - Box, - ), - - /// A token-based attribute macro. - Attr( - /// An expander with signature (TokenStream, TokenStream) -> TokenStream. - /// The first TokenSteam is the attribute itself, the second is the annotated item. - /// The produced TokenSteam replaces the input TokenSteam. - Box, - ), - - /// An AST-based attribute macro. - LegacyAttr( - /// An expander with signature (AST, AST) -> AST. - /// The first AST fragment is the attribute itself, the second is the annotated item. - /// The produced AST fragment replaces the input AST fragment. - Box, - ), - - /// A trivial attribute "macro" that does nothing, - /// only keeps the attribute and marks it as inert, - /// thus making it ineligible for further expansion. - NonMacroAttr { - /// Suppresses the `unused_attributes` lint for this attribute. - mark_used: bool, - }, - - /// A token-based derive macro. - Derive( - /// An expander with signature TokenStream -> TokenStream (not yet). - /// The produced TokenSteam is appended to the input TokenSteam. - Box, - ), - - /// An AST-based derive macro. - LegacyDerive( - /// An expander with signature AST -> AST. - /// The produced AST fragment is appended to the input AST fragment. - Box, - ), -} - -/// A struct representing a macro definition in "lowered" form ready for expansion. -pub struct SyntaxExtension { - /// A syntax extension kind. - pub kind: SyntaxExtensionKind, - /// Span of the macro definition. - pub span: Span, - /// Hygienic properties of spans produced by this macro by default. - pub default_transparency: Transparency, - /// Whitelist of unstable features that are treated as stable inside this macro. - pub allow_internal_unstable: Option>, - /// Suppresses the `unsafe_code` lint for code produced by this macro. - pub allow_internal_unsafe: bool, - /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. - pub local_inner_macros: bool, - /// The macro's stability info. - pub stability: Option, - /// The macro's deprecation info. - pub deprecation: Option, - /// Names of helper attributes registered by this macro. - pub helper_attrs: Vec, - /// Edition of the crate in which this macro is defined. - pub edition: Edition, -} - -impl SyntaxExtensionKind { - /// When a syntax extension is constructed, - /// its transparency can often be inferred from its kind. - fn default_transparency(&self) -> Transparency { - match self { - SyntaxExtensionKind::Bang(..) | - SyntaxExtensionKind::Attr(..) | - SyntaxExtensionKind::Derive(..) | - SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque, - SyntaxExtensionKind::LegacyBang(..) | - SyntaxExtensionKind::LegacyAttr(..) | - SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent, - } - } -} - -impl SyntaxExtension { - /// Returns which kind of macro calls this syntax extension. - pub fn macro_kind(&self) -> MacroKind { - match self.kind { - SyntaxExtensionKind::Bang(..) | - SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang, - SyntaxExtensionKind::Attr(..) | - SyntaxExtensionKind::LegacyAttr(..) | - SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr, - SyntaxExtensionKind::Derive(..) | - SyntaxExtensionKind::LegacyDerive(..) => MacroKind::Derive, - } - } - - /// Constructs a syntax extension with default properties. - pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { - SyntaxExtension { - span: DUMMY_SP, - default_transparency: kind.default_transparency(), - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - stability: None, - deprecation: None, - helper_attrs: Vec::new(), - edition, - kind, - } - } - - fn expn_format(&self, symbol: Symbol) -> ExpnFormat { - match self.kind { - SyntaxExtensionKind::Bang(..) | - SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol), - _ => ExpnFormat::MacroAttribute(symbol), - } - } - - pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { - ExpnInfo { - call_site, - format: self.expn_format(Symbol::intern(format)), - def_site: Some(self.span), - default_transparency: self.default_transparency, - allow_internal_unstable: self.allow_internal_unstable.clone(), - allow_internal_unsafe: self.allow_internal_unsafe, - local_inner_macros: self.local_inner_macros, - edition: self.edition, - } - } -} - -pub type NamedSyntaxExtension = (Name, SyntaxExtension); - -pub trait Resolver { - fn next_node_id(&mut self) -> ast::NodeId; - - fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; - - fn resolve_dollar_crates(&mut self, fragment: &AstFragment); - fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, - derives: &[Mark]); - fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); - - fn resolve_imports(&mut self); - - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) - -> Result>, Determinacy>; - fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark, - derives_in_scope: Vec, force: bool) - -> Result, Determinacy>; - - fn check_unused_macros(&self); -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Determinacy { - Determined, - Undetermined, -} - -impl Determinacy { - pub fn determined(determined: bool) -> Determinacy { - if determined { Determinacy::Determined } else { Determinacy::Undetermined } - } -} - -#[derive(Clone)] -pub struct ModuleData { - pub mod_path: Vec, - pub directory: PathBuf, -} - -#[derive(Clone)] -pub struct ExpansionData { - pub mark: Mark, - pub depth: usize, - pub module: Rc, - pub directory_ownership: DirectoryOwnership, -} - -/// One of these is made during expansion and incrementally updated as we go; -/// when a macro expansion occurs, the resulting nodes have the `backtrace() -/// -> expn_info` of their expansion context stored into their span. -pub struct ExtCtxt<'a> { - pub parse_sess: &'a parse::ParseSess, - pub ecfg: expand::ExpansionConfig<'a>, - pub root_path: PathBuf, - pub resolver: &'a mut dyn Resolver, - pub current_expansion: ExpansionData, - pub expansions: FxHashMap>, -} - -impl<'a> ExtCtxt<'a> { - pub fn new(parse_sess: &'a parse::ParseSess, - ecfg: expand::ExpansionConfig<'a>, - resolver: &'a mut dyn Resolver) - -> ExtCtxt<'a> { - ExtCtxt { - parse_sess, - ecfg, - root_path: PathBuf::new(), - resolver, - current_expansion: ExpansionData { - mark: Mark::root(), - depth: 0, - module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), - directory_ownership: DirectoryOwnership::Owned { relative: None }, - }, - expansions: FxHashMap::default(), - } - } - - /// Returns a `Folder` for deeply expanding all macros in an AST node. - pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { - expand::MacroExpander::new(self, false) - } - - /// Returns a `Folder` that deeply expands all macros and assigns all `NodeId`s in an AST node. - /// Once `NodeId`s are assigned, the node may not be expanded, removed, or otherwise modified. - pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { - expand::MacroExpander::new(self, true) - } - - pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect(), MACRO_ARGUMENTS) - } - pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() } - pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } - pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config } - pub fn call_site(&self) -> Span { - match self.current_expansion.mark.expn_info() { - Some(expn_info) => expn_info.call_site, - None => DUMMY_SP, - } - } - pub fn backtrace(&self) -> SyntaxContext { - SyntaxContext::empty().apply_mark(self.current_expansion.mark) - } - - /// Returns span for the macro which originally caused the current expansion to happen. - /// - /// Stops backtracing at include! boundary. - pub fn expansion_cause(&self) -> Option { - let mut ctxt = self.backtrace(); - let mut last_macro = None; - loop { - if ctxt.outer_expn_info().map_or(None, |info| { - if info.format.name() == sym::include { - // Stop going up the backtrace once include! is encountered - return None; - } - ctxt = info.call_site.ctxt(); - last_macro = Some(info.call_site); - Some(()) - }).is_none() { - break - } - } - last_macro - } - - pub fn struct_span_warn>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_warn(sp, msg) - } - pub fn struct_span_err>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_err(sp, msg) - } - pub fn struct_span_fatal>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg) - } - - /// Emit `msg` attached to `sp`, and stop compilation immediately. - /// - /// `span_err` should be strongly preferred where-ever possible: - /// this should *only* be used when: - /// - /// - continuing has a high risk of flow-on errors (e.g., errors in - /// declaring a macro would cause all uses of that macro to - /// complain about "undefined macro"), or - /// - there is literally nothing else that can be done (however, - /// in most cases one can construct a dummy expression/item to - /// substitute; we never hit resolve/type-checking so the dummy - /// value doesn't have to match anything) - pub fn span_fatal>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise(); - } - - /// Emit `msg` attached to `sp`, without immediately stopping - /// compilation. - /// - /// Compilation will be stopped in the near future (at the end of - /// the macro expansion phase). - pub fn span_err>(&self, sp: S, msg: &str) { - self.parse_sess.span_diagnostic.span_err(sp, msg); - } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); - } - pub fn mut_span_err>(&self, sp: S, msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.mut_span_err(sp, msg) - } - pub fn span_warn>(&self, sp: S, msg: &str) { - self.parse_sess.span_diagnostic.span_warn(sp, msg); - } - pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_unimpl(sp, msg); - } - pub fn span_bug>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_bug(sp, msg); - } - pub fn trace_macros_diag(&mut self) { - for (sp, notes) in self.expansions.iter() { - let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro"); - for note in notes { - db.note(note); - } - db.emit(); - } - // Fixme: does this result in errors? - self.expansions.clear(); - } - pub fn bug(&self, msg: &str) -> ! { - self.parse_sess.span_diagnostic.bug(msg); - } - pub fn trace_macros(&self) -> bool { - self.ecfg.trace_mac - } - pub fn set_trace_macros(&mut self, x: bool) { - self.ecfg.trace_mac = x - } - pub fn ident_of(&self, st: &str) -> ast::Ident { - ast::Ident::from_str(st) - } - pub fn std_path(&self, components: &[Symbol]) -> Vec { - let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark); - iter::once(Ident::new(kw::DollarCrate, def_site)) - .chain(components.iter().map(|&s| Ident::with_empty_ctxt(s))) - .collect() - } - pub fn name_of(&self, st: &str) -> ast::Name { - Symbol::intern(st) - } - - pub fn check_unused_macros(&self) { - self.resolver.check_unused_macros(); - } -} - -/// Extracts a string literal from the macro expanded version of `expr`, -/// emitting `err_msg` if `expr` is not a string literal. This does not stop -/// compilation on error, merely emits a non-fatal error and returns `None`. -pub fn expr_to_spanned_string<'a>( - cx: &'a mut ExtCtxt<'_>, - mut expr: P, - err_msg: &str, -) -> Result, Option>> { - // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. - expr.span = expr.span.apply_mark(cx.current_expansion.mark); - - // we want to be able to handle e.g., `concat!("foo", "bar")` - cx.expander().visit_expr(&mut expr); - Err(match expr.node { - ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), - ast::LitKind::Err(_) => None, - _ => Some(cx.struct_span_err(l.span, err_msg)) - }, - ast::ExprKind::Err => None, - _ => Some(cx.struct_span_err(expr.span, err_msg)) - }) -} - -pub fn expr_to_string(cx: &mut ExtCtxt<'_>, expr: P, err_msg: &str) - -> Option<(Symbol, ast::StrStyle)> { - expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| err.map(|mut err| err.emit())) - .ok() - .map(|s| s.node) -} - -/// Non-fatally assert that `tts` is empty. Note that this function -/// returns even when `tts` is non-empty, macros that *need* to stop -/// compilation should call -/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be -/// done as rarely as possible). -pub fn check_zero_tts(cx: &ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree], - name: &str) { - if !tts.is_empty() { - cx.span_err(sp, &format!("{} takes no arguments", name)); - } -} - -/// Interpreting `tts` as a comma-separated sequence of expressions, -/// expect exactly one string literal, or emit an error and return `None`. -pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree], - name: &str) - -> Option { - let mut p = cx.new_parser_from_tts(tts); - if p.token == token::Eof { - cx.span_err(sp, &format!("{} takes 1 argument", name)); - return None - } - let ret = panictry!(p.parse_expr()); - let _ = p.eat(&token::Comma); - - if p.token != token::Eof { - cx.span_err(sp, &format!("{} takes 1 argument", name)); - } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| { - s.to_string() - }) -} - -/// Extracts comma-separated expressions from `tts`. If there is a -/// parsing error, emit a non-fatal error and return `None`. -pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) -> Option>> { - let mut p = cx.new_parser_from_tts(tts); - let mut es = Vec::new(); - while p.token != token::Eof { - let mut expr = panictry!(p.parse_expr()); - cx.expander().visit_expr(&mut expr); - es.push(expr); - if p.eat(&token::Comma) { - continue; - } - if p.token != token::Eof { - cx.span_err(sp, "expected token: `,`"); - return None; - } - } - Some(es) -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/build.rs b/gcc/rust/rustc_parser/libsyntax/ext/build.rs deleted file mode 100644 index baf1031..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/build.rs +++ /dev/null @@ -1,1210 +0,0 @@ -use crate::ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; -use crate::attr; -use crate::source_map::{dummy_spanned, respan, Spanned}; -use crate::ext::base::ExtCtxt; -use crate::ptr::P; -use crate::symbol::{kw, sym, Symbol}; -use crate::ThinVec; - -use rustc_target::spec::abi::Abi; -use syntax_pos::{Pos, Span}; - -pub trait AstBuilder { - // Paths - fn path(&self, span: Span, strs: Vec ) -> ast::Path; - fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path; - fn path_global(&self, span: Span, strs: Vec ) -> ast::Path; - fn path_all(&self, sp: Span, - global: bool, - idents: Vec, - args: Vec, - constraints: Vec) - -> ast::Path; - - fn qpath(&self, self_type: P, - trait_path: ast::Path, - ident: ast::Ident) - -> (ast::QSelf, ast::Path); - fn qpath_all(&self, self_type: P, - trait_path: ast::Path, - ident: ast::Ident, - args: Vec, - constraints: Vec) - -> (ast::QSelf, ast::Path); - - // types and consts - fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; - - fn ty(&self, span: Span, ty: ast::TyKind) -> P; - fn ty_path(&self, path: ast::Path) -> P; - fn ty_ident(&self, span: Span, idents: ast::Ident) -> P; - fn anon_const(&self, span: Span, expr: ast::ExprKind) -> ast::AnonConst; - fn const_ident(&self, span: Span, idents: ast::Ident) -> ast::AnonConst; - - fn ty_rptr(&self, span: Span, - ty: P, - lifetime: Option, - mutbl: ast::Mutability) -> P; - fn ty_ptr(&self, span: Span, - ty: P, - mutbl: ast::Mutability) -> P; - - fn ty_infer(&self, sp: Span) -> P; - - fn typaram(&self, - span: Span, - id: ast::Ident, - attrs: Vec, - bounds: ast::GenericBounds, - default: Option>) -> ast::GenericParam; - - fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; - fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef; - fn trait_bound(&self, path: ast::Path) -> ast::GenericBound; - fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime; - fn lifetime_def(&self, - span: Span, - ident: ast::Ident, - attrs: Vec, - bounds: ast::GenericBounds) - -> ast::GenericParam; - - // Statements - fn stmt_expr(&self, expr: P) -> ast::Stmt; - fn stmt_semi(&self, expr: P) -> ast::Stmt; - fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P) -> ast::Stmt; - fn stmt_let_typed(&self, - sp: Span, - mutbl: bool, - ident: ast::Ident, - typ: P, - ex: P) - -> ast::Stmt; - fn stmt_let_type_only(&self, span: Span, ty: P) -> ast::Stmt; - fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt; - - // Blocks - fn block(&self, span: Span, stmts: Vec) -> P; - fn block_expr(&self, expr: P) -> P; - - // Expressions - fn expr(&self, span: Span, node: ast::ExprKind) -> P; - fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P; - fn expr_ident(&self, span: Span, id: ast::Ident) -> P; - - fn expr_self(&self, span: Span) -> P; - fn expr_binary(&self, sp: Span, op: ast::BinOpKind, - lhs: P, rhs: P) -> P; - fn expr_deref(&self, sp: Span, e: P) -> P; - fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P) -> P; - - fn expr_addr_of(&self, sp: Span, e: P) -> P; - fn expr_mut_addr_of(&self, sp: Span, e: P) -> P; - fn expr_field_access(&self, span: Span, expr: P, ident: ast::Ident) -> P; - fn expr_tup_field_access(&self, sp: Span, expr: P, - idx: usize) -> P; - fn expr_call(&self, span: Span, expr: P, args: Vec>) -> P; - fn expr_call_ident(&self, span: Span, id: ast::Ident, args: Vec>) -> P; - fn expr_call_global(&self, sp: Span, fn_path: Vec, - args: Vec> ) -> P; - fn expr_method_call(&self, span: Span, - expr: P, ident: ast::Ident, - args: Vec> ) -> P; - fn expr_block(&self, b: P) -> P; - fn expr_cast(&self, sp: Span, expr: P, ty: P) -> P; - - fn field_imm(&self, span: Span, name: Ident, e: P) -> ast::Field; - fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec) -> P; - fn expr_struct_ident(&self, span: Span, id: ast::Ident, - fields: Vec) -> P; - - fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P; - - fn expr_usize(&self, span: Span, i: usize) -> P; - fn expr_isize(&self, sp: Span, i: isize) -> P; - fn expr_u8(&self, sp: Span, u: u8) -> P; - fn expr_u16(&self, sp: Span, u: u16) -> P; - fn expr_u32(&self, sp: Span, u: u32) -> P; - fn expr_bool(&self, sp: Span, value: bool) -> P; - - fn expr_vec(&self, sp: Span, exprs: Vec>) -> P; - fn expr_vec_ng(&self, sp: Span) -> P; - fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P; - fn expr_str(&self, sp: Span, s: Symbol) -> P; - - fn expr_some(&self, sp: Span, expr: P) -> P; - fn expr_none(&self, sp: Span) -> P; - - fn expr_break(&self, sp: Span) -> P; - - fn expr_tuple(&self, sp: Span, exprs: Vec>) -> P; - - fn expr_fail(&self, span: Span, msg: Symbol) -> P; - fn expr_unreachable(&self, span: Span) -> P; - - fn expr_ok(&self, span: Span, expr: P) -> P; - fn expr_err(&self, span: Span, expr: P) -> P; - fn expr_try(&self, span: Span, head: P) -> P; - - fn pat(&self, span: Span, pat: PatKind) -> P; - fn pat_wild(&self, span: Span) -> P; - fn pat_lit(&self, span: Span, expr: P) -> P; - fn pat_ident(&self, span: Span, ident: ast::Ident) -> P; - - fn pat_ident_binding_mode(&self, - span: Span, - ident: ast::Ident, - bm: ast::BindingMode) -> P; - fn pat_path(&self, span: Span, path: ast::Path) -> P; - fn pat_tuple_struct(&self, span: Span, path: ast::Path, - subpats: Vec>) -> P; - fn pat_struct(&self, span: Span, path: ast::Path, - field_pats: Vec>) -> P; - fn pat_tuple(&self, span: Span, pats: Vec>) -> P; - - fn pat_some(&self, span: Span, pat: P) -> P; - fn pat_none(&self, span: Span) -> P; - - fn pat_ok(&self, span: Span, pat: P) -> P; - fn pat_err(&self, span: Span, pat: P) -> P; - - fn arm(&self, span: Span, pats: Vec>, expr: P) -> ast::Arm; - fn arm_unreachable(&self, span: Span) -> ast::Arm; - - fn expr_match(&self, span: Span, arg: P, arms: Vec ) -> P; - fn expr_if(&self, span: Span, - cond: P, then: P, els: Option>) -> P; - fn expr_loop(&self, span: Span, block: P) -> P; - - fn lambda_fn_decl(&self, - span: Span, - fn_decl: P, - body: P, - fn_decl_span: Span) - -> P; - - fn lambda(&self, span: Span, ids: Vec, body: P) -> P; - fn lambda0(&self, span: Span, body: P) -> P; - fn lambda1(&self, span: Span, body: P, ident: ast::Ident) -> P; - - fn lambda_stmts(&self, span: Span, ids: Vec, - blk: Vec) -> P; - fn lambda_stmts_0(&self, span: Span, stmts: Vec) -> P; - fn lambda_stmts_1(&self, span: Span, stmts: Vec, - ident: ast::Ident) -> P; - - // Items - fn item(&self, span: Span, - name: Ident, attrs: Vec , node: ast::ItemKind) -> P; - - fn arg(&self, span: Span, name: Ident, ty: P) -> ast::Arg; - // FIXME: unused `self` - fn fn_decl(&self, inputs: Vec , output: ast::FunctionRetTy) -> P; - - fn item_fn_poly(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - generics: Generics, - body: P) -> P; - fn item_fn(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - body: P) -> P; - - fn variant(&self, span: Span, name: Ident, tys: Vec> ) -> ast::Variant; - fn item_enum_poly(&self, - span: Span, - name: Ident, - enum_definition: ast::EnumDef, - generics: Generics) -> P; - fn item_enum(&self, span: Span, name: Ident, enum_def: ast::EnumDef) -> P; - - fn item_struct_poly(&self, - span: Span, - name: Ident, - struct_def: ast::VariantData, - generics: Generics) -> P; - fn item_struct(&self, span: Span, name: Ident, struct_def: ast::VariantData) -> P; - - fn item_mod(&self, span: Span, inner_span: Span, - name: Ident, attrs: Vec, - items: Vec>) -> P; - - fn item_extern_crate(&self, span: Span, name: Ident) -> P; - - fn item_static(&self, - span: Span, - name: Ident, - ty: P, - mutbl: ast::Mutability, - expr: P) - -> P; - - fn item_const(&self, - span: Span, - name: Ident, - ty: P, - expr: P) - -> P; - - fn item_ty_poly(&self, - span: Span, - name: Ident, - ty: P, - generics: Generics) -> P; - fn item_ty(&self, span: Span, name: Ident, ty: P) -> P; - - fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute; - - fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem; - - fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem; - - fn meta_list(&self, - sp: Span, - name: ast::Name, - mis: Vec ) - -> ast::MetaItem; - fn meta_name_value(&self, - sp: Span, - name: ast::Name, - value: ast::LitKind) - -> ast::MetaItem; - - fn item_use(&self, sp: Span, - vis: ast::Visibility, vp: P) -> P; - fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P; - fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, - ident: Option, path: ast::Path) -> P; - fn item_use_list(&self, sp: Span, vis: ast::Visibility, - path: Vec, imports: &[ast::Ident]) -> P; - fn item_use_glob(&self, sp: Span, - vis: ast::Visibility, path: Vec) -> P; -} - -impl<'a> AstBuilder for ExtCtxt<'a> { - fn path(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, false, strs, vec![], vec![]) - } - fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { - self.path(span, vec![id]) - } - fn path_global(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, true, strs, vec![], vec![]) - } - fn path_all(&self, - span: Span, - global: bool, - mut idents: Vec , - args: Vec, - constraints: Vec ) - -> ast::Path { - assert!(!idents.is_empty()); - let add_root = global && !idents[0].is_path_segment_keyword(); - let mut segments = Vec::with_capacity(idents.len() + add_root as usize); - if add_root { - segments.push(ast::PathSegment::path_root(span)); - } - let last_ident = idents.pop().unwrap(); - segments.extend(idents.into_iter().map(|ident| { - ast::PathSegment::from_ident(ident.with_span_pos(span)) - })); - let args = if !args.is_empty() || !constraints.is_empty() { - ast::AngleBracketedArgs { args, constraints, span }.into() - } else { - None - }; - segments.push(ast::PathSegment { - ident: last_ident.with_span_pos(span), - id: ast::DUMMY_NODE_ID, - args, - }); - ast::Path { span, segments } - } - - /// Constructs a qualified path. - /// - /// Constructs a path like `::ident`. - fn qpath(&self, - self_type: P, - trait_path: ast::Path, - ident: ast::Ident) - -> (ast::QSelf, ast::Path) { - self.qpath_all(self_type, trait_path, ident, vec![], vec![]) - } - - /// Constructs a qualified path. - /// - /// Constructs a path like `::ident<'a, T, A = Bar>`. - fn qpath_all(&self, - self_type: P, - trait_path: ast::Path, - ident: ast::Ident, - args: Vec, - constraints: Vec) - -> (ast::QSelf, ast::Path) { - let mut path = trait_path; - let args = if !args.is_empty() || !constraints.is_empty() { - ast::AngleBracketedArgs { args, constraints, span: ident.span }.into() - } else { - None - }; - path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args }); - - (ast::QSelf { - ty: self_type, - path_span: path.span, - position: path.segments.len() - 1 - }, path) - } - - fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { - ast::MutTy { - ty, - mutbl, - } - } - - fn ty(&self, span: Span, ty: ast::TyKind) -> P { - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - span, - node: ty - }) - } - - fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyKind::Path(None, path)) - } - - // Might need to take bounds as an argument in the future, if you ever want - // to generate a bounded existential trait type. - fn ty_ident(&self, span: Span, ident: ast::Ident) - -> P { - self.ty_path(self.path_ident(span, ident)) - } - - fn anon_const(&self, span: Span, expr: ast::ExprKind) -> ast::AnonConst { - ast::AnonConst { - id: ast::DUMMY_NODE_ID, - value: P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: expr, - span, - attrs: ThinVec::new(), - }) - } - } - - fn const_ident(&self, span: Span, ident: ast::Ident) -> ast::AnonConst { - self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident))) - } - - fn ty_rptr(&self, - span: Span, - ty: P, - lifetime: Option, - mutbl: ast::Mutability) - -> P { - self.ty(span, - ast::TyKind::Rptr(lifetime, self.ty_mt(ty, mutbl))) - } - - fn ty_ptr(&self, - span: Span, - ty: P, - mutbl: ast::Mutability) - -> P { - self.ty(span, - ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) - } - - fn ty_infer(&self, span: Span) -> P { - self.ty(span, ast::TyKind::Infer) - } - - fn typaram(&self, - span: Span, - ident: ast::Ident, - attrs: Vec, - bounds: ast::GenericBounds, - default: Option>) -> ast::GenericParam { - ast::GenericParam { - ident: ident.with_span_pos(span), - id: ast::DUMMY_NODE_ID, - attrs: attrs.into(), - bounds, - kind: ast::GenericParamKind::Type { - default, - } - } - } - - fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { - ast::TraitRef { - path, - ref_id: ast::DUMMY_NODE_ID, - } - } - - fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { - ast::PolyTraitRef { - bound_generic_params: Vec::new(), - trait_ref: self.trait_ref(path), - span, - } - } - - fn trait_bound(&self, path: ast::Path) -> ast::GenericBound { - ast::GenericBound::Trait(self.poly_trait_ref(path.span, path), - ast::TraitBoundModifier::None) - } - - fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime { - ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) } - } - - fn lifetime_def(&self, - span: Span, - ident: ast::Ident, - attrs: Vec, - bounds: ast::GenericBounds) - -> ast::GenericParam { - let lifetime = self.lifetime(span, ident); - ast::GenericParam { - ident: lifetime.ident, - id: lifetime.id, - attrs: attrs.into(), - bounds, - kind: ast::GenericParamKind::Lifetime, - } - } - - fn stmt_expr(&self, expr: P) -> ast::Stmt { - ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: expr.span, - node: ast::StmtKind::Expr(expr), - } - } - - fn stmt_semi(&self, expr: P) -> ast::Stmt { - ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: expr.span, - node: ast::StmtKind::Semi(expr), - } - } - - fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, - ex: P) -> ast::Stmt { - let pat = if mutbl { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); - self.pat_ident_binding_mode(sp, ident, binding_mode) - } else { - self.pat_ident(sp, ident) - }; - let local = P(ast::Local { - pat, - ty: None, - init: Some(ex), - id: ast::DUMMY_NODE_ID, - span: sp, - attrs: ThinVec::new(), - }); - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Local(local), - span: sp, - } - } - - fn stmt_let_typed(&self, - sp: Span, - mutbl: bool, - ident: ast::Ident, - typ: P, - ex: P) - -> ast::Stmt { - let pat = if mutbl { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); - self.pat_ident_binding_mode(sp, ident, binding_mode) - } else { - self.pat_ident(sp, ident) - }; - let local = P(ast::Local { - pat, - ty: Some(typ), - init: Some(ex), - id: ast::DUMMY_NODE_ID, - span: sp, - attrs: ThinVec::new(), - }); - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Local(local), - span: sp, - } - } - - // Generates `let _: Type;`, which is usually used for type assertions. - fn stmt_let_type_only(&self, span: Span, ty: P) -> ast::Stmt { - let local = P(ast::Local { - pat: self.pat_wild(span), - ty: Some(ty), - init: None, - id: ast::DUMMY_NODE_ID, - span, - attrs: ThinVec::new(), - }); - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Local(local), - span, - } - } - - fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt { - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Item(item), - span: sp, - } - } - - fn block_expr(&self, expr: P) -> P { - self.block(expr.span, vec![ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: expr.span, - node: ast::StmtKind::Expr(expr), - }]) - } - fn block(&self, span: Span, stmts: Vec) -> P { - P(ast::Block { - stmts, - id: ast::DUMMY_NODE_ID, - rules: BlockCheckMode::Default, - span, - }) - } - - fn expr(&self, span: Span, node: ast::ExprKind) -> P { - P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node, - span, - attrs: ThinVec::new(), - }) - } - - fn expr_path(&self, path: ast::Path) -> P { - self.expr(path.span, ast::ExprKind::Path(None, path)) - } - - /// Constructs a `QPath` expression. - fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P { - self.expr(span, ast::ExprKind::Path(Some(qself), path)) - } - - fn expr_ident(&self, span: Span, id: ast::Ident) -> P { - self.expr_path(self.path_ident(span, id)) - } - fn expr_self(&self, span: Span) -> P { - self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower)) - } - - fn expr_binary(&self, sp: Span, op: ast::BinOpKind, - lhs: P, rhs: P) -> P { - self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs)) - } - - fn expr_deref(&self, sp: Span, e: P) -> P { - self.expr_unary(sp, UnOp::Deref, e) - } - fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P) -> P { - self.expr(sp, ast::ExprKind::Unary(op, e)) - } - - fn expr_field_access(&self, sp: Span, expr: P, ident: ast::Ident) -> P { - self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp))) - } - fn expr_tup_field_access(&self, sp: Span, expr: P, idx: usize) -> P { - let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp); - self.expr(sp, ast::ExprKind::Field(expr, ident)) - } - fn expr_addr_of(&self, sp: Span, e: P) -> P { - self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e)) - } - fn expr_mut_addr_of(&self, sp: Span, e: P) -> P { - self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Mutable, e)) - } - - fn expr_call(&self, span: Span, expr: P, args: Vec>) -> P { - self.expr(span, ast::ExprKind::Call(expr, args)) - } - fn expr_call_ident(&self, span: Span, id: ast::Ident, - args: Vec>) -> P { - self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args)) - } - fn expr_call_global(&self, sp: Span, fn_path: Vec , - args: Vec> ) -> P { - let pathexpr = self.expr_path(self.path_global(sp, fn_path)); - self.expr_call(sp, pathexpr, args) - } - fn expr_method_call(&self, span: Span, - expr: P, - ident: ast::Ident, - mut args: Vec> ) -> P { - args.insert(0, expr); - let segment = ast::PathSegment::from_ident(ident.with_span_pos(span)); - self.expr(span, ast::ExprKind::MethodCall(segment, args)) - } - fn expr_block(&self, b: P) -> P { - self.expr(b.span, ast::ExprKind::Block(b, None)) - } - fn field_imm(&self, span: Span, ident: Ident, e: P) -> ast::Field { - ast::Field { - ident: ident.with_span_pos(span), - expr: e, - span, - is_shorthand: false, - attrs: ThinVec::new(), - } - } - fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec) -> P { - self.expr(span, ast::ExprKind::Struct(path, fields, None)) - } - fn expr_struct_ident(&self, span: Span, - id: ast::Ident, fields: Vec) -> P { - self.expr_struct(span, self.path_ident(span, id), fields) - } - - fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P { - let lit = ast::Lit::from_lit_kind(lit_kind, span); - self.expr(span, ast::ExprKind::Lit(lit)) - } - fn expr_usize(&self, span: Span, i: usize) -> P { - self.expr_lit(span, ast::LitKind::Int(i as u128, - ast::LitIntType::Unsigned(ast::UintTy::Usize))) - } - fn expr_isize(&self, sp: Span, i: isize) -> P { - if i < 0 { - let i = (-i) as u128; - let lit_ty = ast::LitIntType::Signed(ast::IntTy::Isize); - let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty)); - self.expr_unary(sp, ast::UnOp::Neg, lit) - } else { - self.expr_lit(sp, ast::LitKind::Int(i as u128, - ast::LitIntType::Signed(ast::IntTy::Isize))) - } - } - fn expr_u32(&self, sp: Span, u: u32) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, - ast::LitIntType::Unsigned(ast::UintTy::U32))) - } - fn expr_u16(&self, sp: Span, u: u16) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, - ast::LitIntType::Unsigned(ast::UintTy::U16))) - } - fn expr_u8(&self, sp: Span, u: u8) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8))) - } - fn expr_bool(&self, sp: Span, value: bool) -> P { - self.expr_lit(sp, ast::LitKind::Bool(value)) - } - - fn expr_vec(&self, sp: Span, exprs: Vec>) -> P { - self.expr(sp, ast::ExprKind::Array(exprs)) - } - fn expr_vec_ng(&self, sp: Span) -> P { - self.expr_call_global(sp, self.std_path(&[sym::vec, sym::Vec, sym::new]), - Vec::new()) - } - fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P { - self.expr_addr_of(sp, self.expr_vec(sp, exprs)) - } - fn expr_str(&self, sp: Span, s: Symbol) -> P { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) - } - - fn expr_cast(&self, sp: Span, expr: P, ty: P) -> P { - self.expr(sp, ast::ExprKind::Cast(expr, ty)) - } - - fn expr_some(&self, sp: Span, expr: P) -> P { - let some = self.std_path(&[sym::option, sym::Option, sym::Some]); - self.expr_call_global(sp, some, vec![expr]) - } - - fn expr_none(&self, sp: Span) -> P { - let none = self.std_path(&[sym::option, sym::Option, sym::None]); - let none = self.path_global(sp, none); - self.expr_path(none) - } - - fn expr_break(&self, sp: Span) -> P { - self.expr(sp, ast::ExprKind::Break(None, None)) - } - - fn expr_tuple(&self, sp: Span, exprs: Vec>) -> P { - self.expr(sp, ast::ExprKind::Tup(exprs)) - } - - fn expr_fail(&self, span: Span, msg: Symbol) -> P { - let loc = self.source_map().lookup_char_pos(span.lo()); - let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name.to_string())); - let expr_line = self.expr_u32(span, loc.line as u32); - let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1); - let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]); - let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple); - self.expr_call_global( - span, - self.std_path(&[sym::rt, sym::begin_panic]), - vec![ - self.expr_str(span, msg), - expr_loc_ptr]) - } - - fn expr_unreachable(&self, span: Span) -> P { - self.expr_fail(span, Symbol::intern("internal error: entered unreachable code")) - } - - fn expr_ok(&self, sp: Span, expr: P) -> P { - let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); - self.expr_call_global(sp, ok, vec![expr]) - } - - fn expr_err(&self, sp: Span, expr: P) -> P { - let err = self.std_path(&[sym::result, sym::Result, sym::Err]); - self.expr_call_global(sp, err, vec![expr]) - } - - fn expr_try(&self, sp: Span, head: P) -> P { - let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); - let ok_path = self.path_global(sp, ok); - let err = self.std_path(&[sym::result, sym::Result, sym::Err]); - let err_path = self.path_global(sp, err); - - let binding_variable = self.ident_of("__try_var"); - let binding_pat = self.pat_ident(sp, binding_variable); - let binding_expr = self.expr_ident(sp, binding_variable); - - // `Ok(__try_var)` pattern - let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]); - - // `Err(__try_var)` (pattern and expression respectively) - let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]); - let err_inner_expr = self.expr_call(sp, self.expr_path(err_path), - vec![binding_expr.clone()]); - // `return Err(__try_var)` - let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); - - // `Ok(__try_var) => __try_var` - let ok_arm = self.arm(sp, vec![ok_pat], binding_expr); - // `Err(__try_var) => return Err(__try_var)` - let err_arm = self.arm(sp, vec![err_pat], err_expr); - - // `match head { Ok() => ..., Err() => ... }` - self.expr_match(sp, head, vec![ok_arm, err_arm]) - } - - - fn pat(&self, span: Span, pat: PatKind) -> P { - P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span }) - } - fn pat_wild(&self, span: Span) -> P { - self.pat(span, PatKind::Wild) - } - fn pat_lit(&self, span: Span, expr: P) -> P { - self.pat(span, PatKind::Lit(expr)) - } - fn pat_ident(&self, span: Span, ident: ast::Ident) -> P { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Immutable); - self.pat_ident_binding_mode(span, ident, binding_mode) - } - - fn pat_ident_binding_mode(&self, - span: Span, - ident: ast::Ident, - bm: ast::BindingMode) -> P { - let pat = PatKind::Ident(bm, ident.with_span_pos(span), None); - self.pat(span, pat) - } - fn pat_path(&self, span: Span, path: ast::Path) -> P { - self.pat(span, PatKind::Path(None, path)) - } - fn pat_tuple_struct(&self, span: Span, path: ast::Path, - subpats: Vec>) -> P { - self.pat(span, PatKind::TupleStruct(path, subpats, None)) - } - fn pat_struct(&self, span: Span, path: ast::Path, - field_pats: Vec>) -> P { - self.pat(span, PatKind::Struct(path, field_pats, false)) - } - fn pat_tuple(&self, span: Span, pats: Vec>) -> P { - self.pat(span, PatKind::Tuple(pats, None)) - } - - fn pat_some(&self, span: Span, pat: P) -> P { - let some = self.std_path(&[sym::option, sym::Option, sym::Some]); - let path = self.path_global(span, some); - self.pat_tuple_struct(span, path, vec![pat]) - } - - fn pat_none(&self, span: Span) -> P { - let some = self.std_path(&[sym::option, sym::Option, sym::None]); - let path = self.path_global(span, some); - self.pat_path(span, path) - } - - fn pat_ok(&self, span: Span, pat: P) -> P { - let some = self.std_path(&[sym::result, sym::Result, sym::Ok]); - let path = self.path_global(span, some); - self.pat_tuple_struct(span, path, vec![pat]) - } - - fn pat_err(&self, span: Span, pat: P) -> P { - let some = self.std_path(&[sym::result, sym::Result, sym::Err]); - let path = self.path_global(span, some); - self.pat_tuple_struct(span, path, vec![pat]) - } - - fn arm(&self, span: Span, pats: Vec>, expr: P) -> ast::Arm { - ast::Arm { - attrs: vec![], - pats, - guard: None, - body: expr, - span, - } - } - - fn arm_unreachable(&self, span: Span) -> ast::Arm { - self.arm(span, vec![self.pat_wild(span)], self.expr_unreachable(span)) - } - - fn expr_match(&self, span: Span, arg: P, arms: Vec) -> P { - self.expr(span, ast::ExprKind::Match(arg, arms)) - } - - fn expr_if(&self, span: Span, cond: P, - then: P, els: Option>) -> P { - let els = els.map(|x| self.expr_block(self.block_expr(x))); - self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els)) - } - - fn expr_loop(&self, span: Span, block: P) -> P { - self.expr(span, ast::ExprKind::Loop(block, None)) - } - - fn lambda_fn_decl(&self, - span: Span, - fn_decl: P, - body: P, - fn_decl_span: Span) // span of the `|...|` part - -> P { - self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, - ast::IsAsync::NotAsync, - ast::Movability::Movable, - fn_decl, - body, - fn_decl_span)) - } - - fn lambda(&self, - span: Span, - ids: Vec, - body: P) - -> P { - let fn_decl = self.fn_decl( - ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), - ast::FunctionRetTy::Default(span)); - - // FIXME -- We are using `span` as the span of the `|...|` - // part of the lambda, but it probably (maybe?) corresponds to - // the entire lambda body. Probably we should extend the API - // here, but that's not entirely clear. - self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, - ast::IsAsync::NotAsync, - ast::Movability::Movable, - fn_decl, - body, - span)) - } - - fn lambda0(&self, span: Span, body: P) -> P { - self.lambda(span, Vec::new(), body) - } - - fn lambda1(&self, span: Span, body: P, ident: ast::Ident) -> P { - self.lambda(span, vec![ident], body) - } - - fn lambda_stmts(&self, - span: Span, - ids: Vec, - stmts: Vec) - -> P { - self.lambda(span, ids, self.expr_block(self.block(span, stmts))) - } - fn lambda_stmts_0(&self, span: Span, stmts: Vec) -> P { - self.lambda0(span, self.expr_block(self.block(span, stmts))) - } - fn lambda_stmts_1(&self, span: Span, stmts: Vec, - ident: ast::Ident) -> P { - self.lambda1(span, self.expr_block(self.block(span, stmts)), ident) - } - - fn arg(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Arg { - let arg_pat = self.pat_ident(span, ident); - ast::Arg { - attrs: ThinVec::default(), - id: ast::DUMMY_NODE_ID, - pat: arg_pat, - ty, - } - } - - // FIXME: unused `self` - fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { - P(ast::FnDecl { - inputs, - output, - c_variadic: false - }) - } - - fn item(&self, span: Span, name: Ident, - attrs: Vec, node: ast::ItemKind) -> P { - // FIXME: Would be nice if our generated code didn't violate - // Rust coding conventions - P(ast::Item { - ident: name, - attrs, - id: ast::DUMMY_NODE_ID, - node, - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - span, - tokens: None, - }) - } - - fn item_fn_poly(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - generics: Generics, - body: P) -> P { - self.item(span, - name, - Vec::new(), - ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)), - ast::FnHeader { - unsafety: ast::Unsafety::Normal, - asyncness: dummy_spanned(ast::IsAsync::NotAsync), - constness: dummy_spanned(ast::Constness::NotConst), - abi: Abi::Rust, - }, - generics, - body)) - } - - fn item_fn(&self, - span: Span, - name: Ident, - inputs: Vec , - output: P, - body: P - ) -> P { - self.item_fn_poly( - span, - name, - inputs, - output, - Generics::default(), - body) - } - - fn variant(&self, span: Span, ident: Ident, tys: Vec> ) -> ast::Variant { - let fields: Vec<_> = tys.into_iter().map(|ty| { - ast::StructField { - span: ty.span, - ty, - ident: None, - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - } - }).collect(); - - let vdata = if fields.is_empty() { - ast::VariantData::Unit(ast::DUMMY_NODE_ID) - } else { - ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID) - }; - - respan(span, - ast::Variant_ { - ident, - id: ast::DUMMY_NODE_ID, - attrs: Vec::new(), - data: vdata, - disr_expr: None, - }) - } - - fn item_enum_poly(&self, span: Span, name: Ident, - enum_definition: ast::EnumDef, - generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Enum(enum_definition, generics)) - } - - fn item_enum(&self, span: Span, name: Ident, - enum_definition: ast::EnumDef) -> P { - self.item_enum_poly(span, name, enum_definition, - Generics::default()) - } - - fn item_struct(&self, span: Span, name: Ident, - struct_def: ast::VariantData) -> P { - self.item_struct_poly( - span, - name, - struct_def, - Generics::default() - ) - } - - fn item_struct_poly(&self, span: Span, name: Ident, - struct_def: ast::VariantData, generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Struct(struct_def, generics)) - } - - fn item_mod(&self, span: Span, inner_span: Span, name: Ident, - attrs: Vec, - items: Vec>) -> P { - self.item( - span, - name, - attrs, - ast::ItemKind::Mod(ast::Mod { - inner: inner_span, - items, - inline: true - }) - ) - } - - fn item_extern_crate(&self, span: Span, name: Ident) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::ExternCrate(None)) - } - - fn item_static(&self, - span: Span, - name: Ident, - ty: P, - mutbl: ast::Mutability, - expr: P) - -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, expr)) - } - - fn item_const(&self, - span: Span, - name: Ident, - ty: P, - expr: P) - -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr)) - } - - fn item_ty_poly(&self, span: Span, name: Ident, ty: P, - generics: Generics) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Ty(ty, generics)) - } - - fn item_ty(&self, span: Span, name: Ident, ty: P) -> P { - self.item_ty_poly(span, name, ty, Generics::default()) - } - - fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute { - attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi) - } - - fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem { - attr::mk_word_item(Ident::with_empty_ctxt(w).with_span_pos(sp)) - } - - fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem { - attr::mk_nested_word_item(Ident::with_empty_ctxt(w).with_span_pos(sp)) - } - - fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec) - -> ast::MetaItem { - attr::mk_list_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp), mis) - } - - fn meta_name_value(&self, span: Span, name: ast::Name, lit_kind: ast::LitKind) - -> ast::MetaItem { - attr::mk_name_value_item(span, Ident::with_empty_ctxt(name).with_span_pos(span), - lit_kind, span) - } - - fn item_use(&self, sp: Span, - vis: ast::Visibility, vp: P) -> P { - P(ast::Item { - id: ast::DUMMY_NODE_ID, - ident: Ident::invalid(), - attrs: vec![], - node: ast::ItemKind::Use(vp), - vis, - span: sp, - tokens: None, - }) - } - - fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P { - self.item_use_simple_(sp, vis, None, path) - } - - fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, - rename: Option, path: ast::Path) -> P { - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: path, - kind: ast::UseTreeKind::Simple(rename, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID), - })) - } - - fn item_use_list(&self, sp: Span, vis: ast::Visibility, - path: Vec, imports: &[ast::Ident]) -> P { - let imports = imports.iter().map(|id| { - (ast::UseTree { - span: sp, - prefix: self.path(sp, vec![*id]), - kind: ast::UseTreeKind::Simple(None, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID), - }, ast::DUMMY_NODE_ID) - }).collect(); - - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: self.path(sp, path), - kind: ast::UseTreeKind::Nested(imports), - })) - } - - fn item_use_glob(&self, sp: Span, - vis: ast::Visibility, path: Vec) -> P { - self.item_use(sp, vis, P(ast::UseTree { - span: sp, - prefix: self.path(sp, path), - kind: ast::UseTreeKind::Glob, - })) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/derive.rs b/gcc/rust/rustc_parser/libsyntax/ext/derive.rs deleted file mode 100644 index 2a56f3d..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/derive.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::attr::HasAttrs; -use crate::ast; -use crate::source_map::{ExpnInfo, ExpnFormat}; -use crate::ext::base::ExtCtxt; -use crate::ext::build::AstBuilder; -use crate::parse::parser::PathStyle; -use crate::symbol::{Symbol, sym}; -use crate::errors::Applicability; - -use syntax_pos::Span; - -use rustc_data_structures::fx::FxHashSet; - -pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) -> Vec { - let mut result = Vec::new(); - attrs.retain(|attr| { - if attr.path != sym::derive { - return true; - } - if !attr.is_meta_item_list() { - cx.struct_span_err(attr.span, "malformed `derive` attribute input") - .span_suggestion( - attr.span, - "missing traits to be derived", - "#[derive(Trait1, Trait2, ...)]".to_owned(), - Applicability::HasPlaceholders, - ).emit(); - return false; - } - - match attr.parse_list(cx.parse_sess, - |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { - Ok(traits) => { - result.extend(traits); - true - } - Err(mut e) => { - e.emit(); - false - } - } - }); - result -} - -pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T) - where T: HasAttrs, -{ - let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned()); - for (i, path) in traits.iter().enumerate() { - if i > 0 { - pretty_name.push_str(", "); - } - pretty_name.push_str(&path.to_string()); - names.insert(unwrap_or!(path.segments.get(0), continue).ident.name); - } - pretty_name.push(')'); - - cx.current_expansion.mark.set_expn_info(ExpnInfo::with_unstable( - ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), span, cx.parse_sess.edition, - &[sym::rustc_attrs, sym::structural_match], - )); - - let span = span.with_ctxt(cx.backtrace()); - item.visit_attrs(|attrs| { - if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) { - let meta = cx.meta_word(span, sym::structural_match); - attrs.push(cx.attribute(span, meta)); - } - if names.contains(&sym::Copy) { - let meta = cx.meta_word(span, sym::rustc_copy_clone_marker); - attrs.push(cx.attribute(span, meta)); - } - }); -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/expand.rs b/gcc/rust/rustc_parser/libsyntax/ext/expand.rs deleted file mode 100644 index 74ef5cb..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/expand.rs +++ /dev/null @@ -1,1471 +0,0 @@ -use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; -use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; -use crate::attr::{self, HasAttrs}; -use crate::source_map::{dummy_spanned, respan}; -use crate::config::StripUnconfigured; -use crate::ext::base::*; -use crate::ext::derive::{add_derived_markers, collect_derives}; -use crate::ext::hygiene::{Mark, SyntaxContext}; -use crate::ext::placeholders::{placeholder, PlaceholderExpander}; -use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; -use crate::mut_visit::*; -use crate::parse::{DirectoryOwnership, PResult, ParseSess}; -use crate::parse::token; -use crate::parse::parser::Parser; -use crate::ptr::P; -use crate::symbol::{sym, Symbol}; -use crate::tokenstream::{TokenStream, TokenTree}; -use crate::visit::{self, Visitor}; -use crate::util::map_in_place::MapInPlace; - -use errors::{Applicability, FatalError}; -use smallvec::{smallvec, SmallVec}; -use syntax_pos::{Span, DUMMY_SP, FileName}; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use std::fs; -use std::io::ErrorKind; -use std::{iter, mem}; -use std::ops::DerefMut; -use std::rc::Rc; -use std::path::PathBuf; - -macro_rules! ast_fragments { - ( - $($Kind:ident($AstTy:ty) { - $kind_name:expr; - $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)? - $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)? - fn $make_ast:ident; - })* - ) => { - /// A fragment of AST that can be produced by a single macro expansion. - /// Can also serve as an input and intermediate result for macro expansion operations. - pub enum AstFragment { - OptExpr(Option>), - $($Kind($AstTy),)* - } - - /// "Discriminant" of an AST fragment. - #[derive(Copy, Clone, PartialEq, Eq)] - pub enum AstFragmentKind { - OptExpr, - $($Kind,)* - } - - impl AstFragmentKind { - pub fn name(self) -> &'static str { - match self { - AstFragmentKind::OptExpr => "expression", - $(AstFragmentKind::$Kind => $kind_name,)* - } - } - - fn make_from<'a>(self, result: Box) -> Option { - match self { - AstFragmentKind::OptExpr => - result.make_expr().map(Some).map(AstFragment::OptExpr), - $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* - } - } - } - - impl AstFragment { - pub fn make_opt_expr(self) -> Option> { - match self { - AstFragment::OptExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - } - - $(pub fn $make_ast(self) -> $AstTy { - match self { - AstFragment::$Kind(ast) => ast, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - })* - - pub fn mut_visit_with(&mut self, vis: &mut F) { - match self { - AstFragment::OptExpr(opt_expr) => { - visit_clobber(opt_expr, |opt_expr| { - if let Some(expr) = opt_expr { - vis.filter_map_expr(expr) - } else { - None - } - }); - } - $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* - $($(AstFragment::$Kind(ast) => - ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)* - } - } - - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { - match *self { - AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr), - AstFragment::OptExpr(None) => {} - $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)* - $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] { - visitor.$visit_ast_elt(ast_elt); - })?)* - } - } - } - - impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> { - fn filter_map_expr(&mut self, expr: P) -> Option> { - self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() - } - $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) { - visit_clobber(ast, |ast| self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()); - })?)* - $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy { - self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() - })?)* - } - - impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { - $(fn $make_ast(self: Box>) - -> Option<$AstTy> { - Some(self.make(AstFragmentKind::$Kind).$make_ast()) - })* - } - } -} - -ast_fragments! { - Expr(P) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; } - Pat(P) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; } - Ty(P) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; } - Stmts(SmallVec<[ast::Stmt; 1]>) { - "statement"; many fn flat_map_stmt; fn visit_stmt; fn make_stmts; - } - Items(SmallVec<[P; 1]>) { - "item"; many fn flat_map_item; fn visit_item; fn make_items; - } - TraitItems(SmallVec<[ast::TraitItem; 1]>) { - "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items; - } - ImplItems(SmallVec<[ast::ImplItem; 1]>) { - "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items; - } - ForeignItems(SmallVec<[ast::ForeignItem; 1]>) { - "foreign item"; many fn flat_map_foreign_item; fn visit_foreign_item; fn make_foreign_items; - } -} - -impl AstFragmentKind { - fn dummy(self, span: Span) -> Option { - self.make_from(DummyResult::any(span)) - } - - fn expect_from_annotatables>(self, items: I) - -> AstFragment { - let mut items = items.into_iter(); - match self { - AstFragmentKind::Items => - AstFragment::Items(items.map(Annotatable::expect_item).collect()), - AstFragmentKind::ImplItems => - AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect()), - AstFragmentKind::TraitItems => - AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect()), - AstFragmentKind::ForeignItems => - AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()), - AstFragmentKind::Stmts => - AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect()), - AstFragmentKind::Expr => AstFragment::Expr( - items.next().expect("expected exactly one expression").expect_expr() - ), - AstFragmentKind::OptExpr => - AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)), - AstFragmentKind::Pat | AstFragmentKind::Ty => - panic!("patterns and types aren't annotatable"), - } - } -} - -pub struct Invocation { - pub kind: InvocationKind, - fragment_kind: AstFragmentKind, - pub expansion_data: ExpansionData, -} - -pub enum InvocationKind { - Bang { - mac: ast::Mac, - span: Span, - }, - Attr { - attr: Option, - traits: Vec, - item: Annotatable, - // We temporarily report errors for attribute macros placed after derives - after_derive: bool, - }, - Derive { - path: Path, - item: Annotatable, - }, -} - -impl Invocation { - pub fn span(&self) -> Span { - match self.kind { - InvocationKind::Bang { span, .. } => span, - InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span, - InvocationKind::Attr { attr: None, .. } => DUMMY_SP, - InvocationKind::Derive { ref path, .. } => path.span, - } - } -} - -pub struct MacroExpander<'a, 'b> { - pub cx: &'a mut ExtCtxt<'b>, - monotonic: bool, // cf. `cx.monotonic_expander()` -} - -impl<'a, 'b> MacroExpander<'a, 'b> { - pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - MacroExpander { cx, monotonic } - } - - pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - let mut module = ModuleData { - mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], - directory: match self.cx.source_map().span_to_unmapped_path(krate.span) { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), - }, - }; - module.directory.pop(); - self.cx.root_path = module.directory.clone(); - self.cx.current_expansion.module = Rc::new(module); - - let orig_mod_span = krate.module.inner; - - let krate_item = AstFragment::Items(smallvec![P(ast::Item { - attrs: krate.attrs, - span: krate.span, - node: ast::ItemKind::Mod(krate.module), - ident: Ident::invalid(), - id: ast::DUMMY_NODE_ID, - vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public), - tokens: None, - })]); - - match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) { - Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => { - krate.attrs = attrs; - krate.module = module; - }, - None => { - // Resolution failed so we return an empty expansion - krate.attrs = vec![]; - krate.module = ast::Mod { - inner: orig_mod_span, - items: vec![], - inline: true, - }; - }, - _ => unreachable!(), - }; - self.cx.trace_macros_diag(); - krate - } - - // Fully expand all macro invocations in this AST fragment. - fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { - let orig_expansion_data = self.cx.current_expansion.clone(); - self.cx.current_expansion.depth = 0; - - // Collect all macro invocations and replace them with placeholders. - let (mut fragment_with_placeholders, mut invocations) - = self.collect_invocations(input_fragment, &[]); - - // Optimization: if we resolve all imports now, - // we'll be able to immediately resolve most of imported macros. - self.resolve_imports(); - - // Resolve paths in all invocations and produce output expanded fragments for them, but - // do not insert them into our input AST fragment yet, only store in `expanded_fragments`. - // The output fragments also go through expansion recursively until no invocations are left. - // Unresolved macros produce dummy outputs as a recovery measure. - invocations.reverse(); - let mut expanded_fragments = Vec::new(); - let mut derives: FxHashMap> = FxHashMap::default(); - let mut undetermined_invocations = Vec::new(); - let (mut progress, mut force) = (false, !self.monotonic); - loop { - let invoc = if let Some(invoc) = invocations.pop() { - invoc - } else { - self.resolve_imports(); - if undetermined_invocations.is_empty() { break } - invocations = mem::take(&mut undetermined_invocations); - force = !mem::replace(&mut progress, false); - continue - }; - - let scope = - if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; - let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) { - Ok(ext) => Some(ext), - Err(Determinacy::Determined) => None, - Err(Determinacy::Undetermined) => { - undetermined_invocations.push(invoc); - continue - } - }; - - progress = true; - let ExpansionData { depth, mark, .. } = invoc.expansion_data; - self.cx.current_expansion = invoc.expansion_data.clone(); - - self.cx.current_expansion.mark = scope; - // FIXME(jseyfried): Refactor out the following logic - let (expanded_fragment, new_invocations) = if let Some(ext) = ext { - if let Some(ext) = ext { - let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span()); - let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| { - invoc_fragment_kind.dummy(invoc_span).unwrap() - }); - self.collect_invocations(fragment, &[]) - } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind { - if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), sym::derive) - .expect("`derive` attribute should exist"); - let span = attr.span; - let mut err = self.cx.mut_span_err(span, - "`derive` may only be applied to \ - structs, enums and unions"); - if let ast::AttrStyle::Inner = attr.style { - let trait_list = traits.iter() - .map(|t| t.to_string()).collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, "try an outer attribute", suggestion, - // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT - Applicability::MaybeIncorrect - ); - } - err.emit(); - } - - let mut item = self.fully_configure(item); - item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let mut item_with_markers = item.clone(); - add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers); - let derives = derives.entry(invoc.expansion_data.mark).or_default(); - - derives.reserve(traits.len()); - invocations.reserve(traits.len()); - for path in &traits { - let mark = Mark::fresh(self.cx.current_expansion.mark); - derives.push(mark); - let item = match self.cx.resolver.resolve_macro_path( - path, MacroKind::Derive, Mark::root(), Vec::new(), false) { - Ok(ext) => match ext.kind { - SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(), - _ => item.clone(), - }, - _ => item.clone(), - }; - invocations.push(Invocation { - kind: InvocationKind::Derive { path: path.clone(), item }, - fragment_kind: invoc.fragment_kind, - expansion_data: ExpansionData { - mark, - ..invoc.expansion_data.clone() - }, - }); - } - let fragment = invoc.fragment_kind - .expect_from_annotatables(::std::iter::once(item_with_markers)); - self.collect_invocations(fragment, derives) - } else { - unreachable!() - } - } else { - self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[]) - }; - - if expanded_fragments.len() < depth { - expanded_fragments.push(Vec::new()); - } - expanded_fragments[depth - 1].push((mark, expanded_fragment)); - if !self.cx.ecfg.single_step { - invocations.extend(new_invocations.into_iter().rev()); - } - } - - self.cx.current_expansion = orig_expansion_data; - - // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); - while let Some(expanded_fragments) = expanded_fragments.pop() { - for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_mark(mark), - expanded_fragment, derives); - } - } - fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); - fragment_with_placeholders - } - - fn resolve_imports(&mut self) { - if self.monotonic { - self.cx.resolver.resolve_imports(); - } - } - - /// Collects all macro invocations reachable at this time in this AST fragment, and replace - /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s. - /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and - /// prepares data for resolving paths of macro invocations. - fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[Mark]) - -> (AstFragment, Vec) { - // Resolve `$crate`s in the fragment for pretty-printing. - self.cx.resolver.resolve_dollar_crates(&fragment); - - let invocations = { - let mut collector = InvocationCollector { - cfg: StripUnconfigured { - sess: self.cx.parse_sess, - features: self.cx.ecfg.features, - }, - cx: self.cx, - invocations: Vec::new(), - monotonic: self.monotonic, - }; - fragment.mut_visit_with(&mut collector); - collector.invocations - }; - - if self.monotonic { - self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.mark, &fragment, derives); - } - - (fragment, invocations) - } - - fn fully_configure(&mut self, item: Annotatable) -> Annotatable { - let mut cfg = StripUnconfigured { - sess: self.cx.parse_sess, - features: self.cx.ecfg.features, - }; - // Since the item itself has already been configured by the InvocationCollector, - // we know that fold result vector will contain exactly one element - match item { - Annotatable::Item(item) => { - Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()) - } - Annotatable::TraitItem(item) => { - Annotatable::TraitItem( - item.map(|item| cfg.flat_map_trait_item(item).pop().unwrap())) - } - Annotatable::ImplItem(item) => { - Annotatable::ImplItem(item.map(|item| cfg.flat_map_impl_item(item).pop().unwrap())) - } - Annotatable::ForeignItem(item) => { - Annotatable::ForeignItem( - item.map(|item| cfg.flat_map_foreign_item(item).pop().unwrap()) - ) - } - Annotatable::Stmt(stmt) => { - Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap())) - } - Annotatable::Expr(mut expr) => { - Annotatable::Expr({ cfg.visit_expr(&mut expr); expr }) - } - } - } - - fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option { - if invoc.fragment_kind == AstFragmentKind::ForeignItems && - !self.cx.ecfg.macros_in_extern() { - if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else { - emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern, - invoc.span(), GateIssue::Language, - "macro invocations in `extern {}` blocks are experimental"); - } - } - - let result = match invoc.kind { - InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?, - InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?, - InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?, - }; - - if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - let info = self.cx.current_expansion.mark.expn_info().unwrap(); - let suggested_limit = self.cx.ecfg.recursion_limit * 2; - let mut err = self.cx.struct_span_err(info.call_site, - &format!("recursion limit reached while expanding the macro `{}`", - info.format.name())); - err.help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", - suggested_limit)); - err.emit(); - self.cx.trace_macros_diag(); - FatalError.raise(); - } - - Some(result) - } - - fn expand_attr_invoc(&mut self, - invoc: Invocation, - ext: &SyntaxExtension) - -> Option { - let (attr, mut item) = match invoc.kind { - InvocationKind::Attr { attr, item, .. } => (attr?, item), - _ => unreachable!(), - }; - - match &ext.kind { - SyntaxExtensionKind::NonMacroAttr { mark_used } => { - attr::mark_known(&attr); - if *mark_used { - attr::mark_used(&attr); - } - item.visit_attrs(|attrs| attrs.push(attr)); - Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item))) - } - SyntaxExtensionKind::LegacyAttr(expander) => { - let meta = attr.parse_meta(self.cx.parse_sess) - .map_err(|mut e| { e.emit(); }).ok()?; - let item = expander.expand(self.cx, attr.span, &meta, item); - Some(invoc.fragment_kind.expect_from_annotatables(item)) - } - SyntaxExtensionKind::Attr(expander) => { - self.gate_proc_macro_attr_item(attr.span, &item); - let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item { - Annotatable::Item(item) => token::NtItem(item), - Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()), - Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()), - Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()), - Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), - Annotatable::Expr(expr) => token::NtExpr(expr), - })), DUMMY_SP).into(); - let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span); - let tok_result = expander.expand(self.cx, attr.span, input, item_tok); - let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind, - &attr.path, attr.span); - self.gate_proc_macro_expansion(attr.span, &res); - res - } - SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { - self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path)); - self.cx.trace_macros_diag(); - invoc.fragment_kind.dummy(attr.span) - } - _ => { - let msg = &format!("macro `{}` may not be used in attributes", attr.path); - self.cx.span_err(attr.span, msg); - self.cx.trace_macros_diag(); - invoc.fragment_kind.dummy(attr.span) - } - } - } - - fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream { - let mut trees = tokens.trees(); - match trees.next() { - Some(TokenTree::Delimited(_, _, tts)) => { - if trees.next().is_none() { - return tts.into() - } - } - Some(TokenTree::Token(..)) => {} - None => return TokenStream::empty(), - } - self.cx.span_err(span, "custom attribute invocations must be \ - of the form #[foo] or #[foo(..)], the macro name must only be \ - followed by a delimiter token"); - TokenStream::empty() - } - - fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { - let (kind, gate) = match *item { - Annotatable::Item(ref item) => { - match item.node { - ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return, - ItemKind::Mod(_) => ("modules", sym::proc_macro_hygiene), - _ => return, - } - } - Annotatable::TraitItem(_) => return, - Annotatable::ImplItem(_) => return, - Annotatable::ForeignItem(_) => return, - Annotatable::Stmt(_) | - Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return, - Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene), - Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene), - }; - emit_feature_err( - self.cx.parse_sess, - gate, - span, - GateIssue::Language, - &format!("custom attributes cannot be applied to {}", kind), - ); - } - - fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option) { - if self.cx.ecfg.proc_macro_hygiene() { - return - } - let fragment = match fragment { - Some(fragment) => fragment, - None => return, - }; - - fragment.visit_with(&mut DisallowMacros { - span, - parse_sess: self.cx.parse_sess, - }); - - struct DisallowMacros<'a> { - span: Span, - parse_sess: &'a ParseSess, - } - - impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> { - fn visit_item(&mut self, i: &'ast ast::Item) { - if let ast::ItemKind::MacroDef(_) = i.node { - emit_feature_err( - self.parse_sess, - sym::proc_macro_hygiene, - self.span, - GateIssue::Language, - "procedural macros cannot expand to macro definitions", - ); - } - visit::walk_item(self, i); - } - - fn visit_mac(&mut self, _mac: &'ast ast::Mac) { - // ... - } - } - } - - /// Expand a macro invocation. Returns the resulting expanded AST fragment. - fn expand_bang_invoc(&mut self, - invoc: Invocation, - ext: &SyntaxExtension) - -> Option { - let kind = invoc.fragment_kind; - let (mac, span) = match invoc.kind { - InvocationKind::Bang { mac, span } => (mac, span), - _ => unreachable!(), - }; - let path = &mac.node.path; - - let opt_expanded = match &ext.kind { - SyntaxExtensionKind::Bang(expander) => { - self.gate_proc_macro_expansion_kind(span, kind); - let tok_result = expander.expand(self.cx, span, mac.node.stream()); - let result = self.parse_ast_fragment(tok_result, kind, path, span); - self.gate_proc_macro_expansion(span, &result); - result - } - SyntaxExtensionKind::LegacyBang(expander) => { - let tok_result = expander.expand(self.cx, span, mac.node.stream(), Some(ext.span)); - kind.make_from(tok_result) - } - - SyntaxExtensionKind::Attr(..) | - SyntaxExtensionKind::LegacyAttr(..) | - SyntaxExtensionKind::NonMacroAttr { .. } => { - self.cx.span_err(path.span, - &format!("`{}` can only be used in attributes", path)); - self.cx.trace_macros_diag(); - kind.dummy(span) - } - - SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { - self.cx.span_err(path.span, &format!("`{}` is a derive macro", path)); - self.cx.trace_macros_diag(); - kind.dummy(span) - } - }; - - if opt_expanded.is_some() { - opt_expanded - } else { - let msg = format!("non-{kind} macro in {kind} position: {name}", - name = path.segments[0].ident.name, kind = kind.name()); - self.cx.span_err(path.span, &msg); - self.cx.trace_macros_diag(); - kind.dummy(span) - } - } - - fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) { - let kind = match kind { - AstFragmentKind::Expr => "expressions", - AstFragmentKind::OptExpr => "expressions", - AstFragmentKind::Pat => "patterns", - AstFragmentKind::Ty => "types", - AstFragmentKind::Stmts => "statements", - AstFragmentKind::Items => return, - AstFragmentKind::TraitItems => return, - AstFragmentKind::ImplItems => return, - AstFragmentKind::ForeignItems => return, - }; - if self.cx.ecfg.proc_macro_hygiene() { - return - } - emit_feature_err( - self.cx.parse_sess, - sym::proc_macro_hygiene, - span, - GateIssue::Language, - &format!("procedural macros cannot be expanded to {}", kind), - ); - } - - /// Expand a derive invocation. Returns the resulting expanded AST fragment. - fn expand_derive_invoc(&mut self, - invoc: Invocation, - ext: &SyntaxExtension) - -> Option { - let (path, item) = match invoc.kind { - InvocationKind::Derive { path, item } => (path, item), - _ => unreachable!(), - }; - if !item.derive_allowed() { - return None; - } - - match &ext.kind { - SyntaxExtensionKind::Derive(expander) | - SyntaxExtensionKind::LegacyDerive(expander) => { - let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path }; - let span = meta.span.with_ctxt(self.cx.backtrace()); - let items = expander.expand(self.cx, span, &meta, item); - Some(invoc.fragment_kind.expect_from_annotatables(items)) - } - _ => { - let msg = &format!("macro `{}` may not be used for derive attributes", path); - self.cx.span_err(path.span, msg); - self.cx.trace_macros_diag(); - invoc.fragment_kind.dummy(path.span) - } - } - } - - fn parse_ast_fragment(&mut self, - toks: TokenStream, - kind: AstFragmentKind, - path: &Path, - span: Span) - -> Option { - let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); - match parser.parse_ast_fragment(kind, false) { - Ok(fragment) => { - parser.ensure_complete_parse(path, kind.name(), span); - Some(fragment) - } - Err(mut err) => { - err.set_span(span); - err.emit(); - self.cx.trace_macros_diag(); - kind.dummy(span) - } - } - } -} - -impl<'a> Parser<'a> { - pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool) - -> PResult<'a, AstFragment> { - Ok(match kind { - AstFragmentKind::Items => { - let mut items = SmallVec::new(); - while let Some(item) = self.parse_item()? { - items.push(item); - } - AstFragment::Items(items) - } - AstFragmentKind::TraitItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_trait_item(&mut false)?); - } - AstFragment::TraitItems(items) - } - AstFragmentKind::ImplItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_impl_item(&mut false)?); - } - AstFragment::ImplItems(items) - } - AstFragmentKind::ForeignItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_foreign_item()?); - } - AstFragment::ForeignItems(items) - } - AstFragmentKind::Stmts => { - let mut stmts = SmallVec::new(); - while self.token != token::Eof && - // won't make progress on a `}` - self.token != token::CloseDelim(token::Brace) { - if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? { - stmts.push(stmt); - } - } - AstFragment::Stmts(stmts) - } - AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?), - AstFragmentKind::OptExpr => { - if self.token != token::Eof { - AstFragment::OptExpr(Some(self.parse_expr()?)) - } else { - AstFragment::OptExpr(None) - } - }, - AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?), - AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?), - }) - } - - pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) { - if self.token != token::Eof { - let msg = format!("macro expansion ignores token `{}` and any following", - self.this_token_to_string()); - // Avoid emitting backtrace info twice. - let def_site_span = self.token.span.with_ctxt(SyntaxContext::empty()); - let mut err = self.diagnostic().struct_span_err(def_site_span, &msg); - err.span_label(span, "caused by the macro expansion here"); - let msg = format!( - "the usage of `{}!` is likely invalid in {} context", - macro_path, - kind_name, - ); - err.note(&msg); - let semi_span = self.sess.source_map().next_point(span); - - let semi_full_span = semi_span.to(self.sess.source_map().next_point(semi_span)); - match self.sess.source_map().span_to_snippet(semi_full_span) { - Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => { - err.span_suggestion( - semi_span, - "you might be missing a semicolon here", - ";".to_owned(), - Applicability::MaybeIncorrect, - ); - } - _ => {} - } - err.emit(); - } - } -} - -struct InvocationCollector<'a, 'b> { - cx: &'a mut ExtCtxt<'b>, - cfg: StripUnconfigured<'a>, - invocations: Vec, - monotonic: bool, -} - -impl<'a, 'b> InvocationCollector<'a, 'b> { - fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - let mark = Mark::fresh(self.cx.current_expansion.mark); - self.invocations.push(Invocation { - kind, - fragment_kind, - expansion_data: ExpansionData { - mark, - depth: self.cx.current_expansion.depth + 1, - ..self.cx.current_expansion.clone() - }, - }); - placeholder(fragment_kind, NodeId::placeholder_from_mark(mark)) - } - - fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment { - self.collect(kind, InvocationKind::Bang { mac, span }) - } - - fn collect_attr(&mut self, - attr: Option, - traits: Vec, - item: Annotatable, - kind: AstFragmentKind, - after_derive: bool) - -> AstFragment { - self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive }) - } - - fn find_attr_invoc(&self, attrs: &mut Vec, after_derive: &mut bool) - -> Option { - let attr = attrs.iter() - .position(|a| { - if a.path == sym::derive { - *after_derive = true; - } - !attr::is_known(a) && !is_builtin_attr(a) - }) - .map(|i| attrs.remove(i)); - if let Some(attr) = &attr { - if !self.cx.ecfg.custom_inner_attributes() && - attr.style == ast::AttrStyle::Inner && attr.path != sym::test { - emit_feature_err(&self.cx.parse_sess, sym::custom_inner_attributes, - attr.span, GateIssue::Language, - "non-builtin inner attributes are unstable"); - } - } - attr - } - - /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. - fn classify_item(&mut self, item: &mut T) - -> (Option, Vec, /* after_derive */ bool) - where T: HasAttrs, - { - let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); - - item.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); - traits = collect_derives(&mut self.cx, &mut attrs); - }); - - (attr, traits, after_derive) - } - - /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough - /// to the unused-attributes lint (making it an error on statements and expressions - /// is a breaking change) - fn classify_nonitem(&mut self, nonitem: &mut T) - -> (Option, /* after_derive */ bool) { - let (mut attr, mut after_derive) = (None, false); - - nonitem.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); - }); - - (attr, after_derive) - } - - fn configure(&mut self, node: T) -> Option { - self.cfg.configure(node) - } - - // Detect use of feature-gated or invalid attributes on macro invocations - // since they will not be detected after macro expansion. - fn check_attributes(&mut self, attrs: &[ast::Attribute]) { - let features = self.cx.ecfg.features.unwrap(); - for attr in attrs.iter() { - self.check_attribute_inner(attr, features); - - // macros are expanded before any lint passes so this warning has to be hardcoded - if attr.path == sym::derive { - self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") - .note("this may become a hard error in a future release") - .emit(); - } - } - } - - fn check_attribute(&mut self, at: &ast::Attribute) { - let features = self.cx.ecfg.features.unwrap(); - self.check_attribute_inner(at, features); - } - - fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) { - feature_gate::check_attribute(at, self.cx.parse_sess, features); - } -} - -impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { - fn visit_expr(&mut self, expr: &mut P) { - self.cfg.configure_expr(expr); - visit_clobber(expr.deref_mut(), |mut expr| { - self.cfg.configure_expr_kind(&mut expr.node); - - // ignore derives so they remain unused - let (attr, after_derive) = self.classify_nonitem(&mut expr); - - if attr.is_some() { - // Collect the invoc regardless of whether or not attributes are permitted here - // expansion will eat the attribute so it won't error later. - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - - // AstFragmentKind::Expr requires the macro to emit an expression. - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, after_derive) - .make_expr() - .into_inner() - } - - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::Expr) - .make_expr() - .into_inner() - } else { - noop_visit_expr(&mut expr, self); - expr - } - }); - } - - fn filter_map_expr(&mut self, expr: P) -> Option> { - let expr = configure!(self, expr); - expr.filter_map(|mut expr| { - self.cfg.configure_expr_kind(&mut expr.node); - - // Ignore derives so they remain unused. - let (attr, after_derive) = self.classify_nonitem(&mut expr); - - if attr.is_some() { - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, after_derive) - .make_opt_expr() - .map(|expr| expr.into_inner()) - } - - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) - .make_opt_expr() - .map(|expr| expr.into_inner()) - } else { - Some({ noop_visit_expr(&mut expr, self); expr }) - } - }) - } - - fn visit_pat(&mut self, pat: &mut P) { - self.cfg.configure_pat(pat); - match pat.node { - PatKind::Mac(_) => {} - _ => return noop_visit_pat(pat, self), - } - - visit_clobber(pat, |mut pat| { - match mem::replace(&mut pat.node, PatKind::Wild) { - PatKind::Mac(mac) => - self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(), - _ => unreachable!(), - } - }); - } - - fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { - let mut stmt = configure!(self, stmt); - - // we'll expand attributes on expressions separately - if !stmt.is_expr() { - let (attr, derives, after_derive) = if stmt.is_item() { - self.classify_item(&mut stmt) - } else { - // ignore derives on non-item statements so it falls through - // to the unused-attributes lint - let (attr, after_derive) = self.classify_nonitem(&mut stmt); - (attr, vec![], after_derive) - }; - - if attr.is_some() || !derives.is_empty() { - return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt)), - AstFragmentKind::Stmts, after_derive).make_stmts(); - } - } - - if let StmtKind::Mac(mac) = stmt.node { - let (mac, style, attrs) = mac.into_inner(); - self.check_attributes(&attrs); - let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts) - .make_stmts(); - - // If this is a macro invocation with a semicolon, then apply that - // semicolon to the final statement produced by expansion. - if style == MacStmtStyle::Semicolon { - if let Some(stmt) = placeholder.pop() { - placeholder.push(stmt.add_trailing_semicolon()); - } - } - - return placeholder; - } - - // The placeholder expander gives ids to statements, so we avoid folding the id here. - let ast::Stmt { id, node, span } = stmt; - noop_flat_map_stmt_kind(node, self).into_iter().map(|node| { - ast::Stmt { id, node, span } - }).collect() - - } - - fn visit_block(&mut self, block: &mut P) { - let old_directory_ownership = self.cx.current_expansion.directory_ownership; - self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock; - noop_visit_block(block, self); - self.cx.current_expansion.directory_ownership = old_directory_ownership; - } - - fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { - let mut item = configure!(self, item); - - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { - return self.collect_attr(attr, traits, Annotatable::Item(item), - AstFragmentKind::Items, after_derive).make_items(); - } - - match item.node { - ast::ItemKind::Mac(..) => { - self.check_attributes(&item.attrs); - item.and_then(|item| match item.node { - ItemKind::Mac(mac) => self.collect( - AstFragmentKind::Items, InvocationKind::Bang { mac, span: item.span } - ).make_items(), - _ => unreachable!(), - }) - } - ast::ItemKind::Mod(ast::Mod { inner, .. }) => { - if item.ident == Ident::invalid() { - return noop_flat_map_item(item, self); - } - - let orig_directory_ownership = self.cx.current_expansion.directory_ownership; - let mut module = (*self.cx.current_expansion.module).clone(); - module.mod_path.push(item.ident); - - // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). - // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`). - // Thus, if `inner` is the dummy span, we know the module is inline. - let inline_module = item.span.contains(inner) || inner.is_dummy(); - - if inline_module { - if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { - self.cx.current_expansion.directory_ownership = - DirectoryOwnership::Owned { relative: None }; - module.directory.push(&*path.as_str()); - } else { - module.directory.push(&*item.ident.as_str()); - } - } else { - let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); - let mut path = match path { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), - }; - let directory_ownership = match path.file_name().unwrap().to_str() { - Some("mod.rs") => DirectoryOwnership::Owned { relative: None }, - Some(_) => DirectoryOwnership::Owned { - relative: Some(item.ident), - }, - None => DirectoryOwnership::UnownedViaMod(false), - }; - path.pop(); - module.directory = path; - self.cx.current_expansion.directory_ownership = directory_ownership; - } - - let orig_module = - mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); - let result = noop_flat_map_item(item, self); - self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.directory_ownership = orig_directory_ownership; - result - } - - _ => noop_flat_map_item(item, self), - } - } - - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { - let mut item = configure!(self, item); - - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { - return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)), - AstFragmentKind::TraitItems, after_derive).make_trait_items() - } - - match item.node { - ast::TraitItemKind::Macro(mac) => { - let ast::TraitItem { attrs, span, .. } = item; - self.check_attributes(&attrs); - self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items() - } - _ => noop_flat_map_trait_item(item, self), - } - } - - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - let mut item = configure!(self, item); - - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { - return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)), - AstFragmentKind::ImplItems, after_derive).make_impl_items(); - } - - match item.node { - ast::ImplItemKind::Macro(mac) => { - let ast::ImplItem { attrs, span, .. } = item; - self.check_attributes(&attrs); - self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items() - } - _ => noop_flat_map_impl_item(item, self), - } - } - - fn visit_ty(&mut self, ty: &mut P) { - match ty.node { - ast::TyKind::Mac(_) => {} - _ => return noop_visit_ty(ty, self), - }; - - visit_clobber(ty, |mut ty| { - match mem::replace(&mut ty.node, ast::TyKind::Err) { - ast::TyKind::Mac(mac) => - self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(), - _ => unreachable!(), - } - }); - } - - fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - self.cfg.configure_foreign_mod(foreign_mod); - noop_visit_foreign_mod(foreign_mod, self); - } - - fn flat_map_foreign_item(&mut self, mut foreign_item: ast::ForeignItem) - -> SmallVec<[ast::ForeignItem; 1]> - { - let (attr, traits, after_derive) = self.classify_item(&mut foreign_item); - - if attr.is_some() || !traits.is_empty() { - return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)), - AstFragmentKind::ForeignItems, after_derive) - .make_foreign_items(); - } - - if let ast::ForeignItemKind::Macro(mac) = foreign_item.node { - self.check_attributes(&foreign_item.attrs); - return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems) - .make_foreign_items(); - } - - noop_flat_map_foreign_item(foreign_item, self) - } - - fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { - match item { - ast::ItemKind::MacroDef(..) => {} - _ => { - self.cfg.configure_item_kind(item); - noop_visit_item_kind(item, self); - } - } - } - - fn visit_generic_params(&mut self, params: &mut Vec) { - self.cfg.configure_generic_params(params); - noop_visit_generic_params(params, self); - } - - fn visit_attribute(&mut self, at: &mut ast::Attribute) { - // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename", - // contents="file contents")]` attributes - if !at.check_name(sym::doc) { - return noop_visit_attribute(at, self); - } - - if let Some(list) = at.meta_item_list() { - if !list.iter().any(|it| it.check_name(sym::include)) { - return noop_visit_attribute(at, self); - } - - let mut items = vec![]; - - for mut it in list { - if !it.check_name(sym::include) { - items.push({ noop_visit_meta_list_item(&mut it, self); it }); - continue; - } - - if let Some(file) = it.value_str() { - let err_count = self.cx.parse_sess.span_diagnostic.err_count(); - self.check_attribute(&at); - if self.cx.parse_sess.span_diagnostic.err_count() > err_count { - // avoid loading the file if they haven't enabled the feature - return noop_visit_attribute(at, self); - } - - let filename = self.cx.root_path.join(file.to_string()); - match fs::read_to_string(&filename) { - Ok(src) => { - let src_interned = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - self.cx.source_map().new_source_file(filename.into(), src); - - let include_info = vec![ - ast::NestedMetaItem::MetaItem( - attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::file), - dummy_spanned(file), - ), - ), - ast::NestedMetaItem::MetaItem( - attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::contents), - dummy_spanned(src_interned), - ), - ), - ]; - - let include_ident = Ident::with_empty_ctxt(sym::include); - let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); - items.push(ast::NestedMetaItem::MetaItem(item)); - } - Err(e) => { - let lit = it - .meta_item() - .and_then(|item| item.name_value_literal()) - .unwrap(); - - if e.kind() == ErrorKind::InvalidData { - self.cx - .struct_span_err( - lit.span, - &format!("{} wasn't a utf-8 file", filename.display()), - ) - .span_label(lit.span, "contains invalid utf-8") - .emit(); - } else { - let mut err = self.cx.struct_span_err( - lit.span, - &format!("couldn't read {}: {}", filename.display(), e), - ); - err.span_label(lit.span, "couldn't read file"); - - if e.kind() == ErrorKind::NotFound { - err.help("external doc paths are relative to the crate root"); - } - - err.emit(); - } - } - } - } else { - let mut err = self.cx.struct_span_err( - it.span(), - &format!("expected path to external documentation"), - ); - - // Check if the user erroneously used `doc(include(...))` syntax. - let literal = it.meta_item_list().and_then(|list| { - if list.len() == 1 { - list[0].literal().map(|literal| &literal.node) - } else { - None - } - }); - - let (path, applicability) = match &literal { - Some(LitKind::Str(path, ..)) => { - (path.to_string(), Applicability::MachineApplicable) - } - _ => (String::from(""), Applicability::HasPlaceholders), - }; - - err.span_suggestion( - it.span(), - "provide a file path with `=`", - format!("include = \"{}\"", path), - applicability, - ); - - err.emit(); - } - } - - let meta = attr::mk_list_item(DUMMY_SP, Ident::with_empty_ctxt(sym::doc), items); - match at.style { - ast::AttrStyle::Inner => *at = attr::mk_spanned_attr_inner(at.span, at.id, meta), - ast::AttrStyle::Outer => *at = attr::mk_spanned_attr_outer(at.span, at.id, meta), - } - } else { - noop_visit_attribute(at, self) - } - } - - fn visit_id(&mut self, id: &mut ast::NodeId) { - if self.monotonic { - debug_assert_eq!(*id, ast::DUMMY_NODE_ID); - *id = self.cx.resolver.next_node_id() - } - } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.cfg.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } -} - -pub struct ExpansionConfig<'feat> { - pub crate_name: String, - pub features: Option<&'feat Features>, - pub recursion_limit: usize, - pub trace_mac: bool, - pub should_test: bool, // If false, strip `#[test]` nodes - pub single_step: bool, - pub keep_macs: bool, -} - -impl<'feat> ExpansionConfig<'feat> { - pub fn default(crate_name: String) -> ExpansionConfig<'static> { - ExpansionConfig { - crate_name, - features: None, - recursion_limit: 1024, - trace_mac: false, - should_test: false, - single_step: false, - keep_macs: false, - } - } - - fn macros_in_extern(&self) -> bool { - self.features.map_or(false, |features| features.macros_in_extern) - } - fn proc_macro_hygiene(&self) -> bool { - self.features.map_or(false, |features| features.proc_macro_hygiene) - } - fn custom_inner_attributes(&self) -> bool { - self.features.map_or(false, |features| features.custom_inner_attributes) - } -} - -// A Marker adds the given mark to the syntax context. -#[derive(Debug)] -pub struct Marker(pub Mark); - -impl MutVisitor for Marker { - fn visit_span(&mut self, span: &mut Span) { - *span = span.apply_mark(self.0) - } - - fn visit_mac(&mut self, mac: &mut ast::Mac) { - noop_visit_mac(mac, self) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/placeholders.rs b/gcc/rust/rustc_parser/libsyntax/ext/placeholders.rs deleted file mode 100644 index b2b8bfb..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/placeholders.rs +++ /dev/null @@ -1,203 +0,0 @@ -use crate::ast::{self, NodeId}; -use crate::source_map::{DUMMY_SP, dummy_spanned}; -use crate::ext::base::ExtCtxt; -use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::hygiene::Mark; -use crate::tokenstream::TokenStream; -use crate::mut_visit::*; -use crate::ptr::P; -use crate::ThinVec; - -use smallvec::{smallvec, SmallVec}; - -use rustc_data_structures::fx::FxHashMap; - -pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { - fn mac_placeholder() -> ast::Mac { - dummy_spanned(ast::Mac_ { - path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, - tts: TokenStream::empty().into(), - delim: ast::MacDelimiter::Brace, - }) - } - - let ident = ast::Ident::invalid(); - let attrs = Vec::new(); - let generics = ast::Generics::default(); - let vis = dummy_spanned(ast::VisibilityKind::Inherited); - let span = DUMMY_SP; - let expr_placeholder = || P(ast::Expr { - id, span, - attrs: ThinVec::new(), - node: ast::ExprKind::Mac(mac_placeholder()), - }); - - match kind { - AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), - AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), - AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { - id, span, ident, vis, attrs, - node: ast::ItemKind::Mac(mac_placeholder()), - tokens: None, - })]), - AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem { - id, span, ident, attrs, generics, - node: ast::TraitItemKind::Macro(mac_placeholder()), - tokens: None, - }]), - AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem { - id, span, ident, vis, attrs, generics, - node: ast::ImplItemKind::Macro(mac_placeholder()), - defaultness: ast::Defaultness::Final, - tokens: None, - }]), - AstFragmentKind::ForeignItems => - AstFragment::ForeignItems(smallvec![ast::ForeignItem { - id, span, ident, vis, attrs, - node: ast::ForeignItemKind::Macro(mac_placeholder()), - }]), - AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat { - id, span, node: ast::PatKind::Mac(mac_placeholder()), - })), - AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty { - id, span, node: ast::TyKind::Mac(mac_placeholder()), - })), - AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{ - let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new())); - ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) } - }]), - } -} - -pub struct PlaceholderExpander<'a, 'b> { - expanded_fragments: FxHashMap, - cx: &'a mut ExtCtxt<'b>, - monotonic: bool, -} - -impl<'a, 'b> PlaceholderExpander<'a, 'b> { - pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - PlaceholderExpander { - cx, - expanded_fragments: FxHashMap::default(), - monotonic, - } - } - - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec) { - fragment.mut_visit_with(self); - if let AstFragment::Items(mut items) = fragment { - for derive in derives { - match self.remove(NodeId::placeholder_from_mark(derive)) { - AstFragment::Items(derived_items) => items.extend(derived_items), - _ => unreachable!(), - } - } - fragment = AstFragment::Items(items); - } - self.expanded_fragments.insert(id, fragment); - } - - fn remove(&mut self, id: ast::NodeId) -> AstFragment { - self.expanded_fragments.remove(&id).unwrap() - } -} - -impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { - fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { - match item.node { - ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(), - ast::ItemKind::MacroDef(_) => return smallvec![item], - _ => {} - } - - noop_flat_map_item(item, self) - } - - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { - match item.node { - ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(), - _ => noop_flat_map_trait_item(item, self), - } - } - - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - match item.node { - ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(), - _ => noop_flat_map_impl_item(item, self), - } - } - - fn flat_map_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> { - match item.node { - ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(), - _ => noop_flat_map_foreign_item(item, self), - } - } - - fn visit_expr(&mut self, expr: &mut P) { - match expr.node { - ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(), - _ => noop_visit_expr(expr, self), - } - } - - fn filter_map_expr(&mut self, expr: P) -> Option> { - match expr.node { - ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(), - _ => noop_filter_map_expr(expr, self), - } - } - - fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { - let (style, mut stmts) = match stmt.node { - ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()), - _ => return noop_flat_map_stmt(stmt, self), - }; - - if style == ast::MacStmtStyle::Semicolon { - if let Some(stmt) = stmts.pop() { - stmts.push(stmt.add_trailing_semicolon()); - } - } - - stmts - } - - fn visit_pat(&mut self, pat: &mut P) { - match pat.node { - ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(), - _ => noop_visit_pat(pat, self), - } - } - - fn visit_ty(&mut self, ty: &mut P) { - match ty.node { - ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(), - _ => noop_visit_ty(ty, self), - } - } - - fn visit_block(&mut self, block: &mut P) { - noop_visit_block(block, self); - - for stmt in block.stmts.iter_mut() { - if self.monotonic { - assert_eq!(stmt.id, ast::DUMMY_NODE_ID); - stmt.id = self.cx.resolver.next_node_id(); - } - } - } - - fn visit_mod(&mut self, module: &mut ast::Mod) { - noop_visit_mod(module, self); - module.items.retain(|item| match item.node { - ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions - _ => true, - }); - } - - fn visit_mac(&mut self, _mac: &mut ast::Mac) { - // Do nothing. - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/source_util.rs b/gcc/rust/rustc_parser/libsyntax/ext/source_util.rs deleted file mode 100644 index c2ba8b9..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/source_util.rs +++ /dev/null @@ -1,187 +0,0 @@ -use crate::ast; -use crate::ext::base::{self, *}; -use crate::ext::build::AstBuilder; -use crate::parse::{self, token, DirectoryOwnership}; -use crate::print::pprust; -use crate::ptr::P; -use crate::symbol::Symbol; -use crate::tokenstream; - -use smallvec::SmallVec; -use syntax_pos::{self, Pos, Span, FileName}; - -use std::fs; -use std::io::ErrorKind; -use std::path::PathBuf; -use rustc_data_structures::sync::Lrc; - -// These macros all relate to the file system; they either return -// the column/row/filename of the expression, or they include -// a given file into the current one. - -/// line!(): expands to the current line number -pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - base::check_zero_tts(cx, sp, tts, "line!"); - - let topmost = cx.expansion_cause().unwrap_or(sp); - let loc = cx.source_map().lookup_char_pos(topmost.lo()); - - base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32)) -} - -/* column!(): expands to the current column number */ -pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - base::check_zero_tts(cx, sp, tts, "column!"); - - let topmost = cx.expansion_cause().unwrap_or(sp); - let loc = cx.source_map().lookup_char_pos(topmost.lo()); - - base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)) -} - -/// file!(): expands to the current filename */ -/// The source_file (`loc.file`) contains a bunch more information we could spit -/// out if we wanted. -pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - base::check_zero_tts(cx, sp, tts, "file!"); - - let topmost = cx.expansion_cause().unwrap_or(sp); - let loc = cx.source_map().lookup_char_pos(topmost.lo()); - base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string()))) -} - -pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - let s = pprust::tts_to_string(tts); - base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) -} - -pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - base::check_zero_tts(cx, sp, tts, "module_path!"); - let mod_path = &cx.current_expansion.module.mod_path; - let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); - - base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))) -} - -/// include! : parse the given file as an expr -/// This is generally a bad idea because it's going to behave -/// unhygienically. -pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - let file = match get_single_str_from_tts(cx, sp, tts, "include!") { - Some(f) => f, - None => return DummyResult::any(sp), - }; - // The file will be added to the code map by the parser - let path = res_rel_file(cx, sp, file); - let directory_ownership = DirectoryOwnership::Owned { relative: None }; - let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp); - - struct ExpandResult<'a> { - p: parse::parser::Parser<'a>, - } - impl<'a> base::MacResult for ExpandResult<'a> { - fn make_expr(mut self: Box>) -> Option> { - Some(panictry!(self.p.parse_expr())) - } - - fn make_items(mut self: Box>) -> Option; 1]>> { - let mut ret = SmallVec::new(); - while self.p.token != token::Eof { - match panictry!(self.p.parse_item()) { - Some(item) => ret.push(item), - None => self.p.diagnostic().span_fatal(self.p.token.span, - &format!("expected item, found `{}`", - self.p.this_token_to_string())) - .raise() - } - } - Some(ret) - } - } - - Box::new(ExpandResult { p }) -} - -// include_str! : read the given file, insert it as a literal string expr -pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { - Some(f) => f, - None => return DummyResult::expr(sp) - }; - let file = res_rel_file(cx, sp, file); - match fs::read_to_string(&file) { - Ok(src) => { - let interned_src = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - cx.source_map().new_source_file(file.into(), src); - - base::MacEager::expr(cx.expr_str(sp, interned_src)) - }, - Err(ref e) if e.kind() == ErrorKind::InvalidData => { - cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); - DummyResult::expr(sp) - } - Err(e) => { - cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) - } - } -} - -pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) - -> Box { - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { - Some(f) => f, - None => return DummyResult::expr(sp) - }; - let file = res_rel_file(cx, sp, file); - match fs::read(&file) { - Ok(bytes) => { - // Add the contents to the source map if it contains UTF-8. - let (contents, bytes) = match String::from_utf8(bytes) { - Ok(s) => { - let bytes = s.as_bytes().to_owned(); - (s, bytes) - }, - Err(e) => (String::new(), e.into_bytes()), - }; - cx.source_map().new_source_file(file.into(), contents); - - base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) - }, - Err(e) => { - cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) - } - } -} - -// resolve a file-system path to an absolute file-system path (if it -// isn't already) -fn res_rel_file(cx: &mut ExtCtxt<'_>, sp: syntax_pos::Span, arg: String) -> PathBuf { - let arg = PathBuf::from(arg); - // Relative paths are resolved relative to the file in which they are found - // after macro expansion (that is, they are unhygienic). - if !arg.is_absolute() { - let callsite = sp.source_callsite(); - let mut path = match cx.source_map().span_to_unmapped_path(callsite) { - FileName::Real(path) => path, - FileName::DocTest(path, _) => path, - other => panic!("cannot resolve relative path in non-file source `{}`", other), - }; - path.pop(); - path.push(arg); - path - } else { - arg - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_parser.rs b/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_parser.rs deleted file mode 100644 index fc8aa47..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_parser.rs +++ /dev/null @@ -1,954 +0,0 @@ -//! This is an NFA-based parser, which calls out to the main rust parser for named non-terminals -//! (which it commits to fully when it hits one in a grammar). There's a set of current NFA threads -//! and a set of next ones. Instead of NTs, we have a special case for Kleene star. The big-O, in -//! pathological cases, is worse than traditional use of NFA or Earley parsing, but it's an easier -//! fit for Macro-by-Example-style rules. -//! -//! (In order to prevent the pathological case, we'd need to lazily construct the resulting -//! `NamedMatch`es at the very end. It'd be a pain, and require more memory to keep around old -//! items, but it would also save overhead) -//! -//! We don't say this parser uses the Earley algorithm, because it's unnecessarily inaccurate. -//! The macro parser restricts itself to the features of finite state automata. Earley parsers -//! can be described as an extension of NFAs with completion rules, prediction rules, and recursion. -//! -//! Quick intro to how the parser works: -//! -//! A 'position' is a dot in the middle of a matcher, usually represented as a -//! dot. For example `· a $( a )* a b` is a position, as is `a $( · a )* a b`. -//! -//! The parser walks through the input a character at a time, maintaining a list -//! of threads consistent with the current position in the input string: `cur_items`. -//! -//! As it processes them, it fills up `eof_items` with threads that would be valid if -//! the macro invocation is now over, `bb_items` with threads that are waiting on -//! a Rust non-terminal like `$e:expr`, and `next_items` with threads that are waiting -//! on a particular token. Most of the logic concerns moving the · through the -//! repetitions indicated by Kleene stars. The rules for moving the · without -//! consuming any input are called epsilon transitions. It only advances or calls -//! out to the real Rust parser when no `cur_items` threads remain. -//! -//! Example: -//! -//! ```text, ignore -//! Start parsing a a a a b against [· a $( a )* a b]. -//! -//! Remaining input: a a a a b -//! next: [· a $( a )* a b] -//! -//! - - - Advance over an a. - - - -//! -//! Remaining input: a a a b -//! cur: [a · $( a )* a b] -//! Descend/Skip (first item). -//! next: [a $( · a )* a b] [a $( a )* · a b]. -//! -//! - - - Advance over an a. - - - -//! -//! Remaining input: a a b -//! cur: [a $( a · )* a b] [a $( a )* a · b] -//! Follow epsilon transition: Finish/Repeat (first item) -//! next: [a $( a )* · a b] [a $( · a )* a b] [a $( a )* a · b] -//! -//! - - - Advance over an a. - - - (this looks exactly like the last step) -//! -//! Remaining input: a b -//! cur: [a $( a · )* a b] [a $( a )* a · b] -//! Follow epsilon transition: Finish/Repeat (first item) -//! next: [a $( a )* · a b] [a $( · a )* a b] [a $( a )* a · b] -//! -//! - - - Advance over an a. - - - (this looks exactly like the last step) -//! -//! Remaining input: b -//! cur: [a $( a · )* a b] [a $( a )* a · b] -//! Follow epsilon transition: Finish/Repeat (first item) -//! next: [a $( a )* · a b] [a $( · a )* a b] [a $( a )* a · b] -//! -//! - - - Advance over a b. - - - -//! -//! Remaining input: '' -//! eof: [a $( a )* a b ·] -//! ``` - -pub use NamedMatch::*; -pub use ParseResult::*; -use TokenTreeOrTokenTreeSlice::*; - -use crate::ast::{Ident, Name}; -use crate::ext::tt::quoted::{self, TokenTree}; -use crate::parse::{Directory, ParseSess}; -use crate::parse::parser::{Parser, PathStyle}; -use crate::parse::token::{self, DocComment, Nonterminal, Token}; -use crate::print::pprust; -use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::{DelimSpan, TokenStream}; - -use errors::FatalError; -use smallvec::{smallvec, SmallVec}; -use syntax_pos::Span; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::rc::Rc; - -// To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body. - -/// Either a sequence of token trees or a single one. This is used as the representation of the -/// sequence of tokens that make up a matcher. -#[derive(Clone)] -enum TokenTreeOrTokenTreeSlice<'tt> { - Tt(TokenTree), - TtSeq(&'tt [TokenTree]), -} - -impl<'tt> TokenTreeOrTokenTreeSlice<'tt> { - /// Returns the number of constituent top-level token trees of `self` (top-level in that it - /// will not recursively descend into subtrees). - fn len(&self) -> usize { - match *self { - TtSeq(ref v) => v.len(), - Tt(ref tt) => tt.len(), - } - } - - /// The `index`-th token tree of `self`. - fn get_tt(&self, index: usize) -> TokenTree { - match *self { - TtSeq(ref v) => v[index].clone(), - Tt(ref tt) => tt.get_tt(index), - } - } -} - -/// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`. -/// -/// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have -/// descended into. -#[derive(Clone)] -struct MatcherTtFrame<'tt> { - /// The "parent" matcher that we are descending into. - elts: TokenTreeOrTokenTreeSlice<'tt>, - /// The position of the "dot" in `elts` at the time we descended. - idx: usize, -} - -type NamedMatchVec = SmallVec<[NamedMatch; 4]>; - -/// Represents a single "position" (aka "matcher position", aka "item"), as -/// described in the module documentation. -/// -/// Here: -/// -/// - `'root` represents the lifetime of the stack slot that holds the root -/// `MatcherPos`. As described in `MatcherPosHandle`, the root `MatcherPos` -/// structure is stored on the stack, but subsequent instances are put into -/// the heap. -/// - `'tt` represents the lifetime of the token trees that this matcher -/// position refers to. -/// -/// It is important to distinguish these two lifetimes because we have a -/// `SmallVec>` below, and the destructor of -/// that is considered to possibly access the data from its elements (it lacks -/// a `#[may_dangle]` attribute). As a result, the compiler needs to know that -/// all the elements in that `SmallVec` strictly outlive the root stack slot -/// lifetime. By separating `'tt` from `'root`, we can show that. -#[derive(Clone)] -struct MatcherPos<'root, 'tt> { - /// The token or sequence of tokens that make up the matcher - top_elts: TokenTreeOrTokenTreeSlice<'tt>, - - /// The position of the "dot" in this matcher - idx: usize, - - /// The first span of source that the beginning of this matcher corresponds to. In other - /// words, the token in the source whose span is `sp_open` is matched against the first token of - /// the matcher. - sp_open: Span, - - /// For each named metavar in the matcher, we keep track of token trees matched against the - /// metavar by the black box parser. In particular, there may be more than one match per - /// metavar if we are in a repetition (each repetition matches each of the variables). - /// Moreover, matchers and repetitions can be nested; the `matches` field is shared (hence the - /// `Rc`) among all "nested" matchers. `match_lo`, `match_cur`, and `match_hi` keep track of - /// the current position of the `self` matcher position in the shared `matches` list. - /// - /// Also, note that while we are descending into a sequence, matchers are given their own - /// `matches` vector. Only once we reach the end of a full repetition of the sequence do we add - /// all bound matches from the submatcher into the shared top-level `matches` vector. If `sep` - /// and `up` are `Some`, then `matches` is _not_ the shared top-level list. Instead, if one - /// wants the shared `matches`, one should use `up.matches`. - matches: Box<[Lrc]>, - /// The position in `matches` corresponding to the first metavar in this matcher's sequence of - /// token trees. In other words, the first metavar in the first token of `top_elts` corresponds - /// to `matches[match_lo]`. - match_lo: usize, - /// The position in `matches` corresponding to the metavar we are currently trying to match - /// against the source token stream. `match_lo <= match_cur <= match_hi`. - match_cur: usize, - /// Similar to `match_lo` except `match_hi` is the position in `matches` of the _last_ metavar - /// in this matcher. - match_hi: usize, - - // The following fields are used if we are matching a repetition. If we aren't, they should be - // `None`. - - /// The KleeneOp of this sequence if we are in a repetition. - seq_op: Option, - - /// The separator if we are in a repetition. - sep: Option, - - /// The "parent" matcher position if we are in a repetition. That is, the matcher position just - /// before we enter the sequence. - up: Option>, - - /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from - /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc - /// comment... - /// - /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. ) - /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does - /// that where the bottom of the stack is the outermost matcher. - /// Also, throughout the comments, this "descent" is often referred to as "unzipping"... - stack: SmallVec<[MatcherTtFrame<'tt>; 1]>, -} - -impl<'root, 'tt> MatcherPos<'root, 'tt> { - /// Adds `m` as a named match for the `idx`-th metavar. - fn push_match(&mut self, idx: usize, m: NamedMatch) { - let matches = Lrc::make_mut(&mut self.matches[idx]); - matches.push(m); - } -} - -// Lots of MatcherPos instances are created at runtime. Allocating them on the -// heap is slow. Furthermore, using SmallVec to allocate them all -// on the stack is also slow, because MatcherPos is quite a large type and -// instances get moved around a lot between vectors, which requires lots of -// slow memcpy calls. -// -// Therefore, the initial MatcherPos is always allocated on the stack, -// subsequent ones (of which there aren't that many) are allocated on the heap, -// and this type is used to encapsulate both cases. -enum MatcherPosHandle<'root, 'tt> { - Ref(&'root mut MatcherPos<'root, 'tt>), - Box(Box>), -} - -impl<'root, 'tt> Clone for MatcherPosHandle<'root, 'tt> { - // This always produces a new Box. - fn clone(&self) -> Self { - MatcherPosHandle::Box(match *self { - MatcherPosHandle::Ref(ref r) => Box::new((**r).clone()), - MatcherPosHandle::Box(ref b) => b.clone(), - }) - } -} - -impl<'root, 'tt> Deref for MatcherPosHandle<'root, 'tt> { - type Target = MatcherPos<'root, 'tt>; - fn deref(&self) -> &Self::Target { - match *self { - MatcherPosHandle::Ref(ref r) => r, - MatcherPosHandle::Box(ref b) => b, - } - } -} - -impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> { - fn deref_mut(&mut self) -> &mut MatcherPos<'root, 'tt> { - match *self { - MatcherPosHandle::Ref(ref mut r) => r, - MatcherPosHandle::Box(ref mut b) => b, - } - } -} - -/// Represents the possible results of an attempted parse. -pub enum ParseResult { - /// Parsed successfully. - Success(T), - /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected - /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. - Failure(Token, &'static str), - /// Fatal error (malformed macro?). Abort compilation. - Error(syntax_pos::Span, String), -} - -/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. -/// This represents the mapping of metavars to the token trees they bind to. -pub type NamedParseResult = ParseResult>>; - -/// Count how many metavars are named in the given matcher `ms`. -pub fn count_names(ms: &[TokenTree]) -> usize { - ms.iter().fold(0, |count, elt| { - count + match *elt { - TokenTree::Sequence(_, ref seq) => seq.num_captures, - TokenTree::Delimited(_, ref delim) => count_names(&delim.tts), - TokenTree::MetaVar(..) => 0, - TokenTree::MetaVarDecl(..) => 1, - TokenTree::Token(..) => 0, - } - }) -} - -/// `len` `Vec`s (initially shared and empty) that will store matches of metavars. -fn create_matches(len: usize) -> Box<[Lrc]> { - if len == 0 { - vec![] - } else { - let empty_matches = Lrc::new(SmallVec::new()); - vec![empty_matches; len] - }.into_boxed_slice() -} - -/// Generates the top-level matcher position in which the "dot" is before the first token of the -/// matcher `ms` and we are going to start matching at the span `open` in the source. -fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherPos<'root, 'tt> { - let match_idx_hi = count_names(ms); - let matches = create_matches(match_idx_hi); - MatcherPos { - // Start with the top level matcher given to us - top_elts: TtSeq(ms), // "elts" is an abbr. for "elements" - // The "dot" is before the first token of the matcher - idx: 0, - // We start matching at the span `open` in the source code - sp_open: open, - - // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`. - // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since - // we haven't actually matched anything yet. - matches, - match_lo: 0, - match_cur: 0, - match_hi: match_idx_hi, - - // Haven't descended into any delimiters, so empty stack - stack: smallvec![], - - // Haven't descended into any sequences, so both of these are `None`. - seq_op: None, - sep: None, - up: None, - } -} - -/// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`: -/// so it is associated with a single ident in a parse, and all -/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type -/// (expr, item, etc). Each leaf in a single `NamedMatch` corresponds to a -/// single `token::MATCH_NONTERMINAL` in the `TokenTree` that produced it. -/// -/// The in-memory structure of a particular `NamedMatch` represents the match -/// that occurred when a particular subset of a matcher was applied to a -/// particular token tree. -/// -/// The width of each `MatchedSeq` in the `NamedMatch`, and the identity of -/// the `MatchedNonterminal`s, will depend on the token tree it was applied -/// to: each `MatchedSeq` corresponds to a single `TTSeq` in the originating -/// token tree. The depth of the `NamedMatch` structure will therefore depend -/// only on the nesting depth of `ast::TTSeq`s in the originating -/// token tree it was derived from. -#[derive(Debug, Clone)] -pub enum NamedMatch { - MatchedSeq(Lrc, DelimSpan), - MatchedNonterminal(Lrc), -} - -/// Takes a sequence of token trees `ms` representing a matcher which successfully matched input -/// and an iterator of items that matched input and produces a `NamedParseResult`. -fn nameize>( - sess: &ParseSess, - ms: &[TokenTree], - mut res: I, -) -> NamedParseResult { - // Recursively descend into each type of matcher (e.g., sequences, delimited, metavars) and make - // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one - // binding, then there is an error. If it does, then we insert the binding into the - // `NamedParseResult`. - fn n_rec>( - sess: &ParseSess, - m: &TokenTree, - res: &mut I, - ret_val: &mut FxHashMap>, - ) -> Result<(), (syntax_pos::Span, String)> { - match *m { - TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts { - n_rec(sess, next_m, res.by_ref(), ret_val)? - }, - TokenTree::Delimited(_, ref delim) => for next_m in &delim.tts { - n_rec(sess, next_m, res.by_ref(), ret_val)?; - }, - TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => { - if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { - return Err((span, "missing fragment specifier".to_string())); - } - } - TokenTree::MetaVarDecl(sp, bind_name, _) => { - match ret_val.entry(bind_name) { - Vacant(spot) => { - // FIXME(simulacrum): Don't construct Rc here - spot.insert(Rc::new(res.next().unwrap())); - } - Occupied(..) => { - return Err((sp, format!("duplicated bind name: {}", bind_name))) - } - } - } - TokenTree::MetaVar(..) | TokenTree::Token(..) => (), - } - - Ok(()) - } - - let mut ret_val = FxHashMap::default(); - for m in ms { - match n_rec(sess, m, res.by_ref(), &mut ret_val) { - Ok(_) => {} - Err((sp, msg)) => return Error(sp, msg), - } - } - - Success(ret_val) -} - -/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For -/// other tokens, this is "unexpected token...". -pub fn parse_failure_msg(tok: &Token) -> String { - match tok.kind { - token::Eof => "unexpected end of macro invocation".to_string(), - _ => format!( - "no rules expected the token `{}`", - pprust::token_to_string(tok) - ), - } -} - -/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) -fn token_name_eq(t1: &Token, t2: &Token) -> bool { - if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) { - ident1.name == ident2.name && is_raw1 == is_raw2 - } else if let (Some(ident1), Some(ident2)) = (t1.lifetime(), t2.lifetime()) { - ident1.name == ident2.name - } else { - t1.kind == t2.kind - } -} - -/// Process the matcher positions of `cur_items` until it is empty. In the process, this will -/// produce more items in `next_items`, `eof_items`, and `bb_items`. -/// -/// For more info about the how this happens, see the module-level doc comments and the inline -/// comments of this function. -/// -/// # Parameters -/// -/// - `sess`: the parsing session into which errors are emitted. -/// - `cur_items`: the set of current items to be processed. This should be empty by the end of a -/// successful execution of this function. -/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in -/// the function `parse`. -/// - `eof_items`: the set of items that would be valid if this was the EOF. -/// - `bb_items`: the set of items that are waiting for the black-box parser. -/// - `token`: the current token of the parser. -/// - `span`: the `Span` in the source code corresponding to the token trees we are trying to match -/// against the matcher positions in `cur_items`. -/// -/// # Returns -/// -/// A `ParseResult`. Note that matches are kept track of through the items generated. -fn inner_parse_loop<'root, 'tt>( - sess: &ParseSess, - cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - next_items: &mut Vec>, - eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - token: &Token, -) -> ParseResult<()> { - // Pop items from `cur_items` until it is empty. - while let Some(mut item) = cur_items.pop() { - // When unzipped trees end, remove them. This corresponds to backtracking out of a - // delimited submatcher into which we already descended. In backtracking out again, we need - // to advance the "dot" past the delimiters in the outer matcher. - while item.idx >= item.top_elts.len() { - match item.stack.pop() { - Some(MatcherTtFrame { elts, idx }) => { - item.top_elts = elts; - item.idx = idx + 1; - } - None => break, - } - } - - // Get the current position of the "dot" (`idx`) in `item` and the number of token trees in - // the matcher (`len`). - let idx = item.idx; - let len = item.top_elts.len(); - - // If `idx >= len`, then we are at or past the end of the matcher of `item`. - if idx >= len { - // We are repeating iff there is a parent. If the matcher is inside of a repetition, - // then we could be at the end of a sequence or at the beginning of the next - // repetition. - if item.up.is_some() { - // At this point, regardless of whether there is a separator, we should add all - // matches from the complete repetition of the sequence to the shared, top-level - // `matches` list (actually, `up.matches`, which could itself not be the top-level, - // but anyway...). Moreover, we add another item to `cur_items` in which the "dot" - // is at the end of the `up` matcher. This ensures that the "dot" in the `up` - // matcher is also advanced sufficiently. - // - // NOTE: removing the condition `idx == len` allows trailing separators. - if idx == len { - // Get the `up` matcher - let mut new_pos = item.up.clone().unwrap(); - - // Add matches from this repetition to the `matches` of `up` - for idx in item.match_lo..item.match_hi { - let sub = item.matches[idx].clone(); - let span = DelimSpan::from_pair(item.sp_open, token.span); - new_pos.push_match(idx, MatchedSeq(sub, span)); - } - - // Move the "dot" past the repetition in `up` - new_pos.match_cur = item.match_hi; - new_pos.idx += 1; - cur_items.push(new_pos); - } - - // Check if we need a separator. - if idx == len && item.sep.is_some() { - // We have a separator, and it is the current token. We can advance past the - // separator token. - if item.sep - .as_ref() - .map(|sep| token_name_eq(token, sep)) - .unwrap_or(false) - { - item.idx += 1; - next_items.push(item); - } - } - // We don't need a separator. Move the "dot" back to the beginning of the matcher - // and try to match again UNLESS we are only allowed to have _one_ repetition. - else if item.seq_op != Some(quoted::KleeneOp::ZeroOrOne) { - item.match_cur = item.match_lo; - item.idx = 0; - cur_items.push(item); - } - } - // If we are not in a repetition, then being at the end of a matcher means that we have - // reached the potential end of the input. - else { - eof_items.push(item); - } - } - // We are in the middle of a matcher. - else { - // Look at what token in the matcher we are trying to match the current token (`token`) - // against. Depending on that, we may generate new items. - match item.top_elts.get_tt(idx) { - // Need to descend into a sequence - TokenTree::Sequence(sp, seq) => { - // Examine the case where there are 0 matches of this sequence. We are - // implicitly disallowing OneOrMore from having 0 matches here. Thus, that will - // result in a "no rules expected token" error by virtue of this matcher not - // working. - if seq.op == quoted::KleeneOp::ZeroOrMore - || seq.op == quoted::KleeneOp::ZeroOrOne - { - let mut new_item = item.clone(); - new_item.match_cur += seq.num_captures; - new_item.idx += 1; - for idx in item.match_cur..item.match_cur + seq.num_captures { - new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]), sp)); - } - cur_items.push(new_item); - } - - let matches = create_matches(item.matches.len()); - cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos { - stack: smallvec![], - sep: seq.separator.clone(), - seq_op: Some(seq.op), - idx: 0, - matches, - match_lo: item.match_cur, - match_cur: item.match_cur, - match_hi: item.match_cur + seq.num_captures, - up: Some(item), - sp_open: sp.open, - top_elts: Tt(TokenTree::Sequence(sp, seq)), - }))); - } - - // We need to match a metavar (but the identifier is invalid)... this is an error - TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => { - if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { - return Error(span, "missing fragment specifier".to_string()); - } - } - - // We need to match a metavar with a valid ident... call out to the black-box - // parser by adding an item to `bb_items`. - TokenTree::MetaVarDecl(_, _, id) => { - // Built-in nonterminals never start with these tokens, - // so we can eliminate them from consideration. - if may_begin_with(token, id.name) { - bb_items.push(item); - } - } - - // We need to descend into a delimited submatcher or a doc comment. To do this, we - // push the current matcher onto a stack and push a new item containing the - // submatcher onto `cur_items`. - // - // At the beginning of the loop, if we reach the end of the delimited submatcher, - // we pop the stack to backtrack out of the descent. - seq @ TokenTree::Delimited(..) | - seq @ TokenTree::Token(Token { kind: DocComment(..), .. }) => { - let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); - let idx = item.idx; - item.stack.push(MatcherTtFrame { - elts: lower_elts, - idx, - }); - item.idx = 0; - cur_items.push(item); - } - - // We just matched a normal token. We can just advance the parser. - TokenTree::Token(t) if token_name_eq(&t, token) => { - item.idx += 1; - next_items.push(item); - } - - // There was another token that was not `token`... This means we can't add any - // rules. NOTE that this is not necessarily an error unless _all_ items in - // `cur_items` end up doing this. There may still be some other matchers that do - // end up working out. - TokenTree::Token(..) | TokenTree::MetaVar(..) => {} - } - } - } - - // Yay a successful parse (so far)! - Success(()) -} - -/// Use the given sequence of token trees (`ms`) as a matcher. Match the given token stream `tts` -/// against it and return the match. -/// -/// # Parameters -/// -/// - `sess`: The session into which errors are emitted -/// - `tts`: The tokenstream we are matching against the pattern `ms` -/// - `ms`: A sequence of token trees representing a pattern against which we are matching -/// - `directory`: Information about the file locations (needed for the black-box parser) -/// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box -/// parser) -pub fn parse( - sess: &ParseSess, - tts: TokenStream, - ms: &[TokenTree], - directory: Option>, - recurse_into_modules: bool, -) -> NamedParseResult { - // Create a parser that can be used for the "black box" parts. - let mut parser = Parser::new( - sess, - tts, - directory, - recurse_into_modules, - true, - crate::MACRO_ARGUMENTS, - ); - - // A queue of possible matcher positions. We initialize it with the matcher position in which - // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then - // processes all of these possible matcher positions and produces possible next positions into - // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items` - // and we start over again. - // - // This MatcherPos instance is allocated on the stack. All others -- and - // there are frequently *no* others! -- are allocated on the heap. - let mut initial = initial_matcher_pos(ms, parser.token.span); - let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)]; - let mut next_items = Vec::new(); - - loop { - // Matcher positions black-box parsed by parser.rs (`parser`) - let mut bb_items = SmallVec::new(); - - // Matcher positions that would be valid if the macro invocation was over now - let mut eof_items = SmallVec::new(); - assert!(next_items.is_empty()); - - // Process `cur_items` until either we have finished the input or we need to get some - // parsing from the black-box parser done. The result is that `next_items` will contain a - // bunch of possible next matcher positions in `next_items`. - match inner_parse_loop( - sess, - &mut cur_items, - &mut next_items, - &mut eof_items, - &mut bb_items, - &parser.token, - ) { - Success(_) => {} - Failure(token, msg) => return Failure(token, msg), - Error(sp, msg) => return Error(sp, msg), - } - - // inner parse loop handled all cur_items, so it's empty - assert!(cur_items.is_empty()); - - // We need to do some post processing after the `inner_parser_loop`. - // - // Error messages here could be improved with links to original rules. - - // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise, - // either the parse is ambiguous (which should never happen) or there is a syntax error. - if parser.token == token::Eof { - if eof_items.len() == 1 { - let matches = eof_items[0] - .matches - .iter_mut() - .map(|dv| Lrc::make_mut(dv).pop().unwrap()); - return nameize(sess, ms, matches); - } else if eof_items.len() > 1 { - return Error( - parser.token.span, - "ambiguity: multiple successful parses".to_string(), - ); - } else { - return Failure( - Token::new(token::Eof, if parser.token.span.is_dummy() { - parser.token.span - } else { - sess.source_map().next_point(parser.token.span) - }), - "missing tokens in macro arguments", - ); - } - } - // Performance hack: eof_items may share matchers via Rc with other things that we want - // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an - // unnecessary implicit clone later in Rc::make_mut. - drop(eof_items); - - // Another possibility is that we need to call out to parse some rust nonterminal - // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong. - if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { - let nts = bb_items - .iter() - .map(|item| match item.top_elts.get_tt(item.idx) { - TokenTree::MetaVarDecl(_, bind, name) => format!("{} ('{}')", name, bind), - _ => panic!(), - }) - .collect::>() - .join(" or "); - - return Error( - parser.token.span, - format!( - "local ambiguity: multiple parsing options: {}", - match next_items.len() { - 0 => format!("built-in NTs {}.", nts), - 1 => format!("built-in NTs {} or 1 other option.", nts), - n => format!("built-in NTs {} or {} other options.", nts, n), - } - ), - ); - } - // If there are no possible next positions AND we aren't waiting for the black-box parser, - // then there is a syntax error. - else if bb_items.is_empty() && next_items.is_empty() { - return Failure( - parser.token.take(), - "no rules expected this token in macro call", - ); - } - // Dump all possible `next_items` into `cur_items` for the next iteration. - else if !next_items.is_empty() { - // Now process the next token - cur_items.extend(next_items.drain(..)); - parser.bump(); - } - // Finally, we have the case where we need to call the black-box parser to get some - // nonterminal. - else { - assert_eq!(bb_items.len(), 1); - - let mut item = bb_items.pop().unwrap(); - if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { - let match_cur = item.match_cur; - item.push_match( - match_cur, - MatchedNonterminal(Lrc::new(parse_nt(&mut parser, span, ident.name))), - ); - item.idx += 1; - item.match_cur += 1; - } else { - unreachable!() - } - cur_items.push(item); - } - - assert!(!cur_items.is_empty()); - } -} - -/// The token is an identifier, but not `_`. -/// We prohibit passing `_` to macros expecting `ident` for now. -fn get_macro_name(token: &Token) -> Option<(Name, bool)> { - match token.kind { - token::Ident(name, is_raw) if name != kw::Underscore => Some((name, is_raw)), - _ => None, - } -} - -/// Checks whether a non-terminal may begin with a particular token. -/// -/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that -/// token. Be conservative (return true) if not sure. -fn may_begin_with(token: &Token, name: Name) -> bool { - /// Checks whether the non-terminal may contain a single (non-keyword) identifier. - fn may_be_ident(nt: &token::Nonterminal) -> bool { - match *nt { - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false, - _ => true, - } - } - - match name { - sym::expr => token.can_begin_expr() - // This exception is here for backwards compatibility. - && !token.is_keyword(kw::Let), - sym::ty => token.can_begin_type(), - sym::ident => get_macro_name(token).is_some(), - sym::literal => token.can_begin_literal_or_bool(), - sym::vis => match token.kind { - // The follow-set of :vis + "priv" keyword + interpolated - token::Comma | token::Ident(..) | token::Interpolated(_) => true, - _ => token.can_begin_type(), - }, - sym::block => match token.kind { - token::OpenDelim(token::Brace) => true, - token::Interpolated(ref nt) => match **nt { - token::NtItem(_) - | token::NtPat(_) - | token::NtTy(_) - | token::NtIdent(..) - | token::NtMeta(_) - | token::NtPath(_) - | token::NtVis(_) => false, // none of these may start with '{'. - _ => true, - }, - _ => false, - }, - sym::path | sym::meta => match token.kind { - token::ModSep | token::Ident(..) => true, - token::Interpolated(ref nt) => match **nt { - token::NtPath(_) | token::NtMeta(_) => true, - _ => may_be_ident(&nt), - }, - _ => false, - }, - sym::pat => match token.kind { - token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) - token::OpenDelim(token::Paren) | // tuple pattern - token::OpenDelim(token::Bracket) | // slice pattern - token::BinOp(token::And) | // reference - token::BinOp(token::Minus) | // negative literal - token::AndAnd | // double reference - token::Literal(..) | // literal - token::DotDot | // range pattern (future compat) - token::DotDotDot | // range pattern (future compat) - token::ModSep | // path - token::Lt | // path (UFCS constant) - token::BinOp(token::Shl) => true, // path (double UFCS) - token::Interpolated(ref nt) => may_be_ident(nt), - _ => false, - }, - sym::lifetime => match token.kind { - token::Lifetime(_) => true, - token::Interpolated(ref nt) => match **nt { - token::NtLifetime(_) | token::NtTT(_) => true, - _ => false, - }, - _ => false, - }, - _ => match token.kind { - token::CloseDelim(_) => false, - _ => true, - }, - } -} - -/// A call to the "black-box" parser to parse some Rust non-terminal. -/// -/// # Parameters -/// -/// - `p`: the "black-box" parser to use -/// - `sp`: the `Span` we want to parse -/// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`, -/// etc...) -/// -/// # Returns -/// -/// The parsed non-terminal. -fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { - if name == sym::tt { - return token::NtTT(p.parse_token_tree()); - } - // check at the beginning and the parser checks after each bump - p.process_potential_macro_variable(); - match name { - sym::item => match panictry!(p.parse_item()) { - Some(i) => token::NtItem(i), - None => { - p.fatal("expected an item keyword").emit(); - FatalError.raise(); - } - }, - sym::block => token::NtBlock(panictry!(p.parse_block())), - sym::stmt => match panictry!(p.parse_stmt()) { - Some(s) => token::NtStmt(s), - None => { - p.fatal("expected a statement").emit(); - FatalError.raise(); - } - }, - sym::pat => token::NtPat(panictry!(p.parse_pat(None))), - sym::expr => token::NtExpr(panictry!(p.parse_expr())), - sym::literal => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())), - sym::ty => token::NtTy(panictry!(p.parse_ty())), - // this could be handled like a token, since it is one - sym::ident => if let Some((name, is_raw)) = get_macro_name(&p.token) { - let span = p.token.span; - p.bump(); - token::NtIdent(Ident::new(name, span), is_raw) - } else { - let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected ident, found {}", &token_str)).emit(); - FatalError.raise() - } - sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))), - sym::meta => token::NtMeta(panictry!(p.parse_meta_item())), - sym::vis => token::NtVis(panictry!(p.parse_visibility(true))), - sym::lifetime => if p.check_lifetime() { - token::NtLifetime(p.expect_lifetime().ident) - } else { - let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit(); - FatalError.raise(); - } - // this is not supposed to happen, since it has been checked - // when compiling the macro. - _ => p.span_bug(sp, "invalid fragment specifier"), - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_rules.rs b/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_rules.rs deleted file mode 100644 index 665c794..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/tt/macro_rules.rs +++ /dev/null @@ -1,1206 +0,0 @@ -use crate::edition::Edition; -use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::tt::macro_parser::{parse, parse_failure_msg}; -use crate::ext::tt::macro_parser::{Error, Failure, Success}; -use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq}; -use crate::ext::tt::quoted; -use crate::ext::tt::transcribe::transcribe; -use crate::feature_gate::Features; -use crate::parse::parser::Parser; -use crate::parse::token::TokenKind::*; -use crate::parse::token::{self, NtTT, Token}; -use crate::parse::{Directory, ParseSess}; -use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; -use crate::{ast, attr, attr::TransparencyError}; - -use errors::FatalError; -use log::debug; -use syntax_pos::{symbol::Ident, Span}; - -use rustc_data_structures::fx::FxHashMap; -use std::borrow::Cow; -use std::collections::hash_map::Entry; -use std::slice; - -use errors::Applicability; -use rustc_data_structures::sync::Lrc; - -const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ - `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ - `literal`, `path`, `meta`, `tt`, `item` and `vis`"; - -pub struct ParserAnyMacro<'a> { - parser: Parser<'a>, - - /// Span of the expansion site of the macro this parser is for - site_span: Span, - /// The ident of the macro we're parsing - macro_ident: ast::Ident, - arm_span: Span, -} - -impl<'a> ParserAnyMacro<'a> { - pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { - let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { - if parser.token == token::Eof && e.message().ends_with(", found ``") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } - let msg = &e.message[0]; - e.message[0] = ( - format!( - "macro expansion ends with an incomplete expression: {}", - msg.0.replace(", found ``", ""), - ), - msg.1, - ); - } - if e.span.is_dummy() { - // Get around lack of span in error (#30128) - e.replace_span_with(site_span); - if parser.sess.source_map().span_to_filename(arm_span).is_real() { - e.span_label(arm_span, "in this macro arm"); - } - } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() { - e.span_label(site_span, "in this macro invocation"); - } - e - })); - - // We allow semicolons at the end of expressions -- e.g., the semicolon in - // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, - // but `m!()` is allowed in expression positions (cf. issue #34706). - if kind == AstFragmentKind::Expr && parser.token == token::Semi { - parser.bump(); - } - - // Make sure we don't have any tokens left to parse so we don't silently drop anything. - let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span)); - parser.ensure_complete_parse(&path, kind.name(), site_span); - fragment - } -} - -struct MacroRulesMacroExpander { - name: ast::Ident, - lhses: Vec, - rhses: Vec, - valid: bool, -} - -impl TTMacroExpander for MacroRulesMacroExpander { - fn expand<'cx>( - &self, - cx: &'cx mut ExtCtxt<'_>, - sp: Span, - input: TokenStream, - def_span: Option, - ) -> Box { - if !self.valid { - return DummyResult::any(sp); - } - generic_extension(cx, sp, def_span, self.name, input, &self.lhses, &self.rhses) - } -} - -fn trace_macros_note(cx: &mut ExtCtxt<'_>, sp: Span, message: String) { - let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); - cx.expansions.entry(sp).or_default().push(message); -} - -/// Given `lhses` and `rhses`, this is the new macro we create -fn generic_extension<'cx>( - cx: &'cx mut ExtCtxt<'_>, - sp: Span, - def_span: Option, - name: ast::Ident, - arg: TokenStream, - lhses: &[quoted::TokenTree], - rhses: &[quoted::TokenTree], -) -> Box { - if cx.trace_macros() { - trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg)); - } - - // Which arm's failure should we report? (the one furthest along) - let mut best_failure: Option<(Token, &str)> = None; - - for (i, lhs) in lhses.iter().enumerate() { - // try each arm's matchers - let lhs_tt = match *lhs { - quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..], - _ => cx.span_bug(sp, "malformed macro lhs"), - }; - - match TokenTree::parse(cx, lhs_tt, arg.clone()) { - Success(named_matches) => { - let rhs = match rhses[i] { - // ignore delimiters - quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), - _ => cx.span_bug(sp, "malformed macro rhs"), - }; - let arm_span = rhses[i].span(); - - let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); - // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs); - - // Replace all the tokens for the corresponding positions in the macro, to maintain - // proper positions in error reporting, while maintaining the macro_backtrace. - if rhs_spans.len() == tts.len() { - tts = tts.map_enumerated(|i, mut tt| { - let mut sp = rhs_spans[i]; - sp = sp.with_ctxt(tt.span().ctxt()); - tt.set_span(sp); - tt - }); - } - - if cx.trace_macros() { - trace_macros_note(cx, sp, format!("to `{}`", tts)); - } - - let directory = Directory { - path: Cow::from(cx.current_expansion.module.directory.as_path()), - ownership: cx.current_expansion.directory_ownership, - }; - let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); - p.root_module_name = - cx.current_expansion.module.mod_path.last().map(|id| id.as_str().to_string()); - - p.process_potential_macro_variable(); - // Let the context choose how to interpret the result. - // Weird, but useful for X-macros. - return Box::new(ParserAnyMacro { - parser: p, - - // Pass along the original expansion site and the name of the macro - // so we can print a useful error message if the parse of the expanded - // macro leaves unparsed tokens. - site_span: sp, - macro_ident: name, - arm_span, - }); - } - Failure(token, msg) => match best_failure { - Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} - _ => best_failure = Some((token, msg)), - }, - Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]), - } - } - - let (token, label) = best_failure.expect("ran no matchers"); - let span = token.span.substitute_dummy(sp); - let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); - err.span_label(span, label); - if let Some(sp) = def_span { - if cx.source_map().span_to_filename(sp).is_real() && !sp.is_dummy() { - err.span_label(cx.source_map().def_span(sp), "when calling this macro"); - } - } - - // Check whether there's a missing comma in this macro call, like `println!("{}" a);` - if let Some((arg, comma_span)) = arg.add_comma() { - for lhs in lhses { - // try each arm's matchers - let lhs_tt = match *lhs { - quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..], - _ => continue, - }; - match TokenTree::parse(cx, lhs_tt, arg.clone()) { - Success(_) => { - if comma_span.is_dummy() { - err.note("you might be missing a comma"); - } else { - err.span_suggestion_short( - comma_span, - "missing comma here", - ", ".to_string(), - Applicability::MachineApplicable, - ); - } - } - _ => {} - } - } - } - err.emit(); - cx.trace_macros_diag(); - DummyResult::any(sp) -} - -// Note that macro-by-example's input is also matched against a token tree: -// $( $lhs:tt => $rhs:tt );+ -// -// Holy self-referential! - -/// Converts a `macro_rules!` invocation into a syntax extension. -pub fn compile( - sess: &ParseSess, - features: &Features, - def: &ast::Item, - edition: Edition, -) -> SyntaxExtension { - let lhs_nm = ast::Ident::new(sym::lhs, def.span); - let rhs_nm = ast::Ident::new(sym::rhs, def.span); - let tt_spec = ast::Ident::new(sym::tt, def.span); - - // Parse the macro_rules! invocation - let body = match def.node { - ast::ItemKind::MacroDef(ref body) => body, - _ => unreachable!(), - }; - - // The pattern that macro_rules matches. - // The grammar for macro_rules! is: - // $( $lhs:tt => $rhs:tt );+ - // ...quasiquoting this would be nice. - // These spans won't matter, anyways - let argument_gram = vec![ - quoted::TokenTree::Sequence( - DelimSpan::dummy(), - Lrc::new(quoted::SequenceRepetition { - tts: vec![ - quoted::TokenTree::MetaVarDecl(def.span, lhs_nm, tt_spec), - quoted::TokenTree::token(token::FatArrow, def.span), - quoted::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec), - ], - separator: Some(Token::new( - if body.legacy { token::Semi } else { token::Comma }, - def.span, - )), - op: quoted::KleeneOp::OneOrMore, - num_captures: 2, - }), - ), - // to phase into semicolon-termination instead of semicolon-separation - quoted::TokenTree::Sequence( - DelimSpan::dummy(), - Lrc::new(quoted::SequenceRepetition { - tts: vec![quoted::TokenTree::token(token::Semi, def.span)], - separator: None, - op: quoted::KleeneOp::ZeroOrMore, - num_captures: 0, - }), - ), - ]; - - let argument_map = match parse(sess, body.stream(), &argument_gram, None, true) { - Success(m) => m, - Failure(token, msg) => { - let s = parse_failure_msg(&token); - let sp = token.span.substitute_dummy(def.span); - let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s); - err.span_label(sp, msg); - err.emit(); - FatalError.raise(); - } - Error(sp, s) => { - sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); - } - }; - - let mut valid = true; - - // Extract the arguments: - let lhses = match *argument_map[&lhs_nm] { - MatchedSeq(ref s, _) => s - .iter() - .map(|m| { - if let MatchedNonterminal(ref nt) = *m { - if let NtTT(ref tt) = **nt { - let tt = quoted::parse( - tt.clone().into(), - true, - sess, - features, - &def.attrs, - edition, - def.id, - ) - .pop() - .unwrap(); - valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt); - return tt; - } - } - sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") - }) - .collect::>(), - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), - }; - - let rhses = match *argument_map[&rhs_nm] { - MatchedSeq(ref s, _) => s - .iter() - .map(|m| { - if let MatchedNonterminal(ref nt) = *m { - if let NtTT(ref tt) = **nt { - return quoted::parse( - tt.clone().into(), - false, - sess, - features, - &def.attrs, - edition, - def.id, - ) - .pop() - .unwrap(); - } - } - sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") - }) - .collect::>(), - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"), - }; - - for rhs in &rhses { - valid &= check_rhs(sess, rhs); - } - - // don't abort iteration early, so that errors for multiple lhses can be reported - for lhs in &lhses { - valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs)); - valid &= check_lhs_duplicate_matcher_bindings( - sess, - slice::from_ref(lhs), - &mut FxHashMap::default(), - def.id, - ); - } - - let expander: Box<_> = - Box::new(MacroRulesMacroExpander { name: def.ident, lhses, rhses, valid }); - - let (default_transparency, transparency_error) = - attr::find_transparency(&def.attrs, body.legacy); - match transparency_error { - Some(TransparencyError::UnknownTransparency(value, span)) => - sess.span_diagnostic.span_err( - span, &format!("unknown macro transparency: `{}`", value) - ), - Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => - sess.span_diagnostic.span_err( - vec![old_span, new_span], "multiple macro transparency attributes" - ), - None => {} - } - - let allow_internal_unstable = - attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| { - attr.meta_item_list() - .map(|list| { - list.iter() - .filter_map(|it| { - let name = it.ident().map(|ident| ident.name); - if name.is_none() { - sess.span_diagnostic.span_err( - it.span(), - "allow internal unstable expects feature names", - ) - } - name - }) - .collect::>() - .into() - }) - .unwrap_or_else(|| { - sess.span_diagnostic.span_warn( - attr.span, - "allow_internal_unstable expects list of feature names. In the \ - future this will become a hard error. Please use `allow_internal_unstable(\ - foo, bar)` to only allow the `foo` and `bar` features", - ); - vec![sym::allow_internal_unstable_backcompat_hack].into() - }) - }); - - let mut local_inner_macros = false; - if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) { - if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); - } - } - - SyntaxExtension { - kind: SyntaxExtensionKind::LegacyBang(expander), - span: def.span, - default_transparency, - allow_internal_unstable, - allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), - local_inner_macros, - stability: attr::find_stability(&sess, &def.attrs, def.span), - deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), - helper_attrs: Vec::new(), - edition, - } -} - -fn check_lhs_nt_follows( - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - lhs: "ed::TokenTree, -) -> bool { - // lhs is going to be like TokenTree::Delimited(...), where the - // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. - if let quoted::TokenTree::Delimited(_, ref tts) = *lhs { - check_matcher(sess, features, attrs, &tts.tts) - } else { - let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; - sess.span_diagnostic.span_err(lhs.span(), msg); - false - } - // we don't abort on errors on rejection, the driver will do that for us - // after parsing/expansion. we can report every error in every macro this way. -} - -/// Checks that the lhs contains no repetition which could match an empty token -/// tree, because then the matcher would hang indefinitely. -fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { - use quoted::TokenTree; - for tt in tts { - match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (), - TokenTree::Delimited(_, ref del) => { - if !check_lhs_no_empty_seq(sess, &del.tts) { - return false; - } - } - TokenTree::Sequence(span, ref seq) => { - if seq.separator.is_none() - && seq.tts.iter().all(|seq_tt| match *seq_tt { - TokenTree::MetaVarDecl(_, _, id) => id.name == sym::vis, - TokenTree::Sequence(_, ref sub_seq) => { - sub_seq.op == quoted::KleeneOp::ZeroOrMore - || sub_seq.op == quoted::KleeneOp::ZeroOrOne - } - _ => false, - }) - { - let sp = span.entire(); - sess.span_diagnostic.span_err(sp, "repetition matches empty token tree"); - return false; - } - if !check_lhs_no_empty_seq(sess, &seq.tts) { - return false; - } - } - } - } - - true -} - -/// Check that the LHS contains no duplicate matcher bindings. e.g. `$a:expr, $a:expr` would be -/// illegal, since it would be ambiguous which `$a` to use if we ever needed to. -fn check_lhs_duplicate_matcher_bindings( - sess: &ParseSess, - tts: &[quoted::TokenTree], - metavar_names: &mut FxHashMap, - node_id: ast::NodeId, -) -> bool { - use self::quoted::TokenTree; - for tt in tts { - match *tt { - TokenTree::MetaVarDecl(span, name, _kind) => { - if let Some(&prev_span) = metavar_names.get(&name) { - sess.span_diagnostic - .struct_span_err(span, "duplicate matcher binding") - .span_note(prev_span, "previous declaration was here") - .emit(); - return false; - } else { - metavar_names.insert(name, span); - } - } - TokenTree::Delimited(_, ref del) => { - if !check_lhs_duplicate_matcher_bindings(sess, &del.tts, metavar_names, node_id) { - return false; - } - } - TokenTree::Sequence(_, ref seq) => { - if !check_lhs_duplicate_matcher_bindings(sess, &seq.tts, metavar_names, node_id) { - return false; - } - } - _ => {} - } - } - - true -} - -fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { - match *rhs { - quoted::TokenTree::Delimited(..) => return true, - _ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"), - } - false -} - -fn check_matcher( - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - matcher: &[quoted::TokenTree], -) -> bool { - let first_sets = FirstSets::new(matcher); - let empty_suffix = TokenSet::empty(); - let err = sess.span_diagnostic.err_count(); - check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix); - err == sess.span_diagnostic.err_count() -} - -// `The FirstSets` for a matcher is a mapping from subsequences in the -// matcher to the FIRST set for that subsequence. -// -// This mapping is partially precomputed via a backwards scan over the -// token trees of the matcher, which provides a mapping from each -// repetition sequence to its *first* set. -// -// (Hypothetically, sequences should be uniquely identifiable via their -// spans, though perhaps that is false, e.g., for macro-generated macros -// that do not try to inject artificial span information. My plan is -// to try to catch such cases ahead of time and not include them in -// the precomputed mapping.) -struct FirstSets { - // this maps each TokenTree::Sequence `$(tt ...) SEP OP` that is uniquely identified by its - // span in the original matcher to the First set for the inner sequence `tt ...`. - // - // If two sequences have the same span in a matcher, then map that - // span to None (invalidating the mapping here and forcing the code to - // use a slow path). - first: FxHashMap>, -} - -impl FirstSets { - fn new(tts: &[quoted::TokenTree]) -> FirstSets { - use quoted::TokenTree; - - let mut sets = FirstSets { first: FxHashMap::default() }; - build_recur(&mut sets, tts); - return sets; - - // walks backward over `tts`, returning the FIRST for `tts` - // and updating `sets` at the same time for all sequence - // substructure we find within `tts`. - fn build_recur(sets: &mut FirstSets, tts: &[TokenTree]) -> TokenSet { - let mut first = TokenSet::empty(); - for tt in tts.iter().rev() { - match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { - first.replace_with(tt.clone()); - } - TokenTree::Delimited(span, ref delimited) => { - build_recur(sets, &delimited.tts[..]); - first.replace_with(delimited.open_tt(span.open)); - } - TokenTree::Sequence(sp, ref seq_rep) => { - let subfirst = build_recur(sets, &seq_rep.tts[..]); - - match sets.first.entry(sp.entire()) { - Entry::Vacant(vac) => { - vac.insert(Some(subfirst.clone())); - } - Entry::Occupied(mut occ) => { - // if there is already an entry, then a span must have collided. - // This should not happen with typical macro_rules macros, - // but syntax extensions need not maintain distinct spans, - // so distinct syntax trees can be assigned the same span. - // In such a case, the map cannot be trusted; so mark this - // entry as unusable. - occ.insert(None); - } - } - - // If the sequence contents can be empty, then the first - // token could be the separator token itself. - - if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TokenTree::Token(sep.clone())); - } - - // Reverse scan: Sequence comes before `first`. - if subfirst.maybe_empty - || seq_rep.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.op == quoted::KleeneOp::ZeroOrOne - { - // If sequence is potentially empty, then - // union them (preserving first emptiness). - first.add_all(&TokenSet { maybe_empty: true, ..subfirst }); - } else { - // Otherwise, sequence guaranteed - // non-empty; replace first. - first = subfirst; - } - } - } - } - - first - } - } - - // walks forward over `tts` until all potential FIRST tokens are - // identified. - fn first(&self, tts: &[quoted::TokenTree]) -> TokenSet { - use quoted::TokenTree; - - let mut first = TokenSet::empty(); - for tt in tts.iter() { - assert!(first.maybe_empty); - match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { - first.add_one(tt.clone()); - return first; - } - TokenTree::Delimited(span, ref delimited) => { - first.add_one(delimited.open_tt(span.open)); - return first; - } - TokenTree::Sequence(sp, ref seq_rep) => { - match self.first.get(&sp.entire()) { - Some(&Some(ref subfirst)) => { - // If the sequence contents can be empty, then the first - // token could be the separator token itself. - - if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TokenTree::Token(sep.clone())); - } - - assert!(first.maybe_empty); - first.add_all(subfirst); - if subfirst.maybe_empty - || seq_rep.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.op == quoted::KleeneOp::ZeroOrOne - { - // continue scanning for more first - // tokens, but also make sure we - // restore empty-tracking state - first.maybe_empty = true; - continue; - } else { - return first; - } - } - - Some(&None) => { - panic!("assume all sequences have (unique) spans for now"); - } - - None => { - panic!("We missed a sequence during FirstSets construction"); - } - } - } - } - } - - // we only exit the loop if `tts` was empty or if every - // element of `tts` matches the empty sequence. - assert!(first.maybe_empty); - first - } -} - -// A set of `quoted::TokenTree`s, which may include `TokenTree::Match`s -// (for macro-by-example syntactic variables). It also carries the -// `maybe_empty` flag; that is true if and only if the matcher can -// match an empty token sequence. -// -// The First set is computed on submatchers like `$($a:expr b),* $(c)* d`, -// which has corresponding FIRST = {$a:expr, c, d}. -// Likewise, `$($a:expr b),* $(c)+ d` has FIRST = {$a:expr, c}. -// -// (Notably, we must allow for *-op to occur zero times.) -#[derive(Clone, Debug)] -struct TokenSet { - tokens: Vec, - maybe_empty: bool, -} - -impl TokenSet { - // Returns a set for the empty sequence. - fn empty() -> Self { - TokenSet { tokens: Vec::new(), maybe_empty: true } - } - - // Returns the set `{ tok }` for the single-token (and thus - // non-empty) sequence [tok]. - fn singleton(tok: quoted::TokenTree) -> Self { - TokenSet { tokens: vec![tok], maybe_empty: false } - } - - // Changes self to be the set `{ tok }`. - // Since `tok` is always present, marks self as non-empty. - fn replace_with(&mut self, tok: quoted::TokenTree) { - self.tokens.clear(); - self.tokens.push(tok); - self.maybe_empty = false; - } - - // Changes self to be the empty set `{}`; meant for use when - // the particular token does not matter, but we want to - // record that it occurs. - fn replace_with_irrelevant(&mut self) { - self.tokens.clear(); - self.maybe_empty = false; - } - - // Adds `tok` to the set for `self`, marking sequence as non-empy. - fn add_one(&mut self, tok: quoted::TokenTree) { - if !self.tokens.contains(&tok) { - self.tokens.push(tok); - } - self.maybe_empty = false; - } - - // Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.) - fn add_one_maybe(&mut self, tok: quoted::TokenTree) { - if !self.tokens.contains(&tok) { - self.tokens.push(tok); - } - } - - // Adds all elements of `other` to this. - // - // (Since this is a set, we filter out duplicates.) - // - // If `other` is potentially empty, then preserves the previous - // setting of the empty flag of `self`. If `other` is guaranteed - // non-empty, then `self` is marked non-empty. - fn add_all(&mut self, other: &Self) { - for tok in &other.tokens { - if !self.tokens.contains(tok) { - self.tokens.push(tok.clone()); - } - } - if !other.maybe_empty { - self.maybe_empty = false; - } - } -} - -// Checks that `matcher` is internally consistent and that it -// can legally by followed by a token N, for all N in `follow`. -// (If `follow` is empty, then it imposes no constraint on -// the `matcher`.) -// -// Returns the set of NT tokens that could possibly come last in -// `matcher`. (If `matcher` matches the empty sequence, then -// `maybe_empty` will be set to true.) -// -// Requires that `first_sets` is pre-computed for `matcher`; -// see `FirstSets::new`. -fn check_matcher_core( - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - first_sets: &FirstSets, - matcher: &[quoted::TokenTree], - follow: &TokenSet, -) -> TokenSet { - use quoted::TokenTree; - - let mut last = TokenSet::empty(); - - // 2. For each token and suffix [T, SUFFIX] in M: - // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty, - // then ensure T can also be followed by any element of FOLLOW. - 'each_token: for i in 0..matcher.len() { - let token = &matcher[i]; - let suffix = &matcher[i + 1..]; - - let build_suffix_first = || { - let mut s = first_sets.first(suffix); - if s.maybe_empty { - s.add_all(follow); - } - s - }; - - // (we build `suffix_first` on demand below; you can tell - // which cases are supposed to fall through by looking for the - // initialization of this variable.) - let suffix_first; - - // First, update `last` so that it corresponds to the set - // of NT tokens that might end the sequence `... token`. - match *token { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { - let can_be_followed_by_any; - if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, attrs, token) { - let msg = format!("invalid fragment specifier `{}`", bad_frag); - sess.span_diagnostic - .struct_span_err(token.span(), &msg) - .help(VALID_FRAGMENT_NAMES_MSG) - .emit(); - // (This eliminates false positives and duplicates - // from error messages.) - can_be_followed_by_any = true; - } else { - can_be_followed_by_any = token_can_be_followed_by_any(token); - } - - if can_be_followed_by_any { - // don't need to track tokens that work with any, - last.replace_with_irrelevant(); - // ... and don't need to check tokens that can be - // followed by anything against SUFFIX. - continue 'each_token; - } else { - last.replace_with(token.clone()); - suffix_first = build_suffix_first(); - } - } - TokenTree::Delimited(span, ref d) => { - let my_suffix = TokenSet::singleton(d.close_tt(span.close)); - check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix); - // don't track non NT tokens - last.replace_with_irrelevant(); - - // also, we don't need to check delimited sequences - // against SUFFIX - continue 'each_token; - } - TokenTree::Sequence(_, ref seq_rep) => { - suffix_first = build_suffix_first(); - // The trick here: when we check the interior, we want - // to include the separator (if any) as a potential - // (but not guaranteed) element of FOLLOW. So in that - // case, we make a temp copy of suffix and stuff - // delimiter in there. - // - // FIXME: Should I first scan suffix_first to see if - // delimiter is already in it before I go through the - // work of cloning it? But then again, this way I may - // get a "tighter" span? - let mut new; - let my_suffix = if let Some(sep) = &seq_rep.separator { - new = suffix_first.clone(); - new.add_one_maybe(TokenTree::Token(sep.clone())); - &new - } else { - &suffix_first - }; - - // At this point, `suffix_first` is built, and - // `my_suffix` is some TokenSet that we can use - // for checking the interior of `seq_rep`. - let next = - check_matcher_core(sess, features, attrs, first_sets, &seq_rep.tts, my_suffix); - if next.maybe_empty { - last.add_all(&next); - } else { - last = next; - } - - // the recursive call to check_matcher_core already ran the 'each_last - // check below, so we can just keep going forward here. - continue 'each_token; - } - } - - // (`suffix_first` guaranteed initialized once reaching here.) - - // Now `last` holds the complete set of NT tokens that could - // end the sequence before SUFFIX. Check that every one works with `suffix`. - 'each_last: for token in &last.tokens { - if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token { - for next_token in &suffix_first.tokens { - match is_in_follow(next_token, &frag_spec.as_str()) { - IsInFollow::Invalid(msg, help) => { - sess.span_diagnostic - .struct_span_err(next_token.span(), &msg) - .help(help) - .emit(); - // don't bother reporting every source of - // conflict for a particular element of `last`. - continue 'each_last; - } - IsInFollow::Yes => {} - IsInFollow::No(possible) => { - let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1 - { - "is" - } else { - "may be" - }; - - let sp = next_token.span(); - let mut err = sess.span_diagnostic.struct_span_err( - sp, - &format!( - "`${name}:{frag}` {may_be} followed by `{next}`, which \ - is not allowed for `{frag}` fragments", - name = name, - frag = frag_spec, - next = quoted_tt_to_string(next_token), - may_be = may_be - ), - ); - err.span_label( - sp, - format!("not allowed after `{}` fragments", frag_spec), - ); - let msg = "allowed there are: "; - match possible { - &[] => {} - &[t] => { - err.note(&format!( - "only {} is allowed after `{}` fragments", - t, frag_spec, - )); - } - ts => { - err.note(&format!( - "{}{} or {}", - msg, - ts[..ts.len() - 1] - .iter() - .map(|s| *s) - .collect::>() - .join(", "), - ts[ts.len() - 1], - )); - } - } - err.emit(); - } - } - } - } - } - } - last -} - -fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool { - if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { - frag_can_be_followed_by_any(&frag_spec.as_str()) - } else { - // (Non NT's can always be followed by anthing in matchers.) - true - } -} - -/// Returns `true` if a fragment of type `frag` can be followed by any sort of -/// token. We use this (among other things) as a useful approximation -/// for when `frag` can be followed by a repetition like `$(...)*` or -/// `$(...)+`. In general, these can be a bit tricky to reason about, -/// so we adopt a conservative position that says that any fragment -/// specifier which consumes at most one token tree can be followed by -/// a fragment specifier (indeed, these fragments can be followed by -/// ANYTHING without fear of future compatibility hazards). -fn frag_can_be_followed_by_any(frag: &str) -> bool { - match frag { - "item" | // always terminated by `}` or `;` - "block" | // exactly one token tree - "ident" | // exactly one token tree - "literal" | // exactly one token tree - "meta" | // exactly one token tree - "lifetime" | // exactly one token tree - "tt" => // exactly one token tree - true, - - _ => - false, - } -} - -enum IsInFollow { - Yes, - No(&'static [&'static str]), - Invalid(String, &'static str), -} - -/// Returns `true` if `frag` can legally be followed by the token `tok`. For -/// fragments that can consume an unbounded number of tokens, `tok` -/// must be within a well-defined follow set. This is intended to -/// guarantee future compatibility: for example, without this rule, if -/// we expanded `expr` to include a new binary operator, we might -/// break macros that were relying on that binary operator as a -/// separator. -// when changing this do not forget to update doc/book/macros.md! -fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { - use quoted::TokenTree; - - if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok { - // closing a token tree can never be matched by any fragment; - // iow, we always require that `(` and `)` match, etc. - IsInFollow::Yes - } else { - match frag { - "item" => { - // since items *must* be followed by either a `;` or a `}`, we can - // accept anything after them - IsInFollow::Yes - } - "block" => { - // anything can follow block, the braces provide an easy boundary to - // maintain - IsInFollow::Yes - } - "stmt" | "expr" => { - const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; - match tok { - TokenTree::Token(token) => match token.kind { - FatArrow | Comma | Semi => IsInFollow::Yes, - _ => IsInFollow::No(TOKENS), - }, - _ => IsInFollow::No(TOKENS), - } - } - "pat" => { - const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; - match tok { - TokenTree::Token(token) => match token.kind { - FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes, - Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes, - _ => IsInFollow::No(TOKENS), - }, - _ => IsInFollow::No(TOKENS), - } - } - "path" | "ty" => { - const TOKENS: &[&str] = &[ - "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`", - "`where`", - ]; - match tok { - TokenTree::Token(token) => match token.kind { - OpenDelim(token::DelimToken::Brace) - | OpenDelim(token::DelimToken::Bracket) - | Comma - | FatArrow - | Colon - | Eq - | Gt - | BinOp(token::Shr) - | Semi - | BinOp(token::Or) => IsInFollow::Yes, - Ident(name, false) if name == kw::As || name == kw::Where => { - IsInFollow::Yes - } - _ => IsInFollow::No(TOKENS), - }, - TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block => { - IsInFollow::Yes - } - _ => IsInFollow::No(TOKENS), - } - } - "ident" | "lifetime" => { - // being a single token, idents and lifetimes are harmless - IsInFollow::Yes - } - "literal" => { - // literals may be of a single token, or two tokens (negative numbers) - IsInFollow::Yes - } - "meta" | "tt" => { - // being either a single token or a delimited sequence, tt is - // harmless - IsInFollow::Yes - } - "vis" => { - // Explicitly disallow `priv`, on the off chance it comes back. - const TOKENS: &[&str] = &["`,`", "an ident", "a type"]; - match tok { - TokenTree::Token(token) => match token.kind { - Comma => IsInFollow::Yes, - Ident(name, is_raw) if is_raw || name != kw::Priv => IsInFollow::Yes, - _ => { - if token.can_begin_type() { - IsInFollow::Yes - } else { - IsInFollow::No(TOKENS) - } - } - }, - TokenTree::MetaVarDecl(_, _, frag) - if frag.name == sym::ident - || frag.name == sym::ty - || frag.name == sym::path => - { - IsInFollow::Yes - } - _ => IsInFollow::No(TOKENS), - } - } - "" => IsInFollow::Yes, // kw::Invalid - _ => IsInFollow::Invalid( - format!("invalid fragment specifier `{}`", frag), - VALID_FRAGMENT_NAMES_MSG, - ), - } - } -} - -fn has_legal_fragment_specifier( - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - tok: "ed::TokenTree, -) -> Result<(), String> { - debug!("has_legal_fragment_specifier({:?})", tok); - if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { - let frag_span = tok.span(); - if !is_legal_fragment_specifier(sess, features, attrs, frag_spec.name, frag_span) { - return Err(frag_spec.to_string()); - } - } - Ok(()) -} - -fn is_legal_fragment_specifier( - _sess: &ParseSess, - _features: &Features, - _attrs: &[ast::Attribute], - frag_name: Symbol, - _frag_span: Span, -) -> bool { - /* - * If new fragment specifiers are invented in nightly, `_sess`, - * `_features`, `_attrs`, and `_frag_span` will be useful here - * for checking against feature gates. See past versions of - * this function. - */ - match frag_name { - sym::item - | sym::block - | sym::stmt - | sym::expr - | sym::pat - | sym::lifetime - | sym::path - | sym::ty - | sym::ident - | sym::meta - | sym::tt - | sym::vis - | sym::literal - | kw::Invalid => true, - _ => false, - } -} - -fn quoted_tt_to_string(tt: "ed::TokenTree) -> String { - match *tt { - quoted::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token), - quoted::TokenTree::MetaVar(_, name) => format!("${}", name), - quoted::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), - _ => panic!( - "unexpected quoted::TokenTree::{{Sequence or Delimited}} \ - in follow set checker" - ), - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/tt/quoted.rs b/gcc/rust/rustc_parser/libsyntax/ext/tt/quoted.rs deleted file mode 100644 index ccf9db8..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/tt/quoted.rs +++ /dev/null @@ -1,418 +0,0 @@ -use crate::ast; -use crate::ast::NodeId; -use crate::ext::tt::macro_parser; -use crate::feature_gate::Features; -use crate::parse::token::{self, Token, TokenKind}; -use crate::parse::ParseSess; -use crate::print::pprust; -use crate::symbol::kw; -use crate::tokenstream::{self, DelimSpan}; - -use syntax_pos::{edition::Edition, BytePos, Span}; - -use rustc_data_structures::sync::Lrc; -use std::iter::Peekable; - -/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note -/// that the delimiter itself might be `NoDelim`. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct Delimited { - pub delim: token::DelimToken, - pub tts: Vec, -} - -impl Delimited { - /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. - pub fn open_tt(&self, span: Span) -> TokenTree { - let open_span = if span.is_dummy() { - span - } else { - span.with_lo(span.lo() + BytePos(self.delim.len() as u32)) - }; - TokenTree::token(token::OpenDelim(self.delim), open_span) - } - - /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. - pub fn close_tt(&self, span: Span) -> TokenTree { - let close_span = if span.is_dummy() { - span - } else { - span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) - }; - TokenTree::token(token::CloseDelim(self.delim), close_span) - } -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct SequenceRepetition { - /// The sequence of token trees - pub tts: Vec, - /// The optional separator - pub separator: Option, - /// Whether the sequence can be repeated zero (*), or one or more times (+) - pub op: KleeneOp, - /// The number of `Match`s that appear in the sequence (and subsequences) - pub num_captures: usize, -} - -/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) -/// for token sequences. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum KleeneOp { - /// Kleene star (`*`) for zero or more repetitions - ZeroOrMore, - /// Kleene plus (`+`) for one or more repetitions - OneOrMore, - /// Kleene optional (`?`) for zero or one reptitions - ZeroOrOne, -} - -/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` -/// are "first-class" token trees. Useful for parsing macros. -#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] -pub enum TokenTree { - Token(Token), - Delimited(DelimSpan, Lrc), - /// A kleene-style repetition sequence - Sequence(DelimSpan, Lrc), - /// e.g., `$var` - MetaVar(Span, ast::Ident), - /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. - MetaVarDecl( - Span, - ast::Ident, /* name to bind */ - ast::Ident, /* kind of nonterminal */ - ), -} - -impl TokenTree { - /// Return the number of tokens in the tree. - pub fn len(&self) -> usize { - match *self { - TokenTree::Delimited(_, ref delimed) => match delimed.delim { - token::NoDelim => delimed.tts.len(), - _ => delimed.tts.len() + 2, - }, - TokenTree::Sequence(_, ref seq) => seq.tts.len(), - _ => 0, - } - } - - /// Returns `true` if the given token tree contains no other tokens. This is vacuously true for - /// single tokens or metavar/decls, but may be false for delimited trees or sequences. - pub fn is_empty(&self) -> bool { - match *self { - TokenTree::Delimited(_, ref delimed) => match delimed.delim { - token::NoDelim => delimed.tts.is_empty(), - _ => false, - }, - TokenTree::Sequence(_, ref seq) => seq.tts.is_empty(), - _ => true, - } - } - - /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. - pub fn get_tt(&self, index: usize) -> TokenTree { - match (self, index) { - (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { - delimed.tts[index].clone() - } - (&TokenTree::Delimited(span, ref delimed), _) => { - if index == 0 { - return delimed.open_tt(span.open); - } - if index == delimed.tts.len() + 1 { - return delimed.close_tt(span.close); - } - delimed.tts[index - 1].clone() - } - (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), - _ => panic!("Cannot expand a token tree"), - } - } - - /// Retrieves the `TokenTree`'s span. - pub fn span(&self) -> Span { - match *self { - TokenTree::Token(Token { span, .. }) - | TokenTree::MetaVar(span, _) - | TokenTree::MetaVarDecl(span, _, _) => span, - TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(), - } - } - - crate fn token(kind: TokenKind, span: Span) -> TokenTree { - TokenTree::Token(Token::new(kind, span)) - } -} - -/// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this -/// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a -/// collection of `TokenTree` for use in parsing a macro. -/// -/// # Parameters -/// -/// - `input`: a token stream to read from, the contents of which we are parsing. -/// - `expect_matchers`: `parse` can be used to parse either the "patterns" or the "body" of a -/// macro. Both take roughly the same form _except_ that in a pattern, metavars are declared with -/// their "matcher" type. For example `$var:expr` or `$id:ident`. In this example, `expr` and -/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the -/// pattern, so we pass a parameter to indicate whether to expect them or not. -/// - `sess`: the parsing session. Any errors will be emitted to this session. -/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use -/// unstable features or not. -/// - `edition`: which edition are we in. -/// - `macro_node_id`: the NodeId of the macro we are parsing. -/// -/// # Returns -/// -/// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`. -pub fn parse( - input: tokenstream::TokenStream, - expect_matchers: bool, - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, -) -> Vec { - // Will contain the final collection of `self::TokenTree` - let mut result = Vec::new(); - - // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming - // additional trees if need be. - let mut trees = input.trees().peekable(); - while let Some(tree) = trees.next() { - // Given the parsed tree, if there is a metavar and we are expecting matchers, actually - // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). - let tree = parse_tree( - tree, - &mut trees, - expect_matchers, - sess, - features, - attrs, - edition, - macro_node_id, - ); - match tree { - TokenTree::MetaVar(start_sp, ident) if expect_matchers => { - let span = match trees.next() { - Some(tokenstream::TokenTree::Token(Token { kind: token::Colon, span })) => { - match trees.next() { - Some(tokenstream::TokenTree::Token(token)) => match token.ident() { - Some((kind, _)) => { - let span = token.span.with_lo(start_sp.lo()); - result.push(TokenTree::MetaVarDecl(span, ident, kind)); - continue; - } - _ => token.span, - }, - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span), - } - } - tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp), - }; - sess.missing_fragment_specifiers.borrow_mut().insert(span); - result.push(TokenTree::MetaVarDecl(span, ident, ast::Ident::invalid())); - } - - // Not a metavar or no matchers allowed, so just return the tree - _ => result.push(tree), - } - } - result -} - -/// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a -/// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree` -/// for use in parsing a macro. -/// -/// Converting the given tree may involve reading more tokens. -/// -/// # Parameters -/// -/// - `tree`: the tree we wish to convert. -/// - `trees`: an iterator over trees. We may need to read more tokens from it in order to finish -/// converting `tree` -/// - `expect_matchers`: same as for `parse` (see above). -/// - `sess`: the parsing session. Any errors will be emitted to this session. -/// - `features`, `attrs`: language feature flags and attributes so that we know whether to use -/// unstable features or not. -fn parse_tree( - tree: tokenstream::TokenTree, - trees: &mut Peekable>, - expect_matchers: bool, - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, -) -> TokenTree { - // Depending on what `tree` is, we could be parsing different parts of a macro - match tree { - // `tree` is a `$` token. Look at the next token in `trees` - tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }) => match trees.next() { - // `tree` is followed by a delimited set of token trees. This indicates the beginning - // of a repetition sequence in the macro (e.g. `$(pat)*`). - Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { - // Must have `(` not `{` or `[` - if delim != token::Paren { - let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); - let msg = format!("expected `(`, found `{}`", tok); - sess.span_diagnostic.span_err(span.entire(), &msg); - } - // Parse the contents of the sequence itself - let sequence = parse( - tts.into(), - expect_matchers, - sess, - features, - attrs, - edition, - macro_node_id, - ); - // Get the Kleene operator and optional separator - let (separator, op) = parse_sep_and_kleene_op(trees, span.entire(), sess); - // Count the number of captured "names" (i.e., named metavars) - let name_captures = macro_parser::count_names(&sequence); - TokenTree::Sequence( - span, - Lrc::new(SequenceRepetition { - tts: sequence, - separator, - op, - num_captures: name_captures, - }), - ) - } - - // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special - // metavariable that names the crate of the invocation. - Some(tokenstream::TokenTree::Token(token)) if token.is_ident() => { - let (ident, is_raw) = token.ident().unwrap(); - let span = ident.span.with_lo(span.lo()); - if ident.name == kw::Crate && !is_raw { - TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span) - } else { - TokenTree::MetaVar(span, ident) - } - } - - // `tree` is followed by a random token. This is an error. - Some(tokenstream::TokenTree::Token(token)) => { - let msg = - format!("expected identifier, found `{}`", pprust::token_to_string(&token),); - sess.span_diagnostic.span_err(token.span, &msg); - TokenTree::MetaVar(token.span, ast::Ident::invalid()) - } - - // There are no more tokens. Just return the `$` we already have. - None => TokenTree::token(token::Dollar, span), - }, - - // `tree` is an arbitrary token. Keep it. - tokenstream::TokenTree::Token(token) => TokenTree::Token(token), - - // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to - // descend into the delimited set and further parse it. - tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( - span, - Lrc::new(Delimited { - delim, - tts: parse( - tts.into(), - expect_matchers, - sess, - features, - attrs, - edition, - macro_node_id, - ), - }), - ), - } -} - -/// Takes a token and returns `Some(KleeneOp)` if the token is `+` `*` or `?`. Otherwise, return -/// `None`. -fn kleene_op(token: &Token) -> Option { - match token.kind { - token::BinOp(token::Star) => Some(KleeneOp::ZeroOrMore), - token::BinOp(token::Plus) => Some(KleeneOp::OneOrMore), - token::Question => Some(KleeneOp::ZeroOrOne), - _ => None, - } -} - -/// Parse the next token tree of the input looking for a KleeneOp. Returns -/// -/// - Ok(Ok((op, span))) if the next token tree is a KleeneOp -/// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp -/// - Err(span) if the next token tree is not a token -fn parse_kleene_op( - input: &mut impl Iterator, - span: Span, -) -> Result, Span> { - match input.next() { - Some(tokenstream::TokenTree::Token(token)) => match kleene_op(&token) { - Some(op) => Ok(Ok((op, token.span))), - None => Ok(Err(token)), - }, - tree => Err(tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span)), - } -} - -/// Attempt to parse a single Kleene star, possibly with a separator. -/// -/// For example, in a pattern such as `$(a),*`, `a` is the pattern to be repeated, `,` is the -/// separator, and `*` is the Kleene operator. This function is specifically concerned with parsing -/// the last two tokens of such a pattern: namely, the optional separator and the Kleene operator -/// itself. Note that here we are parsing the _macro_ itself, rather than trying to match some -/// stream of tokens in an invocation of a macro. -/// -/// This function will take some input iterator `input` corresponding to `span` and a parsing -/// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene -/// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an -/// error with the appropriate span is emitted to `sess` and a dummy value is returned. -fn parse_sep_and_kleene_op( - input: &mut Peekable>, - span: Span, - sess: &ParseSess, -) -> (Option, KleeneOp) { - // We basically look at two token trees here, denoted as #1 and #2 below - let span = match parse_kleene_op(input, span) { - // #1 is a `?`, `+`, or `*` KleeneOp - Ok(Ok((op, _))) => return (None, op), - - // #1 is a separator followed by #2, a KleeneOp - Ok(Err(token)) => match parse_kleene_op(input, token.span) { - // #2 is the `?` Kleene op, which does not take a separator (error) - Ok(Ok((KleeneOp::ZeroOrOne, _))) => { - // Error! - sess.span_diagnostic.span_err( - token.span, - "the `?` macro repetition operator does not take a separator", - ); - - // Return a dummy - return (None, KleeneOp::ZeroOrMore); - } - - // #2 is a KleeneOp :D - Ok(Ok((op, _))) => return (Some(token), op), - - // #2 is a random token or not a token at all :( - Ok(Err(Token { span, .. })) | Err(span) => span, - }, - - // #1 is not a token - Err(span) => span, - }; - - // If we ever get to this point, we have experienced an "unexpected token" error - sess.span_diagnostic.span_err(span, "expected one of: `*`, `+`, or `?`"); - - // Return a dummy - (None, KleeneOp::ZeroOrMore) -} diff --git a/gcc/rust/rustc_parser/libsyntax/ext/tt/transcribe.rs b/gcc/rust/rustc_parser/libsyntax/ext/tt/transcribe.rs deleted file mode 100644 index e04fd2d..0000000 --- a/gcc/rust/rustc_parser/libsyntax/ext/tt/transcribe.rs +++ /dev/null @@ -1,372 +0,0 @@ -use crate::ast::Ident; -use crate::ext::base::ExtCtxt; -use crate::ext::expand::Marker; -use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use crate::ext::tt::quoted; -use crate::mut_visit::noop_visit_tt; -use crate::parse::token::{self, NtTT, Token}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; - -use smallvec::{smallvec, SmallVec}; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use std::mem; -use std::rc::Rc; - -/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). -enum Frame { - Delimited { forest: Lrc, idx: usize, span: DelimSpan }, - Sequence { forest: Lrc, idx: usize, sep: Option }, -} - -impl Frame { - /// Construct a new frame around the delimited set of tokens. - fn new(tts: Vec) -> Frame { - let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts }); - Frame::Delimited { forest, idx: 0, span: DelimSpan::dummy() } - } -} - -impl Iterator for Frame { - type Item = quoted::TokenTree; - - fn next(&mut self) -> Option { - match *self { - Frame::Delimited { ref forest, ref mut idx, .. } => { - *idx += 1; - forest.tts.get(*idx - 1).cloned() - } - Frame::Sequence { ref forest, ref mut idx, .. } => { - *idx += 1; - forest.tts.get(*idx - 1).cloned() - } - } - } -} - -/// This can do Macro-By-Example transcription. -/// - `interp` is a map of meta-variables to the tokens (non-terminals) they matched in the -/// invocation. We are assuming we already know there is a match. -/// - `src` is the RHS of the MBE, that is, the "example" we are filling in. -/// -/// For example, -/// -/// ```rust -/// macro_rules! foo { -/// ($id:ident) => { println!("{}", stringify!($id)); } -/// } -/// -/// foo!(bar); -/// ``` -/// -/// `interp` would contain `$id => bar` and `src` would contain `println!("{}", stringify!($id));`. -/// -/// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. -/// -/// Along the way, we do some additional error checking. -pub fn transcribe( - cx: &ExtCtxt<'_>, - interp: &FxHashMap>, - src: Vec, -) -> TokenStream { - // Nothing for us to transcribe... - if src.is_empty() { - return TokenStream::empty(); - } - - // We descend into the RHS (`src`), expanding things as we go. This stack contains the things - // we have yet to expand/are still expanding. We start the stack off with the whole RHS. - let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)]; - - // As we descend in the RHS, we will need to be able to match nested sequences of matchers. - // `repeats` keeps track of where we are in matching at each level, with the last element being - // the most deeply nested sequence. This is used as a stack. - let mut repeats = Vec::new(); - - // `result` contains resulting token stream from the TokenTree we just finished processing. At - // the end, this will contain the full result of transcription, but at arbitrary points during - // `transcribe`, `result` will contain subsets of the final result. - // - // Specifically, as we descend into each TokenTree, we will push the existing results onto the - // `result_stack` and clear `results`. We will then produce the results of transcribing the - // TokenTree into `results`. Then, as we unwind back out of the `TokenTree`, we will pop the - // `result_stack` and append `results` too it to produce the new `results` up to that point. - // - // Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level - // again, and we are done transcribing. - let mut result: Vec = Vec::new(); - let mut result_stack = Vec::new(); - - loop { - // Look at the last frame on the stack. - let tree = if let Some(tree) = stack.last_mut().unwrap().next() { - // If it still has a TokenTree we have not looked at yet, use that tree. - tree - } - // The else-case never produces a value for `tree` (it `continue`s or `return`s). - else { - // Otherwise, if we have just reached the end of a sequence and we can keep repeating, - // go back to the beginning of the sequence. - if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() { - let (repeat_idx, repeat_len) = repeats.last_mut().unwrap(); - *repeat_idx += 1; - if repeat_idx < repeat_len { - *idx = 0; - if let Some(sep) = sep { - result.push(TokenTree::Token(sep.clone()).into()); - } - continue; - } - } - - // We are done with the top of the stack. Pop it. Depending on what it was, we do - // different things. Note that the outermost item must be the delimited, wrapped RHS - // that was passed in originally to `transcribe`. - match stack.pop().unwrap() { - // Done with a sequence. Pop from repeats. - Frame::Sequence { .. } => { - repeats.pop(); - } - - // We are done processing a Delimited. If this is the top-level delimited, we are - // done. Otherwise, we unwind the result_stack to append what we have produced to - // any previous results. - Frame::Delimited { forest, span, .. } => { - if result_stack.is_empty() { - // No results left to compute! We are back at the top-level. - return TokenStream::new(result); - } - - // Step back into the parent Delimited. - let tree = - TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); - result = result_stack.pop().unwrap(); - result.push(tree.into()); - } - } - continue; - }; - - // At this point, we know we are in the middle of a TokenTree (the last one on `stack`). - // `tree` contains the next `TokenTree` to be processed. - match tree { - // We are descending into a sequence. We first make sure that the matchers in the RHS - // and the matches in `interp` have the same shape. Otherwise, either the caller or the - // macro writer has made a mistake. - seq @ quoted::TokenTree::Sequence(..) => { - match lockstep_iter_size(&seq, interp, &repeats) { - LockstepIterSize::Unconstrained => { - cx.span_fatal( - seq.span(), /* blame macro writer */ - "attempted to repeat an expression containing no syntax variables \ - matched as repeating at this depth", - ); - } - - LockstepIterSize::Contradiction(ref msg) => { - // FIXME: this really ought to be caught at macro definition time... It - // happens when two meta-variables are used in the same repetition in a - // sequence, but they come from different sequence matchers and repeat - // different amounts. - cx.span_fatal(seq.span(), &msg[..]); - } - - LockstepIterSize::Constraint(len, _) => { - // We do this to avoid an extra clone above. We know that this is a - // sequence already. - let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { - (sp, seq) - } else { - unreachable!() - }; - - // Is the repetition empty? - if len == 0 { - if seq.op == quoted::KleeneOp::OneOrMore { - // FIXME: this really ought to be caught at macro definition - // time... It happens when the Kleene operator in the matcher and - // the body for the same meta-variable do not match. - cx.span_fatal(sp.entire(), "this must repeat at least once"); - } - } else { - // 0 is the initial counter (we have done 0 repretitions so far). `len` - // is the total number of reptitions we should generate. - repeats.push((0, len)); - - // The first time we encounter the sequence we push it to the stack. It - // then gets reused (see the beginning of the loop) until we are done - // repeating. - stack.push(Frame::Sequence { - idx: 0, - sep: seq.separator.clone(), - forest: seq, - }); - } - } - } - } - - // Replace the meta-var with the matched token tree from the invocation. - quoted::TokenTree::MetaVar(mut sp, ident) => { - // Find the matched nonterminal from the macro invocation, and use it to replace - // the meta-var. - if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { - if let MatchedNonterminal(ref nt) = *cur_matched { - // FIXME #2887: why do we apply a mark when matching a token tree meta-var - // (e.g. `$x:tt`), but not when we are matching any other type of token - // tree? - if let NtTT(ref tt) = **nt { - result.push(tt.clone().into()); - } else { - sp = sp.apply_mark(cx.current_expansion.mark); - let token = TokenTree::token(token::Interpolated(nt.clone()), sp); - result.push(token.into()); - } - } else { - // We were unable to descend far enough. This is an error. - cx.span_fatal( - sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", ident), - ); - } - } else { - // If we aren't able to match the meta-var, we push it back into the result but - // with modified syntax context. (I believe this supports nested macros). - let ident = - Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.mark)); - sp = sp.apply_mark(cx.current_expansion.mark); - result.push(TokenTree::token(token::Dollar, sp).into()); - result.push(TokenTree::Token(Token::from_ast_ident(ident)).into()); - } - } - - // If we are entering a new delimiter, we push its contents to the `stack` to be - // processed, and we push all of the currently produced results to the `result_stack`. - // We will produce all of the results of the inside of the `Delimited` and then we will - // jump back out of the Delimited, pop the result_stack and add the new results back to - // the previous results (from outside the Delimited). - quoted::TokenTree::Delimited(mut span, delimited) => { - span = span.apply_mark(cx.current_expansion.mark); - stack.push(Frame::Delimited { forest: delimited, idx: 0, span }); - result_stack.push(mem::take(&mut result)); - } - - // Nothing much to do here. Just push the token to the result, being careful to - // preserve syntax context. - quoted::TokenTree::Token(token) => { - let mut marker = Marker(cx.current_expansion.mark); - let mut tt = TokenTree::Token(token); - noop_visit_tt(&mut tt, &mut marker); - result.push(tt.into()); - } - - // There should be no meta-var declarations in the invocation of a macro. - quoted::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), - } - } -} - -/// Lookup the meta-var named `ident` and return the matched token tree from the invocation using -/// the set of matches `interpolations`. -/// -/// See the definition of `repeats` in the `transcribe` function. `repeats` is used to descend -/// into the right place in nested matchers. If we attempt to descend too far, the macro writer has -/// made a mistake, and we return `None`. -fn lookup_cur_matched( - ident: Ident, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)], -) -> Option> { - interpolations.get(&ident).map(|matched| { - let mut matched = matched.clone(); - for &(idx, _) in repeats { - let m = matched.clone(); - match *m { - MatchedNonterminal(_) => break, - MatchedSeq(ref ads, _) => matched = Rc::new(ads[idx].clone()), - } - } - - matched - }) -} - -/// An accumulator over a TokenTree to be used with `fold`. During transcription, we need to make -/// sure that the size of each sequence and all of its nested sequences are the same as the sizes -/// of all the matched (nested) sequences in the macro invocation. If they don't match, somebody -/// has made a mistake (either the macro writer or caller). -#[derive(Clone)] -enum LockstepIterSize { - /// No constraints on length of matcher. This is true for any TokenTree variants except a - /// `MetaVar` with an actual `MatchedSeq` (as opposed to a `MatchedNonterminal`). - Unconstrained, - - /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the - /// meta-var are returned. - Constraint(usize, Ident), - - /// Two `Constraint`s on the same sequence had different lengths. This is an error. - Contradiction(String), -} - -impl LockstepIterSize { - /// Find incompatibilities in matcher/invocation sizes. - /// - `Unconstrained` is compatible with everything. - /// - `Contradiction` is incompatible with everything. - /// - `Constraint(len)` is only compatible with other constraints of the same length. - fn with(self, other: LockstepIterSize) -> LockstepIterSize { - match self { - LockstepIterSize::Unconstrained => other, - LockstepIterSize::Contradiction(_) => self, - LockstepIterSize::Constraint(l_len, ref l_id) => match other { - LockstepIterSize::Unconstrained => self, - LockstepIterSize::Contradiction(_) => other, - LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, - LockstepIterSize::Constraint(r_len, r_id) => { - let msg = format!( - "meta-variable `{}` repeats {} times, but `{}` repeats {} times", - l_id, l_len, r_id, r_len - ); - LockstepIterSize::Contradiction(msg) - } - }, - } - } -} - -/// Given a `tree`, make sure that all sequences have the same length as the matches for the -/// appropriate meta-vars in `interpolations`. -/// -/// Note that if `repeats` does not match the exact correct depth of a meta-var, -/// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of -/// multiple nested matcher sequences. -fn lockstep_iter_size( - tree: "ed::TokenTree, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)], -) -> LockstepIterSize { - use quoted::TokenTree; - match *tree { - TokenTree::Delimited(_, ref delimed) => { - delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size.with(lockstep_iter_size(tt, interpolations, repeats)) - }) - } - TokenTree::Sequence(_, ref seq) => { - seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size.with(lockstep_iter_size(tt, interpolations, repeats)) - }) - } - TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { - match lookup_cur_matched(name, interpolations, repeats) { - Some(matched) => match *matched { - MatchedNonterminal(_) => LockstepIterSize::Unconstrained, - MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name), - }, - _ => LockstepIterSize::Unconstrained, - } - } - TokenTree::Token(..) => LockstepIterSize::Unconstrained, - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/feature_gate.rs b/gcc/rust/rustc_parser/libsyntax/feature_gate.rs deleted file mode 100644 index fd1cb3d..0000000 --- a/gcc/rust/rustc_parser/libsyntax/feature_gate.rs +++ /dev/null @@ -1,2646 +0,0 @@ -//! # Feature gating -//! -//! This module implements the gating necessary for preventing certain compiler -//! features from being used by default. This module will crawl a pre-expanded -//! AST to ensure that there are no features which are used that are not -//! enabled. -//! -//! Features are enabled in programs via the crate-level attributes of -//! `#![feature(...)]` with a comma-separated list of features. -//! -//! For the purpose of future feature-tracking, once code for detection of feature -//! gate usage is added, *do not remove it again* even once the feature -//! becomes stable. - -use AttributeType::*; -use AttributeGate::*; - -use crate::ast::{ - self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, - PatKind, RangeEnd, -}; -use crate::attr; -use crate::early_buffered_lints::BufferedEarlyLintId; -use crate::source_map::Spanned; -use crate::edition::{ALL_EDITIONS, Edition}; -use crate::visit::{self, FnKind, Visitor}; -use crate::parse::{token, ParseSess}; -use crate::parse::parser::Parser; -use crate::symbol::{Symbol, sym}; -use crate::tokenstream::TokenTree; - -use errors::{Applicability, DiagnosticBuilder, Handler}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lock; -use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -use log::debug; -use lazy_static::lazy_static; - -use std::env; - -macro_rules! set { - ($field: ident) => {{ - fn f(features: &mut Features, _: Span) { - features.$field = true; - } - f as fn(&mut Features, Span) - }} -} - -macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { - /// Represents active features that are currently being implemented or - /// currently being considered for addition/removal. - const ACTIVE_FEATURES: - &[(Symbol, &str, Option, Option, fn(&mut Features, Span))] = - &[$((sym::$feature, $ver, $issue, $edition, set!($feature))),+]; - - /// A set of features to be used by later passes. - #[derive(Clone)] - pub struct Features { - /// `#![feature]` attrs for language features, for error reporting - pub declared_lang_features: Vec<(Symbol, Span, Option)>, - /// `#![feature]` attrs for non-language (library) features - pub declared_lib_features: Vec<(Symbol, Span)>, - $(pub $feature: bool),+ - } - - impl Features { - pub fn new() -> Features { - Features { - declared_lang_features: Vec::new(), - declared_lib_features: Vec::new(), - $($feature: false),+ - } - } - - pub fn walk_feature_fields(&self, mut f: F) - where F: FnMut(&str, bool) - { - $(f(stringify!($feature), self.$feature);)+ - } - } - }; - - ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { - /// Represents unstable features which have since been removed (it was once Active) - const REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, $reason)),+ - ]; - }; - - ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Represents stable features which have since been removed (it was once Accepted) - const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - }; - - ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { - /// Those language feature has since been Accepted (it was once Active) - const ACCEPTED_FEATURES: &[(Symbol, &str, Option, Option<&str>)] = &[ - $((sym::$feature, $ver, $issue, None)),+ - ]; - } -} - -// If you change this, please modify `src/doc/unstable-book` as well. -// -// Don't ever remove anything from this list; set them to 'Removed'. -// -// The version numbers here correspond to the version in which the current status -// was set. This is most important for knowing when a particular feature became -// stable (active). -// -// Note that the features are grouped into internal/user-facing and then -// sorted by version inside those groups. This is inforced with tidy. -// -// N.B., `tools/tidy/src/features.rs` parses this information directly out of the -// source, so take care when modifying it. - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: internal feature gates - // ------------------------------------------------------------------------- - - // no-tracking-issue-start - - // Allows using the `rust-intrinsic`'s "ABI". - (active, intrinsics, "1.0.0", None, None), - - // Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. - (active, lang_items, "1.0.0", None, None), - - // Allows using the `#[stable]` and `#[unstable]` attributes. - (active, staged_api, "1.0.0", None, None), - - // Allows using `#[allow_internal_unstable]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unstable, "1.0.0", None, None), - - // Allows using `#[allow_internal_unsafe]`. This is an - // attribute on `macro_rules!` and can't use the attribute handling - // below (it has to be checked before expansion possibly makes - // macros disappear). - (active, allow_internal_unsafe, "1.0.0", None, None), - - // Allows using the macros: - // + `__diagnostic_used` - // + `__register_diagnostic` - // +`__build_diagnostic_array` - (active, rustc_diagnostic_macros, "1.0.0", None, None), - - // Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which - // lets a function to be `const` when opted into with `#![feature(foo)]`. - (active, rustc_const_unstable, "1.0.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - - // Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", Some(29642), None), - - // Allows using `#[on_unimplemented(..)]` on traits. - (active, on_unimplemented, "1.0.0", Some(29628), None), - - // Allows using the `box $expr` syntax. - (active, box_syntax, "1.0.0", Some(49733), None), - - // Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - - // Allows using `#[start]` on a function indicating that it is the program entrypoint. - (active, start, "1.0.0", Some(29633), None), - - // Allows using the `#[fundamental]` attribute. - (active, fundamental, "1.0.0", Some(29635), None), - - // Allows using the `rust-call` ABI. - (active, unboxed_closures, "1.0.0", Some(29625), None), - - // Allows using the `#[linkage = ".."]` attribute. - (active, linkage, "1.0.0", Some(29603), None), - - // Allows features specific to OIBIT (auto traits). - (active, optin_builtin_traits, "1.0.0", Some(13231), None), - - // Allows using `box` in patterns (RFC 469). - (active, box_patterns, "1.0.0", Some(29641), None), - - // no-tracking-issue-start - - // Allows using `#[prelude_import]` on glob `use` items. - (active, prelude_import, "1.2.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). - (active, dropck_parametricity, "1.3.0", Some(28498), None), - - // no-tracking-issue-start - - // Allows using `#[omit_gdb_pretty_printer_section]`. - (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - - // Allows using the `vectorcall` ABI. - (active, abi_vectorcall, "1.7.0", None, None), - - // no-tracking-issue-end - - // Allows using `#[structural_match]` which indicates that a type is structurally matchable. - (active, structural_match, "1.8.0", Some(31434), None), - - // Allows using the `may_dangle` attribute (RFC 1327). - (active, dropck_eyepatch, "1.10.0", Some(34761), None), - - // Allows using the `#![panic_runtime]` attribute. - (active, panic_runtime, "1.10.0", Some(32837), None), - - // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. - (active, needs_panic_runtime, "1.10.0", Some(32837), None), - - // no-tracking-issue-start - - // Allows identifying the `compiler_builtins` crate. - (active, compiler_builtins, "1.13.0", None, None), - - // Allows using the `unadjusted` ABI; perma-unstable. - (active, abi_unadjusted, "1.16.0", None, None), - - // Allows identifying crates that contain sanitizer runtimes. - (active, sanitizer_runtime, "1.17.0", None, None), - - // Used to identify crates that contain the profiler runtime. - (active, profiler_runtime, "1.18.0", None, None), - - // Allows using the `thiscall` ABI. - (active, abi_thiscall, "1.19.0", None, None), - - // Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. - (active, allocator_internals, "1.20.0", None, None), - - // Allows using the `format_args_nl` macro. - (active, format_args_nl, "1.29.0", Some(0), None), - - // no-tracking-issue-end - - // Added for testing E0705; perma-unstable. - (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), - - // ------------------------------------------------------------------------- - // feature-group-end: internal feature gates - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // FIXME: Document these and merge with the list below. - - // Unstable `#[target_feature]` directives. - (active, arm_target_feature, "1.27.0", Some(44839), None), - (active, aarch64_target_feature, "1.27.0", Some(44839), None), - (active, hexagon_target_feature, "1.27.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), - (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, avx512_target_feature, "1.27.0", Some(44839), None), - (active, mmx_target_feature, "1.27.0", Some(44839), None), - (active, sse4a_target_feature, "1.27.0", Some(44839), None), - (active, tbm_target_feature, "1.27.0", Some(44839), None), - (active, wasm_target_feature, "1.30.0", Some(44839), None), - (active, adx_target_feature, "1.32.0", Some(44839), None), - (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, rtm_target_feature, "1.35.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates (target features) - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: actual feature gates - // ------------------------------------------------------------------------- - - // Allows using `asm!` macro with which inline assembly can be embedded. - (active, asm, "1.0.0", Some(29722), None), - - // Allows using the `concat_idents!` macro with which identifiers can be concatenated. - (active, concat_idents, "1.0.0", Some(29599), None), - - // Allows using the `#[link_args]` attribute. - (active, link_args, "1.0.0", Some(29596), None), - - // Allows defining identifiers beyond ASCII. - (active, non_ascii_idents, "1.0.0", Some(55467), None), - - // Allows using `#[plugin_registrar]` on functions. - (active, plugin_registrar, "1.0.0", Some(29597), None), - - // Allows using `#![plugin(myplugin)]`. - (active, plugin, "1.0.0", Some(29597), None), - - // Allows using `#[thread_local]` on `static` items. - (active, thread_local, "1.0.0", Some(29594), None), - - // Allows using the `log_syntax!` macro. - (active, log_syntax, "1.0.0", Some(29598), None), - - // Allows using the `trace_macros!` macro. - (active, trace_macros, "1.0.0", Some(29598), None), - - // Allows the use of SIMD types in functions declared in `extern` blocks. - (active, simd_ffi, "1.0.0", Some(27731), None), - - // Allows using custom attributes (RFC 572). - (active, custom_attribute, "1.0.0", Some(29642), None), - - // Allows using non lexical lifetimes (RFC 2094). - (active, nll, "1.0.0", Some(43234), None), - - // Allows using slice patterns. - (active, slice_patterns, "1.0.0", Some(62254), None), - - // Allows the definition of `const` functions with some advanced features. - (active, const_fn, "1.2.0", Some(57563), None), - - // Allows associated type defaults. - (active, associated_type_defaults, "1.2.0", Some(29661), None), - - // Allows `#![no_core]`. - (active, no_core, "1.3.0", Some(29639), None), - - // Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - - // Allows `repr(simd)` and importing the various simd intrinsics. - (active, repr_simd, "1.4.0", Some(27731), None), - - // Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), - - // Allows `#[unwind(..)]`. - // - // Permits specifying whether a function should permit unwinding or abort on unwind. - (active, unwind_attributes, "1.4.0", Some(58760), None), - - // Allows `#[no_debug]`. - (active, no_debug, "1.5.0", Some(29721), None), - - // Allows attributes on expressions and non-item statements. - (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - - // Allows the use of type ascription in expressions. - (active, type_ascription, "1.6.0", Some(23416), None), - - // Allows `cfg(target_thread_local)`. - (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - - // Allows specialization of implementations (RFC 1210). - (active, specialization, "1.7.0", Some(31844), None), - - // Allows using `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408), None), - - // Allows `cfg(target_has_atomic = "...")`. - (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - - // Allows `X..Y` patterns. - (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - - // Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. - (active, never_type, "1.13.0", Some(35121), None), - - // Allows exhaustive pattern matching on types that contain uninhabited types. - (active, exhaustive_patterns, "1.13.0", Some(51085), None), - - // Allows untagged unions `union U { ... }`. - (active, untagged_unions, "1.13.0", Some(32836), None), - - // Allows `#[link(..., cfg(..))]`. - (active, link_cfg, "1.14.0", Some(37406), None), - - // Allows `extern "ptx-*" fn()`. - (active, abi_ptx, "1.15.0", Some(38788), None), - - // Allows the `#[repr(i128)]` attribute for enums. - (active, repr128, "1.16.0", Some(35118), None), - - // Allows `#[link(kind="static-nobundle"...)]`. - (active, static_nobundle, "1.16.0", Some(37403), None), - - // Allows `extern "msp430-interrupt" fn()`. - (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - - // Allows declarative macros 2.0 (`macro`). - (active, decl_macro, "1.17.0", Some(39412), None), - - // Allows `extern "x86-interrupt" fn()`. - (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - - // Allows module-level inline assembly by way of `global_asm!()`. - (active, global_asm, "1.18.0", Some(35119), None), - - // Allows overlapping impls of marker traits. - (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - - // Allows a test to fail without failing the whole suite. - (active, allow_fail, "1.19.0", Some(46488), None), - - // Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - - // Allows defining generators. - (active, generators, "1.21.0", Some(43122), None), - - // Allows `#[doc(cfg(...))]`. - (active, doc_cfg, "1.21.0", Some(43781), None), - - // Allows `#[doc(masked)]`. - (active, doc_masked, "1.21.0", Some(44027), None), - - // Allows `#[doc(spotlight)]`. - (active, doc_spotlight, "1.22.0", Some(45040), None), - - // Allows `#[doc(include = "some-file")]`. - (active, external_doc, "1.22.0", Some(44732), None), - - // Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). - (active, non_exhaustive, "1.22.0", Some(44109), None), - - // Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - - // Allows defining `extern type`s. - (active, extern_types, "1.23.0", Some(43467), None), - - // Allows trait methods with arbitrary self types. - (active, arbitrary_self_types, "1.23.0", Some(44874), None), - - // Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (active, in_band_lifetimes, "1.23.0", Some(44524), None), - - // Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). - (active, generic_associated_types, "1.23.0", Some(44265), None), - - // Allows defining `trait X = A + B;` alias items. - (active, trait_alias, "1.24.0", Some(41517), None), - - // Allows infering `'static` outlives requirements (RFC 2093). - (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - - // Allows macro invocations in `extern {}` blocks. - (active, macros_in_extern, "1.27.0", Some(49476), None), - - // Allows accessing fields of unions inside `const` functions. - (active, const_fn_union, "1.27.0", Some(51909), None), - - // Allows casting raw pointers to `usize` during const eval. - (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - - // Allows dereferencing raw pointers during const eval. - (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - - // Allows comparing raw pointers during const eval. - (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - - // Allows `#[doc(alias = "...")]`. - (active, doc_alias, "1.27.0", Some(50146), None), - - // Allows defining `existential type`s. - (active, existential_type, "1.28.0", Some(34511), None), - - // Allows inconsistent bounds in where clauses. - (active, trivial_bounds, "1.28.0", Some(48214), None), - - // Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), - - // Allows using `#[doc(keyword = "...")]`. - (active, doc_keyword, "1.28.0", Some(51315), None), - - // Allows async and await syntax. - (active, async_await, "1.28.0", Some(50547), None), - - // Allows await! macro-like syntax. - // This will likely be removed prior to stabilization of async/await. - (active, await_macro, "1.28.0", Some(50547), None), - - // Allows reinterpretation of the bits of a value of one type as another type during const eval. - (active, const_transmute, "1.29.0", Some(53605), None), - - // Allows using `try {...}` expressions. - (active, try_blocks, "1.29.0", Some(31436), None), - - // Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), - - // Allows using the `amdgpu-kernel` ABI. - (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - - // Allows panicking during const eval (producing compile-time errors). - (active, const_panic, "1.30.0", Some(51999), None), - - // Allows `#[marker]` on certain traits allowing overlapping implementations. - (active, marker_trait_attr, "1.30.0", Some(29864), None), - - // Allows macro invocations on modules expressions and statements and - // procedural macros to expand to non-items. - (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - - // Allows unsized rvalues at arguments and parameters. - (active, unsized_locals, "1.30.0", Some(48055), None), - - // Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. - (active, custom_test_frameworks, "1.30.0", Some(50297), None), - - // Allows non-builtin attributes in inner attribute position. - (active, custom_inner_attributes, "1.30.0", Some(54726), None), - - // Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - - // Allows `impl Trait` in bindings (`let`, `const`, `static`). - (active, impl_trait_in_bindings, "1.30.0", Some(34511), None), - - // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. - (active, lint_reasons, "1.31.0", Some(54503), None), - - // Allows exhaustive integer pattern matching on `usize` and `isize`. - (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - - // Allows relaxing the coherence rules such that - // `impl ForeignTrait for ForeignType is permitted. - (active, re_rebalance_coherence, "1.32.0", Some(55437), None), - - // Allows using `#[ffi_returns_twice]` on foreign functions. - (active, ffi_returns_twice, "1.34.0", Some(58314), None), - - // Allows const generic types (e.g. `struct Foo(...);`). - (active, const_generics, "1.34.0", Some(44580), None), - - // Allows using `#[optimize(X)]`. - (active, optimize_attribute, "1.34.0", Some(54882), None), - - // Allows using C-variadics. - (active, c_variadic, "1.34.0", Some(44930), None), - - // Allows the user of associated type bounds. - (active, associated_type_bounds, "1.34.0", Some(52662), None), - - // Attributes on formal function params. - (active, param_attrs, "1.36.0", Some(60406), None), - - // Allows calling constructor functions in `const fn`. - (active, const_constructor, "1.37.0", Some(61456), None), - - // Allows `if/while p && let q = r && ...` chains. - (active, let_chains, "1.37.0", Some(53667), None), - - // #[repr(transparent)] on enums. - (active, transparent_enums, "1.37.0", Some(60405), None), - - // #[repr(transparent)] on unions. - (active, transparent_unions, "1.37.0", Some(60405), None), - - // Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - - // Allows `impl Trait` with multiple unrelated lifetimes. - (active, member_constraints, "1.37.0", Some(61977), None), - - // Allows `async || body` closures. - (active, async_closure, "1.37.0", Some(62290), None), - - // Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests - (active, cfg_doctest, "1.37.0", Some(62210), None), - - // ------------------------------------------------------------------------- - // feature-group-end: actual feature gates - // ------------------------------------------------------------------------- -); - -// Some features are known to be incomplete and using them is likely to have -// unanticipated results, such as compiler crashes. We warn the user about these -// to alert them. -const INCOMPLETE_FEATURES: &[Symbol] = &[ - sym::impl_trait_in_bindings, - sym::generic_associated_types, - sym::const_generics, - sym::let_chains, -]; - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: removed features - // ------------------------------------------------------------------------- - - (removed, import_shadowing, "1.0.0", None, None, None), - (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645), None, None), - (removed, reflect, "1.0.0", Some(27749), None, None), - // A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None, None), - (removed, quad_precision_float, "1.0.0", None, None, None), - (removed, struct_inherit, "1.0.0", None, None, None), - (removed, test_removed_feature, "1.0.0", None, None, None), - (removed, visible_private_types, "1.0.0", None, None, None), - (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), - // Allows using items which are missing stability attributes - (removed, unmarked_api, "1.0.0", None, None, None), - (removed, allocator, "1.0.0", None, None, None), - (removed, simd, "1.0.0", Some(27731), None, - Some("removed in favor of `#[repr(simd)]`")), - (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, - Some("merged into `#![feature(slice_patterns)]`")), - (removed, macro_reexport, "1.0.0", Some(29638), None, - Some("subsumed by `pub use`")), - (removed, pushpop_unsafe, "1.2.0", None, None, None), - (removed, needs_allocator, "1.4.0", Some(27389), None, - Some("subsumed by `#![feature(allocator_internals)]`")), - (removed, proc_macro_mod, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_expr, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_non_items, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_gen, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, panic_implementation, "1.28.0", Some(44489), None, - Some("subsumed by `#[panic_handler]`")), - // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.32.0", Some(29644), None, - Some("subsumed by `#[proc_macro_derive]`")), - // Paths of the form: `extern::foo::bar` - (removed, extern_in_paths, "1.33.0", Some(55600), None, - Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.33.0", Some(29601), None, None), - - // ------------------------------------------------------------------------- - // feature-group-end: removed features - // ------------------------------------------------------------------------- -); - -declare_features! ( - (stable_removed, no_stack_check, "1.0.0", None, None), -); - -declare_features! ( - // ------------------------------------------------------------------------- - // feature-group-start: for testing purposes - // ------------------------------------------------------------------------- - - // A temporary feature gate used to enable parser extensions needed - // to bootstrap fix for #5723. - (accepted, issue_5723_bootstrap, "1.0.0", None, None), - // These are used to test this portion of the compiler, - // they don't actually mean anything. - (accepted, test_accepted_feature, "1.0.0", None, None), - - // ------------------------------------------------------------------------- - // feature-group-end: for testing purposes - // ------------------------------------------------------------------------- - - // ------------------------------------------------------------------------- - // feature-group-start: accepted features - // ------------------------------------------------------------------------- - - // Allows using associated `type`s in `trait`s. - (accepted, associated_types, "1.0.0", None, None), - // Allows using assigning a default type to type parameters in algebraic data type definitions. - (accepted, default_type_params, "1.0.0", None, None), - // FIXME: explain `globs`. - (accepted, globs, "1.0.0", None, None), - // Allows `macro_rules!` items. - (accepted, macro_rules, "1.0.0", None, None), - // Allows use of `&foo[a..b]` as a slicing syntax. - (accepted, slicing_syntax, "1.0.0", None, None), - // Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). - (accepted, struct_variant, "1.0.0", None, None), - // Allows indexing tuples. - (accepted, tuple_indexing, "1.0.0", None, None), - // Allows the use of `if let` expressions. - (accepted, if_let, "1.0.0", None, None), - // Allows the use of `while let` expressions. - (accepted, while_let, "1.0.0", None, None), - // Allows using `#![no_std]`. - (accepted, no_std, "1.6.0", None, None), - // Allows overloading augmented assignment operations like `a += b`. - (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // Allows empty structs and enum variants with braces. - (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - // Allows `#[deprecated]` attribute. - (accepted, deprecated, "1.9.0", Some(29935), None), - // Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245), None), - // Allows use of the postfix `?` operator in expressions. - (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns. - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - // Allows some increased flexibility in the name resolution rules, - // especially around globs and shadowing (RFC 1560). - (accepted, item_like_imports, "1.15.0", Some(35120), None), - // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // Allows elision of `'static` lifetimes in `static`s and `const`s. - (accepted, static_in_const, "1.17.0", Some(35897), None), - // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - // Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719), None), - // Allows `pub(restricted)` visibilities (RFC 1422). - (accepted, pub_restricted, "1.18.0", Some(32409), None), - // Allows `#![windows_subsystem]`. - (accepted, windows_subsystem, "1.18.0", Some(37499), None), - // Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339), None), - // Allows numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Allows coercing non capturing closures to function pointers. - (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - // Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` blocks. - (accepted, associated_consts, "1.20.0", Some(29646), None), - // Allows usage of the `compile_error!` macro. - (accepted, compile_error, "1.20.0", Some(40872), None), - // Allows code like `let x: &'static u32 = &42` to work (RFC 1414). - (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allows `Drop` types in constants (RFC 1440). - (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI. - (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358). - (accepted, repr_align, "1.25.0", Some(33626), None), - // Allows '|' at beginning of match arms (RFC 1925). - (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - // Allows nested groups in `use` items (RFC 2128). - (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // Allows indexing into constant arrays. - (accepted, const_indexing, "1.26.0", Some(29947), None), - // Allows using `a..=b` and `..=b` as inclusive range syntaxes. - (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // Allows `..=` in patterns (RFC 1192). - (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - // Allows `fn main()` with return types which implements `Termination` (RFC 1937). - (accepted, termination_trait, "1.26.0", Some(43301), None), - // Allows implementing `Clone` for closures where possible (RFC 2132). - (accepted, clone_closures, "1.26.0", Some(44490), None), - // Allows implementing `Copy` for closures where possible (RFC 2132). - (accepted, copy_closures, "1.26.0", Some(44490), None), - // Allows `impl Trait` in function arguments. - (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - // Allows `impl Trait` in function return types. - (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - // Allows using the `u128` and `i128` types. - (accepted, i128_type, "1.26.0", Some(35118), None), - // Allows default match binding modes (RFC 2005). - (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // Allows `'_` placeholder lifetimes. - (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). - (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows `cfg(target_feature = "...")`. - (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows `#[target_feature(...)]`. - (accepted, target_feature, "1.27.0", None, None), - // Allows using `dyn Trait` as a syntax for trait objects. - (accepted, dyn_trait, "1.27.0", Some(44662), None), - // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). - (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the `:lifetime` macro fragment specifier. - (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - // Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). - (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // Allows the `#[global_allocator]` attribute. - (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs. - (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Allows procedural macros in `proc-macro` crates. - (accepted, proc_macro, "1.29.0", Some(38356), None), - // Allows `foo.rs` as an alternative to `foo/mod.rs`. - (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the `:vis` macro fragment specifier - (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - // Allows importing and reexporting macros with `use`, - // enables macro modularization in general. - (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers. - (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Allows attributes scoped to tools. - (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives. - (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - // Allows all literals in attribute lists and values of key-value pairs. - (accepted, attr_literals, "1.30.0", Some(34981), None), - // Allows inferring outlives requirements (RFC 2093). - (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - // Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - // This defines the behavior of panics. - (accepted, panic_handler, "1.30.0", Some(44489), None), - // Allows `#[used]` to preserve symbols (see llvm.used). - (accepted, used, "1.30.0", Some(40289), None), - // Allows `crate` in paths. - (accepted, crate_in_paths, "1.30.0", Some(45477), None), - // Allows resolving absolute paths as paths from other crates. - (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), - // Allows access to crate names passed via `--extern` through prelude. - (accepted, extern_prelude, "1.30.0", Some(44660), None), - // Allows parentheses in patterns. - (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions. - (accepted, min_const_fn, "1.31.0", Some(53555), None), - // Allows scoped lints. - (accepted, tool_lints, "1.31.0", Some(44690), None), - // Allows lifetime elision in `impl` headers. For example: - // + `impl Iterator for &mut Iterator` - // + `impl Debug for Foo<'_>` - (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. - (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - // Allows use of `?` as the Kleene "at most one" operator in macros. - (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - // Allows `Self` struct constructor (RFC 2302). - (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - // Allows `Self` in type definitions (RFC 2300). - (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - // Allows `use x::y;` to search `x` in the current scope. - (accepted, uniform_paths, "1.32.0", Some(53130), None), - // Allows integer match exhaustiveness checking (RFC 2591). - (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - // Allows `use path as _;` and `extern crate c as _;`. - (accepted, underscore_imports, "1.33.0", Some(48216), None), - // Allows `#[repr(packed(N))]` attribute on structs. - (accepted, repr_packed, "1.33.0", Some(33158), None), - // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). - (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - // Allows let bindings, assignments and destructuring in `const` functions and constants. - // As long as control flow is not implemented in const eval, `&&` and `||` may not be used - // at the same time as let bindings. - (accepted, const_let, "1.33.0", Some(48821), None), - // Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. - (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - // Allows top level or-patterns (`p | q`) in `if let` and `while let`. - (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - // Allows `cfg(target_vendor = "...")`. - (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - // Allows `extern crate self as foo;`. - // This puts local crate root into extern prelude under name `foo`. - (accepted, extern_crate_self, "1.34.0", Some(56409), None), - // Allows arbitrary delimited token streams in non-macro attributes. - (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - // Allows paths to enum variants on type aliases including `Self`. - (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - // Allows using `#[repr(align(X))]` on enums with equivalent semantics - // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. - (accepted, repr_align_enum, "1.37.0", Some(57996), None), - // Allows `const _: TYPE = VALUE`. - (accepted, underscore_const_names, "1.37.0", Some(54912), None), - - // ------------------------------------------------------------------------- - // feature-group-end: accepted features - // ------------------------------------------------------------------------- -); - -// If you change this, please modify `src/doc/unstable-book` as well. You must -// move that documentation into the relevant place in the other docs, and -// remove the chapter on the flag. - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AttributeType { - /// Normal, builtin attribute that is consumed - /// by the compiler before the unused_attribute check - Normal, - - /// Builtin attribute that may not be consumed by the compiler - /// before the unused_attribute check. These attributes - /// will be ignored by the unused_attribute lint - Whitelisted, - - /// Builtin attribute that is only allowed at the crate level - CrateLevel, -} - -pub enum AttributeGate { - /// Is gated by a given feature gate, reason - /// and function to check if enabled - Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), - - /// Ungated attribute, can be used on all release channels - Ungated, -} - -/// A template that the attribute input must match. -/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. -#[derive(Clone, Copy)] -pub struct AttributeTemplate { - word: bool, - list: Option<&'static str>, - name_value_str: Option<&'static str>, -} - -impl AttributeTemplate { - /// Checks that the given meta-item is compatible with this template. - fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool { - match meta_item_kind { - ast::MetaItemKind::Word => self.word, - ast::MetaItemKind::List(..) => self.list.is_some(), - ast::MetaItemKind::NameValue(lit) if lit.node.is_str() => self.name_value_str.is_some(), - ast::MetaItemKind::NameValue(..) => false, - } - } -} - -/// A convenience macro for constructing attribute templates. -/// E.g., `template!(Word, List: "description")` means that the attribute -/// supports forms `#[attr]` and `#[attr(description)]`. -macro_rules! template { - (Word) => { template!(@ true, None, None) }; - (List: $descr: expr) => { template!(@ false, Some($descr), None) }; - (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; - (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; - (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; - (List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ false, Some($descr1), Some($descr2)) - }; - (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { - template!(@ true, Some($descr1), Some($descr2)) - }; - (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { - word: $word, list: $list, name_value_str: $name_value_str - } }; -} - -impl AttributeGate { - fn is_deprecated(&self) -> bool { - match *self { - Gated(Stability::Deprecated(_, _), ..) => true, - _ => false, - } - } -} - -#[derive(Copy, Clone, Debug)] -pub enum Stability { - Unstable, - // First argument is tracking issue link; second argument is an optional - // help message, which defaults to "remove this attribute" - Deprecated(&'static str, Option<&'static str>), -} - -// fn() is not Debug -impl std::fmt::Debug for AttributeGate { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Gated(ref stab, name, expl, _) => - write!(fmt, "Gated({:?}, {}, {})", stab, name, expl), - Ungated => write!(fmt, "Ungated") - } - } -} - -macro_rules! cfg_fn { - ($field: ident) => {{ - fn f(features: &Features) -> bool { - features.$field - } - f as fn(&Features) -> bool - }} -} - -pub fn deprecated_attributes() -> Vec<&'static (Symbol, AttributeType, - AttributeTemplate, AttributeGate)> { - BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() -} - -pub fn is_builtin_attr_name(name: ast::Name) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() -} - -pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some() -} - -/// Attributes that have a special meaning to rustc or rustdoc -pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ - // Normal attributes - - ( - sym::warn, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::allow, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::forbid, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - ( - sym::deny, - Normal, - template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), - Ungated - ), - - (sym::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated), - (sym::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated), - (sym::plugin_registrar, Normal, template!(Word), Ungated), - - (sym::cfg, Normal, template!(List: "predicate"), Ungated), - (sym::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated), - (sym::main, Normal, template!(Word), Ungated), - (sym::start, Normal, template!(Word), Ungated), - (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), - (sym::path, Normal, template!(NameValueStr: "file"), Ungated), - (sym::automatically_derived, Normal, template!(Word), Ungated), - (sym::no_mangle, Whitelisted, template!(Word), Ungated), - (sym::no_link, Normal, template!(Word), Ungated), - (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), - ( - sym::should_panic, - Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), - Ungated - ), - (sym::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated), - (sym::no_implicit_prelude, Normal, template!(Word), Ungated), - (sym::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated), - (sym::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable, - sym::link_args, - "the `link_args` attribute is experimental and not \ - portable across platforms, it is recommended to \ - use `#[link(name = \"foo\")] instead", - cfg_fn!(link_args))), - (sym::macro_escape, Normal, template!(Word), Ungated), - - // RFC #1445. - (sym::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::structural_match, - "the semantics of constant patterns is \ - not yet settled", - cfg_fn!(structural_match))), - - // RFC #2008 - (sym::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::non_exhaustive, - "non exhaustive is an experimental feature", - cfg_fn!(non_exhaustive))), - - // RFC #1268 - (sym::marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::marker_trait_attr, - "marker traits is an experimental feature", - cfg_fn!(marker_trait_attr))), - - (sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable, - sym::plugin, - "compiler plugins are experimental \ - and possibly buggy", - cfg_fn!(plugin))), - - (sym::no_std, CrateLevel, template!(Word), Ungated), - (sym::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable, - sym::no_core, - "no_core is experimental", - cfg_fn!(no_core))), - (sym::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable, - sym::lang_items, - "language items are subject to change", - cfg_fn!(lang_items))), - (sym::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), - Gated(Stability::Unstable, - sym::linkage, - "the `linkage` attribute is experimental \ - and not portable across platforms", - cfg_fn!(linkage))), - (sym::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::thread_local, - "`#[thread_local]` is an experimental feature, and does \ - not currently handle destructors", - cfg_fn!(thread_local))), - - (sym::rustc_on_unimplemented, Whitelisted, template!(List: - r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, - NameValueStr: "message"), - Gated(Stability::Unstable, - sym::on_unimplemented, - "the `#[rustc_on_unimplemented]` attribute \ - is an experimental feature", - cfg_fn!(on_unimplemented))), - (sym::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), - Gated(Stability::Unstable, - sym::rustc_const_unstable, - "the `#[rustc_const_unstable]` attribute \ - is an internal feature", - cfg_fn!(rustc_const_unstable))), - (sym::global_allocator, Normal, template!(Word), Ungated), - (sym::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[default_lib_allocator]` \ - attribute is an experimental feature", - cfg_fn!(allocator_internals))), - (sym::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable, - sym::allocator_internals, - "the `#[needs_allocator]` \ - attribute is an experimental \ - feature", - cfg_fn!(allocator_internals))), - (sym::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::panic_runtime, - "the `#[panic_runtime]` attribute is \ - an experimental feature", - cfg_fn!(panic_runtime))), - (sym::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::needs_panic_runtime, - "the `#[needs_panic_runtime]` \ - attribute is an experimental \ - feature", - cfg_fn!(needs_panic_runtime))), - (sym::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_outlives]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_variance]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout, Normal, template!(List: "field1, field2, ..."), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_start]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_layout_scalar_valid_range_end]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ - is just used to enable niche optimizations in libcore \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_regions]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_error]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_if_this_changed]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dirty]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...", - /*opt*/ except = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_clean]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_partition_reused, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs) - ) - ), - ( - sym::rustc_partition_codegened, - Whitelisted, - template!(List: r#"cfg = "...", module = "...""#), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - (sym::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...", - kind = "...""#), - Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal rustc attributes will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_mir]` attribute \ - is just used for rustc unit tests \ - and will never be stable", - cfg_fn!(rustc_attrs))), - ( - sym::rustc_inherit_overflow_checks, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_inherit_overflow_checks]` \ - attribute is just used to control \ - overflow checking behavior of several \ - libcore functions that are inlined \ - across crates and will never be stable", - cfg_fn!(rustc_attrs), - ) - ), - - (sym::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_dump_env_program_clauses]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_object_lifetime_default]` \ - attribute is just used for rustc unit \ - tests and will never be stable", - cfg_fn!(rustc_attrs))), - (sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "the `#[rustc_test_marker]` attribute \ - is used internally to track tests", - cfg_fn!(rustc_attrs))), - (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr: - "transparent|semitransparent|opaque"), - Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally for testing macro hygiene", - cfg_fn!(rustc_attrs))), - (sym::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::compiler_builtins, - "the `#[compiler_builtins]` attribute is used to \ - identify the `compiler_builtins` crate which \ - contains compiler-rt intrinsics and will never be \ - stable", - cfg_fn!(compiler_builtins))), - (sym::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::sanitizer_runtime, - "the `#[sanitizer_runtime]` attribute is used to \ - identify crates that contain the runtime of a \ - sanitizer and will never be stable", - cfg_fn!(sanitizer_runtime))), - (sym::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::profiler_runtime, - "the `#[profiler_runtime]` attribute is used to \ - identify the `profiler_builtins` crate which \ - contains the profiler runtime and will never be \ - stable", - cfg_fn!(profiler_runtime))), - - (sym::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), - Gated(Stability::Unstable, - sym::allow_internal_unstable, - EXPLAIN_ALLOW_INTERNAL_UNSTABLE, - cfg_fn!(allow_internal_unstable))), - - (sym::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_internal_unsafe, - EXPLAIN_ALLOW_INTERNAL_UNSAFE, - cfg_fn!(allow_internal_unsafe))), - - (sym::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::fundamental, - "the `#[fundamental]` attribute \ - is an experimental feature", - cfg_fn!(fundamental))), - - (sym::proc_macro_derive, Normal, template!(List: "TraitName, \ - /*opt*/ attributes(name1, name2, ...)"), - Ungated), - - (sym::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "internal implementation detail", - cfg_fn!(rustc_attrs))), - - (sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable, - sym::rustc_attrs, - "used by the test suite", - cfg_fn!(rustc_attrs))), - - // FIXME: #14408 whitelist docs since rustdoc looks at them - ( - sym::doc, - Whitelisted, - template!(List: "hidden|inline|...", NameValueStr: "string"), - Ungated - ), - - // FIXME: #14406 these are processed in codegen, which happens after the - // lint pass - (sym::cold, Whitelisted, template!(Word), Ungated), - (sym::naked, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::naked_functions, - "the `#[naked]` attribute \ - is an experimental feature", - cfg_fn!(naked_functions))), - (sym::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::ffi_returns_twice, - "the `#[ffi_returns_twice]` attribute \ - is an experimental feature", - cfg_fn!(ffi_returns_twice))), - (sym::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated), - (sym::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::inline, Whitelisted, template!(Word, List: "always|never"), Ungated), - (sym::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", - /*opt*/ cfg = "...""#), Ungated), - (sym::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated), - (sym::no_builtins, Whitelisted, template!(Word), Ungated), - (sym::no_debug, Whitelisted, template!(Word), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - sym::no_debug, - "the `#[no_debug]` attribute was an experimental feature that has been \ - deprecated due to lack of demand", - cfg_fn!(no_debug))), - ( - sym::omit_gdb_pretty_printer_section, - Whitelisted, - template!(Word), - Gated( - Stability::Unstable, - sym::omit_gdb_pretty_printer_section, - "the `#[omit_gdb_pretty_printer_section]` \ - attribute is just used for the Rust test \ - suite", - cfg_fn!(omit_gdb_pretty_printer_section) - ) - ), - (sym::unsafe_destructor_blind_to_params, - Normal, - template!(Word), - Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761", - Some("replace this attribute with `#[may_dangle]`")), - sym::dropck_parametricity, - "unsafe_destructor_blind_to_params has been replaced by \ - may_dangle and will be removed in the future", - cfg_fn!(dropck_parametricity))), - (sym::may_dangle, - Normal, - template!(Word), - Gated(Stability::Unstable, - sym::dropck_eyepatch, - "may_dangle has unstable semantics and may be removed in the future", - cfg_fn!(dropck_eyepatch))), - (sym::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, - sym::unwind_attributes, - "#[unwind] is experimental", - cfg_fn!(unwind_attributes))), - (sym::used, Whitelisted, template!(Word), Ungated), - - // used in resolve - (sym::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::prelude_import, - "`#[prelude_import]` is for use by rustc only", - cfg_fn!(prelude_import))), - - // FIXME: #14407 these are only looked at on-demand so we can't - // guarantee they'll have already been checked - ( - sym::rustc_deprecated, - Whitelisted, - template!(List: r#"since = "version", reason = "...""#), - Ungated - ), - (sym::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated), - ( - sym::stable, - Whitelisted, - template!(List: r#"feature = "name", since = "version""#), - Ungated - ), - ( - sym::unstable, - Whitelisted, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), - Ungated - ), - (sym::deprecated, - Normal, - template!( - Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, - NameValueStr: "reason" - ), - Ungated - ), - - (sym::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable, - sym::unboxed_closures, - "unboxed_closures are still evolving", - cfg_fn!(unboxed_closures))), - - (sym::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated), - - (sym::proc_macro_attribute, Normal, template!(Word), Ungated), - (sym::proc_macro, Normal, template!(Word), Ungated), - - (sym::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "used internally by rustc", - cfg_fn!(rustc_attrs))), - - (sym::allow_fail, Normal, template!(Word), Gated(Stability::Unstable, - sym::allow_fail, - "allow_fail attribute is currently unstable", - cfg_fn!(allow_fail))), - - (sym::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - // whitelists "identity-like" conversion methods to suggest on type mismatch - (sym::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable, - sym::rustc_attrs, - "this is an internal attribute that will \ - never be stable", - cfg_fn!(rustc_attrs))), - - ( - sym::rustc_args_required_const, - Whitelisted, - template!(List: "N"), - Gated(Stability::Unstable, sym::rustc_attrs, "never will be stable", - cfg_fn!(rustc_attrs)) - ), - // RFC 2070 - (sym::panic_handler, Normal, template!(Word), Ungated), - - (sym::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable, - sym::alloc_error_handler, - "#[alloc_error_handler] is an unstable feature", - cfg_fn!(alloc_error_handler))), - - // RFC 2412 - (sym::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable, - sym::optimize_attribute, - "#[optimize] attribute is an unstable feature", - cfg_fn!(optimize_attribute))), - - // Crate level attributes - (sym::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated), - (sym::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated), - (sym::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated), - (sym::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated), - (sym::no_start, CrateLevel, template!(Word), Ungated), - (sym::no_main, CrateLevel, template!(Word), Ungated), - (sym::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated), - (sym::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable, - sym::custom_test_frameworks, - "custom test frameworks are an unstable feature", - cfg_fn!(custom_test_frameworks))), -]; - -pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); - -lazy_static! { - pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap = { - let mut map = FxHashMap::default(); - for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.0, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.0); - } - } - map - }; -} - -// cfg(...)'s that are feature gated -const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[ - // (name in cfg, feature, function to check if the feature is enabled) - (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), - (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), - (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), - (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), -]; - -#[derive(Debug)] -pub struct GatedCfg { - span: Span, - index: usize, -} - -impl GatedCfg { - pub fn gate(cfg: &ast::MetaItem) -> Option { - GATED_CFGS.iter() - .position(|info| cfg.check_name(info.0)) - .map(|idx| { - GatedCfg { - span: cfg.span, - index: idx - } - }) - } - - pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { - let (cfg, feature, has_feature) = GATED_CFGS[self.index]; - if !has_feature(features) && !self.span.allows_unstable(feature) { - let explain = format!("`cfg({})` is experimental and subject to change", cfg); - emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); - } - } -} - -struct Context<'a> { - features: &'a Features, - parse_sess: &'a ParseSess, - plugin_attributes: &'a [(Symbol, AttributeType)], -} - -macro_rules! gate_feature_fn { - ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ - let (cx, has_feature, span, - name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); - let has_feature: bool = has_feature(&$cx.features); - debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); - if !has_feature && !span.allows_unstable($name) { - leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) - .emit(); - } - }} -} - -macro_rules! gate_feature { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, GateStrength::Hard) - }; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, - sym::$feature, $explain, $level) - }; -} - -impl<'a> Context<'a> { - fn check_attribute( - &self, - attr: &ast::Attribute, - attr_info: Option<&BuiltinAttribute>, - is_macro: bool - ) { - debug!("check_attribute(attr = {:?})", attr); - if let Some(&(name, ty, _template, ref gateage)) = attr_info { - if let Gated(_, name, desc, ref has_feature) = *gateage { - if !attr.span.allows_unstable(name) { - gate_feature_fn!( - self, has_feature, attr.span, name, desc, GateStrength::Hard - ); - } - } else if name == sym::doc { - if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name(sym::include)) { - gate_feature!(self, external_doc, attr.span, - "#[doc(include = \"...\")] is experimental" - ); - } - } - } - debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); - return; - } else { - for segment in &attr.path.segments { - if segment.ident.as_str().starts_with("rustc") { - let msg = "attributes starting with `rustc` are \ - reserved for use by the `rustc` compiler"; - gate_feature!(self, rustc_attrs, segment.ident.span, msg); - } - } - } - for &(n, ty) in self.plugin_attributes { - if attr.path == n { - // Plugins can't gate attributes, so we don't check for it - // unlike the code above; we only use this loop to - // short-circuit to avoid the checks below. - debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); - return; - } - } - if !is_macro && !attr::is_known(attr) { - // Only run the custom attribute lint during regular feature gate - // checking. Macro gating runs before the plugin attributes are - // registered, so we skip this in that case. - let msg = format!("The attribute `{}` is currently unknown to the compiler and \ - may have meaning added to it in the future", attr.path); - gate_feature!(self, custom_attribute, attr.span, &msg); - } - } -} - -pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { - let cx = Context { features, parse_sess, plugin_attributes: &[] }; - cx.check_attribute( - attr, - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)), - true - ); -} - -fn find_lang_feature_issue(feature: Symbol) -> Option { - if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) { - let issue = info.2; - // FIXME (#28244): enforce that active features have issue numbers - // assert!(issue.is_some()) - issue - } else { - // search in Accepted, Removed, or Stable Removed features - let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) - .find(|t| t.0 == feature); - match found { - Some(&(_, _, issue, _)) => issue, - None => panic!("Feature `{}` is not declared anywhere", feature), - } - } -} - -pub enum GateIssue { - Language, - Library(Option) -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum GateStrength { - /// A hard error. (Most feature gates should use this.) - Hard, - /// Only a warning. (Use this only as backwards-compatibility demands.) - Soft, -} - -pub fn emit_feature_err( - sess: &ParseSess, - feature: Symbol, - span: Span, - issue: GateIssue, - explain: &str, -) { - feature_err(sess, feature, span, issue, explain).emit(); -} - -pub fn feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, -) -> DiagnosticBuilder<'a> { - leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) -} - -fn leveled_feature_err<'a, S: Into>( - sess: &'a ParseSess, - feature: Symbol, - span: S, - issue: GateIssue, - explain: &str, - level: GateStrength, -) -> DiagnosticBuilder<'a> { - let diag = &sess.span_diagnostic; - - let issue = match issue { - GateIssue::Language => find_lang_feature_issue(feature), - GateIssue::Library(lib) => lib, - }; - - let mut err = match level { - GateStrength::Hard => { - diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658)) - } - GateStrength::Soft => diag.struct_span_warn(span, explain), - }; - - match issue { - None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility - Some(n) => { - err.note(&format!( - "for more information, see https://github.com/rust-lang/rust/issues/{}", - n, - )); - } - } - - // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { - err.help(&format!("add #![feature({})] to the crate attributes to enable", feature)); - } - - // If we're on stable and only emitting a "soft" warning, add a note to - // clarify that the feature isn't "on" (rather than being on but - // warning-worthy). - if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { - err.help("a nightly build of the compiler is required to enable this feature"); - } - - err - -} - -const EXPLAIN_BOX_SYNTAX: &str = - "box expression syntax is experimental; you can call `Box::new` instead"; - -pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = - "attributes on expressions are experimental"; - -pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = - "allow_internal_unstable side-steps feature gating and stability checks"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = - "allow_internal_unsafe side-steps the unsafe_code lint"; - -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = - "unsized tuple coercion is not stable enough for use and is subject to change"; - -struct PostExpansionVisitor<'a> { - context: &'a Context<'a>, - builtin_attributes: &'static FxHashMap, -} - -macro_rules! gate_feature_post { - ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain) - } - }}; - ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ - let (cx, span) = ($cx, $span); - if !span.allows_unstable(sym::$feature) { - gate_feature!(cx.context, $feature, span, $explain, $level) - } - }} -} - -impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: Abi, span: Span) { - match abi { - Abi::RustIntrinsic => { - gate_feature_post!(&self, intrinsics, span, - "intrinsics are subject to change"); - }, - Abi::PlatformIntrinsic => { - gate_feature_post!(&self, platform_intrinsics, span, - "platform intrinsics are experimental and possibly buggy"); - }, - Abi::Vectorcall => { - gate_feature_post!(&self, abi_vectorcall, span, - "vectorcall is experimental and subject to change"); - }, - Abi::Thiscall => { - gate_feature_post!(&self, abi_thiscall, span, - "thiscall is experimental and subject to change"); - }, - Abi::RustCall => { - gate_feature_post!(&self, unboxed_closures, span, - "rust-call ABI is subject to change"); - }, - Abi::PtxKernel => { - gate_feature_post!(&self, abi_ptx, span, - "PTX ABIs are experimental and subject to change"); - }, - Abi::Unadjusted => { - gate_feature_post!(&self, abi_unadjusted, span, - "unadjusted ABI is an implementation detail and perma-unstable"); - }, - Abi::Msp430Interrupt => { - gate_feature_post!(&self, abi_msp430_interrupt, span, - "msp430-interrupt ABI is experimental and subject to change"); - }, - Abi::X86Interrupt => { - gate_feature_post!(&self, abi_x86_interrupt, span, - "x86-interrupt ABI is experimental and subject to change"); - }, - Abi::AmdGpuKernel => { - gate_feature_post!(&self, abi_amdgpu_kernel, span, - "amdgpu-kernel ABI is experimental and subject to change"); - }, - // Stable - Abi::Cdecl | - Abi::Stdcall | - Abi::Fastcall | - Abi::Aapcs | - Abi::Win64 | - Abi::SysV64 | - Abi::Rust | - Abi::C | - Abi::System => {} - } - } - - fn check_builtin_attribute(&mut self, attr: &ast::Attribute, name: Symbol, - template: AttributeTemplate) { - // Some special attributes like `cfg` must be checked - // before the generic check, so we skip them here. - let should_skip = |name| name == sym::cfg; - // Some of previously accepted forms were used in practice, - // report them as warnings for now. - let should_warn = |name| name == sym::doc || name == sym::ignore || - name == sym::inline || name == sym::link; - - match attr.parse_meta(self.context.parse_sess) { - Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) { - let error_msg = format!("malformed `{}` attribute input", name); - let mut msg = "attribute must be of the form ".to_owned(); - let mut suggestions = vec![]; - let mut first = true; - if template.word { - first = false; - let code = format!("#[{}]", name); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if let Some(descr) = template.list { - if !first { - msg.push_str(" or "); - } - first = false; - let code = format!("#[{}({})]", name, descr); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if let Some(descr) = template.name_value_str { - if !first { - msg.push_str(" or "); - } - let code = format!("#[{} = \"{}\"]", name, descr); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if should_warn(name) { - self.context.parse_sess.buffer_lint( - BufferedEarlyLintId::IllFormedAttributeInput, - meta.span, - ast::CRATE_NODE_ID, - &msg, - ); - } else { - self.context.parse_sess.span_diagnostic.struct_span_err(meta.span, &error_msg) - .span_suggestions( - meta.span, - if suggestions.len() == 1 { - "must be of the form" - } else { - "the following are the possible correct uses" - }, - suggestions.into_iter(), - Applicability::HasPlaceholders, - ).emit(); - } - } - Err(mut err) => err.emit(), - } - } -} - -impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { - fn visit_attribute(&mut self, attr: &ast::Attribute) { - let attr_info = attr.ident().and_then(|ident| { - self.builtin_attributes.get(&ident.name).map(|a| *a) - }); - - // Check for gated attributes. - self.context.check_attribute(attr, attr_info, false); - - if attr.check_name(sym::doc) { - if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name(sym::cfg) { - gate_feature_post!(&self, doc_cfg, attr.span, - "#[doc(cfg(...))] is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::masked)) { - gate_feature_post!(&self, doc_masked, attr.span, - "#[doc(masked)] is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::spotlight)) { - gate_feature_post!(&self, doc_spotlight, attr.span, - "#[doc(spotlight)] is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::alias)) { - gate_feature_post!(&self, doc_alias, attr.span, - "#[doc(alias = \"...\")] is experimental" - ); - } else if content.iter().any(|c| c.check_name(sym::keyword)) { - gate_feature_post!(&self, doc_keyword, attr.span, - "#[doc(keyword = \"...\")] is experimental" - ); - } - } - } - - match attr_info { - // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(&(name, _, template, _)) if name != sym::rustc_dummy => - self.check_builtin_attribute(attr, name, template), - _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() { - if token == token::Eq { - // All key-value attributes are restricted to meta-item syntax. - attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok(); - } - } - } - } - - fn visit_name(&mut self, sp: Span, name: ast::Name) { - if !name.as_str().is_ascii() { - gate_feature_post!( - &self, - non_ascii_idents, - self.context.parse_sess.source_map().def_span(sp), - "non-ascii idents are not fully supported" - ); - } - } - - fn visit_item(&mut self, i: &'a ast::Item) { - match i.node { - ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi, i.span); - } - - ast::ItemKind::Fn(..) => { - if attr::contains_name(&i.attrs[..], sym::plugin_registrar) { - gate_feature_post!(&self, plugin_registrar, i.span, - "compiler plugins are experimental and possibly buggy"); - } - if attr::contains_name(&i.attrs[..], sym::start) { - gate_feature_post!(&self, start, i.span, - "a #[start] function is an experimental \ - feature whose signature may change \ - over time"); - } - if attr::contains_name(&i.attrs[..], sym::main) { - gate_feature_post!(&self, main, i.span, - "declaration of a nonstandard #[main] \ - function may change over time, for now \ - a top-level `fn main()` is required"); - } - } - - ast::ItemKind::Struct(..) => { - for attr in attr::filter_by_name(&i.attrs[..], sym::repr) { - for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name(sym::simd) { - gate_feature_post!(&self, repr_simd, attr.span, - "SIMD types are experimental and possibly buggy"); - } - } - } - } - - ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { - for variant in variants { - match (&variant.node.data, &variant.node.disr_expr) { - (ast::VariantData::Unit(..), _) => {}, - (_, Some(disr_expr)) => - gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental"), - _ => {}, - } - } - - let has_feature = self.context.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - Parser::maybe_report_invalid_custom_discriminants( - self.context.parse_sess, - &variants, - ); - } - } - - ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => { - if polarity == ast::ImplPolarity::Negative { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "negative trait bounds are not yet fully implemented; \ - use marker types for now"); - } - - if let ast::Defaultness::Default = defaultness { - gate_feature_post!(&self, specialization, - i.span, - "specialization is unstable"); - } - } - - ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { - gate_feature_post!(&self, optin_builtin_traits, - i.span, - "auto traits are experimental and possibly buggy"); - } - - ast::ItemKind::TraitAlias(..) => { - gate_feature_post!( - &self, - trait_alias, - i.span, - "trait aliases are experimental" - ); - } - - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { - let msg = "`macro` is experimental"; - gate_feature_post!(&self, decl_macro, i.span, msg); - } - - ast::ItemKind::Existential(..) => { - gate_feature_post!( - &self, - existential_type, - i.span, - "existential types are unstable" - ); - } - - _ => {} - } - - visit::walk_item(self, i); - } - - fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) { - match i.node { - ast::ForeignItemKind::Fn(..) | - ast::ForeignItemKind::Static(..) => { - let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name); - let links_to_llvm = match link_name { - Some(val) => val.as_str().starts_with("llvm."), - _ => false - }; - if links_to_llvm { - gate_feature_post!(&self, link_llvm_intrinsics, i.span, - "linking to LLVM intrinsics is experimental"); - } - } - ast::ForeignItemKind::Ty => { - gate_feature_post!(&self, extern_types, i.span, - "extern types are experimental"); - } - ast::ForeignItemKind::Macro(..) => {} - } - - visit::walk_foreign_item(self, i) - } - - fn visit_ty(&mut self, ty: &'a ast::Ty) { - match ty.node { - ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi, ty.span); - } - ast::TyKind::Never => { - gate_feature_post!(&self, never_type, ty.span, - "The `!` type is experimental"); - } - _ => {} - } - visit::walk_ty(self, ty) - } - - fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { - if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { - if let ast::TyKind::Never = output_ty.node { - // Do nothing. - } else { - self.visit_ty(output_ty) - } - } - } - - fn visit_expr(&mut self, e: &'a ast::Expr) { - match e.node { - ast::ExprKind::Box(_) => { - gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); - } - ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. - if self.context.parse_sess.span_diagnostic.err_count() == 0 { - gate_feature_post!(&self, type_ascription, e.span, - "type ascription is experimental"); - } - } - ast::ExprKind::Yield(..) => { - gate_feature_post!(&self, generators, - e.span, - "yield syntax is experimental"); - } - ast::ExprKind::TryBlock(_) => { - gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); - } - ast::ExprKind::Block(_, opt_label) => { - if let Some(label) = opt_label { - gate_feature_post!(&self, label_break_value, label.ident.span, - "labels on blocks are unstable"); - } - } - ast::ExprKind::Async(..) => { - gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); - } - ast::ExprKind::Await(origin, _) => { - match origin { - ast::AwaitOrigin::FieldLike => - gate_feature_post!(&self, async_await, e.span, "async/await is unstable"), - ast::AwaitOrigin::MacroLike => - gate_feature_post!( - &self, - await_macro, - e.span, - "`await!()` macro syntax is unstable, and will soon be removed \ - in favor of `.await` syntax." - ), - } - } - _ => {} - } - visit::walk_expr(self, e) - } - - fn visit_arm(&mut self, arm: &'a ast::Arm) { - visit::walk_arm(self, arm) - } - - fn visit_pat(&mut self, pattern: &'a ast::Pat) { - match pattern.node { - PatKind::Slice(_, Some(ref subslice), _) => { - gate_feature_post!(&self, slice_patterns, - subslice.span, - "syntax for subslices in slice patterns is not yet stabilized"); - } - PatKind::Box(..) => { - gate_feature_post!(&self, box_patterns, - pattern.span, - "box pattern syntax is experimental"); - } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { - gate_feature_post!(&self, exclusive_range_pattern, pattern.span, - "exclusive range pattern syntax is experimental"); - } - _ => {} - } - visit::walk_pat(self, pattern) - } - - fn visit_fn(&mut self, - fn_kind: FnKind<'a>, - fn_decl: &'a ast::FnDecl, - span: Span, - _node_id: NodeId) { - if let Some(header) = fn_kind.header() { - // Check for const fn and async fn declarations. - if header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, span, "async fn is unstable"); - } - - // Stability of const fn methods are covered in - // `visit_trait_item` and `visit_impl_item` below; this is - // because default methods don't pass through this point. - self.check_abi(header.abi, span); - } - - if fn_decl.c_variadic { - gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); - } - - visit::walk_fn(self, fn_kind, fn_decl, span) - } - - fn visit_generic_param(&mut self, param: &'a GenericParam) { - match param.kind { - GenericParamKind::Const { .. } => - gate_feature_post!(&self, const_generics, param.ident.span, - "const generics are unstable"), - _ => {} - } - visit::walk_generic_param(self, param) - } - - fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { - match constraint.kind { - AssocTyConstraintKind::Bound { .. } => - gate_feature_post!(&self, associated_type_bounds, constraint.span, - "associated type bounds are unstable"), - _ => {} - } - visit::walk_assoc_ty_constraint(self, constraint) - } - - fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { - match ti.node { - ast::TraitItemKind::Method(ref sig, ref block) => { - if block.is_none() { - self.check_abi(sig.header.abi, ti.span); - } - if sig.header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, ti.span, "async fn is unstable"); - } - if sig.decl.c_variadic { - gate_feature_post!(&self, c_variadic, ti.span, - "C-variadic functions are unstable"); - } - if sig.header.constness.node == ast::Constness::Const { - gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); - } - } - ast::TraitItemKind::Type(_, ref default) => { - // We use three if statements instead of something like match guards so that all - // of these errors can be emitted if all cases apply. - if default.is_some() { - gate_feature_post!(&self, associated_type_defaults, ti.span, - "associated type defaults are unstable"); - } - if !ti.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "generic associated types are unstable"); - } - if !ti.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_trait_item(self, ti) - } - - fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { - if ii.defaultness == ast::Defaultness::Default { - gate_feature_post!(&self, specialization, - ii.span, - "specialization is unstable"); - } - - match ii.node { - ast::ImplItemKind::Method(..) => {} - ast::ImplItemKind::Existential(..) => { - gate_feature_post!( - &self, - existential_type, - ii.span, - "existential types are unstable" - ); - } - ast::ImplItemKind::Type(_) => { - if !ii.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "generic associated types are unstable"); - } - if !ii.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "where clauses on associated types are unstable"); - } - } - _ => {} - } - visit::walk_impl_item(self, ii) - } - - fn visit_vis(&mut self, vis: &'a ast::Visibility) { - if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { - gate_feature_post!(&self, crate_visibility_modifier, vis.span, - "`crate` visibility modifier is experimental"); - } - visit::walk_vis(self, vis) - } -} - -pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], - crate_edition: Edition, allow_features: &Option>) -> Features { - fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { - let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); - if let Some(reason) = reason { - err.span_note(span, reason); - } else { - err.span_label(span, "feature has been removed"); - } - err.emit(); - } - - let mut features = Features::new(); - let mut edition_enabled_features = FxHashMap::default(); - - for &edition in ALL_EDITIONS { - if edition <= crate_edition { - // The `crate_edition` implies its respective umbrella feature-gate - // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). - edition_enabled_features.insert(edition.feature_name(), edition); - } - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= crate_edition { - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, crate_edition); - } - } - } - - // Process the edition umbrella feature-gates first, to ensure - // `edition_enabled_features` is completed before it's queried. - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - for mi in list { - if !mi.is_word() { - continue; - } - - let name = mi.name_or_empty(); - if INCOMPLETE_FEATURES.iter().any(|f| name == *f) { - span_handler.struct_span_warn( - mi.span(), - &format!( - "the feature `{}` is incomplete and may cause the compiler to crash", - name - ) - ).emit(); - } - - if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { - if *edition <= crate_edition { - continue; - } - - for &(name, .., f_edition, set) in ACTIVE_FEATURES { - if let Some(f_edition) = f_edition { - if f_edition <= *edition { - // FIXME(Manishearth) there is currently no way to set - // lib features by edition - set(&mut features, DUMMY_SP); - edition_enabled_features.insert(name, *edition); - } - } - } - } - } - } - - for attr in krate_attrs { - if !attr.check_name(sym::feature) { - continue - } - - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, - }; - - let bad_input = |span| { - struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") - }; - - for mi in list { - let name = match mi.ident() { - Some(ident) if mi.is_word() => ident.name, - Some(ident) => { - bad_input(mi.span()).span_suggestion( - mi.span(), - "expected just one word", - format!("{}", ident.name), - Applicability::MaybeIncorrect, - ).emit(); - continue - } - None => { - bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); - continue - } - }; - - if let Some(edition) = edition_enabled_features.get(&name) { - struct_span_warn!( - span_handler, - mi.span(), - E0705, - "the feature `{}` is included in the Rust {} edition", - name, - edition, - ).emit(); - continue; - } - - if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { - // Handled in the separate loop above. - continue; - } - - let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); - let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); - if let Some((.., reason)) = removed.or(stable_removed) { - feature_removed(span_handler, mi.span(), *reason); - continue; - } - - if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { - let since = Some(Symbol::intern(since)); - features.declared_lang_features.push((name, mi.span(), since)); - continue; - } - - if let Some(allowed) = allow_features.as_ref() { - if allowed.iter().find(|f| *f == name.as_str()).is_none() { - span_err!(span_handler, mi.span(), E0725, - "the feature `{}` is not in the list of allowed features", - name); - continue; - } - } - - if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - set(&mut features, mi.span()); - features.declared_lang_features.push((name, mi.span(), None)); - continue; - } - - features.declared_lib_features.push((name, mi.span())); - } - } - - features -} - -fn for_each_in_lock(vec: &Lock>, f: impl Fn(&T)) { - vec.borrow().iter().for_each(f); -} - -pub fn check_crate(krate: &ast::Crate, - sess: &ParseSess, - features: &Features, - plugin_attributes: &[(Symbol, AttributeType)], - unstable: UnstableFeatures) { - maybe_stage_features(&sess.span_diagnostic, krate, unstable); - let ctx = Context { - features, - parse_sess: sess, - plugin_attributes, - }; - - for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( - &ctx, - let_chains, - *span, - "`let` expressions in this position are experimental" - )); - - for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!( - &ctx, - async_closure, - *span, - "async closures are unstable" - )); - - let visitor = &mut PostExpansionVisitor { - context: &ctx, - builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, - }; - visit::walk_crate(visitor, krate); -} - -#[derive(Clone, Copy, Hash)] -pub enum UnstableFeatures { - /// Hard errors for unstable features are active, as on beta/stable channels. - Disallow, - /// Allow features to be activated, as on nightly. - Allow, - /// Errors are bypassed for bootstrapping. This is required any time - /// during the build that feature-related lints are set to warn or above - /// because the build turns on warnings-as-errors and uses lots of unstable - /// features. As a result, this is always required for building Rust itself. - Cheat -} - -impl UnstableFeatures { - pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e., on the beta or stable channel - let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // Whether we should enable unstable features for bootstrapping - let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); - match (disable_unstable_features, bootstrap) { - (_, true) => UnstableFeatures::Cheat, - (true, _) => UnstableFeatures::Disallow, - (false, _) => UnstableFeatures::Allow - } - } - - pub fn is_nightly_build(&self) -> bool { - match *self { - UnstableFeatures::Allow | UnstableFeatures::Cheat => true, - _ => false, - } - } -} - -fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, - unstable: UnstableFeatures) { - let allow_features = match unstable { - UnstableFeatures::Allow => true, - UnstableFeatures::Disallow => false, - UnstableFeatures::Cheat => true - }; - if !allow_features { - for attr in &krate.attrs { - if attr.check_name(sym::feature) { - let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); - span_err!(span_handler, attr.span, E0554, - "#![feature] may not be used on the {} release channel", - release_channel); - } - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/json.rs b/gcc/rust/rustc_parser/libsyntax/json.rs deleted file mode 100644 index 767ab74..0000000 --- a/gcc/rust/rustc_parser/libsyntax/json.rs +++ /dev/null @@ -1,412 +0,0 @@ -//! A JSON emitter for errors. -//! -//! This works by converting errors to a simplified structural format (see the -//! structs at the start of the file) and then serializing them. These should -//! contain as much information about the error as possible. -//! -//! The format of the JSON output should be considered *unstable*. For now the -//! structs at the end of this file (Diagnostic*) specify the error format. - -// FIXME: spec the JSON output properly. - -use crate::source_map::{SourceMap, FilePathMapping}; - -use errors::registry::Registry; -use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, SourceMapper}; -use errors::{DiagnosticId, Applicability}; -use errors::emitter::{Emitter, HumanReadableErrorType}; - -use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; -use rustc_data_structures::sync::{self, Lrc}; -use std::io::{self, Write}; -use std::path::Path; -use std::vec; -use std::sync::{Arc, Mutex}; - -use rustc_serialize::json::{as_json, as_pretty_json}; - -pub struct JsonEmitter { - dst: Box, - registry: Option, - sm: Lrc, - pretty: bool, - ui_testing: bool, - json_rendered: HumanReadableErrorType, -} - -impl JsonEmitter { - pub fn stderr( - registry: Option, - source_map: Lrc, - pretty: bool, - json_rendered: HumanReadableErrorType, - ) -> JsonEmitter { - JsonEmitter { - dst: Box::new(io::stderr()), - registry, - sm: source_map, - pretty, - ui_testing: false, - json_rendered, - } - } - - pub fn basic(pretty: bool, json_rendered: HumanReadableErrorType) -> JsonEmitter { - let file_path_mapping = FilePathMapping::empty(); - JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)), - pretty, json_rendered) - } - - pub fn new( - dst: Box, - registry: Option, - source_map: Lrc, - pretty: bool, - json_rendered: HumanReadableErrorType, - ) -> JsonEmitter { - JsonEmitter { - dst, - registry, - sm: source_map, - pretty, - ui_testing: false, - json_rendered, - } - } - - pub fn ui_testing(self, ui_testing: bool) -> Self { - Self { ui_testing, ..self } - } -} - -impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let data = Diagnostic::from_diagnostic_builder(db, self); - let result = if self.pretty { - writeln!(&mut self.dst, "{}", as_pretty_json(&data)) - } else { - writeln!(&mut self.dst, "{}", as_json(&data)) - }; - if let Err(e) = result { - panic!("failed to print diagnostics: {:?}", e); - } - } - - fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { - let data = ArtifactNotification { artifact: path, emit: artifact_type }; - let result = if self.pretty { - writeln!(&mut self.dst, "{}", as_pretty_json(&data)) - } else { - writeln!(&mut self.dst, "{}", as_json(&data)) - }; - if let Err(e) = result { - panic!("failed to print notification: {:?}", e); - } - } -} - -// The following data types are provided just for serialisation. - -#[derive(RustcEncodable)] -struct Diagnostic { - /// The primary error message. - message: String, - code: Option, - /// "error: internal compiler error", "error", "warning", "note", "help". - level: &'static str, - spans: Vec, - /// Associated diagnostic messages. - children: Vec, - /// The message as rustc would render it. - rendered: Option, -} - -#[derive(RustcEncodable)] -#[allow(unused_attributes)] -struct DiagnosticSpan { - file_name: String, - byte_start: u32, - byte_end: u32, - /// 1-based. - line_start: usize, - line_end: usize, - /// 1-based, character offset. - column_start: usize, - column_end: usize, - /// Is this a "primary" span -- meaning the point, or one of the points, - /// where the error occurred? - is_primary: bool, - /// Source text from the start of line_start to the end of line_end. - text: Vec, - /// Label that should be placed at this location (if any) - label: Option, - /// If we are suggesting a replacement, this will contain text - /// that should be sliced in atop this span. - suggested_replacement: Option, - /// If the suggestion is approximate - suggestion_applicability: Option, - /// Macro invocations that created the code at this span, if any. - expansion: Option>, -} - -#[derive(RustcEncodable)] -struct DiagnosticSpanLine { - text: String, - - /// 1-based, character offset in self.text. - highlight_start: usize, - - highlight_end: usize, -} - -#[derive(RustcEncodable)] -struct DiagnosticSpanMacroExpansion { - /// span where macro was applied to generate this code; note that - /// this may itself derive from a macro (if - /// `span.expansion.is_some()`) - span: DiagnosticSpan, - - /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") - macro_decl_name: String, - - /// span where macro was defined (if known) - def_site_span: Option, -} - -#[derive(RustcEncodable)] -struct DiagnosticCode { - /// The code itself. - code: String, - /// An explanation for the code. - explanation: Option<&'static str>, -} - -#[derive(RustcEncodable)] -struct ArtifactNotification<'a> { - /// The path of the artifact. - artifact: &'a Path, - /// What kind of artifact we're emitting. - emit: &'a str, -} - -impl Diagnostic { - fn from_diagnostic_builder(db: &DiagnosticBuilder<'_>, - je: &JsonEmitter) - -> Diagnostic { - let sugg = db.suggestions.iter().map(|sugg| { - Diagnostic { - message: sugg.msg.clone(), - code: None, - level: "help", - spans: DiagnosticSpan::from_suggestion(sugg, je), - children: vec![], - rendered: None, - } - }); - - // generate regular command line output and store it in the json - - // A threadsafe buffer for writing. - #[derive(Default, Clone)] - struct BufWriter(Arc>>); - - impl Write for BufWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.lock().unwrap().write(buf) - } - fn flush(&mut self) -> io::Result<()> { - self.0.lock().unwrap().flush() - } - } - let buf = BufWriter::default(); - let output = buf.clone(); - je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false) - .ui_testing(je.ui_testing).emit_diagnostic(db); - let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); - let output = String::from_utf8(output).unwrap(); - - Diagnostic { - message: db.message(), - code: DiagnosticCode::map_opt_string(db.code.clone(), je), - level: db.level.to_str(), - spans: DiagnosticSpan::from_multispan(&db.span, je), - children: db.children.iter().map(|c| { - Diagnostic::from_sub_diagnostic(c, je) - }).chain(sugg).collect(), - rendered: Some(output), - } - } - - fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { - Diagnostic { - message: db.message(), - code: None, - level: db.level.to_str(), - spans: db.render_span.as_ref() - .map(|sp| DiagnosticSpan::from_multispan(sp, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)), - children: vec![], - rendered: None, - } - } -} - -impl DiagnosticSpan { - fn from_span_label(span: SpanLabel, - suggestion: Option<(&String, Applicability)>, - je: &JsonEmitter) - -> DiagnosticSpan { - Self::from_span_etc(span.span, - span.is_primary, - span.label, - suggestion, - je) - } - - fn from_span_etc(span: Span, - is_primary: bool, - label: Option, - suggestion: Option<(&String, Applicability)>, - je: &JsonEmitter) - -> DiagnosticSpan { - // obtain the full backtrace from the `macro_backtrace` - // helper; in some ways, it'd be better to expand the - // backtrace ourselves, but the `macro_backtrace` helper makes - // some decision, such as dropping some frames, and I don't - // want to duplicate that logic here. - let backtrace = span.macro_backtrace().into_iter(); - DiagnosticSpan::from_span_full(span, - is_primary, - label, - suggestion, - backtrace, - je) - } - - fn from_span_full(span: Span, - is_primary: bool, - label: Option, - suggestion: Option<(&String, Applicability)>, - mut backtrace: vec::IntoIter, - je: &JsonEmitter) - -> DiagnosticSpan { - let start = je.sm.lookup_char_pos(span.lo()); - let end = je.sm.lookup_char_pos(span.hi()); - let backtrace_step = backtrace.next().map(|bt| { - let call_site = - Self::from_span_full(bt.call_site, - false, - None, - None, - backtrace, - je); - let def_site_span = bt.def_site_span.map(|sp| { - Self::from_span_full(sp, - false, - None, - None, - vec![].into_iter(), - je) - }); - Box::new(DiagnosticSpanMacroExpansion { - span: call_site, - macro_decl_name: bt.macro_decl_name, - def_site_span, - }) - }); - - DiagnosticSpan { - file_name: start.file.name.to_string(), - byte_start: span.lo().0 - start.file.start_pos.0, - byte_end: span.hi().0 - start.file.start_pos.0, - line_start: start.line, - line_end: end.line, - column_start: start.col.0 + 1, - column_end: end.col.0 + 1, - is_primary, - text: DiagnosticSpanLine::from_span(span, je), - suggested_replacement: suggestion.map(|x| x.0.clone()), - suggestion_applicability: suggestion.map(|x| x.1), - expansion: backtrace_step, - label, - } - } - - fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec { - msp.span_labels() - .into_iter() - .map(|span_str| Self::from_span_label(span_str, None, je)) - .collect() - } - - fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter) - -> Vec { - suggestion.substitutions - .iter() - .flat_map(|substitution| { - substitution.parts.iter().map(move |suggestion_inner| { - let span_label = SpanLabel { - span: suggestion_inner.span, - is_primary: true, - label: None, - }; - DiagnosticSpan::from_span_label(span_label, - Some((&suggestion_inner.snippet, - suggestion.applicability)), - je) - }) - }) - .collect() - } -} - -impl DiagnosticSpanLine { - fn line_from_source_file(fm: &syntax_pos::SourceFile, - index: usize, - h_start: usize, - h_end: usize) - -> DiagnosticSpanLine { - DiagnosticSpanLine { - text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()), - highlight_start: h_start, - highlight_end: h_end, - } - } - - /// Creates a list of DiagnosticSpanLines from span - each line with any part - /// of `span` gets a DiagnosticSpanLine, with the highlight indicating the - /// `span` within the line. - fn from_span(span: Span, je: &JsonEmitter) -> Vec { - je.sm.span_to_lines(span) - .map(|lines| { - let fm = &*lines.file; - lines.lines - .iter() - .map(|line| DiagnosticSpanLine::line_from_source_file( - fm, - line.line_index, - line.start_col.0 + 1, - line.end_col.0 + 1, - )).collect() - }).unwrap_or_else(|_| vec![]) - } -} - -impl DiagnosticCode { - fn map_opt_string(s: Option, je: &JsonEmitter) -> Option { - s.map(|s| { - let s = match s { - DiagnosticId::Error(s) => s, - DiagnosticId::Lint(s) => s, - }; - let explanation = je.registry - .as_ref() - .and_then(|registry| registry.find_description(&s)); - - DiagnosticCode { - code: s, - explanation, - } - }) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/lib.rs b/gcc/rust/rustc_parser/libsyntax/lib.rs deleted file mode 100644 index a7c5ed1..0000000 --- a/gcc/rust/rustc_parser/libsyntax/lib.rs +++ /dev/null @@ -1,189 +0,0 @@ -//! The Rust parser and macro expander. -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", - test(attr(deny(warnings))))] - -#![deny(rust_2018_idioms)] -#![deny(unused_lifetimes)] - -#![feature(bind_by_move_pattern_guards)] -#![feature(box_syntax)] -#![feature(const_fn)] -#![feature(const_transmute)] -#![feature(crate_visibility_modifier)] -#![feature(label_break_value)] -#![feature(mem_take)] -#![feature(nll)] -#![feature(rustc_attrs)] -#![feature(rustc_diagnostic_macros)] -#![feature(step_trait)] -#![feature(try_trait)] -#![feature(unicode_internals)] - -#![recursion_limit="256"] - -#[allow(unused_extern_crates)] -extern crate serialize as rustc_serialize; // used by deriving - -pub use errors; -use rustc_data_structures::sync::Lock; -use rustc_data_structures::bit_set::GrowableBitSet; -pub use rustc_data_structures::thin_vec::ThinVec; -use ast::AttrId; -use syntax_pos::edition::Edition; - -const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments"); - -// A variant of 'try!' that panics on an Err. This is used as a crutch on the -// way towards a non-panic!-prone parser. It should be used for fatal parsing -// errors; eventually we plan to convert all code using panictry to just use -// normal try. -macro_rules! panictry { - ($e:expr) => ({ - use std::result::Result::{Ok, Err}; - use errors::FatalError; - match $e { - Ok(e) => e, - Err(mut e) => { - e.emit(); - FatalError.raise() - } - } - }) -} - -// A variant of 'panictry!' that works on a Vec instead of a single DiagnosticBuilder. -macro_rules! panictry_buffer { - ($handler:expr, $e:expr) => ({ - use std::result::Result::{Ok, Err}; - use errors::{FatalError, DiagnosticBuilder}; - match $e { - Ok(e) => e, - Err(errs) => { - for e in errs { - DiagnosticBuilder::new_diagnostic($handler, e).emit(); - } - FatalError.raise() - } - } - }) -} - -#[macro_export] -macro_rules! unwrap_or { - ($opt:expr, $default:expr) => { - match $opt { - Some(x) => x, - None => $default, - } - } -} - -pub struct Globals { - used_attrs: Lock>, - known_attrs: Lock>, - syntax_pos_globals: syntax_pos::Globals, -} - -impl Globals { - fn new(edition: Edition) -> Globals { - Globals { - // We have no idea how many attributes their will be, so just - // initiate the vectors with 0 bits. We'll grow them as necessary. - used_attrs: Lock::new(GrowableBitSet::new_empty()), - known_attrs: Lock::new(GrowableBitSet::new_empty()), - syntax_pos_globals: syntax_pos::Globals::new(edition), - } - } -} - -pub fn with_globals(edition: Edition, f: F) -> R - where F: FnOnce() -> R -{ - let globals = Globals::new(edition); - GLOBALS.set(&globals, || { - syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f) - }) -} - -pub fn with_default_globals(f: F) -> R - where F: FnOnce() -> R -{ - with_globals(edition::DEFAULT_EDITION, f) -} - -scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); - -#[macro_use] -pub mod diagnostics { - #[macro_use] - pub mod macros; - pub mod plugin; - pub mod metadata; -} - -// N.B., this module needs to be declared first so diagnostics are -// registered before they are used. -pub mod error_codes; - -pub mod util { - pub mod lev_distance; - pub mod node_count; - pub mod parser; - #[cfg(test)] - pub mod parser_testing; - pub mod map_in_place; -} - -pub mod json; - -pub mod ast; -pub mod attr; -pub mod source_map; -#[macro_use] -pub mod config; -pub mod entry; -pub mod feature_gate; -pub mod mut_visit; -pub mod parse; -pub mod ptr; -pub mod show_span; -pub mod std_inject; -pub use syntax_pos::edition; -pub use syntax_pos::symbol; -pub mod test; -pub mod tokenstream; -pub mod visit; - -pub mod print { - pub mod pp; - pub mod pprust; -} - -pub mod ext { - pub use syntax_pos::hygiene; - pub mod base; - pub mod build; - pub mod derive; - pub mod expand; - pub mod placeholders; - pub mod source_util; - - pub mod tt { - pub mod transcribe; - pub mod macro_parser; - pub mod macro_rules; - pub mod quoted; - } -} - -pub mod early_buffered_lints; - -#[cfg(test)] -mod test_snippet; - -__build_diagnostic_array! { libsyntax, DIAGNOSTICS } diff --git a/gcc/rust/rustc_parser/libsyntax/mut_visit.rs b/gcc/rust/rustc_parser/libsyntax/mut_visit.rs deleted file mode 100644 index 11a1de1..0000000 --- a/gcc/rust/rustc_parser/libsyntax/mut_visit.rs +++ /dev/null @@ -1,1334 +0,0 @@ -//! A MutVisitor represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a MutVisitor -//! that walks over an AST and modifies it. -//! -//! Note: using a MutVisitor (other than the MacroExpander MutVisitor) on -//! an AST before macro expansion is probably a bad idea. For instance, -//! a MutVisitor renaming item names in a module will miss all of those -//! that are created by the expansion of a macro. - -use crate::ast::*; -use crate::source_map::{Spanned, respan}; -use crate::parse::token::{self, Token}; -use crate::ptr::P; -use crate::ThinVec; -use crate::tokenstream::*; -use crate::util::map_in_place::MapInPlace; - -use smallvec::{smallvec, Array, SmallVec}; -use syntax_pos::Span; - -use rustc_data_structures::sync::Lrc; -use std::ops::DerefMut; -use std::{panic, process, ptr}; - -pub trait ExpectOne { - fn expect_one(self, err: &'static str) -> A::Item; -} - -impl ExpectOne for SmallVec { - fn expect_one(self, err: &'static str) -> A::Item { - assert!(self.len() == 1, err); - self.into_iter().next().unwrap() - } -} - -pub trait MutVisitor: Sized { - // Methods in this trait have one of three forms: - // - // fn visit_t(&mut self, t: &mut T); // common - // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare - // fn filter_map_t(&mut self, t: T) -> Option; // rarest - // - // Any additions to this trait should happen in form of a call to a public - // `noop_*` function that only calls out to the visitor again, not other - // `noop_*` functions. This is a necessary API workaround to the problem of - // not being able to call out to the super default method in an overridden - // default method. - // - // When writing these methods, it is better to use destructuring like this: - // - // fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { - // visit_a(a); - // visit_b(b); - // } - // - // than to use field access like this: - // - // fn visit_abc(&mut self, abc: &mut ABC) { - // visit_a(&mut abc.a); - // visit_b(&mut abc.b); - // // ignore abc.c - // } - // - // As well as being more concise, the former is explicit about which fields - // are skipped. Furthermore, if a new field is added, the destructuring - // version will cause a compile error, which is good. In comparison, the - // field access version will continue working and it would be easy to - // forget to add handling for it. - - fn visit_crate(&mut self, c: &mut Crate) { - noop_visit_crate(c, self) - } - - fn visit_meta_list_item(&mut self, list_item: &mut NestedMetaItem) { - noop_visit_meta_list_item(list_item, self); - } - - fn visit_meta_item(&mut self, meta_item: &mut MetaItem) { - noop_visit_meta_item(meta_item, self); - } - - fn visit_use_tree(&mut self, use_tree: &mut UseTree) { - noop_visit_use_tree(use_tree, self); - } - - fn flat_map_foreign_item(&mut self, ni: ForeignItem) -> SmallVec<[ForeignItem; 1]> { - noop_flat_map_foreign_item(ni, self) - } - - fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - noop_flat_map_item(i, self) - } - - fn visit_fn_header(&mut self, header: &mut FnHeader) { - noop_visit_fn_header(header, self); - } - - fn visit_struct_field(&mut self, sf: &mut StructField) { - noop_visit_struct_field(sf, self); - } - - fn visit_item_kind(&mut self, i: &mut ItemKind) { - noop_visit_item_kind(i, self); - } - - fn flat_map_trait_item(&mut self, i: TraitItem) -> SmallVec<[TraitItem; 1]> { - noop_flat_map_trait_item(i, self) - } - - fn flat_map_impl_item(&mut self, i: ImplItem) -> SmallVec<[ImplItem; 1]> { - noop_flat_map_impl_item(i, self) - } - - fn visit_fn_decl(&mut self, d: &mut P) { - noop_visit_fn_decl(d, self); - } - - fn visit_asyncness(&mut self, a: &mut IsAsync) { - noop_visit_asyncness(a, self); - } - - fn visit_block(&mut self, b: &mut P) { - noop_visit_block(b, self); - } - - fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> { - noop_flat_map_stmt(s, self) - } - - fn visit_arm(&mut self, a: &mut Arm) { - noop_visit_arm(a, self); - } - - fn visit_pat(&mut self, p: &mut P) { - noop_visit_pat(p, self); - } - - fn visit_anon_const(&mut self, c: &mut AnonConst) { - noop_visit_anon_const(c, self); - } - - fn visit_expr(&mut self, e: &mut P) { - noop_visit_expr(e, self); - } - - fn filter_map_expr(&mut self, e: P) -> Option> { - noop_filter_map_expr(e, self) - } - - fn visit_generic_arg(&mut self, arg: &mut GenericArg) { - noop_visit_generic_arg(arg, self); - } - - fn visit_ty(&mut self, t: &mut P) { - noop_visit_ty(t, self); - } - - fn visit_lifetime(&mut self, l: &mut Lifetime) { - noop_visit_lifetime(l, self); - } - - fn visit_ty_constraint(&mut self, t: &mut AssocTyConstraint) { - noop_visit_ty_constraint(t, self); - } - - fn visit_mod(&mut self, m: &mut Mod) { - noop_visit_mod(m, self); - } - - fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { - noop_visit_foreign_mod(nm, self); - } - - fn visit_variant(&mut self, v: &mut Variant) { - noop_visit_variant(v, self); - } - - fn visit_ident(&mut self, i: &mut Ident) { - noop_visit_ident(i, self); - } - - fn visit_path(&mut self, p: &mut Path) { - noop_visit_path(p, self); - } - - fn visit_qself(&mut self, qs: &mut Option) { - noop_visit_qself(qs, self); - } - - fn visit_generic_args(&mut self, p: &mut GenericArgs) { - noop_visit_generic_args(p, self); - } - - fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) { - noop_visit_angle_bracketed_parameter_data(p, self); - } - - fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) { - noop_visit_parenthesized_parameter_data(p, self); - } - - fn visit_local(&mut self, l: &mut P) { - noop_visit_local(l, self); - } - - fn visit_mac(&mut self, _mac: &mut Mac) { - panic!("visit_mac disabled by default"); - // N.B., see note about macros above. If you really want a visitor that - // works on macros, use this definition in your trait impl: - // mut_visit::noop_visit_mac(_mac, self); - } - - fn visit_macro_def(&mut self, def: &mut MacroDef) { - noop_visit_macro_def(def, self); - } - - fn visit_label(&mut self, label: &mut Label) { - noop_visit_label(label, self); - } - - fn visit_attribute(&mut self, at: &mut Attribute) { - noop_visit_attribute(at, self); - } - - fn visit_arg(&mut self, a: &mut Arg) { - noop_visit_arg(a, self); - } - - fn visit_generics(&mut self, generics: &mut Generics) { - noop_visit_generics(generics, self); - } - - fn visit_trait_ref(&mut self, tr: &mut TraitRef) { - noop_visit_trait_ref(tr, self); - } - - fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) { - noop_visit_poly_trait_ref(p, self); - } - - fn visit_variant_data(&mut self, vdata: &mut VariantData) { - noop_visit_variant_data(vdata, self); - } - - fn visit_generic_param(&mut self, param: &mut GenericParam) { - noop_visit_generic_param(param, self); - } - - fn visit_generic_params(&mut self, params: &mut Vec) { - noop_visit_generic_params(params, self); - } - - fn visit_tt(&mut self, tt: &mut TokenTree) { - noop_visit_tt(tt, self); - } - - fn visit_tts(&mut self, tts: &mut TokenStream) { - noop_visit_tts(tts, self); - } - - fn visit_token(&mut self, t: &mut Token) { - noop_visit_token(t, self); - } - - fn visit_interpolated(&mut self, nt: &mut token::Nonterminal) { - noop_visit_interpolated(nt, self); - } - - fn visit_param_bound(&mut self, tpb: &mut GenericBound) { - noop_visit_param_bound(tpb, self); - } - - fn visit_mt(&mut self, mt: &mut MutTy) { - noop_visit_mt(mt, self); - } - - fn visit_field(&mut self, field: &mut Field) { - noop_visit_field(field, self); - } - - fn visit_where_clause(&mut self, where_clause: &mut WhereClause) { - noop_visit_where_clause(where_clause, self); - } - - fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) { - noop_visit_where_predicate(where_predicate, self); - } - - fn visit_vis(&mut self, vis: &mut Visibility) { - noop_visit_vis(vis, self); - } - - fn visit_id(&mut self, _id: &mut NodeId) { - // Do nothing. - } - - fn visit_span(&mut self, _sp: &mut Span) { - // Do nothing. - } -} - -/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful -/// when using a `flat_map_*` or `filter_map_*` method within a `visit_` -/// method. Abort the program if the closure panics. -// -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_clobber(t: &mut T, f: F) where F: FnOnce(T) -> T { - unsafe { - // Safe because `t` is used in a read-only fashion by `read()` before - // being overwritten by `write()`. - let old_t = ptr::read(t); - let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))) - .unwrap_or_else(|_| process::abort()); - ptr::write(t, new_t); - } -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -#[inline] -pub fn visit_vec(elems: &mut Vec, mut visit_elem: F) where F: FnMut(&mut T) { - for elem in elems { - visit_elem(elem); - } -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -#[inline] -pub fn visit_opt(opt: &mut Option, mut visit_elem: F) where F: FnMut(&mut T) { - if let Some(elem) = opt { - visit_elem(elem); - } -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_attrs(attrs: &mut Vec, vis: &mut T) { - visit_vec(attrs, |attr| vis.visit_attribute(attr)); -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_thin_attrs(attrs: &mut ThinVec, vis: &mut T) { - for attr in attrs.iter_mut() { - vis.visit_attribute(attr); - } -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_exprs(exprs: &mut Vec>, vis: &mut T) { - exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr)) -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_bounds(bounds: &mut GenericBounds, vis: &mut T) { - visit_vec(bounds, |bound| vis.visit_param_bound(bound)); -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_method_sig(MethodSig { header, decl }: &mut MethodSig, vis: &mut T) { - vis.visit_fn_header(header); - vis.visit_fn_decl(decl); -} - -pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { - let UseTree { prefix, kind, span } = use_tree; - vis.visit_path(prefix); - match kind { - UseTreeKind::Simple(rename, id1, id2) => { - visit_opt(rename, |rename| vis.visit_ident(rename)); - vis.visit_id(id1); - vis.visit_id(id2); - } - UseTreeKind::Nested(items) => { - for (tree, id) in items { - vis.visit_use_tree(tree); - vis.visit_id(id); - } - } - UseTreeKind::Glob => {} - } - vis.visit_span(span); -} - -pub fn noop_visit_arm( - Arm { attrs, pats, guard, body, span }: &mut Arm, - vis: &mut T, -) { - visit_attrs(attrs, vis); - visit_vec(pats, |pat| vis.visit_pat(pat)); - visit_opt(guard, |guard| vis.visit_expr(guard)); - vis.visit_expr(body); - vis.visit_span(span); -} - -pub fn noop_visit_ty_constraint( - AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint, - vis: &mut T -) { - vis.visit_id(id); - vis.visit_ident(ident); - match kind { - AssocTyConstraintKind::Equality { ref mut ty } => { - vis.visit_ty(ty); - } - AssocTyConstraintKind::Bound { ref mut bounds } => { - visit_bounds(bounds, vis); - } - } - vis.visit_span(span); -} - -pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { - let Ty { id, node, span } = ty.deref_mut(); - vis.visit_id(id); - match node { - TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | - TyKind::Never | TyKind::CVarArgs => {} - TyKind::Slice(ty) => vis.visit_ty(ty), - TyKind::Ptr(mt) => vis.visit_mt(mt), - TyKind::Rptr(lt, mt) => { - visit_opt(lt, |lt| noop_visit_lifetime(lt, vis)); - vis.visit_mt(mt); - } - TyKind::BareFn(bft) => { - let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut(); - vis.visit_generic_params(generic_params); - vis.visit_fn_decl(decl); - } - TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), - TyKind::Paren(ty) => vis.visit_ty(ty), - TyKind::Path(qself, path) => { - vis.visit_qself(qself); - vis.visit_path(path); - } - TyKind::Array(ty, length) => { - vis.visit_ty(ty); - vis.visit_anon_const(length); - } - TyKind::Typeof(expr) => vis.visit_anon_const(expr), - TyKind::TraitObject(bounds, _syntax) => - visit_vec(bounds, |bound| vis.visit_param_bound(bound)), - TyKind::ImplTrait(id, bounds) => { - vis.visit_id(id); - visit_vec(bounds, |bound| vis.visit_param_bound(bound)); - } - TyKind::Mac(mac) => vis.visit_mac(mac), - } - vis.visit_span(span); -} - -pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: &mut T) { - let ForeignMod { abi: _, items} = foreign_mod; - items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); -} - -pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; - vis.visit_ident(ident); - visit_attrs(attrs, vis); - vis.visit_id(id); - vis.visit_variant_data(data); - visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); - vis.visit_span(span); -} - -pub fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mut T) { - vis.visit_span(span); -} - -pub fn noop_visit_path(Path { segments, span }: &mut Path, vis: &mut T) { - vis.visit_span(span); - for PathSegment { ident, id, args } in segments { - vis.visit_ident(ident); - vis.visit_id(id); - visit_opt(args, |args| vis.visit_generic_args(args)); - } -} - -pub fn noop_visit_qself(qself: &mut Option, vis: &mut T) { - visit_opt(qself, |QSelf { ty, path_span, position: _ }| { - vis.visit_ty(ty); - vis.visit_span(path_span); - }) -} - -pub fn noop_visit_generic_args(generic_args: &mut GenericArgs, vis: &mut T) { - match generic_args { - GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data), - GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data), - } -} - -pub fn noop_visit_generic_arg(arg: &mut GenericArg, vis: &mut T) { - match arg { - GenericArg::Lifetime(lt) => vis.visit_lifetime(lt), - GenericArg::Type(ty) => vis.visit_ty(ty), - GenericArg::Const(ct) => vis.visit_anon_const(ct), - } -} - -pub fn noop_visit_angle_bracketed_parameter_data(data: &mut AngleBracketedArgs, - vis: &mut T) { - let AngleBracketedArgs { args, constraints, span } = data; - visit_vec(args, |arg| vis.visit_generic_arg(arg)); - visit_vec(constraints, |constraint| vis.visit_ty_constraint(constraint)); - vis.visit_span(span); -} - -pub fn noop_visit_parenthesized_parameter_data(args: &mut ParenthesizedArgs, - vis: &mut T) { - let ParenthesizedArgs { inputs, output, span } = args; - visit_vec(inputs, |input| vis.visit_ty(input)); - visit_opt(output, |output| vis.visit_ty(output)); - vis.visit_span(span); -} - -pub fn noop_visit_local(local: &mut P, vis: &mut T) { - let Local { id, pat, ty, init, span, attrs } = local.deref_mut(); - vis.visit_id(id); - vis.visit_pat(pat); - visit_opt(ty, |ty| vis.visit_ty(ty)); - visit_opt(init, |init| vis.visit_expr(init)); - vis.visit_span(span); - visit_thin_attrs(attrs, vis); -} - -pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { - let Attribute { id: _, style: _, path, tokens, is_sugared_doc: _, span } = attr; - vis.visit_path(path); - vis.visit_tts(tokens); - vis.visit_span(span); -} - -pub fn noop_visit_mac(Spanned { node, span }: &mut Mac, vis: &mut T) { - let Mac_ { path, delim: _, tts } = node; - vis.visit_path(path); - vis.visit_tts(tts); - vis.visit_span(span); -} - -pub fn noop_visit_macro_def(macro_def: &mut MacroDef, vis: &mut T) { - let MacroDef { tokens, legacy: _ } = macro_def; - vis.visit_tts(tokens); -} - -pub fn noop_visit_meta_list_item(li: &mut NestedMetaItem, vis: &mut T) { - match li { - NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi), - NestedMetaItem::Literal(_lit) => {} - } -} - -pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { - let MetaItem { path: _, node, span } = mi; - match node { - MetaItemKind::Word => {} - MetaItemKind::List(mis) => visit_vec(mis, |mi| vis.visit_meta_list_item(mi)), - MetaItemKind::NameValue(_s) => {} - } - vis.visit_span(span); -} - -pub fn noop_visit_arg(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) { - vis.visit_id(id); - visit_thin_attrs(attrs, vis); - vis.visit_pat(pat); - vis.visit_ty(ty); -} - -pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { - match tt { - TokenTree::Token(token) => { - vis.visit_token(token); - } - TokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => { - vis.visit_span(open); - vis.visit_span(close); - vis.visit_tts(tts); - } - } -} - -pub fn noop_visit_tts(TokenStream(tts): &mut TokenStream, vis: &mut T) { - visit_opt(tts, |tts| { - let tts = Lrc::make_mut(tts); - visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree)); - }) -} - -// Apply ident visitor if it's an ident, apply other visits to interpolated nodes. -// In practice the ident part is not actually used by specific visitors right now, -// but there's a test below checking that it works. -pub fn noop_visit_token(t: &mut Token, vis: &mut T) { - let Token { kind, span } = t; - match kind { - token::Ident(name, _) | token::Lifetime(name) => { - let mut ident = Ident::new(*name, *span); - vis.visit_ident(&mut ident); - *name = ident.name; - *span = ident.span; - return; // avoid visiting the span for the second time - } - token::Interpolated(nt) => { - let mut nt = Lrc::make_mut(nt); - vis.visit_interpolated(&mut nt); - } - _ => {} - } - vis.visit_span(span); -} - -/// Apply visitor to elements of interpolated nodes. -// -// N.B., this can occur only when applying a visitor to partially expanded -// code, where parsed pieces have gotten implanted ito *other* macro -// invocations. This is relevant for macro hygiene, but possibly not elsewhere. -// -// One problem here occurs because the types for flat_map_item, flat_map_stmt, -// etc. allow the visitor to return *multiple* items; this is a problem for the -// nodes here, because they insist on having exactly one piece. One solution -// would be to mangle the MutVisitor trait to include one-to-many and -// one-to-one versions of these entry points, but that would probably confuse a -// lot of people and help very few. Instead, I'm just going to put in dynamic -// checks. I think the performance impact of this will be pretty much -// nonexistent. The danger is that someone will apply a MutVisitor to a -// partially expanded node, and will be confused by the fact that their -// "flat_map_item" or "flat_map_stmt" isn't getting called on NtItem or NtStmt -// nodes. Hopefully they'll wind up reading this comment, and doing something -// appropriate. -// -// BTW, design choice: I considered just changing the type of, e.g., NtItem to -// contain multiple items, but decided against it when I looked at -// parse_item_or_view_item and tried to figure out what I would do with -// multiple items there.... -pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: &mut T) { - match nt { - token::NtItem(item) => - visit_clobber(item, |item| { - // This is probably okay, because the only visitors likely to - // peek inside interpolated nodes will be renamings/markings, - // which map single items to single items. - vis.flat_map_item(item).expect_one("expected visitor to produce exactly one item") - }), - token::NtBlock(block) => vis.visit_block(block), - token::NtStmt(stmt) => - visit_clobber(stmt, |stmt| { - // See reasoning above. - vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") - }), - token::NtPat(pat) => vis.visit_pat(pat), - token::NtExpr(expr) => vis.visit_expr(expr), - token::NtTy(ty) => vis.visit_ty(ty), - token::NtIdent(ident, _is_raw) => vis.visit_ident(ident), - token::NtLifetime(ident) => vis.visit_ident(ident), - token::NtLiteral(expr) => vis.visit_expr(expr), - token::NtMeta(meta) => vis.visit_meta_item(meta), - token::NtPath(path) => vis.visit_path(path), - token::NtTT(tt) => vis.visit_tt(tt), - token::NtImplItem(item) => - visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_impl_item(item) - .expect_one("expected visitor to produce exactly one item") - }), - token::NtTraitItem(item) => - visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_trait_item(item) - .expect_one("expected visitor to produce exactly one item") - }), - token::NtVis(visib) => vis.visit_vis(visib), - token::NtForeignItem(item) => - visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_foreign_item(item) - .expect_one("expected visitor to produce exactly one item") - }), - } -} - -pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) { - match asyncness { - IsAsync::Async { closure_id, return_impl_trait_id } => { - vis.visit_id(closure_id); - vis.visit_id(return_impl_trait_id); - } - IsAsync::NotAsync => {} - } -} - -pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { - let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut(); - visit_vec(inputs, |input| vis.visit_arg(input)); - match output { - FunctionRetTy::Default(span) => vis.visit_span(span), - FunctionRetTy::Ty(ty) => vis.visit_ty(ty), - } -} - -pub fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) { - match pb { - GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty), - GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis), - } -} - -pub fn noop_visit_generic_param(param: &mut GenericParam, vis: &mut T) { - let GenericParam { id, ident, attrs, bounds, kind } = param; - vis.visit_id(id); - vis.visit_ident(ident); - visit_thin_attrs(attrs, vis); - visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); - match kind { - GenericParamKind::Lifetime => {} - GenericParamKind::Type { default } => { - visit_opt(default, |default| vis.visit_ty(default)); - } - GenericParamKind::Const { ty } => { - vis.visit_ty(ty); - } - } -} - -pub fn noop_visit_generic_params(params: &mut Vec, vis: &mut T){ - visit_vec(params, |param| vis.visit_generic_param(param)); -} - -pub fn noop_visit_label(Label { ident }: &mut Label, vis: &mut T) { - vis.visit_ident(ident); -} - -fn noop_visit_lifetime(Lifetime { id, ident }: &mut Lifetime, vis: &mut T) { - vis.visit_id(id); - vis.visit_ident(ident); -} - -pub fn noop_visit_generics(generics: &mut Generics, vis: &mut T) { - let Generics { params, where_clause, span } = generics; - vis.visit_generic_params(params); - vis.visit_where_clause(where_clause); - vis.visit_span(span); -} - -pub fn noop_visit_where_clause(wc: &mut WhereClause, vis: &mut T) { - let WhereClause { predicates, span } = wc; - visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate)); - vis.visit_span(span); -} - -pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: &mut T) { - match pred { - WherePredicate::BoundPredicate(bp) => { - let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp; - vis.visit_span(span); - vis.visit_generic_params(bound_generic_params); - vis.visit_ty(bounded_ty); - visit_vec(bounds, |bound| vis.visit_param_bound(bound)); - } - WherePredicate::RegionPredicate(rp) => { - let WhereRegionPredicate { span, lifetime, bounds } = rp; - vis.visit_span(span); - noop_visit_lifetime(lifetime, vis); - visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); - } - WherePredicate::EqPredicate(ep) => { - let WhereEqPredicate { id, span, lhs_ty, rhs_ty } = ep; - vis.visit_id(id); - vis.visit_span(span); - vis.visit_ty(lhs_ty); - vis.visit_ty(rhs_ty); - } - } -} - -pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { - match vdata { - VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), - VariantData::Tuple(fields, id) => { - visit_vec(fields, |field| vis.visit_struct_field(field)); - vis.visit_id(id); - }, - VariantData::Unit(id) => vis.visit_id(id), - } -} - -pub fn noop_visit_trait_ref(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) { - vis.visit_path(path); - vis.visit_id(ref_id); -} - -pub fn noop_visit_poly_trait_ref(p: &mut PolyTraitRef, vis: &mut T) { - let PolyTraitRef { bound_generic_params, trait_ref, span } = p; - vis.visit_generic_params(bound_generic_params); - vis.visit_trait_ref(trait_ref); - vis.visit_span(span); -} - -pub fn noop_visit_struct_field(f: &mut StructField, visitor: &mut T) { - let StructField { span, ident, vis, id, ty, attrs } = f; - visitor.visit_span(span); - visit_opt(ident, |ident| visitor.visit_ident(ident)); - visitor.visit_vis(vis); - visitor.visit_id(id); - visitor.visit_ty(ty); - visit_attrs(attrs, visitor); -} - -pub fn noop_visit_field(f: &mut Field, vis: &mut T) { - let Field { ident, expr, span, is_shorthand: _, attrs } = f; - vis.visit_ident(ident); - vis.visit_expr(expr); - vis.visit_span(span); - visit_thin_attrs(attrs, vis); -} - -pub fn noop_visit_mt(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) { - vis.visit_ty(ty); -} - -pub fn noop_visit_block(block: &mut P, vis: &mut T) { - let Block { id, stmts, rules: _, span } = block.deref_mut(); - vis.visit_id(id); - stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt)); - vis.visit_span(span); -} - -pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { - match kind { - ItemKind::ExternCrate(_orig_name) => {} - ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(ty, _mut, expr) => { - vis.visit_ty(ty); - vis.visit_expr(expr); - } - ItemKind::Const(ty, expr) => { - vis.visit_ty(ty); - vis.visit_expr(expr); - } - ItemKind::Fn(decl, header, generics, body) => { - vis.visit_fn_decl(decl); - vis.visit_fn_header(header); - vis.visit_generics(generics); - vis.visit_block(body); - } - ItemKind::Mod(m) => vis.visit_mod(m), - ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), - ItemKind::GlobalAsm(_ga) => {} - ItemKind::Ty(ty, generics) => { - vis.visit_ty(ty); - vis.visit_generics(generics); - } - ItemKind::Existential(bounds, generics) => { - visit_bounds(bounds, vis); - vis.visit_generics(generics); - } - ItemKind::Enum(EnumDef { variants }, generics) => { - visit_vec(variants, |variant| vis.visit_variant(variant)); - vis.visit_generics(generics); - } - ItemKind::Struct(variant_data, generics) | - ItemKind::Union(variant_data, generics) => { - vis.visit_variant_data(variant_data); - vis.visit_generics(generics); - } - ItemKind::Impl(_unsafety, _polarity, _defaultness, generics, trait_ref, ty, items) => { - vis.visit_generics(generics); - visit_opt(trait_ref, |trait_ref| vis.visit_trait_ref(trait_ref)); - vis.visit_ty(ty); - items.flat_map_in_place(|item| vis.flat_map_impl_item(item)); - } - ItemKind::Trait(_is_auto, _unsafety, generics, bounds, items) => { - vis.visit_generics(generics); - visit_bounds(bounds, vis); - items.flat_map_in_place(|item| vis.flat_map_trait_item(item)); - } - ItemKind::TraitAlias(generics, bounds) => { - vis.visit_generics(generics); - visit_bounds(bounds, vis); - } - ItemKind::Mac(m) => vis.visit_mac(m), - ItemKind::MacroDef(def) => vis.visit_macro_def(def), - } -} - -pub fn noop_flat_map_trait_item(mut item: TraitItem, vis: &mut T) - -> SmallVec<[TraitItem; 1]> -{ - let TraitItem { id, ident, attrs, generics, node, span, tokens: _ } = &mut item; - vis.visit_id(id); - vis.visit_ident(ident); - visit_attrs(attrs, vis); - vis.visit_generics(generics); - match node { - TraitItemKind::Const(ty, default) => { - vis.visit_ty(ty); - visit_opt(default, |default| vis.visit_expr(default)); - } - TraitItemKind::Method(sig, body) => { - visit_method_sig(sig, vis); - visit_opt(body, |body| vis.visit_block(body)); - } - TraitItemKind::Type(bounds, default) => { - visit_bounds(bounds, vis); - visit_opt(default, |default| vis.visit_ty(default)); - } - TraitItemKind::Macro(mac) => { - vis.visit_mac(mac); - } - } - vis.visit_span(span); - - smallvec![item] -} - -pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut T) - -> SmallVec<[ImplItem; 1]> -{ - let ImplItem { id, ident, vis, defaultness: _, attrs, generics, node, span, tokens: _ } = - &mut item; - visitor.visit_id(id); - visitor.visit_ident(ident); - visitor.visit_vis(vis); - visit_attrs(attrs, visitor); - visitor.visit_generics(generics); - match node { - ImplItemKind::Const(ty, expr) => { - visitor.visit_ty(ty); - visitor.visit_expr(expr); - } - ImplItemKind::Method(sig, body) => { - visit_method_sig(sig, visitor); - visitor.visit_block(body); - } - ImplItemKind::Type(ty) => visitor.visit_ty(ty), - ImplItemKind::Existential(bounds) => visit_bounds(bounds, visitor), - ImplItemKind::Macro(mac) => visitor.visit_mac(mac), - } - visitor.visit_span(span); - - smallvec![item] -} - -pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header; - vis.visit_asyncness(&mut asyncness.node); -} - -pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) { - vis.visit_span(inner); - items.flat_map_in_place(|item| vis.flat_map_item(item)); -} - -pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { - visit_clobber(krate, |Crate { module, attrs, span }| { - let item = P(Item { - ident: Ident::invalid(), - attrs, - id: DUMMY_NODE_ID, - vis: respan(span.shrink_to_lo(), VisibilityKind::Public), - span, - node: ItemKind::Mod(module), - tokens: None, - }); - let items = vis.flat_map_item(item); - - let len = items.len(); - if len == 0 { - let module = Mod { inner: span, items: vec![], inline: true }; - Crate { module, attrs: vec![], span } - } else if len == 1 { - let Item { attrs, span, node, .. } = items.into_iter().next().unwrap().into_inner(); - match node { - ItemKind::Mod(module) => Crate { module, attrs, span }, - _ => panic!("visitor converted a module to not a module"), - } - } else { - panic!("a crate cannot expand to more than one item"); - } - }); -} - -// Mutate one item into possibly many items. -pub fn noop_flat_map_item(mut item: P, visitor: &mut T) - -> SmallVec<[P; 1]> { - let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut(); - visitor.visit_ident(ident); - visit_attrs(attrs, visitor); - visitor.visit_id(id); - visitor.visit_item_kind(node); - visitor.visit_vis(vis); - visitor.visit_span(span); - - // FIXME: if `tokens` is modified with a call to `vis.visit_tts` it causes - // an ICE during resolve... odd! - - smallvec![item] -} - -pub fn noop_flat_map_foreign_item(mut item: ForeignItem, visitor: &mut T) - -> SmallVec<[ForeignItem; 1]> -{ - let ForeignItem { ident, attrs, node, id, span, vis } = &mut item; - visitor.visit_ident(ident); - visit_attrs(attrs, visitor); - match node { - ForeignItemKind::Fn(fdec, generics) => { - visitor.visit_fn_decl(fdec); - visitor.visit_generics(generics); - } - ForeignItemKind::Static(t, _m) => visitor.visit_ty(t), - ForeignItemKind::Ty => {} - ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), - } - visitor.visit_id(id); - visitor.visit_span(span); - visitor.visit_vis(vis); - - smallvec![item] -} - -pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { - let Pat { id, node, span } = pat.deref_mut(); - vis.visit_id(id); - match node { - PatKind::Wild => {} - PatKind::Ident(_binding_mode, ident, sub) => { - vis.visit_ident(ident); - visit_opt(sub, |sub| vis.visit_pat(sub)); - } - PatKind::Lit(e) => vis.visit_expr(e), - PatKind::TupleStruct(path, pats, _ddpos) => { - vis.visit_path(path); - visit_vec(pats, |pat| vis.visit_pat(pat)); - } - PatKind::Path(qself, path) => { - vis.visit_qself(qself); - vis.visit_path(path); - } - PatKind::Struct(path, fields, _etc) => { - vis.visit_path(path); - for Spanned { node: FieldPat { ident, pat, is_shorthand: _, attrs }, span } in fields { - vis.visit_ident(ident); - vis.visit_pat(pat); - visit_thin_attrs(attrs, vis); - vis.visit_span(span); - }; - } - PatKind::Tuple(elts, _ddpos) => visit_vec(elts, |elt| vis.visit_pat(elt)), - PatKind::Box(inner) => vis.visit_pat(inner), - PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), - PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { - vis.visit_expr(e1); - vis.visit_expr(e2); - vis.visit_span(span); - } - PatKind::Slice(before, slice, after) => { - visit_vec(before, |pat| vis.visit_pat(pat)); - visit_opt(slice, |slice| vis.visit_pat(slice)); - visit_vec(after, |pat| vis.visit_pat(pat)); - } - PatKind::Paren(inner) => vis.visit_pat(inner), - PatKind::Mac(mac) => vis.visit_mac(mac), - } - vis.visit_span(span); -} - -pub fn noop_visit_anon_const(AnonConst { id, value }: &mut AnonConst, vis: &mut T) { - vis.visit_id(id); - vis.visit_expr(value); -} - -pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, vis: &mut T) { - match node { - ExprKind::Box(expr) => vis.visit_expr(expr), - ExprKind::Array(exprs) => visit_exprs(exprs, vis), - ExprKind::Repeat(expr, count) => { - vis.visit_expr(expr); - vis.visit_anon_const(count); - } - ExprKind::Tup(exprs) => visit_exprs(exprs, vis), - ExprKind::Call(f, args) => { - vis.visit_expr(f); - visit_exprs(args, vis); - } - ExprKind::MethodCall(PathSegment { ident, id, args }, exprs) => { - vis.visit_ident(ident); - vis.visit_id(id); - visit_opt(args, |args| vis.visit_generic_args(args)); - visit_exprs(exprs, vis); - } - ExprKind::Binary(_binop, lhs, rhs) => { - vis.visit_expr(lhs); - vis.visit_expr(rhs); - } - ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs), - ExprKind::Cast(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::Type(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::AddrOf(_m, ohs) => vis.visit_expr(ohs), - ExprKind::Let(pats, scrutinee) => { - visit_vec(pats, |pat| vis.visit_pat(pat)); - vis.visit_expr(scrutinee); - } - ExprKind::If(cond, tr, fl) => { - vis.visit_expr(cond); - vis.visit_block(tr); - visit_opt(fl, |fl| vis.visit_expr(fl)); - } - ExprKind::While(cond, body, label) => { - vis.visit_expr(cond); - vis.visit_block(body); - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::ForLoop(pat, iter, body, label) => { - vis.visit_pat(pat); - vis.visit_expr(iter); - vis.visit_block(body); - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Loop(body, label) => { - vis.visit_block(body); - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Match(expr, arms) => { - vis.visit_expr(expr); - visit_vec(arms, |arm| vis.visit_arm(arm)); - } - ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => { - vis.visit_asyncness(asyncness); - vis.visit_fn_decl(decl); - vis.visit_expr(body); - vis.visit_span(span); - } - ExprKind::Block(blk, label) => { - vis.visit_block(blk); - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Async(_capture_by, node_id, body) => { - vis.visit_id(node_id); - vis.visit_block(body); - } - ExprKind::Await(_origin, expr) => vis.visit_expr(expr), - ExprKind::Assign(el, er) => { - vis.visit_expr(el); - vis.visit_expr(er); - } - ExprKind::AssignOp(_op, el, er) => { - vis.visit_expr(el); - vis.visit_expr(er); - } - ExprKind::Field(el, ident) => { - vis.visit_expr(el); - vis.visit_ident(ident); - } - ExprKind::Index(el, er) => { - vis.visit_expr(el); - vis.visit_expr(er); - } - ExprKind::Range(e1, e2, _lim) => { - visit_opt(e1, |e1| vis.visit_expr(e1)); - visit_opt(e2, |e2| vis.visit_expr(e2)); - } - ExprKind::Path(qself, path) => { - vis.visit_qself(qself); - vis.visit_path(path); - } - ExprKind::Break(label, expr) => { - visit_opt(label, |label| vis.visit_label(label)); - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Continue(label) => { - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Ret(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::InlineAsm(asm) => { - let InlineAsm { asm: _, asm_str_style: _, outputs, inputs, clobbers: _, volatile: _, - alignstack: _, dialect: _, ctxt: _ } = asm.deref_mut(); - for out in outputs { - let InlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out; - vis.visit_expr(expr); - } - visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr)); - } - ExprKind::Mac(mac) => vis.visit_mac(mac), - ExprKind::Struct(path, fields, expr) => { - vis.visit_path(path); - visit_vec(fields, |field| vis.visit_field(field)); - visit_opt(expr, |expr| vis.visit_expr(expr)); - }, - ExprKind::Paren(expr) => { - vis.visit_expr(expr); - - // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids. - *id = expr.id; - vis.visit_span(span); - visit_thin_attrs(attrs, vis); - return; - } - ExprKind::Yield(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Try(expr) => vis.visit_expr(expr), - ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_) | ExprKind::Err => {} - } - vis.visit_id(id); - vis.visit_span(span); - visit_thin_attrs(attrs, vis); -} - -pub fn noop_filter_map_expr(mut e: P, vis: &mut T) -> Option> { - Some({ vis.visit_expr(&mut e); e }) -} - -pub fn noop_flat_map_stmt(Stmt { node, mut span, mut id }: Stmt, vis: &mut T) - -> SmallVec<[Stmt; 1]> -{ - vis.visit_id(&mut id); - vis.visit_span(&mut span); - noop_flat_map_stmt_kind(node, vis).into_iter().map(|node| { - Stmt { id, node, span } - }).collect() -} - -pub fn noop_flat_map_stmt_kind(node: StmtKind, vis: &mut T) - -> SmallVec<[StmtKind; 1]> { - match node { - StmtKind::Local(mut local) => - smallvec![StmtKind::Local({ vis.visit_local(&mut local); local })], - StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(), - StmtKind::Expr(expr) => { - vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect() - } - StmtKind::Semi(expr) => { - vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect() - } - StmtKind::Mac(mut mac) => { - let (mac_, _semi, attrs) = mac.deref_mut(); - vis.visit_mac(mac_); - visit_thin_attrs(attrs, vis); - smallvec![StmtKind::Mac(mac)] - } - } -} - -pub fn noop_visit_vis(Spanned { node, span }: &mut Visibility, vis: &mut T) { - match node { - VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} - VisibilityKind::Restricted { path, id } => { - vis.visit_path(path); - vis.visit_id(id); - } - } - vis.visit_span(span); -} - -#[cfg(test)] -mod tests { - use crate::ast::{self, Ident}; - use crate::util::parser_testing::{string_to_crate, matches_codepattern}; - use crate::print::pprust; - use crate::mut_visit; - use crate::with_default_globals; - use super::*; - - // this version doesn't care about getting comments or docstrings in. - fn fake_print_crate(s: &mut pprust::State<'_>, - krate: &ast::Crate) { - s.print_mod(&krate.module, &krate.attrs) - } - - // change every identifier to "zz" - struct ToZzIdentMutVisitor; - - impl MutVisitor for ToZzIdentMutVisitor { - fn visit_ident(&mut self, ident: &mut ast::Ident) { - *ident = Ident::from_str("zz"); - } - fn visit_mac(&mut self, mac: &mut ast::Mac) { - mut_visit::noop_visit_mac(mac, self) - } - } - - // maybe add to expand.rs... - macro_rules! assert_pred { - ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( - { - let pred_val = $pred; - let a_val = $a; - let b_val = $b; - if !(pred_val(&a_val, &b_val)) { - panic!("expected args satisfying {}, got {} and {}", - $predname, a_val, b_val); - } - } - ) - } - - // make sure idents get transformed everywhere - #[test] fn ident_transformation () { - with_default_globals(|| { - let mut zz_visitor = ToZzIdentMutVisitor; - let mut krate = string_to_crate( - "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string()); - zz_visitor.visit_crate(&mut krate); - assert_pred!( - matches_codepattern, - "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &krate)), - "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()); - }) - } - - // even inside macro defs.... - #[test] fn ident_transformation_in_defs () { - with_default_globals(|| { - let mut zz_visitor = ToZzIdentMutVisitor; - let mut krate = string_to_crate( - "macro_rules! a {(b $c:expr $(d $e:token)f+ => \ - (g $(d $d $e)+))} ".to_string()); - zz_visitor.visit_crate(&mut krate); - assert_pred!( - matches_codepattern, - "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &krate)), - "macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); - }) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/attr.rs b/gcc/rust/rustc_parser/libsyntax/parse/attr.rs deleted file mode 100644 index b28d48b..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/attr.rs +++ /dev/null @@ -1,305 +0,0 @@ -use crate::attr; -use crate::ast; -use crate::parse::{SeqSep, PResult}; -use crate::parse::token::{self, Nonterminal, DelimToken}; -use crate::parse::parser::{Parser, TokenType, PathStyle}; -use crate::tokenstream::{TokenStream, TokenTree}; - -use log::debug; -use smallvec::smallvec; - -#[derive(Debug)] -enum InnerAttributeParsePolicy<'a> { - Permitted, - NotPermitted { reason: &'a str }, -} - -const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ - permitted in this context"; - -impl<'a> Parser<'a> { - crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec> { - let attrs = self.parse_outer_attributes()?; - attrs.iter().for_each(|a| - self.sess.param_attr_spans.borrow_mut().push(a.span) - ); - Ok(attrs) - } - - /// Parse attributes that appear before an item - crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { - let mut attrs: Vec = Vec::new(); - let mut just_parsed_doc_comment = false; - loop { - debug!("parse_outer_attributes: self.token={:?}", self.token); - match self.token.kind { - token::Pound => { - let inner_error_reason = if just_parsed_doc_comment { - "an inner attribute is not permitted following an outer doc comment" - } else if !attrs.is_empty() { - "an inner attribute is not permitted following an outer attribute" - } else { - DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG - }; - let inner_parse_policy = - InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason }; - let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?; - attrs.push(attr); - just_parsed_doc_comment = false; - } - token::DocComment(s) => { - let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.token.span); - if attr.style != ast::AttrStyle::Outer { - let mut err = self.fatal("expected outer doc comment"); - err.note("inner doc comments like this (starting with \ - `//!` or `/*!`) can only appear before items"); - return Err(err); - } - attrs.push(attr); - self.bump(); - just_parsed_doc_comment = true; - } - _ => break, - } - } - Ok(attrs) - } - - /// Matches `attribute = # ! [ meta_item ]` - /// - /// If permit_inner is true, then a leading `!` indicates an inner - /// attribute - pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { - debug!("parse_attribute: permit_inner={:?} self.token={:?}", - permit_inner, - self.token); - let inner_parse_policy = if permit_inner { - InnerAttributeParsePolicy::Permitted - } else { - InnerAttributeParsePolicy::NotPermitted - { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG } - }; - self.parse_attribute_with_inner_parse_policy(inner_parse_policy) - } - - /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy` - /// that prescribes how to handle inner attributes. - fn parse_attribute_with_inner_parse_policy(&mut self, - inner_parse_policy: InnerAttributeParsePolicy<'_>) - -> PResult<'a, ast::Attribute> { - debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", - inner_parse_policy, - self.token); - let (span, path, tokens, style) = match self.token.kind { - token::Pound => { - let lo = self.token.span; - self.bump(); - - if let InnerAttributeParsePolicy::Permitted = inner_parse_policy { - self.expected_tokens.push(TokenType::Token(token::Not)); - } - let style = if self.token == token::Not { - self.bump(); - if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy - { - let span = self.token.span; - self.diagnostic() - .struct_span_err(span, reason) - .note("inner attributes, like `#![no_std]`, annotate the item \ - enclosing them, and are usually found at the beginning of \ - source files. Outer attributes, like `#[test]`, annotate the \ - item following them.") - .emit() - } - ast::AttrStyle::Inner - } else { - ast::AttrStyle::Outer - }; - - self.expect(&token::OpenDelim(token::Bracket))?; - let (path, tokens) = self.parse_meta_item_unrestricted()?; - self.expect(&token::CloseDelim(token::Bracket))?; - let hi = self.prev_span; - - (lo.to(hi), path, tokens, style) - } - _ => { - let token_str = self.this_token_to_string(); - return Err(self.fatal(&format!("expected `#`, found `{}`", token_str))); - } - }; - - Ok(ast::Attribute { - id: attr::mk_attr_id(), - style, - path, - tokens, - is_sugared_doc: false, - span, - }) - } - - /// Parse an inner part of attribute - path and following tokens. - /// The tokens must be either a delimited token stream, or empty token stream, - /// or the "legacy" key-value form. - /// PATH `(` TOKEN_STREAM `)` - /// PATH `[` TOKEN_STREAM `]` - /// PATH `{` TOKEN_STREAM `}` - /// PATH - /// PATH `=` TOKEN_TREE - /// The delimiters or `=` are still put into the resulting token stream. - crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { - let meta = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - Nonterminal::NtMeta(ref meta) => Some(meta.clone()), - _ => None, - }, - _ => None, - }; - Ok(if let Some(meta) = meta { - self.bump(); - (meta.path, meta.node.tokens(meta.span)) - } else { - let path = self.parse_path(PathStyle::Mod)?; - let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) || - self.check(&token::OpenDelim(DelimToken::Bracket)) || - self.check(&token::OpenDelim(DelimToken::Brace)) { - self.parse_token_tree().into() - } else if self.eat(&token::Eq) { - let eq = TokenTree::token(token::Eq, self.prev_span); - let mut is_interpolated_expr = false; - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtExpr(..) = **nt { - is_interpolated_expr = true; - } - } - let tokens = if is_interpolated_expr { - // We need to accept arbitrary interpolated expressions to continue - // supporting things like `doc = $expr` that work on stable. - // Non-literal interpolated expressions are rejected after expansion. - self.parse_token_tree().into() - } else { - self.parse_unsuffixed_lit()?.tokens() - }; - TokenStream::from_streams(smallvec![eq.into(), tokens]) - } else { - TokenStream::empty() - }; - (path, tokens) - }) - } - - /// Parse attributes that appear after the opening of an item. These should - /// be preceded by an exclamation mark, but we accept and warn about one - /// terminated by a semicolon. - - /// matches inner_attrs* - crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { - let mut attrs: Vec = vec![]; - loop { - match self.token.kind { - token::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !self.look_ahead(1, |t| t == &token::Not) { - break; - } - - let attr = self.parse_attribute(true)?; - assert_eq!(attr.style, ast::AttrStyle::Inner); - attrs.push(attr); - } - token::DocComment(s) => { - // we need to get the position of this token before we bump. - let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.token.span); - if attr.style == ast::AttrStyle::Inner { - attrs.push(attr); - self.bump(); - } else { - break; - } - } - _ => break, - } - } - Ok(attrs) - } - - fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> { - let lit = self.parse_lit()?; - debug!("Checking if {:?} is unusuffixed.", lit); - - if !lit.node.is_unsuffixed() { - let msg = "suffixed literals are not allowed in attributes"; - self.diagnostic().struct_span_err(lit.span, msg) - .help("instead of using a suffixed literal \ - (1u8, 1.0f32, etc.), use an unsuffixed version \ - (1, 1.0, etc.).") - .emit() - } - - Ok(lit) - } - - /// Per RFC#1559, matches the following grammar: - /// - /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; - /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; - pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { - let nt_meta = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtMeta(ref e) => Some(e.clone()), - _ => None, - }, - _ => None, - }; - - if let Some(meta) = nt_meta { - self.bump(); - return Ok(meta); - } - - let lo = self.token.span; - let path = self.parse_path(PathStyle::Mod)?; - let node = self.parse_meta_item_kind()?; - let span = lo.to(self.prev_span); - Ok(ast::MetaItem { path, node, span }) - } - - crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { - Ok(if self.eat(&token::Eq) { - ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?) - } else if self.eat(&token::OpenDelim(token::Paren)) { - ast::MetaItemKind::List(self.parse_meta_seq()?) - } else { - ast::MetaItemKind::Word - }) - } - - /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ; - fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { - match self.parse_unsuffixed_lit() { - Ok(lit) => { - return Ok(ast::NestedMetaItem::Literal(lit)) - } - Err(ref mut err) => self.diagnostic().cancel(err) - } - - match self.parse_meta_item() { - Ok(mi) => { - return Ok(ast::NestedMetaItem::MetaItem(mi)) - } - Err(ref mut err) => self.diagnostic().cancel(err) - } - - let found = self.this_token_to_string(); - let msg = format!("expected unsuffixed literal or identifier, found `{}`", found); - Err(self.diagnostic().struct_span_err(self.token.span, &msg)) - } - - /// matches meta_seq = ( COMMASEP(meta_item_inner) ) - fn parse_meta_seq(&mut self) -> PResult<'a, Vec> { - self.parse_seq_to_end(&token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p: &mut Parser<'a>| p.parse_meta_item_inner()) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/classify.rs b/gcc/rust/rustc_parser/libsyntax/parse/classify.rs deleted file mode 100644 index 6ebfab3..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/classify.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Routines the parser uses to classify AST nodes - -// Predicates on exprs and stmts that the pretty-printer and parser use - -use crate::ast; - -/// Does this expression require a semicolon to be treated -/// as a statement? The negation of this: 'can this expression -/// be used as a statement without a semicolon' -- is used -/// as an early-bail-out in the parser so that, for instance, -/// if true {...} else {...} -/// |x| 5 -/// isn't parsed as (if true {...} else {...} | x) | 5 -pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { - match e.node { - ast::ExprKind::If(..) | - ast::ExprKind::Match(..) | - ast::ExprKind::Block(..) | - ast::ExprKind::While(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::ForLoop(..) | - ast::ExprKind::TryBlock(..) => false, - _ => true, - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/diagnostics.rs b/gcc/rust/rustc_parser/libsyntax/parse/diagnostics.rs deleted file mode 100644 index edcdb18..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/diagnostics.rs +++ /dev/null @@ -1,1273 +0,0 @@ -use crate::ast::{ - self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, - Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, -}; -use crate::parse::{SeqSep, PResult, Parser, ParseSess}; -use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType}; -use crate::parse::token::{self, TokenKind}; -use crate::print::pprust; -use crate::ptr::P; -use crate::source_map::Spanned; -use crate::symbol::{kw, sym}; -use crate::ThinVec; -use crate::util::parser::AssocOp; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; -use rustc_data_structures::fx::FxHashSet; -use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -use log::{debug, trace}; - -/// Creates a placeholder argument. -crate fn dummy_arg(ident: Ident) -> Arg { - let pat = P(Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), - span: ident.span, - }); - let ty = Ty { - node: TyKind::Err, - span: ident.span, - id: ast::DUMMY_NODE_ID - }; - Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, ty: P(ty) } -} - -pub enum Error { - FileNotFoundForModule { - mod_name: String, - default_path: String, - secondary_path: String, - dir_path: String, - }, - DuplicatePaths { - mod_name: String, - default_path: String, - secondary_path: String, - }, - UselessDocComment, - InclusiveRangeWithNoEnd, -} - -impl Error { - fn span_err>( - self, - sp: S, - handler: &errors::Handler, - ) -> DiagnosticBuilder<'_> { - match self { - Error::FileNotFoundForModule { - ref mod_name, - ref default_path, - ref secondary_path, - ref dir_path, - } => { - let mut err = struct_span_err!( - handler, - sp, - E0583, - "file not found for module `{}`", - mod_name, - ); - err.help(&format!( - "name the file either {} or {} inside the directory \"{}\"", - default_path, - secondary_path, - dir_path, - )); - err - } - Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { - let mut err = struct_span_err!( - handler, - sp, - E0584, - "file for module `{}` found at both {} and {}", - mod_name, - default_path, - secondary_path, - ); - err.help("delete or rename one of them to remove the ambiguity"); - err - } - Error::UselessDocComment => { - let mut err = struct_span_err!( - handler, - sp, - E0585, - "found a documentation comment that doesn't document anything", - ); - err.help("doc comments must come before what they document, maybe a comment was \ - intended with `//`?"); - err - } - Error::InclusiveRangeWithNoEnd => { - let mut err = struct_span_err!( - handler, - sp, - E0586, - "inclusive range with no end", - ); - err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)"); - err - } - } - } -} - -pub trait RecoverQPath: Sized + 'static { - const PATH_STYLE: PathStyle = PathStyle::Expr; - fn to_ty(&self) -> Option>; - fn recovered(qself: Option, path: ast::Path) -> Self; -} - -impl RecoverQPath for Ty { - const PATH_STYLE: PathStyle = PathStyle::Type; - fn to_ty(&self) -> Option> { - Some(P(self.clone())) - } - fn recovered(qself: Option, path: ast::Path) -> Self { - Self { - span: path.span, - node: TyKind::Path(qself, path), - id: ast::DUMMY_NODE_ID, - } - } -} - -impl RecoverQPath for Pat { - fn to_ty(&self) -> Option> { - self.to_ty() - } - fn recovered(qself: Option, path: ast::Path) -> Self { - Self { - span: path.span, - node: PatKind::Path(qself, path), - id: ast::DUMMY_NODE_ID, - } - } -} - -impl RecoverQPath for Expr { - fn to_ty(&self) -> Option> { - self.to_ty() - } - fn recovered(qself: Option, path: ast::Path) -> Self { - Self { - span: path.span, - node: ExprKind::Path(qself, path), - attrs: ThinVec::new(), - id: ast::DUMMY_NODE_ID, - } - } -} - -impl<'a> Parser<'a> { - pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { - self.span_fatal(self.token.span, m) - } - - pub fn span_fatal>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { - self.sess.span_diagnostic.struct_span_fatal(sp, m) - } - - pub fn span_fatal_err>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { - err.span_err(sp, self.diagnostic()) - } - - pub fn bug(&self, m: &str) -> ! { - self.sess.span_diagnostic.span_bug(self.token.span, m) - } - - pub fn span_err>(&self, sp: S, m: &str) { - self.sess.span_diagnostic.span_err(sp, m) - } - - crate fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { - self.sess.span_diagnostic.struct_span_err(sp, m) - } - - crate fn span_bug>(&self, sp: S, m: &str) -> ! { - self.sess.span_diagnostic.span_bug(sp, m) - } - - crate fn cancel(&self, err: &mut DiagnosticBuilder<'_>) { - self.sess.span_diagnostic.cancel(err) - } - - crate fn diagnostic(&self) -> &'a errors::Handler { - &self.sess.span_diagnostic - } - - crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { - let mut err = self.struct_span_err( - self.token.span, - &format!("expected identifier, found {}", self.this_token_descr()), - ); - if let token::Ident(name, false) = self.token.kind { - if Ident::new(name, self.token.span).is_raw_guess() { - err.span_suggestion( - self.token.span, - "you can escape reserved keywords to use them as identifiers", - format!("r#{}", name), - Applicability::MaybeIncorrect, - ); - } - } - if let Some(token_descr) = self.token_descr() { - err.span_label(self.token.span, format!("expected identifier, found {}", token_descr)); - } else { - err.span_label(self.token.span, "expected identifier"); - if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) { - err.span_suggestion( - self.token.span, - "remove this comma", - String::new(), - Applicability::MachineApplicable, - ); - } - } - err - } - - pub fn expected_one_of_not_found( - &mut self, - edible: &[TokenKind], - inedible: &[TokenKind], - ) -> PResult<'a, bool /* recovered */> { - fn tokens_to_string(tokens: &[TokenType]) -> String { - let mut i = tokens.iter(); - // This might be a sign we need a connect method on Iterator. - let b = i.next() - .map_or(String::new(), |t| t.to_string()); - i.enumerate().fold(b, |mut b, (i, a)| { - if tokens.len() > 2 && i == tokens.len() - 2 { - b.push_str(", or "); - } else if tokens.len() == 2 && i == tokens.len() - 2 { - b.push_str(" or "); - } else { - b.push_str(", "); - } - b.push_str(&a.to_string()); - b - }) - } - - let mut expected = edible.iter() - .map(|x| TokenType::Token(x.clone())) - .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) - .chain(self.expected_tokens.iter().cloned()) - .collect::>(); - expected.sort_by_cached_key(|x| x.to_string()); - expected.dedup(); - let expect = tokens_to_string(&expected[..]); - let actual = self.this_token_to_string(); - let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { - let short_expect = if expected.len() > 6 { - format!("{} possible tokens", expected.len()) - } else { - expect.clone() - }; - (format!("expected one of {}, found `{}`", expect, actual), - (self.sess.source_map().next_point(self.prev_span), - format!("expected one of {} here", short_expect))) - } else if expected.is_empty() { - (format!("unexpected token: `{}`", actual), - (self.prev_span, "unexpected token after this".to_string())) - } else { - (format!("expected {}, found `{}`", expect, actual), - (self.sess.source_map().next_point(self.prev_span), - format!("expected {} here", expect))) - }; - self.last_unexpected_token_span = Some(self.token.span); - let mut err = self.fatal(&msg_exp); - if self.token.is_ident_named(sym::and) { - err.span_suggestion_short( - self.token.span, - "use `&&` instead of `and` for the boolean operator", - "&&".to_string(), - Applicability::MaybeIncorrect, - ); - } - if self.token.is_ident_named(sym::or) { - err.span_suggestion_short( - self.token.span, - "use `||` instead of `or` for the boolean operator", - "||".to_string(), - Applicability::MaybeIncorrect, - ); - } - let sp = if self.token == token::Eof { - // This is EOF, don't want to point at the following char, but rather the last token - self.prev_span - } else { - label_sp - }; - match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt { - TokenType::Token(t) => Some(t.clone()), - _ => None, - }).collect::>(), err) { - Err(e) => err = e, - Ok(recovered) => { - return Ok(recovered); - } - } - - let is_semi_suggestable = expected.iter().any(|t| match t { - TokenType::Token(token::Semi) => true, // we expect a `;` here - _ => false, - }) && ( // a `;` would be expected before the current keyword - self.token.is_keyword(kw::Break) || - self.token.is_keyword(kw::Continue) || - self.token.is_keyword(kw::For) || - self.token.is_keyword(kw::If) || - self.token.is_keyword(kw::Let) || - self.token.is_keyword(kw::Loop) || - self.token.is_keyword(kw::Match) || - self.token.is_keyword(kw::Return) || - self.token.is_keyword(kw::While) - ); - let cm = self.sess.source_map(); - match (cm.lookup_line(self.token.span.lo()), cm.lookup_line(sp.lo())) { - (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => { - // The spans are in different lines, expected `;` and found `let` or `return`. - // High likelihood that it is only a missing `;`. - err.span_suggestion_short( - label_sp, - "a semicolon may be missing here", - ";".to_string(), - Applicability::MaybeIncorrect, - ); - err.emit(); - return Ok(true); - } - (Ok(ref a), Ok(ref b)) if a.line == b.line => { - // When the spans are in the same line, it means that the only content between - // them is whitespace, point at the found token in that case: - // - // X | () => { syntax error }; - // | ^^^^^ expected one of 8 possible tokens here - // - // instead of having: - // - // X | () => { syntax error }; - // | -^^^^^ unexpected token - // | | - // | expected one of 8 possible tokens here - err.span_label(self.token.span, label_exp); - } - _ if self.prev_span == syntax_pos::DUMMY_SP => { - // Account for macro context where the previous span might not be - // available to avoid incorrect output (#54841). - err.span_label(self.token.span, "unexpected token"); - } - _ => { - err.span_label(sp, label_exp); - err.span_label(self.token.span, "unexpected token"); - } - } - Err(err) - } - - /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, - /// passes through any errors encountered. Used for error recovery. - crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { - let handler = self.diagnostic(); - - if let Err(ref mut err) = self.parse_seq_to_before_tokens( - kets, - SeqSep::none(), - TokenExpectType::Expect, - |p| Ok(p.parse_token_tree()), - ) { - handler.cancel(err); - } - } - - /// This function checks if there are trailing angle brackets and produces - /// a diagnostic to suggest removing them. - /// - /// ```ignore (diagnostic) - /// let _ = vec![1, 2, 3].into_iter().collect::>>>(); - /// ^^ help: remove extra angle brackets - /// ``` - crate fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { - // This function is intended to be invoked after parsing a path segment where there are two - // cases: - // - // 1. A specific token is expected after the path segment. - // eg. `x.foo(`, `x.foo::(` (parenthesis - method call), - // `Foo::`, or `Foo::::` (mod sep - continued path). - // 2. No specific token is expected after the path segment. - // eg. `x.foo` (field access) - // - // This function is called after parsing `.foo` and before parsing the token `end` (if - // present). This includes any angle bracket arguments, such as `.foo::` or - // `Foo::`. - - // We only care about trailing angle brackets if we previously parsed angle bracket - // arguments. This helps stop us incorrectly suggesting that extra angle brackets be - // removed in this case: - // - // `x.foo >> (3)` (where `x.foo` is a `u32` for example) - // - // This case is particularly tricky as we won't notice it just looking at the tokens - - // it will appear the same (in terms of upcoming tokens) as below (since the `::` will - // have already been parsed): - // - // `x.foo::>>(3)` - let parsed_angle_bracket_args = segment.args - .as_ref() - .map(|args| args.is_angle_bracketed()) - .unwrap_or(false); - - debug!( - "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}", - parsed_angle_bracket_args, - ); - if !parsed_angle_bracket_args { - return; - } - - // Keep the span at the start so we can highlight the sequence of `>` characters to be - // removed. - let lo = self.token.span; - - // We need to look-ahead to see if we have `>` characters without moving the cursor forward - // (since we might have the field access case and the characters we're eating are - // actual operators and not trailing characters - ie `x.foo >> 3`). - let mut position = 0; - - // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how - // many of each (so we can correctly pluralize our error messages) and continue to - // advance. - let mut number_of_shr = 0; - let mut number_of_gt = 0; - while self.look_ahead(position, |t| { - trace!("check_trailing_angle_brackets: t={:?}", t); - if *t == token::BinOp(token::BinOpToken::Shr) { - number_of_shr += 1; - true - } else if *t == token::Gt { - number_of_gt += 1; - true - } else { - false - } - }) { - position += 1; - } - - // If we didn't find any trailing `>` characters, then we have nothing to error about. - debug!( - "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}", - number_of_gt, number_of_shr, - ); - if number_of_gt < 1 && number_of_shr < 1 { - return; - } - - // Finally, double check that we have our end token as otherwise this is the - // second case. - if self.look_ahead(position, |t| { - trace!("check_trailing_angle_brackets: t={:?}", t); - *t == end - }) { - // Eat from where we started until the end token so that parsing can continue - // as if we didn't have those extra angle brackets. - self.eat_to_tokens(&[&end]); - let span = lo.until(self.token.span); - - let plural = number_of_gt > 1 || number_of_shr >= 1; - self.diagnostic() - .struct_span_err( - span, - &format!("unmatched angle bracket{}", if plural { "s" } else { "" }), - ) - .span_suggestion( - span, - &format!("remove extra angle bracket{}", if plural { "s" } else { "" }), - String::new(), - Applicability::MachineApplicable, - ) - .emit(); - } - } - - /// Produce an error if comparison operators are chained (RFC #558). - /// We only need to check lhs, not rhs, because all comparison ops - /// have same precedence and are left-associative - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) { - debug_assert!(outer_op.is_comparison(), - "check_no_chained_comparison: {:?} is not comparison", - outer_op); - match lhs.node { - ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // respan to include both operators - let op_span = op.span.to(self.token.span); - let mut err = self.diagnostic().struct_span_err(op_span, - "chained comparison operators require parentheses"); - if op.node == BinOpKind::Lt && - *outer_op == AssocOp::Less || // Include `<` to provide this recommendation - *outer_op == AssocOp::Greater // even in a case like the following: - { // Foo>> - err.help( - "use `::<...>` instead of `<...>` if you meant to specify type arguments"); - err.help("or use `(...)` if you meant to specify fn arguments"); - } - err.emit(); - } - _ => {} - } - } - - crate fn maybe_report_ambiguous_plus( - &mut self, - allow_plus: bool, - impl_dyn_multi: bool, - ty: &Ty, - ) { - if !allow_plus && impl_dyn_multi { - let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); - self.struct_span_err(ty.span, "ambiguous `+` in a type") - .span_suggestion( - ty.span, - "use parentheses to disambiguate", - sum_with_parens, - Applicability::MachineApplicable, - ) - .emit(); - } - } - - crate fn maybe_report_invalid_custom_discriminants( - sess: &ParseSess, - variants: &[Spanned], - ) { - let has_fields = variants.iter().any(|variant| match variant.node.data { - VariantData::Tuple(..) | VariantData::Struct(..) => true, - VariantData::Unit(..) => false, - }); - - let discriminant_spans = variants.iter().filter(|variant| match variant.node.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.node.disr_expr.as_ref().map(|c| c.value.span)) - .collect::>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = crate::feature_gate::feature_err( - sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - crate::feature_gate::GateIssue::Language, - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.node.data { - VariantData::Struct(..) => { - err.span_label( - variant.span, - "struct variant defined here", - ); - } - VariantData::Tuple(..) => { - err.span_label( - variant.span, - "tuple variant defined here", - ); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - - crate fn maybe_recover_from_bad_type_plus( - &mut self, - allow_plus: bool, - ty: &Ty, - ) -> PResult<'a, ()> { - // Do not add `+` to expected tokens. - if !allow_plus || !self.token.is_like_plus() { - return Ok(()); - } - - self.bump(); // `+` - let bounds = self.parse_generic_bounds(None)?; - let sum_span = ty.span.to(self.prev_span); - - let mut err = struct_span_err!( - self.sess.span_diagnostic, - sum_span, - E0178, - "expected a path on the left-hand side of `+`, not `{}`", - pprust::ty_to_string(ty) - ); - - match ty.node { - TyKind::Rptr(ref lifetime, ref mut_ty) => { - let sum_with_parens = pprust::to_string(|s| { - use crate::print::pprust::PrintState; - - s.s.word("&"); - s.print_opt_lifetime(lifetime); - s.print_mutability(mut_ty.mutbl); - s.popen(); - s.print_type(&mut_ty.ty); - s.print_type_bounds(" +", &bounds); - s.pclose() - }); - err.span_suggestion( - sum_span, - "try adding parentheses", - sum_with_parens, - Applicability::MachineApplicable, - ); - } - TyKind::Ptr(..) | TyKind::BareFn(..) => { - err.span_label(sum_span, "perhaps you forgot parentheses?"); - } - _ => { - err.span_label(sum_span, "expected a path"); - } - } - err.emit(); - Ok(()) - } - - /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. - /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem` - /// tail, and combine them into a `::AssocItem` expression/pattern/type. - crate fn maybe_recover_from_bad_qpath( - &mut self, - base: P, - allow_recovery: bool, - ) -> PResult<'a, P> { - // Do not add `::` to expected tokens. - if allow_recovery && self.token == token::ModSep { - if let Some(ty) = base.to_ty() { - return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty); - } - } - Ok(base) - } - - /// Given an already parsed `Ty` parse the `::AssocItem` tail and - /// combine them into a `::AssocItem` expression/pattern/type. - crate fn maybe_recover_from_bad_qpath_stage_2( - &mut self, - ty_span: Span, - ty: P, - ) -> PResult<'a, P> { - self.expect(&token::ModSep)?; - - let mut path = ast::Path { - segments: Vec::new(), - span: DUMMY_SP, - }; - self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?; - path.span = ty_span.to(self.prev_span); - - let ty_str = self - .sess - .source_map() - .span_to_snippet(ty_span) - .unwrap_or_else(|_| pprust::ty_to_string(&ty)); - self.diagnostic() - .struct_span_err(path.span, "missing angle brackets in associated item path") - .span_suggestion( - // this is a best-effort recovery - path.span, - "try", - format!("<{}>::{}", ty_str, path), - Applicability::MaybeIncorrect, - ) - .emit(); - - let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0 - Ok(P(T::recovered( - Some(QSelf { - ty, - path_span, - position: 0, - }), - path, - ))) - } - - crate fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { - if self.eat(&token::Semi) { - let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`"); - err.span_suggestion_short( - self.prev_span, - "remove this semicolon", - String::new(), - Applicability::MachineApplicable, - ); - if !items.is_empty() { - let previous_item = &items[items.len() - 1]; - let previous_item_kind_name = match previous_item.node { - // say "braced struct" because tuple-structs and - // braceless-empty-struct declarations do take a semicolon - ItemKind::Struct(..) => Some("braced struct"), - ItemKind::Enum(..) => Some("enum"), - ItemKind::Trait(..) => Some("trait"), - ItemKind::Union(..) => Some("union"), - _ => None, - }; - if let Some(name) = previous_item_kind_name { - err.help(&format!( - "{} declarations are not followed by a semicolon", - name - )); - } - } - err.emit(); - true - } else { - false - } - } - - /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a - /// closing delimiter. - pub fn unexpected_try_recover( - &mut self, - t: &TokenKind, - ) -> PResult<'a, bool /* recovered */> { - let token_str = pprust::token_kind_to_string(t); - let this_token_str = self.this_token_descr(); - let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) { - // Point at the end of the macro call when reaching end of macro arguments. - (token::Eof, Some(_)) => { - let sp = self.sess.source_map().next_point(self.token.span); - (sp, sp) - } - // We don't want to point at the following span after DUMMY_SP. - // This happens when the parser finds an empty TokenStream. - _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span), - // EOF, don't want to point at the following char, but rather the last token. - (token::Eof, None) => (self.prev_span, self.token.span), - _ => (self.sess.source_map().next_point(self.prev_span), self.token.span), - }; - let msg = format!( - "expected `{}`, found {}", - token_str, - match (&self.token.kind, self.subparser_name) { - (token::Eof, Some(origin)) => format!("end of {}", origin), - _ => this_token_str, - }, - ); - let mut err = self.struct_span_err(sp, &msg); - let label_exp = format!("expected `{}`", token_str); - match self.recover_closing_delimiter(&[t.clone()], err) { - Err(e) => err = e, - Ok(recovered) => { - return Ok(recovered); - } - } - let cm = self.sess.source_map(); - match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) { - (Ok(ref a), Ok(ref b)) if a.line == b.line => { - // When the spans are in the same line, it means that the only content - // between them is whitespace, point only at the found token. - err.span_label(sp, label_exp); - } - _ => { - err.span_label(prev_sp, label_exp); - err.span_label(sp, "unexpected token"); - } - } - Err(err) - } - - /// Consume alternative await syntaxes like `await `, `await? `, `await()` - /// and `await { }`. - crate fn parse_incorrect_await_syntax( - &mut self, - lo: Span, - await_sp: Span, - ) -> PResult<'a, (Span, ExprKind)> { - let is_question = self.eat(&token::Question); // Handle `await? `. - let expr = if self.token == token::OpenDelim(token::Brace) { - // Handle `await { }`. - // This needs to be handled separatedly from the next arm to avoid - // interpreting `await { }?` as `?.await`. - self.parse_block_expr( - None, - self.token.span, - BlockCheckMode::Default, - ThinVec::new(), - ) - } else { - self.parse_expr() - }.map_err(|mut err| { - err.span_label(await_sp, "while parsing this incorrect await expression"); - err - })?; - let expr_str = self.sess.source_map().span_to_snippet(expr.span) - .unwrap_or_else(|_| pprust::expr_to_string(&expr)); - let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" }); - let sp = lo.to(expr.span); - let app = match expr.node { - ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await ?` - _ => Applicability::MachineApplicable, - }; - self.struct_span_err(sp, "incorrect use of `await`") - .span_suggestion(sp, "`await` is a postfix operation", suggestion, app) - .emit(); - Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr))) - } - - /// If encountering `future.await()`, consume and emit error. - crate fn recover_from_await_method_call(&mut self) { - if self.token == token::OpenDelim(token::Paren) && - self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) - { - // future.await() - let lo = self.token.span; - self.bump(); // ( - let sp = lo.to(self.token.span); - self.bump(); // ) - self.struct_span_err(sp, "incorrect use of `await`") - .span_suggestion( - sp, - "`await` is not a method call, remove the parentheses", - String::new(), - Applicability::MachineApplicable, - ).emit() - } - } - - crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { - self.token.is_ident() && - if let ast::ExprKind::Path(..) = node { true } else { false } && - !self.token.is_reserved_ident() && // v `foo:bar(baz)` - self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) || - self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar, - lhs_span: Span, - cur_op_span: Span, - next_sp: Span, - maybe_path: bool, - ) { - err.span_label(self.token.span, "expecting a type here because of type ascription"); - let cm = self.sess.source_map(); - let next_pos = cm.lookup_char_pos(next_sp.lo()); - let op_pos = cm.lookup_char_pos(cur_op_span.hi()); - if op_pos.line != next_pos.line { - err.span_suggestion( - cur_op_span, - "try using a semicolon", - ";".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - if maybe_path { - err.span_suggestion( - cur_op_span, - "maybe you meant to write a path separator here", - "::".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - err.note("#![feature(type_ascription)] lets you annotate an \ - expression with a type: `: `") - .span_note( - lhs_span, - "this expression expects an ascribed type after the colon", - ) - .help("this might be indicative of a syntax error elsewhere"); - } - } - } - - crate fn recover_seq_parse_error( - &mut self, - delim: token::DelimToken, - lo: Span, - result: PResult<'a, P>, - ) -> P { - match result { - Ok(x) => x, - Err(mut err) => { - err.emit(); - // recover from parse error - self.consume_block(delim); - self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) - } - } - } - - crate fn recover_closing_delimiter( - &mut self, - tokens: &[TokenKind], - mut err: DiagnosticBuilder<'a>, - ) -> PResult<'a, bool> { - let mut pos = None; - // we want to use the last closing delim that would apply - for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { - if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) - && Some(self.token.span) > unmatched.unclosed_span - { - pos = Some(i); - } - } - match pos { - Some(pos) => { - // Recover and assume that the detected unclosed delimiter was meant for - // this location. Emit the diagnostic and act as if the delimiter was - // present for the parser's sake. - - // Don't attempt to recover from this unclosed delimiter more than once. - let unmatched = self.unclosed_delims.remove(pos); - let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); - - // We want to suggest the inclusion of the closing delimiter where it makes - // the most sense, which is immediately after the last token: - // - // {foo(bar {}} - // - ^ - // | | - // | help: `)` may belong here - // | - // unclosed delimiter - if let Some(sp) = unmatched.unclosed_span { - err.span_label(sp, "unclosed delimiter"); - } - err.span_suggestion_short( - self.sess.source_map().next_point(self.prev_span), - &format!("{} may belong here", delim.to_string()), - delim.to_string(), - Applicability::MaybeIncorrect, - ); - err.emit(); - self.expected_tokens.clear(); // reduce errors - Ok(true) - } - _ => Err(err), - } - } - - /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid. - crate fn eat_bad_pub(&mut self) { - if self.token.is_keyword(kw::Pub) { - match self.parse_visibility(false) { - Ok(vis) => { - self.diagnostic() - .struct_span_err(vis.span, "unnecessary visibility qualifier") - .span_label(vis.span, "`pub` not permitted here") - .emit(); - } - Err(mut err) => err.emit(), - } - } - } - - // Eat tokens until we can be relatively sure we reached the end of the - // statement. This is something of a best-effort heuristic. - // - // We terminate when we find an unmatched `}` (without consuming it). - crate fn recover_stmt(&mut self) { - self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) - } - - // If `break_on_semi` is `Break`, then we will stop consuming tokens after - // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is - // approximate - it can mean we break too early due to macros, but that - // should only lead to sub-optimal recovery, not inaccurate parsing). - // - // If `break_on_block` is `Break`, then we will stop consuming tokens - // after finding (and consuming) a brace-delimited block. - crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { - let mut brace_depth = 0; - let mut bracket_depth = 0; - let mut in_block = false; - debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", - break_on_semi, break_on_block); - loop { - debug!("recover_stmt_ loop {:?}", self.token); - match self.token.kind { - token::OpenDelim(token::DelimToken::Brace) => { - brace_depth += 1; - self.bump(); - if break_on_block == BlockMode::Break && - brace_depth == 1 && - bracket_depth == 0 { - in_block = true; - } - } - token::OpenDelim(token::DelimToken::Bracket) => { - bracket_depth += 1; - self.bump(); - } - token::CloseDelim(token::DelimToken::Brace) => { - if brace_depth == 0 { - debug!("recover_stmt_ return - close delim {:?}", self.token); - break; - } - brace_depth -= 1; - self.bump(); - if in_block && bracket_depth == 0 && brace_depth == 0 { - debug!("recover_stmt_ return - block end {:?}", self.token); - break; - } - } - token::CloseDelim(token::DelimToken::Bracket) => { - bracket_depth -= 1; - if bracket_depth < 0 { - bracket_depth = 0; - } - self.bump(); - } - token::Eof => { - debug!("recover_stmt_ return - Eof"); - break; - } - token::Semi => { - self.bump(); - if break_on_semi == SemiColonMode::Break && - brace_depth == 0 && - bracket_depth == 0 { - debug!("recover_stmt_ return - Semi"); - break; - } - } - token::Comma if break_on_semi == SemiColonMode::Comma && - brace_depth == 0 && - bracket_depth == 0 => - { - debug!("recover_stmt_ return - Semi"); - break; - } - _ => { - self.bump() - } - } - } - } - - crate fn check_for_for_in_in_typo(&mut self, in_span: Span) { - if self.eat_keyword(kw::In) { - // a common typo: `for _ in in bar {}` - let mut err = self.sess.span_diagnostic.struct_span_err( - self.prev_span, - "expected iterable, found keyword `in`", - ); - err.span_suggestion_short( - in_span.until(self.prev_span), - "remove the duplicated `in`", - String::new(), - Applicability::MachineApplicable, - ); - err.emit(); - } - } - - crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> { - let token_str = self.this_token_descr(); - let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str)); - err.span_label(self.token.span, "expected `;` or `{`"); - Err(err) - } - - crate fn eat_incorrect_doc_comment_for_arg_type(&mut self) { - if let token::DocComment(_) = self.token.kind { - let mut err = self.diagnostic().struct_span_err( - self.token.span, - "documentation comments cannot be applied to a function parameter's type", - ); - err.span_label(self.token.span, "doc comments are not allowed here"); - err.emit(); - self.bump(); - } else if self.token == token::Pound && self.look_ahead(1, |t| { - *t == token::OpenDelim(token::Bracket) - }) { - let lo = self.token.span; - // Skip every token until next possible arg. - while self.token != token::CloseDelim(token::Bracket) { - self.bump(); - } - let sp = lo.to(self.token.span); - self.bump(); - let mut err = self.diagnostic().struct_span_err( - sp, - "attributes cannot be applied to a function parameter's type", - ); - err.span_label(sp, "attributes are not allowed here"); - err.emit(); - } - } - - crate fn argument_without_type( - &mut self, - err: &mut DiagnosticBuilder<'_>, - pat: P, - require_name: bool, - is_trait_item: bool, - ) -> Option { - // If we find a pattern followed by an identifier, it could be an (incorrect) - // C-style parameter declaration. - if self.check_ident() && self.look_ahead(1, |t| { - *t == token::Comma || *t == token::CloseDelim(token::Paren) - }) { // `fn foo(String s) {}` - let ident = self.parse_ident().unwrap(); - let span = pat.span.with_hi(ident.span.hi()); - - err.span_suggestion( - span, - "declare the type after the parameter binding", - String::from(": "), - Applicability::HasPlaceholders, - ); - return Some(ident); - } else if let PatKind::Ident(_, ident, _) = pat.node { - if require_name && ( - is_trait_item || - self.token == token::Comma || - self.token == token::CloseDelim(token::Paren) - ) { // `fn foo(a, b) {}` or `fn foo(usize, usize) {}` - err.span_suggestion( - pat.span, - "if this was a parameter name, give it a type", - format!("{}: TypeName", ident), - Applicability::HasPlaceholders, - ); - err.span_suggestion( - pat.span, - "if this is a type, explicitly ignore the parameter name", - format!("_: {}", ident), - Applicability::MachineApplicable, - ); - err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); - return Some(ident); - } - } - None - } - - crate fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { - let pat = self.parse_pat(Some("argument name"))?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - - let mut err = self.diagnostic().struct_span_err_with_code( - pat.span, - "patterns aren't allowed in methods without bodies", - DiagnosticId::Error("E0642".into()), - ); - err.span_suggestion_short( - pat.span, - "give this argument a name or use an underscore to ignore it", - "_".to_owned(), - Applicability::MachineApplicable, - ); - err.emit(); - - // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. - let pat = P(Pat { - node: PatKind::Wild, - span: pat.span, - id: ast::DUMMY_NODE_ID - }); - Ok((pat, ty)) - } - - crate fn recover_bad_self_arg( - &mut self, - mut arg: ast::Arg, - is_trait_item: bool, - ) -> PResult<'a, ast::Arg> { - let sp = arg.pat.span; - arg.ty.node = TyKind::Err; - let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); - if is_trait_item { - err.span_label(sp, "must be the first associated function parameter"); - } else { - err.span_label(sp, "not valid as function parameter"); - err.note("`self` is only valid as the first parameter of an associated function"); - } - err.emit(); - Ok(arg) - } - - crate fn consume_block(&mut self, delim: token::DelimToken) { - let mut brace_depth = 0; - loop { - if self.eat(&token::OpenDelim(delim)) { - brace_depth += 1; - } else if self.eat(&token::CloseDelim(delim)) { - if brace_depth == 0 { - return; - } else { - brace_depth -= 1; - continue; - } - } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { - return; - } else { - self.bump(); - } - } - } - - crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { - let (span, msg) = match (&self.token.kind, self.subparser_name) { - (&token::Eof, Some(origin)) => { - let sp = self.sess.source_map().next_point(self.token.span); - (sp, format!("expected expression, found end of {}", origin)) - } - _ => (self.token.span, format!( - "expected expression, found {}", - self.this_token_descr(), - )), - }; - let mut err = self.struct_span_err(span, &msg); - let sp = self.sess.source_map().start_point(self.token.span); - if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - self.sess.expr_parentheses_needed(&mut err, *sp, None); - } - err.span_label(span, "expected expression"); - err - } - - /// Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors. - /// - /// This is necessary because at this point we don't know whether we parsed a function with - /// anonymous arguments or a function with names but no types. In order to minimize - /// unecessary errors, we assume the arguments are in the shape of `fn foo(a, b, c)` where - /// the arguments are *names* (so we don't emit errors about not being able to find `b` in - /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`, - /// we deduplicate them to not complain about duplicated argument names. - crate fn deduplicate_recovered_arg_names(&self, fn_inputs: &mut Vec) { - let mut seen_inputs = FxHashSet::default(); - for input in fn_inputs.iter_mut() { - let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = ( - &input.pat.node, &input.ty.node, - ) { - Some(*ident) - } else { - None - }; - if let Some(ident) = opt_ident { - if seen_inputs.contains(&ident) { - input.pat.node = PatKind::Wild; - } - seen_inputs.insert(ident); - } - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/lexer/comments.rs b/gcc/rust/rustc_parser/libsyntax/parse/lexer/comments.rs deleted file mode 100644 index 988f1aa..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/lexer/comments.rs +++ /dev/null @@ -1,433 +0,0 @@ -pub use CommentStyle::*; - -use crate::ast; -use crate::source_map::SourceMap; -use crate::parse::lexer::{is_block_doc_comment, is_pattern_whitespace}; -use crate::parse::lexer::{self, ParseSess, StringReader}; - -use syntax_pos::{BytePos, CharPos, Pos, FileName}; -use log::debug; - -use std::io::Read; -use std::usize; - -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum CommentStyle { - /// No code on either side of each line of the comment - Isolated, - /// Code exists to the left of the comment - Trailing, - /// Code before /* foo */ and after the comment - Mixed, - /// Just a manual blank line "\n\n", for layout - BlankLine, -} - -#[derive(Clone)] -pub struct Comment { - pub style: CommentStyle, - pub lines: Vec, - pub pos: BytePos, -} - -fn is_doc_comment(s: &str) -> bool { - (s.starts_with("///") && super::is_doc_comment(s)) || s.starts_with("//!") || - (s.starts_with("/**") && is_block_doc_comment(s)) || s.starts_with("/*!") -} - -pub fn doc_comment_style(comment: &str) -> ast::AttrStyle { - assert!(is_doc_comment(comment)); - if comment.starts_with("//!") || comment.starts_with("/*!") { - ast::AttrStyle::Inner - } else { - ast::AttrStyle::Outer - } -} - -pub fn strip_doc_comment_decoration(comment: &str) -> String { - /// remove whitespace-only lines from the start/end of lines - fn vertical_trim(lines: Vec) -> Vec { - let mut i = 0; - let mut j = lines.len(); - // first line of all-stars should be omitted - if !lines.is_empty() && lines[0].chars().all(|c| c == '*') { - i += 1; - } - - while i < j && lines[i].trim().is_empty() { - i += 1; - } - // like the first, a last line of all stars should be omitted - if j > i && - lines[j - 1] - .chars() - .skip(1) - .all(|c| c == '*') { - j -= 1; - } - - while j > i && lines[j - 1].trim().is_empty() { - j -= 1; - } - - lines[i..j].to_vec() - } - - /// remove a "[ \t]*\*" block from each line, if possible - fn horizontal_trim(lines: Vec) -> Vec { - let mut i = usize::MAX; - let mut can_trim = true; - let mut first = true; - - for line in &lines { - for (j, c) in line.chars().enumerate() { - if j > i || !"* \t".contains(c) { - can_trim = false; - break; - } - if c == '*' { - if first { - i = j; - first = false; - } else if i != j { - can_trim = false; - } - break; - } - } - if i >= line.len() { - can_trim = false; - } - if !can_trim { - break; - } - } - - if can_trim { - lines.iter() - .map(|line| (&line[i + 1..line.len()]).to_string()) - .collect() - } else { - lines - } - } - - // one-line comments lose their prefix - const ONELINERS: &[&str] = &["///!", "///", "//!", "//"]; - - for prefix in ONELINERS { - if comment.starts_with(*prefix) { - return (&comment[prefix.len()..]).to_string(); - } - } - - if comment.starts_with("/*") { - let lines = comment[3..comment.len() - 2] - .lines() - .map(|s| s.to_string()) - .collect::>(); - - let lines = vertical_trim(lines); - let lines = horizontal_trim(lines); - - return lines.join("\n"); - } - - panic!("not a doc-comment: {}", comment); -} - -fn push_blank_line_comment(rdr: &StringReader<'_>, comments: &mut Vec) { - debug!(">>> blank-line comment"); - comments.push(Comment { - style: BlankLine, - lines: Vec::new(), - pos: rdr.pos, - }); -} - -fn consume_whitespace_counting_blank_lines( - rdr: &mut StringReader<'_>, - comments: &mut Vec -) { - while is_pattern_whitespace(rdr.ch) && !rdr.is_eof() { - if rdr.ch_is('\n') { - push_blank_line_comment(rdr, &mut *comments); - } - rdr.bump(); - } -} - -fn read_shebang_comment(rdr: &mut StringReader<'_>, - code_to_the_left: bool, - comments: &mut Vec) { - debug!(">>> shebang comment"); - let p = rdr.pos; - debug!("<<< shebang comment"); - comments.push(Comment { - style: if code_to_the_left { Trailing } else { Isolated }, - lines: vec![rdr.read_one_line_comment()], - pos: p, - }); -} - -fn read_line_comments(rdr: &mut StringReader<'_>, - code_to_the_left: bool, - comments: &mut Vec) { - debug!(">>> line comments"); - let p = rdr.pos; - let mut lines: Vec = Vec::new(); - while rdr.ch_is('/') && rdr.nextch_is('/') { - let line = rdr.read_one_line_comment(); - debug!("{}", line); - // Doc comments are not put in comments. - if is_doc_comment(&line[..]) { - break; - } - lines.push(line); - rdr.consume_non_eol_whitespace(); - } - debug!("<<< line comments"); - if !lines.is_empty() { - comments.push(Comment { - style: if code_to_the_left { Trailing } else { Isolated }, - lines, - pos: p, - }); - } -} - -/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char. -/// Otherwise returns `Some(k)` where `k` is first char offset after that leading -/// whitespace. Note that `k` may be outside bounds of `s`. -fn all_whitespace(s: &str, col: CharPos) -> Option { - let mut idx = 0; - for (i, ch) in s.char_indices().take(col.to_usize()) { - if !ch.is_whitespace() { - return None; - } - idx = i + ch.len_utf8(); - } - Some(idx) -} - -fn trim_whitespace_prefix_and_push_line(lines: &mut Vec, s: String, col: CharPos) { - let len = s.len(); - let s1 = match all_whitespace(&s[..], col) { - Some(col) => { - if col < len { - s[col..len].to_string() - } else { - String::new() - } - } - None => s, - }; - debug!("pushing line: {}", s1); - lines.push(s1); -} - -fn read_block_comment(rdr: &mut StringReader<'_>, - code_to_the_left: bool, - comments: &mut Vec) { - debug!(">>> block comment"); - let p = rdr.pos; - let mut lines: Vec = Vec::new(); - - // Count the number of chars since the start of the line by rescanning. - let src_index = rdr.src_index(rdr.source_file.line_begin_pos(rdr.pos)); - let end_src_index = rdr.src_index(rdr.pos); - assert!(src_index <= end_src_index, - "src_index={}, end_src_index={}, line_begin_pos={}", - src_index, end_src_index, rdr.source_file.line_begin_pos(rdr.pos).to_u32()); - - let col = CharPos(rdr.src[src_index..end_src_index].chars().count()); - - rdr.bump(); - rdr.bump(); - - let mut curr_line = String::from("/*"); - - // doc-comments are not really comments, they are attributes - if (rdr.ch_is('*') && !rdr.nextch_is('*')) || rdr.ch_is('!') { - while !(rdr.ch_is('*') && rdr.nextch_is('/')) && !rdr.is_eof() { - curr_line.push(rdr.ch.unwrap()); - rdr.bump(); - } - if !rdr.is_eof() { - curr_line.push_str("*/"); - rdr.bump(); - rdr.bump(); - } - if is_block_doc_comment(&curr_line[..]) { - return; - } - assert!(!curr_line.contains('\n')); - lines.push(curr_line); - } else { - let mut level: isize = 1; - while level > 0 { - debug!("=== block comment level {}", level); - if rdr.is_eof() { - rdr.fatal_span_(rdr.pos, rdr.pos, "unterminated block comment").raise(); - } - if rdr.ch_is('\n') { - trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col); - curr_line = String::new(); - rdr.bump(); - } else { - curr_line.push(rdr.ch.unwrap()); - if rdr.ch_is('/') && rdr.nextch_is('*') { - rdr.bump(); - rdr.bump(); - curr_line.push('*'); - level += 1; - } else { - if rdr.ch_is('*') && rdr.nextch_is('/') { - rdr.bump(); - rdr.bump(); - curr_line.push('/'); - level -= 1; - } else { - rdr.bump(); - } - } - } - } - if !curr_line.is_empty() { - trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col); - } - } - - let mut style = if code_to_the_left { - Trailing - } else { - Isolated - }; - rdr.consume_non_eol_whitespace(); - if !rdr.is_eof() && !rdr.ch_is('\n') && lines.len() == 1 { - style = Mixed; - } - debug!("<<< block comment"); - comments.push(Comment { - style, - lines, - pos: p, - }); -} - - -fn consume_comment(rdr: &mut StringReader<'_>, - comments: &mut Vec, - code_to_the_left: &mut bool, - anything_to_the_left: &mut bool) { - debug!(">>> consume comment"); - if rdr.ch_is('/') && rdr.nextch_is('/') { - read_line_comments(rdr, *code_to_the_left, comments); - *code_to_the_left = false; - *anything_to_the_left = false; - } else if rdr.ch_is('/') && rdr.nextch_is('*') { - read_block_comment(rdr, *code_to_the_left, comments); - *anything_to_the_left = true; - } else if rdr.ch_is('#') && rdr.nextch_is('!') { - read_shebang_comment(rdr, *code_to_the_left, comments); - *code_to_the_left = false; - *anything_to_the_left = false; - } else { - panic!(); - } - debug!("<<< consume comment"); -} - -// it appears this function is called only from pprust... that's -// probably not a good thing. -pub fn gather_comments(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) -> Vec -{ - let mut src = String::new(); - srdr.read_to_string(&mut src).unwrap(); - let cm = SourceMap::new(sess.source_map().path_mapping().clone()); - let source_file = cm.new_source_file(path, src); - let mut rdr = lexer::StringReader::new(sess, source_file, None); - - let mut comments: Vec = Vec::new(); - let mut code_to_the_left = false; // Only code - let mut anything_to_the_left = false; // Code or comments - - while !rdr.is_eof() { - loop { - // Eat all the whitespace and count blank lines. - rdr.consume_non_eol_whitespace(); - if rdr.ch_is('\n') { - if anything_to_the_left { - rdr.bump(); // The line is not blank, do not count. - } - consume_whitespace_counting_blank_lines(&mut rdr, &mut comments); - code_to_the_left = false; - anything_to_the_left = false; - } - // Eat one comment group - if rdr.peeking_at_comment() { - consume_comment(&mut rdr, &mut comments, - &mut code_to_the_left, &mut anything_to_the_left); - } else { - break - } - } - - rdr.next_token(); - code_to_the_left = true; - anything_to_the_left = true; - } - - comments -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_block_doc_comment_1() { - let comment = "/**\n * Test \n ** Test\n * Test\n*/"; - let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " Test \n* Test\n Test"); - } - - #[test] - fn test_block_doc_comment_2() { - let comment = "/**\n * Test\n * Test\n*/"; - let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " Test\n Test"); - } - - #[test] - fn test_block_doc_comment_3() { - let comment = "/**\n let a: *i32;\n *a = 5;\n*/"; - let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " let a: *i32;\n *a = 5;"); - } - - #[test] - fn test_block_doc_comment_4() { - let comment = "/*******************\n test\n *********************/"; - let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " test"); - } - - #[test] - fn test_line_doc_comment() { - let stripped = strip_doc_comment_decoration("/// test"); - assert_eq!(stripped, " test"); - let stripped = strip_doc_comment_decoration("///! test"); - assert_eq!(stripped, " test"); - let stripped = strip_doc_comment_decoration("// test"); - assert_eq!(stripped, " test"); - let stripped = strip_doc_comment_decoration("// test"); - assert_eq!(stripped, " test"); - let stripped = strip_doc_comment_decoration("///test"); - assert_eq!(stripped, "test"); - let stripped = strip_doc_comment_decoration("///!test"); - assert_eq!(stripped, "test"); - let stripped = strip_doc_comment_decoration("//test"); - assert_eq!(stripped, "test"); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/lexer/mod.rs b/gcc/rust/rustc_parser/libsyntax/parse/lexer/mod.rs deleted file mode 100644 index d0c4e8d..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/lexer/mod.rs +++ /dev/null @@ -1,1609 +0,0 @@ -use crate::parse::ParseSess; -use crate::parse::token::{self, Token, TokenKind}; -use crate::symbol::{sym, Symbol}; -use crate::parse::unescape; -use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; - -use errors::{FatalError, Diagnostic, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; -use core::unicode::property::Pattern_White_Space; - -use std::borrow::Cow; -use std::char; -use std::iter; -use rustc_data_structures::sync::Lrc; -use log::debug; - -pub mod comments; -mod tokentrees; -mod unicode_chars; - -#[derive(Clone, Debug)] -pub struct UnmatchedBrace { - pub expected_delim: token::DelimToken, - pub found_delim: token::DelimToken, - pub found_span: Span, - pub unclosed_span: Option, - pub candidate_span: Option, -} - -pub struct StringReader<'a> { - crate sess: &'a ParseSess, - /// The absolute offset within the source_map of the next character to read - crate next_pos: BytePos, - /// The absolute offset within the source_map of the current character - crate pos: BytePos, - /// The current character (which has been read from self.pos) - crate ch: Option, - crate source_file: Lrc, - /// Stop reading src at this index. - crate end_src_index: usize, - fatal_errs: Vec>, - // cache a direct reference to the source text, so that we don't have to - // retrieve it via `self.source_file.src.as_ref().unwrap()` all the time. - src: Lrc, - override_span: Option, -} - -impl<'a> StringReader<'a> { - pub fn new(sess: &'a ParseSess, - source_file: Lrc, - override_span: Option) -> Self { - let mut sr = StringReader::new_internal(sess, source_file, override_span); - sr.bump(); - sr - } - - pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self { - let begin = sess.source_map().lookup_byte_offset(span.lo()); - let end = sess.source_map().lookup_byte_offset(span.hi()); - - // Make the range zero-length if the span is invalid. - if span.lo() > span.hi() || begin.sf.start_pos != end.sf.start_pos { - span = span.shrink_to_lo(); - } - - let mut sr = StringReader::new_internal(sess, begin.sf, None); - - // Seek the lexer to the right byte range. - sr.next_pos = span.lo(); - sr.end_src_index = sr.src_index(span.hi()); - - sr.bump(); - - sr - } - - fn new_internal(sess: &'a ParseSess, source_file: Lrc, - override_span: Option) -> Self - { - if source_file.src.is_none() { - sess.span_diagnostic.bug(&format!("Cannot lex source_file without source: {}", - source_file.name)); - } - - let src = (*source_file.src.as_ref().unwrap()).clone(); - - StringReader { - sess, - next_pos: source_file.start_pos, - pos: source_file.start_pos, - ch: Some('\n'), - source_file, - end_src_index: src.len(), - src, - fatal_errs: Vec::new(), - override_span, - } - } - - fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { - self.override_span.unwrap_or_else(|| Span::new(lo, hi, NO_EXPANSION)) - } - - fn unwrap_or_abort(&mut self, res: Result) -> Token { - match res { - Ok(tok) => tok, - Err(_) => { - self.emit_fatal_errors(); - FatalError.raise(); - } - } - } - - /// Returns the next token, including trivia like whitespace or comments. - /// - /// `Err(())` means that some errors were encountered, which can be - /// retrieved using `buffer_fatal_errors`. - pub fn try_next_token(&mut self) -> Result { - assert!(self.fatal_errs.is_empty()); - match self.scan_whitespace_or_comment() { - Some(comment) => Ok(comment), - None => { - let (kind, start_pos, end_pos) = if self.is_eof() { - (token::Eof, self.source_file.end_pos, self.source_file.end_pos) - } else { - let start_pos = self.pos; - (self.next_token_inner()?, start_pos, self.pos) - }; - let span = self.mk_sp(start_pos, end_pos); - Ok(Token::new(kind, span)) - } - } - } - - /// Returns the next token, including trivia like whitespace or comments. - /// - /// Aborts in case of an error. - pub fn next_token(&mut self) -> Token { - let res = self.try_next_token(); - self.unwrap_or_abort(res) - } - - #[inline] - fn is_eof(&self) -> bool { - self.ch.is_none() - } - - fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) -> ! { - let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string"); - err.span_label(self.mk_sp(pos, pos), "unterminated raw string"); - - if hash_count > 0 { - err.note(&format!("this raw string should be terminated with `\"{}`", - "#".repeat(hash_count as usize))); - } - - err.emit(); - FatalError.raise(); - } - - crate fn emit_fatal_errors(&mut self) { - for err in &mut self.fatal_errs { - err.emit(); - } - - self.fatal_errs.clear(); - } - - pub fn buffer_fatal_errors(&mut self) -> Vec { - let mut buffer = Vec::new(); - - for err in self.fatal_errs.drain(..) { - err.buffer(&mut buffer); - } - - buffer - } - - #[inline] - fn ch_is(&self, c: char) -> bool { - self.ch == Some(c) - } - - /// Report a fatal lexical error with a given span. - fn fatal_span(&self, sp: Span, m: &str) -> FatalError { - self.sess.span_diagnostic.span_fatal(sp, m) - } - - /// Report a lexical error with a given span. - fn err_span(&self, sp: Span, m: &str) { - self.sess.span_diagnostic.struct_span_err(sp, m).emit(); - } - - - /// Report a fatal error spanning [`from_pos`, `to_pos`). - fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError { - self.fatal_span(self.mk_sp(from_pos, to_pos), m) - } - - /// Report a lexical error spanning [`from_pos`, `to_pos`). - fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) { - self.err_span(self.mk_sp(from_pos, to_pos), m) - } - - /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an - /// escaped character to the error message - fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError { - let mut m = m.to_string(); - m.push_str(": "); - push_escaped_char(&mut m, c); - - self.fatal_span_(from_pos, to_pos, &m[..]) - } - - fn struct_span_fatal(&self, from_pos: BytePos, to_pos: BytePos, m: &str) - -> DiagnosticBuilder<'a> - { - self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), m) - } - - fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) - -> DiagnosticBuilder<'a> - { - let mut m = m.to_string(); - m.push_str(": "); - push_escaped_char(&mut m, c); - - self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..]) - } - - #[inline] - fn src_index(&self, pos: BytePos) -> usize { - (pos - self.source_file.start_pos).to_usize() - } - - /// Slice of the source text from `start` up to but excluding `self.pos`, - /// meaning the slice does not include the character `self.ch`. - fn str_from(&self, start: BytePos) -> &str - { - self.str_from_to(start, self.pos) - } - - /// Creates a Symbol from a given offset to the current offset. - fn symbol_from(&self, start: BytePos) -> Symbol { - debug!("taking an ident from {:?} to {:?}", start, self.pos); - Symbol::intern(self.str_from(start)) - } - - /// As symbol_from, with an explicit endpoint. - fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol { - debug!("taking an ident from {:?} to {:?}", start, end); - Symbol::intern(self.str_from_to(start, end)) - } - - /// Slice of the source text spanning from `start` up to but excluding `end`. - fn str_from_to(&self, start: BytePos, end: BytePos) -> &str - { - &self.src[self.src_index(start)..self.src_index(end)] - } - - /// Converts CRLF to LF in the given string, raising an error on bare CR. - fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> { - let mut chars = s.char_indices().peekable(); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if let Some((lf_idx, '\n')) = chars.peek() { - return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into(); - } - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos((i + ch.len_utf8()) as u32); - self.err_span_(pos, end_pos, errmsg); - } - } - return s.into(); - - fn translate_crlf_(rdr: &StringReader<'_>, - start: BytePos, - s: &str, - mut j: usize, - mut chars: iter::Peekable>, - errmsg: &str) - -> String { - let mut buf = String::with_capacity(s.len()); - // Skip first CR - buf.push_str(&s[.. j - 1]); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if j < i { - buf.push_str(&s[j..i]); - } - let next = i + ch.len_utf8(); - j = next; - if chars.peek().map(|(_, ch)| *ch) != Some('\n') { - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos(next as u32); - rdr.err_span_(pos, end_pos, errmsg); - } - } - } - if j < s.len() { - buf.push_str(&s[j..]); - } - buf - } - } - - /// Advance the StringReader by one character. - crate fn bump(&mut self) { - let next_src_index = self.src_index(self.next_pos); - if next_src_index < self.end_src_index { - let next_ch = char_at(&self.src, next_src_index); - let next_ch_len = next_ch.len_utf8(); - - self.ch = Some(next_ch); - self.pos = self.next_pos; - self.next_pos = self.next_pos + Pos::from_usize(next_ch_len); - } else { - self.ch = None; - self.pos = self.next_pos; - } - } - - fn nextch(&self) -> Option { - let next_src_index = self.src_index(self.next_pos); - if next_src_index < self.end_src_index { - Some(char_at(&self.src, next_src_index)) - } else { - None - } - } - - #[inline] - fn nextch_is(&self, c: char) -> bool { - self.nextch() == Some(c) - } - - fn nextnextch(&self) -> Option { - let next_src_index = self.src_index(self.next_pos); - if next_src_index < self.end_src_index { - let next_next_src_index = - next_src_index + char_at(&self.src, next_src_index).len_utf8(); - if next_next_src_index < self.end_src_index { - return Some(char_at(&self.src, next_next_src_index)); - } - } - None - } - - #[inline] - fn nextnextch_is(&self, c: char) -> bool { - self.nextnextch() == Some(c) - } - - /// Eats *, if possible. - fn scan_optional_raw_name(&mut self) -> Option { - if !ident_start(self.ch) { - return None; - } - - let start = self.pos; - self.bump(); - - while ident_continue(self.ch) { - self.bump(); - } - - match self.str_from(start) { - "_" => { - self.sess.span_diagnostic - .struct_span_warn(self.mk_sp(start, self.pos), - "underscore literal suffix is not allowed") - .warn("this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!") - .note("for more information, see issue #42326 \ - ") - .emit(); - None - } - name => Some(Symbol::intern(name)) - } - } - - /// PRECONDITION: self.ch is not whitespace - /// Eats any kind of comment. - fn scan_comment(&mut self) -> Option { - if let Some(c) = self.ch { - if c.is_whitespace() { - let msg = "called consume_any_line_comment, but there was whitespace"; - self.sess.span_diagnostic.span_err(self.mk_sp(self.pos, self.pos), msg); - } - } - - if self.ch_is('/') { - match self.nextch() { - Some('/') => { - self.bump(); - self.bump(); - - // line comments starting with "///" or "//!" are doc-comments - let doc_comment = (self.ch_is('/') && !self.nextch_is('/')) || self.ch_is('!'); - let start_bpos = self.pos - BytePos(2); - - while !self.is_eof() { - match self.ch.unwrap() { - '\n' => break, - '\r' => { - if self.nextch_is('\n') { - // CRLF - break; - } else if doc_comment { - self.err_span_(self.pos, - self.next_pos, - "bare CR not allowed in doc-comment"); - } - } - _ => (), - } - self.bump(); - } - - let kind = if doc_comment { - token::DocComment(self.symbol_from(start_bpos)) - } else { - token::Comment - }; - Some(Token::new(kind, self.mk_sp(start_bpos, self.pos))) - } - Some('*') => { - self.bump(); - self.bump(); - self.scan_block_comment() - } - _ => None, - } - } else if self.ch_is('#') { - if self.nextch_is('!') { - - // Parse an inner attribute. - if self.nextnextch_is('[') { - return None; - } - - let is_beginning_of_file = self.pos == self.source_file.start_pos; - if is_beginning_of_file { - debug!("Skipping a shebang"); - let start = self.pos; - while !self.ch_is('\n') && !self.is_eof() { - self.bump(); - } - return Some(Token::new( - token::Shebang(self.symbol_from(start)), - self.mk_sp(start, self.pos), - )); - } - } - None - } else { - None - } - } - - /// If there is whitespace, shebang, or a comment, scan it. Otherwise, - /// return `None`. - fn scan_whitespace_or_comment(&mut self) -> Option { - match self.ch.unwrap_or('\0') { - // # to handle shebang at start of file -- this is the entry point - // for skipping over all "junk" - '/' | '#' => { - let c = self.scan_comment(); - debug!("scanning a comment {:?}", c); - c - }, - c if is_pattern_whitespace(Some(c)) => { - let start_bpos = self.pos; - while is_pattern_whitespace(self.ch) { - self.bump(); - } - let c = Some(Token::new(token::Whitespace, self.mk_sp(start_bpos, self.pos))); - debug!("scanning whitespace: {:?}", c); - c - } - _ => None, - } - } - - /// Might return a sugared-doc-attr - fn scan_block_comment(&mut self) -> Option { - // block comments starting with "/**" or "/*!" are doc-comments - let is_doc_comment = self.ch_is('*') || self.ch_is('!'); - let start_bpos = self.pos - BytePos(2); - - let mut level: isize = 1; - let mut has_cr = false; - while level > 0 { - if self.is_eof() { - let msg = if is_doc_comment { - "unterminated block doc-comment" - } else { - "unterminated block comment" - }; - let last_bpos = self.pos; - self.fatal_span_(start_bpos, last_bpos, msg).raise(); - } - let n = self.ch.unwrap(); - match n { - '/' if self.nextch_is('*') => { - level += 1; - self.bump(); - } - '*' if self.nextch_is('/') => { - level -= 1; - self.bump(); - } - '\r' => { - has_cr = true; - } - _ => (), - } - self.bump(); - } - - let string = self.str_from(start_bpos); - // but comments with only "*"s between two "/"s are not - let kind = if is_block_doc_comment(string) { - let string = if has_cr { - self.translate_crlf(start_bpos, - string, - "bare CR not allowed in block doc-comment") - } else { - string.into() - }; - token::DocComment(Symbol::intern(&string[..])) - } else { - token::Comment - }; - - Some(Token::new(kind, self.mk_sp(start_bpos, self.pos))) - } - - /// Scan through any digits (base `scan_radix`) or underscores, - /// and return how many digits there were. - /// - /// `real_radix` represents the true radix of the number we're - /// interested in, and errors will be emitted for any digits - /// between `real_radix` and `scan_radix`. - fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize { - assert!(real_radix <= scan_radix); - let mut len = 0; - - loop { - let c = self.ch; - if c == Some('_') { - debug!("skipping a _"); - self.bump(); - continue; - } - match c.and_then(|cc| cc.to_digit(scan_radix)) { - Some(_) => { - debug!("{:?} in scan_digits", c); - // check that the hypothetical digit is actually - // in range for the true radix - if c.unwrap().to_digit(real_radix).is_none() { - self.err_span_(self.pos, - self.next_pos, - &format!("invalid digit for a base {} literal", real_radix)); - } - len += 1; - self.bump(); - } - _ => return len, - } - } - } - - /// Lex a LIT_INTEGER or a LIT_FLOAT - fn scan_number(&mut self, c: char) -> (token::LitKind, Symbol) { - let mut base = 10; - let start_bpos = self.pos; - self.bump(); - - let num_digits = if c == '0' { - match self.ch.unwrap_or('\0') { - 'b' => { - self.bump(); - base = 2; - self.scan_digits(2, 10) - } - 'o' => { - self.bump(); - base = 8; - self.scan_digits(8, 10) - } - 'x' => { - self.bump(); - base = 16; - self.scan_digits(16, 16) - } - '0'..='9' | '_' | '.' | 'e' | 'E' => { - self.scan_digits(10, 10) + 1 - } - _ => { - // just a 0 - return (token::Integer, sym::integer(0)); - } - } - } else if c.is_digit(10) { - self.scan_digits(10, 10) + 1 - } else { - 0 - }; - - if num_digits == 0 { - self.err_span_(start_bpos, self.pos, "no valid digits found for number"); - - return (token::Integer, sym::integer(0)); - } - - // might be a float, but don't be greedy if this is actually an - // integer literal followed by field/method access or a range pattern - // (`0..2` and `12.foo()`) - if self.ch_is('.') && !self.nextch_is('.') && - !ident_start(self.nextch()) { - // might have stuff after the ., and if it does, it needs to start - // with a number - self.bump(); - if self.ch.unwrap_or('\0').is_digit(10) { - self.scan_digits(10, 10); - self.scan_float_exponent(); - } - let pos = self.pos; - self.check_float_base(start_bpos, pos, base); - - (token::Float, self.symbol_from(start_bpos)) - } else { - // it might be a float if it has an exponent - if self.ch_is('e') || self.ch_is('E') { - self.scan_float_exponent(); - let pos = self.pos; - self.check_float_base(start_bpos, pos, base); - return (token::Float, self.symbol_from(start_bpos)); - } - // but we certainly have an integer! - (token::Integer, self.symbol_from(start_bpos)) - } - } - - /// Scan over a float exponent. - fn scan_float_exponent(&mut self) { - if self.ch_is('e') || self.ch_is('E') { - self.bump(); - - if self.ch_is('-') || self.ch_is('+') { - self.bump(); - } - - if self.scan_digits(10, 10) == 0 { - let mut err = self.struct_span_fatal( - self.pos, self.next_pos, - "expected at least one digit in exponent" - ); - if let Some(ch) = self.ch { - // check for e.g., Unicode minus '−' (Issue #49746) - if unicode_chars::check_for_substitution(self, ch, &mut err) { - self.bump(); - self.scan_digits(10, 10); - } - } - err.emit(); - } - } - } - - /// Checks that a base is valid for a floating literal, emitting a nice - /// error if it isn't. - fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: usize) { - match base { - 16 => { - self.err_span_(start_bpos, - last_bpos, - "hexadecimal float literal is not supported") - } - 8 => { - self.err_span_(start_bpos, - last_bpos, - "octal float literal is not supported") - } - 2 => { - self.err_span_(start_bpos, - last_bpos, - "binary float literal is not supported") - } - _ => (), - } - } - - fn binop(&mut self, op: token::BinOpToken) -> TokenKind { - self.bump(); - if self.ch_is('=') { - self.bump(); - token::BinOpEq(op) - } else { - token::BinOp(op) - } - } - - /// Returns the next token from the string, advances the input past that - /// token, and updates the interner - fn next_token_inner(&mut self) -> Result { - let c = self.ch; - - if ident_start(c) { - let (is_ident_start, is_raw_ident) = - match (c.unwrap(), self.nextch(), self.nextnextch()) { - // r# followed by an identifier starter is a raw identifier. - // This is an exception to the r# case below. - ('r', Some('#'), x) if ident_start(x) => (true, true), - // r as in r" or r#" is part of a raw string literal. - // b as in b' is part of a byte literal. - // They are not identifiers, and are handled further down. - ('r', Some('"'), _) | - ('r', Some('#'), _) | - ('b', Some('"'), _) | - ('b', Some('\''), _) | - ('b', Some('r'), Some('"')) | - ('b', Some('r'), Some('#')) => (false, false), - _ => (true, false), - }; - - if is_ident_start { - let raw_start = self.pos; - if is_raw_ident { - // Consume the 'r#' characters. - self.bump(); - self.bump(); - } - - let start = self.pos; - self.bump(); - - while ident_continue(self.ch) { - self.bump(); - } - - // FIXME: perform NFKC normalization here. (Issue #2253) - let name = self.symbol_from(start); - if is_raw_ident { - let span = self.mk_sp(raw_start, self.pos); - if !name.can_be_raw() { - self.err_span(span, &format!("`{}` cannot be a raw identifier", name)); - } - self.sess.raw_identifier_spans.borrow_mut().push(span); - } - - return Ok(token::Ident(name, is_raw_ident)); - } - } - - if is_dec_digit(c) { - let (kind, symbol) = self.scan_number(c.unwrap()); - let suffix = self.scan_optional_raw_name(); - debug!("next_token_inner: scanned number {:?}, {:?}, {:?}", kind, symbol, suffix); - return Ok(TokenKind::lit(kind, symbol, suffix)); - } - - match c.expect("next_token_inner called at EOF") { - // One-byte tokens. - ';' => { - self.bump(); - Ok(token::Semi) - } - ',' => { - self.bump(); - Ok(token::Comma) - } - '.' => { - self.bump(); - if self.ch_is('.') { - self.bump(); - if self.ch_is('.') { - self.bump(); - Ok(token::DotDotDot) - } else if self.ch_is('=') { - self.bump(); - Ok(token::DotDotEq) - } else { - Ok(token::DotDot) - } - } else { - Ok(token::Dot) - } - } - '(' => { - self.bump(); - Ok(token::OpenDelim(token::Paren)) - } - ')' => { - self.bump(); - Ok(token::CloseDelim(token::Paren)) - } - '{' => { - self.bump(); - Ok(token::OpenDelim(token::Brace)) - } - '}' => { - self.bump(); - Ok(token::CloseDelim(token::Brace)) - } - '[' => { - self.bump(); - Ok(token::OpenDelim(token::Bracket)) - } - ']' => { - self.bump(); - Ok(token::CloseDelim(token::Bracket)) - } - '@' => { - self.bump(); - Ok(token::At) - } - '#' => { - self.bump(); - Ok(token::Pound) - } - '~' => { - self.bump(); - Ok(token::Tilde) - } - '?' => { - self.bump(); - Ok(token::Question) - } - ':' => { - self.bump(); - if self.ch_is(':') { - self.bump(); - Ok(token::ModSep) - } else { - Ok(token::Colon) - } - } - - '$' => { - self.bump(); - Ok(token::Dollar) - } - - // Multi-byte tokens. - '=' => { - self.bump(); - if self.ch_is('=') { - self.bump(); - Ok(token::EqEq) - } else if self.ch_is('>') { - self.bump(); - Ok(token::FatArrow) - } else { - Ok(token::Eq) - } - } - '!' => { - self.bump(); - if self.ch_is('=') { - self.bump(); - Ok(token::Ne) - } else { - Ok(token::Not) - } - } - '<' => { - self.bump(); - match self.ch.unwrap_or('\x00') { - '=' => { - self.bump(); - Ok(token::Le) - } - '<' => { - Ok(self.binop(token::Shl)) - } - '-' => { - self.bump(); - Ok(token::LArrow) - } - _ => { - Ok(token::Lt) - } - } - } - '>' => { - self.bump(); - match self.ch.unwrap_or('\x00') { - '=' => { - self.bump(); - Ok(token::Ge) - } - '>' => { - Ok(self.binop(token::Shr)) - } - _ => { - Ok(token::Gt) - } - } - } - '\'' => { - // Either a character constant 'a' OR a lifetime name 'abc - let start_with_quote = self.pos; - self.bump(); - let start = self.pos; - - // If the character is an ident start not followed by another single - // quote, then this is a lifetime name: - let starts_with_number = self.ch.unwrap_or('\x00').is_numeric(); - if (ident_start(self.ch) || starts_with_number) && !self.nextch_is('\'') { - self.bump(); - while ident_continue(self.ch) { - self.bump(); - } - // lifetimes shouldn't end with a single quote - // if we find one, then this is an invalid character literal - if self.ch_is('\'') { - let symbol = self.symbol_from(start); - self.bump(); - self.validate_char_escape(start_with_quote); - return Ok(TokenKind::lit(token::Char, symbol, None)); - } - - if starts_with_number { - // this is a recovered lifetime written `'1`, error but accept it - self.err_span_( - start_with_quote, - self.pos, - "lifetimes cannot start with a number", - ); - } - - // Include the leading `'` in the real identifier, for macro - // expansion purposes. See #12512 for the gory details of why - // this is necessary. - return Ok(token::Lifetime(self.symbol_from(start_with_quote))); - } - let msg = "unterminated character literal"; - let symbol = self.scan_single_quoted_string(start_with_quote, msg); - self.validate_char_escape(start_with_quote); - let suffix = self.scan_optional_raw_name(); - Ok(TokenKind::lit(token::Char, symbol, suffix)) - } - 'b' => { - self.bump(); - let (kind, symbol) = match self.ch { - Some('\'') => { - let start_with_quote = self.pos; - self.bump(); - let msg = "unterminated byte constant"; - let symbol = self.scan_single_quoted_string(start_with_quote, msg); - self.validate_byte_escape(start_with_quote); - (token::Byte, symbol) - }, - Some('"') => { - let start_with_quote = self.pos; - let msg = "unterminated double quote byte string"; - let symbol = self.scan_double_quoted_string(msg); - self.validate_byte_str_escape(start_with_quote); - (token::ByteStr, symbol) - }, - Some('r') => { - let (start, end, hash_count) = self.scan_raw_string(); - let symbol = self.symbol_from_to(start, end); - self.validate_raw_byte_str_escape(start, end); - - (token::ByteStrRaw(hash_count), symbol) - } - _ => unreachable!(), // Should have been a token::Ident above. - }; - let suffix = self.scan_optional_raw_name(); - - Ok(TokenKind::lit(kind, symbol, suffix)) - } - '"' => { - let start_with_quote = self.pos; - let msg = "unterminated double quote string"; - let symbol = self.scan_double_quoted_string(msg); - self.validate_str_escape(start_with_quote); - let suffix = self.scan_optional_raw_name(); - Ok(TokenKind::lit(token::Str, symbol, suffix)) - } - 'r' => { - let (start, end, hash_count) = self.scan_raw_string(); - let symbol = self.symbol_from_to(start, end); - self.validate_raw_str_escape(start, end); - let suffix = self.scan_optional_raw_name(); - - Ok(TokenKind::lit(token::StrRaw(hash_count), symbol, suffix)) - } - '-' => { - if self.nextch_is('>') { - self.bump(); - self.bump(); - Ok(token::RArrow) - } else { - Ok(self.binop(token::Minus)) - } - } - '&' => { - if self.nextch_is('&') { - self.bump(); - self.bump(); - Ok(token::AndAnd) - } else { - Ok(self.binop(token::And)) - } - } - '|' => { - match self.nextch() { - Some('|') => { - self.bump(); - self.bump(); - Ok(token::OrOr) - } - _ => { - Ok(self.binop(token::Or)) - } - } - } - '+' => { - Ok(self.binop(token::Plus)) - } - '*' => { - Ok(self.binop(token::Star)) - } - '/' => { - Ok(self.binop(token::Slash)) - } - '^' => { - Ok(self.binop(token::Caret)) - } - '%' => { - Ok(self.binop(token::Percent)) - } - c => { - let last_bpos = self.pos; - let bpos = self.next_pos; - let mut err = self.struct_fatal_span_char(last_bpos, - bpos, - "unknown start of token", - c); - unicode_chars::check_for_substitution(self, c, &mut err); - self.fatal_errs.push(err); - - Err(()) - } - } - } - - fn read_to_eol(&mut self) -> String { - let mut val = String::new(); - while !self.ch_is('\n') && !self.is_eof() { - val.push(self.ch.unwrap()); - self.bump(); - } - - if self.ch_is('\n') { - self.bump(); - } - - val - } - - fn read_one_line_comment(&mut self) -> String { - let val = self.read_to_eol(); - assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') || - (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!')); - val - } - - fn consume_non_eol_whitespace(&mut self) { - while is_pattern_whitespace(self.ch) && !self.ch_is('\n') && !self.is_eof() { - self.bump(); - } - } - - fn peeking_at_comment(&self) -> bool { - (self.ch_is('/') && self.nextch_is('/')) || (self.ch_is('/') && self.nextch_is('*')) || - // consider shebangs comments, but not inner attributes - (self.ch_is('#') && self.nextch_is('!') && !self.nextnextch_is('[')) - } - - fn scan_single_quoted_string(&mut self, - start_with_quote: BytePos, - unterminated_msg: &str) -> Symbol { - // assumes that first `'` is consumed - let start = self.pos; - // lex `'''` as a single char, for recovery - if self.ch_is('\'') && self.nextch_is('\'') { - self.bump(); - } else { - let mut first = true; - loop { - if self.ch_is('\'') { - break; - } - if self.ch_is('\\') && (self.nextch_is('\'') || self.nextch_is('\\')) { - self.bump(); - self.bump(); - } else { - // Only attempt to infer single line string literals. If we encounter - // a slash, bail out in order to avoid nonsensical suggestion when - // involving comments. - if self.is_eof() - || (self.ch_is('/') && !first) - || (self.ch_is('\n') && !self.nextch_is('\'')) { - - self.fatal_span_(start_with_quote, self.pos, unterminated_msg.into()) - .raise() - } - self.bump(); - } - first = false; - } - } - - let id = self.symbol_from(start); - self.bump(); - id - } - - fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> Symbol { - debug_assert!(self.ch_is('\"')); - let start_with_quote = self.pos; - self.bump(); - let start = self.pos; - while !self.ch_is('"') { - if self.is_eof() { - let pos = self.pos; - self.fatal_span_(start_with_quote, pos, unterminated_msg).raise(); - } - if self.ch_is('\\') && (self.nextch_is('\\') || self.nextch_is('"')) { - self.bump(); - } - self.bump(); - } - let id = self.symbol_from(start); - self.bump(); - id - } - - /// Scans a raw (byte) string, returning byte position range for `""` - /// (including quotes) along with `#` character count in `(b)r##...""##...`; - fn scan_raw_string(&mut self) -> (BytePos, BytePos, u16) { - let start_bpos = self.pos; - self.bump(); - let mut hash_count: u16 = 0; - while self.ch_is('#') { - if hash_count == 65535 { - let bpos = self.next_pos; - self.fatal_span_(start_bpos, - bpos, - "too many `#` symbols: raw strings may be \ - delimited by up to 65535 `#` symbols").raise(); - } - self.bump(); - hash_count += 1; - } - - if self.is_eof() { - self.fail_unterminated_raw_string(start_bpos, hash_count); - } else if !self.ch_is('"') { - let last_bpos = self.pos; - let curr_char = self.ch.unwrap(); - self.fatal_span_char(start_bpos, - last_bpos, - "found invalid character; only `#` is allowed \ - in raw string delimitation", - curr_char).raise(); - } - self.bump(); - let content_start_bpos = self.pos; - let mut content_end_bpos; - 'outer: loop { - match self.ch { - None => { - self.fail_unterminated_raw_string(start_bpos, hash_count); - } - Some('"') => { - content_end_bpos = self.pos; - for _ in 0..hash_count { - self.bump(); - if !self.ch_is('#') { - continue 'outer; - } - } - break; - } - _ => (), - } - self.bump(); - } - - self.bump(); - - (content_start_bpos, content_end_bpos, hash_count) - } - - fn validate_char_escape(&self, start_with_quote: BytePos) { - let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); - if let Err((off, err)) = unescape::unescape_char(lit) { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Char, - 0..off, - err, - ) - } - } - - fn validate_byte_escape(&self, start_with_quote: BytePos) { - let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); - if let Err((off, err)) = unescape::unescape_byte(lit) { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Byte, - 0..off, - err, - ) - } - } - - fn validate_str_escape(&self, start_with_quote: BytePos) { - let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); - unescape::unescape_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Str, - range, - err, - ) - } - }) - } - - fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_raw_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Str, - range, - err, - ) - } - }) - } - - fn validate_raw_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_raw_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) - } - - fn validate_byte_str_escape(&self, start_with_quote: BytePos) { - let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); - unescape::unescape_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) - } -} - -// This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which -// is guaranteed to be forward compatible. http://unicode.org/reports/tr31/#R3 -#[inline] -crate fn is_pattern_whitespace(c: Option) -> bool { - c.map_or(false, Pattern_White_Space) -} - -#[inline] -fn in_range(c: Option, lo: char, hi: char) -> bool { - c.map_or(false, |c| lo <= c && c <= hi) -} - -#[inline] -fn is_dec_digit(c: Option) -> bool { - in_range(c, '0', '9') -} - -fn is_doc_comment(s: &str) -> bool { - let res = (s.starts_with("///") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'/') || - s.starts_with("//!"); - debug!("is {:?} a doc comment? {}", s, res); - res -} - -fn is_block_doc_comment(s: &str) -> bool { - // Prevent `/**/` from being parsed as a doc comment - let res = ((s.starts_with("/**") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'*') || - s.starts_with("/*!")) && s.len() >= 5; - debug!("is {:?} a doc comment? {}", s, res); - res -} - -/// Determine whether `c` is a valid start for an ident. -fn ident_start(c: Option) -> bool { - let c = match c { - Some(c) => c, - None => return false, - }; - - (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c > '\x7f' && c.is_xid_start()) -} - -fn ident_continue(c: Option) -> bool { - let c = match c { - Some(c) => c, - None => return false, - }; - - (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || - (c > '\x7f' && c.is_xid_continue()) -} - -#[inline] -fn char_at(s: &str, byte: usize) -> char { - s[byte..].chars().next().unwrap() -} - -#[cfg(test)] -mod tests { - use super::*; - - use crate::ast::CrateConfig; - use crate::symbol::Symbol; - use crate::source_map::{SourceMap, FilePathMapping}; - use crate::feature_gate::UnstableFeatures; - use crate::parse::token; - use crate::diagnostics::plugin::ErrorMap; - use crate::with_default_globals; - use std::io; - use std::path::PathBuf; - use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition}; - use rustc_data_structures::fx::{FxHashSet, FxHashMap}; - use rustc_data_structures::sync::Lock; - - fn mk_sess(sm: Lrc) -> ParseSess { - let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), - Some(sm.clone()), - false, - false, - false); - ParseSess { - span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)), - unstable_features: UnstableFeatures::from_environment(), - config: CrateConfig::default(), - included_mod_stack: Lock::new(Vec::new()), - source_map: sm, - missing_fragment_specifiers: Lock::new(FxHashSet::default()), - raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), - buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), - ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), - } - } - - // open a string reader for the given string - fn setup<'a>(sm: &SourceMap, - sess: &'a ParseSess, - teststr: String) - -> StringReader<'a> { - let sf = sm.new_source_file(PathBuf::from(teststr.clone()).into(), teststr); - StringReader::new(sess, sf, None) - } - - #[test] - fn t1() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - let mut string_reader = setup(&sm, - &sh, - "/* my source file */ fn main() { println!(\"zebra\"); }\n" - .to_string()); - assert_eq!(string_reader.next_token(), token::Comment); - assert_eq!(string_reader.next_token(), token::Whitespace); - let tok1 = string_reader.next_token(); - let tok2 = Token::new( - mk_ident("fn"), - Span::new(BytePos(21), BytePos(23), NO_EXPANSION), - ); - assert_eq!(tok1.kind, tok2.kind); - assert_eq!(tok1.span, tok2.span); - assert_eq!(string_reader.next_token(), token::Whitespace); - // read another token: - let tok3 = string_reader.next_token(); - assert_eq!(string_reader.pos.clone(), BytePos(28)); - let tok4 = Token::new( - mk_ident("main"), - Span::new(BytePos(24), BytePos(28), NO_EXPANSION), - ); - assert_eq!(tok3.kind, tok4.kind); - assert_eq!(tok3.span, tok4.span); - - assert_eq!(string_reader.next_token(), token::OpenDelim(token::Paren)); - assert_eq!(string_reader.pos.clone(), BytePos(29)) - }) - } - - // check that the given reader produces the desired stream - // of tokens (stop checking after exhausting the expected vec) - fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec) { - for expected_tok in &expected { - assert_eq!(&string_reader.next_token(), expected_tok); - } - } - - // make the identifier by looking up the string in the interner - fn mk_ident(id: &str) -> TokenKind { - token::Ident(Symbol::intern(id), false) - } - - fn mk_lit(kind: token::LitKind, symbol: &str, suffix: Option<&str>) -> TokenKind { - TokenKind::lit(kind, Symbol::intern(symbol), suffix.map(Symbol::intern)) - } - - #[test] - fn doublecolonparsing() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a b".to_string()), - vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); - }) - } - - #[test] - fn dcparsing_2() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a::b".to_string()), - vec![mk_ident("a"), token::ModSep, mk_ident("b")]); - }) - } - - #[test] - fn dcparsing_3() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a ::b".to_string()), - vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); - }) - } - - #[test] - fn dcparsing_4() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a:: b".to_string()), - vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); - }) - } - - #[test] - fn character_a() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token(), - mk_lit(token::Char, "a", None)); - }) - } - - #[test] - fn character_space() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token(), - mk_lit(token::Char, " ", None)); - }) - } - - #[test] - fn character_escaped() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token(), - mk_lit(token::Char, "\\n", None)); - }) - } - - #[test] - fn lifetime_name() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token(), - token::Lifetime(Symbol::intern("'abc"))); - }) - } - - #[test] - fn raw_string() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token(), - mk_lit(token::StrRaw(3), "\"#a\\b\x00c\"", None)); - }) - } - - #[test] - fn literal_suffixes() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - macro_rules! test { - ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ - assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, Some("suffix"))); - // with a whitespace separator: - assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token(), - mk_lit(token::$tok_type, $tok_contents, None)); - }} - } - - test!("'a'", Char, "a"); - test!("b'a'", Byte, "a"); - test!("\"a\"", Str, "a"); - test!("b\"a\"", ByteStr, "a"); - test!("1234", Integer, "1234"); - test!("0b101", Integer, "0b101"); - test!("0xABC", Integer, "0xABC"); - test!("1.0", Float, "1.0"); - test!("1.0e10", Float, "1.0e10"); - - assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token(), - mk_lit(token::Integer, "2", Some("us"))); - assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::StrRaw(3), "raw", Some("suffix"))); - assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token(), - mk_lit(token::ByteStrRaw(3), "raw", Some("suffix"))); - }) - } - - #[test] - fn line_doc_comments() { - assert!(is_doc_comment("///")); - assert!(is_doc_comment("/// blah")); - assert!(!is_doc_comment("////")); - } - - #[test] - fn nested_block_comments() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - let mut lexer = setup(&sm, &sh, "/* /* */ */'a'".to_string()); - assert_eq!(lexer.next_token(), token::Comment); - assert_eq!(lexer.next_token(), mk_lit(token::Char, "a", None)); - }) - } - - #[test] - fn crlf_comments() { - with_default_globals(|| { - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sh = mk_sess(sm.clone()); - let mut lexer = setup(&sm, &sh, "// test\r\n/// test\r\n".to_string()); - let comment = lexer.next_token(); - assert_eq!(comment.kind, token::Comment); - assert_eq!((comment.span.lo(), comment.span.hi()), (BytePos(0), BytePos(7))); - assert_eq!(lexer.next_token(), token::Whitespace); - assert_eq!(lexer.next_token(), token::DocComment(Symbol::intern("/// test"))); - }) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/lexer/tokentrees.rs b/gcc/rust/rustc_parser/libsyntax/parse/lexer/tokentrees.rs deleted file mode 100644 index 830fbec..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/lexer/tokentrees.rs +++ /dev/null @@ -1,230 +0,0 @@ -use syntax_pos::Span; - -use crate::print::pprust::token_to_string; -use crate::parse::lexer::{StringReader, UnmatchedBrace}; -use crate::parse::token::{self, Token}; -use crate::parse::PResult; -use crate::tokenstream::{DelimSpan, IsJoint::{self, *}, TokenStream, TokenTree, TreeAndJoint}; - -impl<'a> StringReader<'a> { - crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec) { - let mut tt_reader = TokenTreesReader { - string_reader: self, - token: Token::dummy(), - joint_to_prev: Joint, - open_braces: Vec::new(), - unmatched_braces: Vec::new(), - matching_delim_spans: Vec::new(), - last_unclosed_found_span: None, - }; - let res = tt_reader.parse_all_token_trees(); - (res, tt_reader.unmatched_braces) - } -} - -struct TokenTreesReader<'a> { - string_reader: StringReader<'a>, - token: Token, - joint_to_prev: IsJoint, - /// Stack of open delimiters and their spans. Used for error message. - open_braces: Vec<(token::DelimToken, Span)>, - unmatched_braces: Vec, - /// The type and spans for all braces - /// - /// Used only for error recovery when arriving to EOF with mismatched braces. - matching_delim_spans: Vec<(token::DelimToken, Span, Span)>, - last_unclosed_found_span: Option, -} - -impl<'a> TokenTreesReader<'a> { - // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. - fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { - let mut tts = Vec::new(); - - self.real_token(); - while self.token != token::Eof { - tts.push(self.parse_token_tree()?); - } - - Ok(TokenStream::new(tts)) - } - - // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. - fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { - let mut tts = vec![]; - loop { - if let token::CloseDelim(..) = self.token.kind { - return TokenStream::new(tts); - } - - match self.parse_token_tree() { - Ok(tree) => tts.push(tree), - Err(mut e) => { - e.emit(); - return TokenStream::new(tts); - } - } - } - } - - fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { - let sm = self.string_reader.sess.source_map(); - match self.token.kind { - token::Eof => { - let msg = "this file contains an un-closed delimiter"; - let mut err = self.string_reader.sess.span_diagnostic - .struct_span_err(self.token.span, msg); - for &(_, sp) in &self.open_braces { - err.span_label(sp, "un-closed delimiter"); - } - - if let Some((delim, _)) = self.open_braces.last() { - if let Some((_, open_sp, close_sp)) = self.matching_delim_spans.iter() - .filter(|(d, open_sp, close_sp)| { - if let Some(close_padding) = sm.span_to_margin(*close_sp) { - if let Some(open_padding) = sm.span_to_margin(*open_sp) { - return delim == d && close_padding != open_padding; - } - } - false - }).next() // these are in reverse order as they get inserted on close, but - { // we want the last open/first close - err.span_label( - *open_sp, - "this delimiter might not be properly closed...", - ); - err.span_label( - *close_sp, - "...as it matches this but it has different indentation", - ); - } - } - Err(err) - }, - token::OpenDelim(delim) => { - // The span for beginning of the delimited section - let pre_span = self.token.span; - - // Parse the open delimiter. - self.open_braces.push((delim, self.token.span)); - self.real_token(); - - // Parse the token trees within the delimiters. - // We stop at any delimiter so we can try to recover if the user - // uses an incorrect delimiter. - let tts = self.parse_token_trees_until_close_delim(); - - // Expand to cover the entire delimited token tree - let delim_span = DelimSpan::from_pair(pre_span, self.token.span); - - match self.token.kind { - // Correct delimiter. - token::CloseDelim(d) if d == delim => { - let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); - if self.open_braces.len() == 0 { - // Clear up these spans to avoid suggesting them as we've found - // properly matched delimiters so far for an entire block. - self.matching_delim_spans.clear(); - } else { - self.matching_delim_spans.push( - (open_brace, open_brace_span, self.token.span), - ); - } - // Parse the close delimiter. - self.real_token(); - } - // Incorrect delimiter. - token::CloseDelim(other) => { - let mut unclosed_delimiter = None; - let mut candidate = None; - if self.last_unclosed_found_span != Some(self.token.span) { - // do not complain about the same unclosed delimiter multiple times - self.last_unclosed_found_span = Some(self.token.span); - // This is a conservative error: only report the last unclosed - // delimiter. The previous unclosed delimiters could actually be - // closed! The parser just hasn't gotten to them yet. - if let Some(&(_, sp)) = self.open_braces.last() { - unclosed_delimiter = Some(sp); - }; - if let Some(current_padding) = sm.span_to_margin(self.token.span) { - for (brace, brace_span) in &self.open_braces { - if let Some(padding) = sm.span_to_margin(*brace_span) { - // high likelihood of these two corresponding - if current_padding == padding && brace == &other { - candidate = Some(*brace_span); - } - } - } - } - let (tok, _) = self.open_braces.pop().unwrap(); - self.unmatched_braces.push(UnmatchedBrace { - expected_delim: tok, - found_delim: other, - found_span: self.token.span, - unclosed_span: unclosed_delimiter, - candidate_span: candidate, - }); - } else { - self.open_braces.pop(); - } - - // If the incorrect delimiter matches an earlier opening - // delimiter, then don't consume it (it can be used to - // close the earlier one). Otherwise, consume it. - // E.g., we try to recover from: - // fn foo() { - // bar(baz( - // } // Incorrect delimiter but matches the earlier `{` - if !self.open_braces.iter().any(|&(b, _)| b == other) { - self.real_token(); - } - } - token::Eof => { - // Silently recover, the EOF token will be seen again - // and an error emitted then. Thus we don't pop from - // self.open_braces here. - }, - _ => {} - } - - Ok(TokenTree::Delimited( - delim_span, - delim, - tts.into() - ).into()) - }, - token::CloseDelim(_) => { - // An unexpected closing delimiter (i.e., there is no - // matching opening delimiter). - let token_str = token_to_string(&self.token); - let msg = format!("unexpected close delimiter: `{}`", token_str); - let mut err = self.string_reader.sess.span_diagnostic - .struct_span_err(self.token.span, &msg); - err.span_label(self.token.span, "unexpected close delimiter"); - Err(err) - }, - _ => { - let tt = TokenTree::Token(self.token.take()); - self.real_token(); - let is_joint = self.joint_to_prev == Joint && self.token.is_op(); - Ok((tt, if is_joint { Joint } else { NonJoint })) - } - } - } - - fn real_token(&mut self) { - self.joint_to_prev = Joint; - loop { - let token = self.string_reader.next_token(); - match token.kind { - token::Whitespace | token::Comment | token::Shebang(_) => { - self.joint_to_prev = NonJoint; - } - _ => { - self.token = token; - return; - }, - } - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/lexer/unicode_chars.rs b/gcc/rust/rustc_parser/libsyntax/parse/lexer/unicode_chars.rs deleted file mode 100644 index 6a87068..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/lexer/unicode_chars.rs +++ /dev/null @@ -1,393 +0,0 @@ -// Characters and their corresponding confusables were collected from -// http://www.unicode.org/Public/security/10.0.0/confusables.txt - -use super::StringReader; -use errors::{Applicability, DiagnosticBuilder}; -use syntax_pos::{Pos, Span, NO_EXPANSION}; - -#[rustfmt::skip] // for line breaks -const UNICODE_ARRAY: &[(char, &str, char)] = &[ - ('
', "Line Separator", ' '), - ('
', "Paragraph Separator", ' '), - (' ', "Ogham Space mark", ' '), - (' ', "En Quad", ' '), - (' ', "Em Quad", ' '), - (' ', "En Space", ' '), - (' ', "Em Space", ' '), - (' ', "Three-Per-Em Space", ' '), - (' ', "Four-Per-Em Space", ' '), - (' ', "Six-Per-Em Space", ' '), - (' ', "Punctuation Space", ' '), - (' ', "Thin Space", ' '), - (' ', "Hair Space", ' '), - (' ', "Medium Mathematical Space", ' '), - (' ', "No-Break Space", ' '), - (' ', "Figure Space", ' '), - (' ', "Narrow No-Break Space", ' '), - (' ', "Ideographic Space", ' '), - - ('ߺ', "Nko Lajanyalan", '_'), - ('﹍', "Dashed Low Line", '_'), - ('﹎', "Centreline Low Line", '_'), - ('﹏', "Wavy Low Line", '_'), - ('_', "Fullwidth Low Line", '_'), - - ('‐', "Hyphen", '-'), - ('‑', "Non-Breaking Hyphen", '-'), - ('‒', "Figure Dash", '-'), - ('–', "En Dash", '-'), - ('—', "Em Dash", '-'), - ('﹘', "Small Em Dash", '-'), - ('۔', "Arabic Full Stop", '-'), - ('⁃', "Hyphen Bullet", '-'), - ('˗', "Modifier Letter Minus Sign", '-'), - ('−', "Minus Sign", '-'), - ('➖', "Heavy Minus Sign", '-'), - ('Ⲻ', "Coptic Letter Dialect-P Ni", '-'), - ('ー', "Katakana-Hiragana Prolonged Sound Mark", '-'), - ('-', "Fullwidth Hyphen-Minus", '-'), - ('―', "Horizontal Bar", '-'), - ('─', "Box Drawings Light Horizontal", '-'), - ('━', "Box Drawings Heavy Horizontal", '-'), - ('㇐', "CJK Stroke H", '-'), - ('ꟷ', "Latin Epigraphic Letter Dideways", '-'), - ('ᅳ', "Hangul Jungseong Eu", '-'), - ('ㅡ', "Hangul Letter Eu", '-'), - ('一', "CJK Unified Ideograph-4E00", '-'), - ('⼀', "Kangxi Radical One", '-'), - - ('؍', "Arabic Date Separator", ','), - ('٫', "Arabic Decimal Separator", ','), - ('‚', "Single Low-9 Quotation Mark", ','), - ('¸', "Cedilla", ','), - ('ꓹ', "Lisu Letter Tone Na Po", ','), - (',', "Fullwidth Comma", ','), - - (';', "Greek Question Mark", ';'), - (';', "Fullwidth Semicolon", ';'), - ('︔', "Presentation Form For Vertical Semicolon", ';'), - - ('ः', "Devanagari Sign Visarga", ':'), - ('ઃ', "Gujarati Sign Visarga", ':'), - (':', "Fullwidth Colon", ':'), - ('։', "Armenian Full Stop", ':'), - ('܃', "Syriac Supralinear Colon", ':'), - ('܄', "Syriac Sublinear Colon", ':'), - ('᛬', "Runic Multiple Punctuation", ':'), - ('︰', "Presentation Form For Vertical Two Dot Leader", ':'), - ('᠃', "Mongolian Full Stop", ':'), - ('᠉', "Mongolian Manchu Full Stop", ':'), - ('⁚', "Two Dot Punctuation", ':'), - ('׃', "Hebrew Punctuation Sof Pasuq", ':'), - ('˸', "Modifier Letter Raised Colon", ':'), - ('꞉', "Modifier Letter Colon", ':'), - ('∶', "Ratio", ':'), - ('ː', "Modifier Letter Triangular Colon", ':'), - ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'), - ('︓', "Presentation Form For Vertical Colon", ':'), - - ('!', "Fullwidth Exclamation Mark", '!'), - ('ǃ', "Latin Letter Retroflex Click", '!'), - ('ⵑ', "Tifinagh Letter Tuareg Yang", '!'), - ('︕', "Presentation Form For Vertical Exclamation Mark", '!'), - - ('ʔ', "Latin Letter Glottal Stop", '?'), - ('Ɂ', "Latin Capital Letter Glottal Stop", '?'), - ('ॽ', "Devanagari Letter Glottal Stop", '?'), - ('Ꭾ', "Cherokee Letter He", '?'), - ('ꛫ', "Bamum Letter Ntuu", '?'), - ('?', "Fullwidth Question Mark", '?'), - ('︖', "Presentation Form For Vertical Question Mark", '?'), - - ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'), - ('․', "One Dot Leader", '.'), - ('܁', "Syriac Supralinear Full Stop", '.'), - ('܂', "Syriac Sublinear Full Stop", '.'), - ('꘎', "Vai Full Stop", '.'), - ('𐩐', "Kharoshthi Punctuation Dot", '.'), - ('٠', "Arabic-Indic Digit Zero", '.'), - ('۰', "Extended Arabic-Indic Digit Zero", '.'), - ('ꓸ', "Lisu Letter Tone Mya Ti", '.'), - ('·', "Middle Dot", '.'), - ('・', "Katakana Middle Dot", '.'), - ('・', "Halfwidth Katakana Middle Dot", '.'), - ('᛫', "Runic Single Punctuation", '.'), - ('·', "Greek Ano Teleia", '.'), - ('⸱', "Word Separator Middle Dot", '.'), - ('𐄁', "Aegean Word Separator Dot", '.'), - ('•', "Bullet", '.'), - ('‧', "Hyphenation Point", '.'), - ('∙', "Bullet Operator", '.'), - ('⋅', "Dot Operator", '.'), - ('ꞏ', "Latin Letter Sinological Dot", '.'), - ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'), - ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'), - ('.', "Fullwidth Full Stop", '.'), - ('。', "Ideographic Full Stop", '.'), - ('︒', "Presentation Form For Vertical Ideographic Full Stop", '.'), - - ('՝', "Armenian Comma", '\''), - (''', "Fullwidth Apostrophe", '\''), - ('‘', "Left Single Quotation Mark", '\''), - ('’', "Right Single Quotation Mark", '\''), - ('‛', "Single High-Reversed-9 Quotation Mark", '\''), - ('′', "Prime", '\''), - ('‵', "Reversed Prime", '\''), - ('՚', "Armenian Apostrophe", '\''), - ('׳', "Hebrew Punctuation Geresh", '\''), - ('`', "Grave Accent", '\''), - ('`', "Greek Varia", '\''), - ('`', "Fullwidth Grave Accent", '\''), - ('´', "Acute Accent", '\''), - ('΄', "Greek Tonos", '\''), - ('´', "Greek Oxia", '\''), - ('᾽', "Greek Koronis", '\''), - ('᾿', "Greek Psili", '\''), - ('῾', "Greek Dasia", '\''), - ('ʹ', "Modifier Letter Prime", '\''), - ('ʹ', "Greek Numeral Sign", '\''), - ('ˈ', "Modifier Letter Vertical Line", '\''), - ('ˊ', "Modifier Letter Acute Accent", '\''), - ('ˋ', "Modifier Letter Grave Accent", '\''), - ('˴', "Modifier Letter Middle Grave Accent", '\''), - ('ʻ', "Modifier Letter Turned Comma", '\''), - ('ʽ', "Modifier Letter Reversed Comma", '\''), - ('ʼ', "Modifier Letter Apostrophe", '\''), - ('ʾ', "Modifier Letter Right Half Ring", '\''), - ('ꞌ', "Latin Small Letter Saltillo", '\''), - ('י', "Hebrew Letter Yod", '\''), - ('ߴ', "Nko High Tone Apostrophe", '\''), - ('ߵ', "Nko Low Tone Apostrophe", '\''), - ('ᑊ', "Canadian Syllabics West-Cree P", '\''), - ('ᛌ', "Runic Letter Short-Twig-Sol S", '\''), - ('𖽑', "Miao Sign Aspiration", '\''), - ('𖽒', "Miao Sign Reformed Voicing", '\''), - - ('᳓', "Vedic Sign Nihshvasa", '"'), - ('"', "Fullwidth Quotation Mark", '"'), - ('“', "Left Double Quotation Mark", '"'), - ('”', "Right Double Quotation Mark", '"'), - ('‟', "Double High-Reversed-9 Quotation Mark", '"'), - ('″', "Double Prime", '"'), - ('‶', "Reversed Double Prime", '"'), - ('〃', "Ditto Mark", '"'), - ('״', "Hebrew Punctuation Gershayim", '"'), - ('˝', "Double Acute Accent", '"'), - ('ʺ', "Modifier Letter Double Prime", '"'), - ('˶', "Modifier Letter Middle Double Acute Accent", '"'), - ('˵', "Modifier Letter Middle Double Grave Accent", '"'), - ('ˮ', "Modifier Letter Double Apostrophe", '"'), - ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'), - ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'), - ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'), - - ('(', "Fullwidth Left Parenthesis", '('), - ('❨', "Medium Left Parenthesis Ornament", '('), - ('﴾', "Ornate Left Parenthesis", '('), - - (')', "Fullwidth Right Parenthesis", ')'), - ('❩', "Medium Right Parenthesis Ornament", ')'), - ('﴿', "Ornate Right Parenthesis", ')'), - - ('[', "Fullwidth Left Square Bracket", '['), - ('❲', "Light Left Tortoise Shell Bracket Ornament", '['), - ('「', "Left Corner Bracket", '['), - ('『', "Left White Corner Bracket", '['), - ('【', "Left Black Lenticular Bracket", '['), - ('〔', "Left Tortoise Shell Bracket", '['), - ('〖', "Left White Lenticular Bracket", '['), - ('〘', "Left White Tortoise Shell Bracket", '['), - ('〚', "Left White Square Bracket", '['), - - (']', "Fullwidth Right Square Bracket", ']'), - ('❳', "Light Right Tortoise Shell Bracket Ornament", ']'), - ('」', "Right Corner Bracket", ']'), - ('』', "Right White Corner Bracket", ']'), - ('】', "Right Black Lenticular Bracket", ']'), - ('〕', "Right Tortoise Shell Bracket", ']'), - ('〗', "Right White Lenticular Bracket", ']'), - ('〙', "Right White Tortoise Shell Bracket", ']'), - ('〛', "Right White Square Bracket", ']'), - - ('❴', "Medium Left Curly Bracket Ornament", '{'), - ('𝄔', "Musical Symbol Brace", '{'), - ('{', "Fullwidth Left Curly Bracket", '{'), - - ('❵', "Medium Right Curly Bracket Ornament", '}'), - ('}', "Fullwidth Right Curly Bracket", '}'), - - ('⁎', "Low Asterisk", '*'), - ('٭', "Arabic Five Pointed Star", '*'), - ('∗', "Asterisk Operator", '*'), - ('𐌟', "Old Italic Letter Ess", '*'), - ('*', "Fullwidth Asterisk", '*'), - - ('᜵', "Philippine Single Punctuation", '/'), - ('⁁', "Caret Insertion Point", '/'), - ('∕', "Division Slash", '/'), - ('⁄', "Fraction Slash", '/'), - ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'), - ('⟋', "Mathematical Rising Diagonal", '/'), - ('⧸', "Big Solidus", '/'), - ('𝈺', "Greek Instrumental Notation Symbol-47", '/'), - ('㇓', "CJK Stroke Sp", '/'), - ('〳', "Vertical Kana Repeat Mark Upper Half", '/'), - ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), - ('ノ', "Katakana Letter No", '/'), - ('丿', "CJK Unified Ideograph-4E3F", '/'), - ('⼃', "Kangxi Radical Slash", '/'), - ('/', "Fullwidth Solidus", '/'), - - ('\', "Fullwidth Reverse Solidus", '\\'), - ('﹨', "Small Reverse Solidus", '\\'), - ('∖', "Set Minus", '\\'), - ('⟍', "Mathematical Falling Diagonal", '\\'), - ('⧵', "Reverse Solidus Operator", '\\'), - ('⧹', "Big Reverse Solidus", '\\'), - ('⧹', "Greek Vocal Notation Symbol-16", '\\'), - ('⧹', "Greek Instrumental Symbol-48", '\\'), - ('㇔', "CJK Stroke D", '\\'), - ('丶', "CJK Unified Ideograph-4E36", '\\'), - ('⼂', "Kangxi Radical Dot", '\\'), - ('、', "Ideographic Comma", '\\'), - ('ヽ', "Katakana Iteration Mark", '\\'), - - ('ꝸ', "Latin Small Letter Um", '&'), - ('&', "Fullwidth Ampersand", '&'), - - ('᛭', "Runic Cross Punctuation", '+'), - ('➕', "Heavy Plus Sign", '+'), - ('𐊛', "Lycian Letter H", '+'), - ('﬩', "Hebrew Letter Alternative Plus Sign", '+'), - ('+', "Fullwidth Plus Sign", '+'), - - ('‹', "Single Left-Pointing Angle Quotation Mark", '<'), - ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'), - ('˂', "Modifier Letter Left Arrowhead", '<'), - ('𝈶', "Greek Instrumental Symbol-40", '<'), - ('ᐸ', "Canadian Syllabics Pa", '<'), - ('ᚲ', "Runic Letter Kauna", '<'), - ('❬', "Medium Left-Pointing Angle Bracket Ornament", '<'), - ('⟨', "Mathematical Left Angle Bracket", '<'), - ('〈', "Left-Pointing Angle Bracket", '<'), - ('〈', "Left Angle Bracket", '<'), - ('㇛', "CJK Stroke Pd", '<'), - ('く', "Hiragana Letter Ku", '<'), - ('𡿨', "CJK Unified Ideograph-21FE8", '<'), - ('《', "Left Double Angle Bracket", '<'), - ('<', "Fullwidth Less-Than Sign", '<'), - - ('᐀', "Canadian Syllabics Hyphen", '='), - ('⹀', "Double Hyphen", '='), - ('゠', "Katakana-Hiragana Double Hyphen", '='), - ('꓿', "Lisu Punctuation Full Stop", '='), - ('=', "Fullwidth Equals Sign", '='), - - ('›', "Single Right-Pointing Angle Quotation Mark", '>'), - ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'), - ('˃', "Modifier Letter Right Arrowhead", '>'), - ('𝈷', "Greek Instrumental Symbol-42", '>'), - ('ᐳ', "Canadian Syllabics Po", '>'), - ('𖼿', "Miao Letter Archaic Zza", '>'), - ('❭', "Medium Right-Pointing Angle Bracket Ornament", '>'), - ('⟩', "Mathematical Right Angle Bracket", '>'), - ('〉', "Right-Pointing Angle Bracket", '>'), - ('〉', "Right Angle Bracket", '>'), - ('》', "Right Double Angle Bracket", '>'), - ('>', "Fullwidth Greater-Than Sign", '>'), -]; - -const ASCII_ARRAY: &[(char, &str)] = &[ - (' ', "Space"), - ('_', "Underscore"), - ('-', "Minus/Hyphen"), - (',', "Comma"), - (';', "Semicolon"), - (':', "Colon"), - ('!', "Exclamation Mark"), - ('?', "Question Mark"), - ('.', "Period"), - ('\'', "Single Quote"), - ('"', "Quotation Mark"), - ('(', "Left Parenthesis"), - (')', "Right Parenthesis"), - ('[', "Left Square Bracket"), - (']', "Right Square Bracket"), - ('{', "Left Curly Brace"), - ('}', "Right Curly Brace"), - ('*', "Asterisk"), - ('/', "Slash"), - ('\\', "Backslash"), - ('&', "Ampersand"), - ('+', "Plus Sign"), - ('<', "Less-Than Sign"), - ('=', "Equals Sign"), - ('>', "Greater-Than Sign"), -]; - -crate fn check_for_substitution<'a>( - reader: &StringReader<'a>, - ch: char, - err: &mut DiagnosticBuilder<'a>, -) -> bool { - let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) { - Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char), - None => return false, - }; - - let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION); - - let ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) { - Some((_ascii_char, ascii_name)) => ascii_name, - None => { - let msg = format!("substitution character not found for '{}'", ch); - reader.sess.span_diagnostic.span_bug_no_panic(span, &msg); - return false - }, - }; - - // special help suggestion for "directed" double quotes - if let Some(s) = reader.peek_delimited('“', '”') { - let msg = format!( - "Unicode characters '“' (Left Double Quotation Mark) and \ - '”' (Right Double Quotation Mark) look like '{}' ({}), but are not", - ascii_char, ascii_name - ); - err.span_suggestion( - Span::new( - reader.pos, - reader.next_pos + Pos::from_usize(s.len()) + Pos::from_usize('”'.len_utf8()), - NO_EXPANSION, - ), - &msg, - format!("\"{}\"", s), - Applicability::MaybeIncorrect, - ); - } else { - let msg = format!( - "Unicode character '{}' ({}) looks like '{}' ({}), but it is not", - ch, u_name, ascii_char, ascii_name - ); - err.span_suggestion( - span, - &msg, - ascii_char.to_string(), - Applicability::MaybeIncorrect, - ); - } - true -} - -impl StringReader<'_> { - /// Immutably extract string if found at current position with given delimiters - fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<&str> { - let tail = &self.src[self.src_index(self.pos)..]; - let mut chars = tail.chars(); - let first_char = chars.next()?; - if first_char != from_ch { - return None; - } - let last_char_idx = chars.as_str().find(to_ch)?; - Some(&chars.as_str()[..last_char_idx]) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/literal.rs b/gcc/rust/rustc_parser/libsyntax/parse/literal.rs deleted file mode 100644 index ef55bf6..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/literal.rs +++ /dev/null @@ -1,470 +0,0 @@ -//! Code related to parsing literals. - -use crate::ast::{self, Lit, LitKind}; -use crate::parse::parser::Parser; -use crate::parse::PResult; -use crate::parse::token::{self, Token, TokenKind}; -use crate::parse::unescape::{unescape_char, unescape_byte}; -use crate::parse::unescape::{unescape_str, unescape_byte_str}; -use crate::parse::unescape::{unescape_raw_str, unescape_raw_byte_str}; -use crate::print::pprust; -use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::{TokenStream, TokenTree}; - -use errors::{Applicability, Handler}; -use log::debug; -use rustc_data_structures::sync::Lrc; -use syntax_pos::Span; - -use std::ascii; - -crate enum LitError { - NotLiteral, - LexerError, - InvalidSuffix, - InvalidIntSuffix, - InvalidFloatSuffix, - NonDecimalFloat(u32), - IntTooLarge, -} - -impl LitError { - fn report(&self, diag: &Handler, lit: token::Lit, span: Span) { - let token::Lit { kind, suffix, .. } = lit; - match *self { - // `NotLiteral` is not an error by itself, so we don't report - // it and give the parser opportunity to try something else. - LitError::NotLiteral => {} - // `LexerError` *is* an error, but it was already reported - // by lexer, so here we don't report it the second time. - LitError::LexerError => {} - LitError::InvalidSuffix => { - expect_no_suffix( - diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix - ); - } - LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['i', 'u'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for integer literal", &suf[1..]); - diag.struct_span_err(span, &msg) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for integer literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("the suffix must be one of the integral types (`u32`, `isize`, etc)") - .emit(); - } - } - LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['f'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for float literal", &suf[1..]); - diag.struct_span_err(span, &msg) - .help("valid widths are 32 and 64") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for float literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("valid suffixes are `f32` and `f64`") - .emit(); - } - } - LitError::NonDecimalFloat(base) => { - let descr = match base { - 16 => "hexadecimal", - 8 => "octal", - 2 => "binary", - _ => unreachable!(), - }; - diag.struct_span_err(span, &format!("{} float literal is not supported", descr)) - .span_label(span, "not supported") - .emit(); - } - LitError::IntTooLarge => { - diag.struct_span_err(span, "integer literal is too large") - .emit(); - } - } - } -} - -impl LitKind { - /// Converts literal token into a semantic literal. - fn from_lit_token(lit: token::Lit) -> Result { - let token::Lit { kind, symbol, suffix } = lit; - if suffix.is_some() && !kind.may_have_suffix() { - return Err(LitError::InvalidSuffix); - } - - Ok(match kind { - token::Bool => { - assert!(symbol == kw::True || symbol == kw::False); - LitKind::Bool(symbol == kw::True) - } - token::Byte => return unescape_byte(&symbol.as_str()) - .map(LitKind::Byte).map_err(|_| LitError::LexerError), - token::Char => return unescape_char(&symbol.as_str()) - .map(LitKind::Char).map_err(|_| LitError::LexerError), - - // There are some valid suffixes for integer and float literals, - // so all the handling is done internally. - token::Integer => return integer_lit(symbol, suffix), - token::Float => return float_lit(symbol, suffix), - - token::Str => { - // If there are no characters requiring special treatment we can - // reuse the symbol from the token. Otherwise, we must generate a - // new symbol because the string in the LitKind is different to the - // string in the token. - let s = symbol.as_str(); - let symbol = if s.contains(&['\\', '\r'][..]) { - let mut buf = String::with_capacity(s.len()); - let mut error = Ok(()); - unescape_str(&s, &mut |_, unescaped_char| { - match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - } - }); - error?; - Symbol::intern(&buf) - } else { - symbol - }; - LitKind::Str(symbol, ast::StrStyle::Cooked) - } - token::StrRaw(n) => { - // Ditto. - let s = symbol.as_str(); - let symbol = if s.contains('\r') { - let mut buf = String::with_capacity(s.len()); - let mut error = Ok(()); - unescape_raw_str(&s, &mut |_, unescaped_char| { - match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - } - }); - error?; - buf.shrink_to_fit(); - Symbol::intern(&buf) - } else { - symbol - }; - LitKind::Str(symbol, ast::StrStyle::Raw(n)) - } - token::ByteStr => { - let s = symbol.as_str(); - let mut buf = Vec::with_capacity(s.len()); - let mut error = Ok(()); - unescape_byte_str(&s, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - } - }); - error?; - buf.shrink_to_fit(); - LitKind::ByteStr(Lrc::new(buf)) - } - token::ByteStrRaw(_) => { - let s = symbol.as_str(); - let bytes = if s.contains('\r') { - let mut buf = Vec::with_capacity(s.len()); - let mut error = Ok(()); - unescape_raw_byte_str(&s, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - } - }); - error?; - buf.shrink_to_fit(); - buf - } else { - symbol.to_string().into_bytes() - }; - - LitKind::ByteStr(Lrc::new(bytes)) - }, - token::Err => LitKind::Err(symbol), - }) - } - - /// Attempts to recover a token from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn to_lit_token(&self) -> token::Lit { - let (kind, symbol, suffix) = match *self { - LitKind::Str(symbol, ast::StrStyle::Cooked) => { - // Don't re-intern unless the escaped string is different. - let s = &symbol.as_str(); - let escaped = s.escape_default().to_string(); - let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) }; - (token::Str, symbol, None) - } - LitKind::Str(symbol, ast::StrStyle::Raw(n)) => { - (token::StrRaw(n), symbol, None) - } - LitKind::ByteStr(ref bytes) => { - let string = bytes.iter().cloned().flat_map(ascii::escape_default) - .map(Into::::into).collect::(); - (token::ByteStr, Symbol::intern(&string), None) - } - LitKind::Byte(byte) => { - let string: String = ascii::escape_default(byte).map(Into::::into).collect(); - (token::Byte, Symbol::intern(&string), None) - } - LitKind::Char(ch) => { - let string: String = ch.escape_default().map(Into::::into).collect(); - (token::Char, Symbol::intern(&string), None) - } - LitKind::Int(n, ty) => { - let suffix = match ty { - ast::LitIntType::Unsigned(ty) => Some(ty.to_symbol()), - ast::LitIntType::Signed(ty) => Some(ty.to_symbol()), - ast::LitIntType::Unsuffixed => None, - }; - (token::Integer, sym::integer(n), suffix) - } - LitKind::Float(symbol, ty) => { - (token::Float, symbol, Some(ty.to_symbol())) - } - LitKind::FloatUnsuffixed(symbol) => { - (token::Float, symbol, None) - } - LitKind::Bool(value) => { - let symbol = if value { kw::True } else { kw::False }; - (token::Bool, symbol, None) - } - LitKind::Err(symbol) => { - (token::Err, symbol, None) - } - }; - - token::Lit::new(kind, symbol, suffix) - } -} - -impl Lit { - /// Converts literal token into an AST literal. - fn from_lit_token(token: token::Lit, span: Span) -> Result { - Ok(Lit { token, node: LitKind::from_lit_token(token)?, span }) - } - - /// Converts arbitrary token into an AST literal. - crate fn from_token(token: &Token) -> Result { - let lit = match token.kind { - token::Ident(name, false) if name == kw::True || name == kw::False => - token::Lit::new(token::Bool, name, None), - token::Literal(lit) => - lit, - token::Interpolated(ref nt) => { - if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { - if let ast::ExprKind::Lit(lit) = &expr.node { - return Ok(lit.clone()); - } - } - return Err(LitError::NotLiteral); - } - _ => return Err(LitError::NotLiteral) - }; - - Lit::from_lit_token(lit, token.span) - } - - /// Attempts to recover an AST literal from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn from_lit_kind(node: LitKind, span: Span) -> Lit { - Lit { token: node.to_lit_token(), node, span } - } - - /// Losslessly convert an AST literal into a token stream. - crate fn tokens(&self) -> TokenStream { - let token = match self.token.kind { - token::Bool => token::Ident(self.token.symbol, false), - _ => token::Literal(self.token), - }; - TokenTree::token(token, self.span).into() - } -} - -impl<'a> Parser<'a> { - /// Matches `lit = true | false | token_lit`. - crate fn parse_lit(&mut self) -> PResult<'a, Lit> { - let mut recovered = None; - if self.token == token::Dot { - // Attempt to recover `.4` as `0.4`. - recovered = self.look_ahead(1, |next_token| { - if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) - = next_token.kind { - if self.token.span.hi() == next_token.span.lo() { - let s = String::from("0.") + &symbol.as_str(); - let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); - return Some(Token::new(kind, self.token.span.to(next_token.span))); - } - } - None - }); - if let Some(token) = &recovered { - self.bump(); - self.diagnostic() - .struct_span_err(token.span, "float literals must have an integer part") - .span_suggestion( - token.span, - "must have an integer part", - pprust::token_to_string(token), - Applicability::MachineApplicable, - ) - .emit(); - } - } - - let token = recovered.as_ref().unwrap_or(&self.token); - match Lit::from_token(token) { - Ok(lit) => { - self.bump(); - Ok(lit) - } - Err(LitError::NotLiteral) => { - let msg = format!("unexpected token: {}", self.this_token_descr()); - Err(self.span_fatal(token.span, &msg)) - } - Err(err) => { - let (lit, span) = (token.expect_lit(), token.span); - self.bump(); - err.report(&self.sess.span_diagnostic, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&pprust::literal_to_string(suffixless_lit)); - let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) - } - } - } -} - -crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option) { - if let Some(suf) = suffix { - let mut err = if kind == "a tuple index" && - [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = diag.struct_span_warn( - sp, - &format!("suffixes on {} are invalid", kind), - ); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - suf, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "for more context, see https://github.com/rust-lang/rust/issues/60210", - ); - err - } else { - diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) - }; - err.span_label(sp, format!("invalid suffix `{}`", suf)); - err.emit(); - } -} - -// Checks if `s` looks like i32 or u1234 etc. -fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) -} - -fn strip_underscores(symbol: Symbol) -> Symbol { - // Do not allocate a new string unless necessary. - let s = symbol.as_str(); - if s.contains('_') { - let mut s = s.to_string(); - s.retain(|c| c != '_'); - return Symbol::intern(&s); - } - symbol -} - -fn filtered_float_lit(symbol: Symbol, suffix: Option, base: u32) - -> Result { - debug!("filtered_float_lit: {:?}, {:?}, {:?}", symbol, suffix, base); - if base != 10 { - return Err(LitError::NonDecimalFloat(base)); - } - Ok(match suffix { - Some(suf) => match suf { - sym::f32 => LitKind::Float(symbol, ast::FloatTy::F32), - sym::f64 => LitKind::Float(symbol, ast::FloatTy::F64), - _ => return Err(LitError::InvalidFloatSuffix), - } - None => LitKind::FloatUnsuffixed(symbol) - }) -} - -fn float_lit(symbol: Symbol, suffix: Option) -> Result { - debug!("float_lit: {:?}, {:?}", symbol, suffix); - filtered_float_lit(strip_underscores(symbol), suffix, 10) -} - -fn integer_lit(symbol: Symbol, suffix: Option) -> Result { - debug!("integer_lit: {:?}, {:?}", symbol, suffix); - let symbol = strip_underscores(symbol); - let s = symbol.as_str(); - - let mut base = 10; - if s.len() > 1 && s.as_bytes()[0] == b'0' { - match s.as_bytes()[1] { - b'x' => base = 16, - b'o' => base = 8, - b'b' => base = 2, - _ => {} - } - } - - let ty = match suffix { - Some(suf) => match suf { - sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize), - sym::i8 => ast::LitIntType::Signed(ast::IntTy::I8), - sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16), - sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32), - sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64), - sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128), - sym::usize => ast::LitIntType::Unsigned(ast::UintTy::Usize), - sym::u8 => ast::LitIntType::Unsigned(ast::UintTy::U8), - sym::u16 => ast::LitIntType::Unsigned(ast::UintTy::U16), - sym::u32 => ast::LitIntType::Unsigned(ast::UintTy::U32), - sym::u64 => ast::LitIntType::Unsigned(ast::UintTy::U64), - sym::u128 => ast::LitIntType::Unsigned(ast::UintTy::U128), - // `1f64` and `2f32` etc. are valid float literals, and - // `fxxx` looks more like an invalid float literal than invalid integer literal. - _ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base), - _ => return Err(LitError::InvalidIntSuffix), - } - _ => ast::LitIntType::Unsuffixed - }; - - let s = &s[if base != 10 { 2 } else { 0 } ..]; - u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| { - // Small bases are lexed as if they were base 10, e.g, the string - // might be `0b10201`. This will cause the conversion above to fail, - // but these kinds of errors are already reported by the lexer. - let from_lexer = - base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge } - }) -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/mod.rs b/gcc/rust/rustc_parser/libsyntax/parse/mod.rs deleted file mode 100644 index 4c4551b..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/mod.rs +++ /dev/null @@ -1,680 +0,0 @@ -//! The main parser interface. - -use crate::ast::{self, CrateConfig, NodeId}; -use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; -use crate::source_map::{SourceMap, FilePathMapping}; -use crate::feature_gate::UnstableFeatures; -use crate::parse::parser::Parser; -use crate::parse::parser::emit_unclosed_delims; -use crate::parse::token::TokenKind; -use crate::tokenstream::{TokenStream, TokenTree}; -use crate::diagnostics::plugin::ErrorMap; -use crate::print::pprust; - -use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; -use rustc_data_structures::sync::{Lrc, Lock}; -use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; -use syntax_pos::edition::Edition; - -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use std::borrow::Cow; -use std::path::{Path, PathBuf}; -use std::str; - -pub type PResult<'a, T> = Result>; - -#[macro_use] -pub mod parser; -pub mod attr; -pub mod lexer; -pub mod token; - -crate mod classify; -crate mod diagnostics; -crate mod literal; -crate mod unescape; -crate mod unescape_error_reporting; - -/// Info about a parsing session. -pub struct ParseSess { - pub span_diagnostic: Handler, - pub unstable_features: UnstableFeatures, - pub config: CrateConfig, - pub edition: Edition, - pub missing_fragment_specifiers: Lock>, - /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. - pub raw_identifier_spans: Lock>, - /// The registered diagnostics codes. - crate registered_diagnostics: Lock, - /// Used to determine and report recursive module inclusions. - included_mod_stack: Lock>, - source_map: Lrc, - pub buffered_lints: Lock>, - /// Contains the spans of block expressions that could have been incomplete based on the - /// operation token that followed it, but that the parser cannot identify without further - /// analysis. - pub ambiguous_block_expr_parse: Lock>, - pub param_attr_spans: Lock>, - // Places where `let` exprs were used and should be feature gated according to `let_chains`. - pub let_chains_spans: Lock>, - // Places where `async || ..` exprs were used and should be feature gated. - pub async_closure_spans: Lock>, -} - -impl ParseSess { - pub fn new(file_path_mapping: FilePathMapping) -> Self { - let cm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, - true, - None, - Some(cm.clone())); - ParseSess::with_span_handler(handler, cm) - } - - pub fn with_span_handler(handler: Handler, source_map: Lrc) -> ParseSess { - ParseSess { - span_diagnostic: handler, - unstable_features: UnstableFeatures::from_environment(), - config: FxHashSet::default(), - missing_fragment_specifiers: Lock::new(FxHashSet::default()), - raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), - included_mod_stack: Lock::new(vec![]), - source_map, - buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), - ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), - } - } - - #[inline] - pub fn source_map(&self) -> &SourceMap { - &self.source_map - } - - pub fn buffer_lint>(&self, - lint_id: BufferedEarlyLintId, - span: S, - id: NodeId, - msg: &str, - ) { - self.buffered_lints.with_lock(|buffered_lints| { - buffered_lints.push(BufferedEarlyLint{ - span: span.into(), - id, - msg: msg.into(), - lint_id, - }); - }); - } - - /// Extend an error with a suggestion to wrap an expression with parentheses to allow the - /// parser to continue parsing the following operation as part of the same expression. - pub fn expr_parentheses_needed( - &self, - err: &mut DiagnosticBuilder<'_>, - span: Span, - alt_snippet: Option, - ) { - if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { - err.span_suggestion( - span, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } - } -} - -#[derive(Clone)] -pub struct Directory<'a> { - pub path: Cow<'a, Path>, - pub ownership: DirectoryOwnership, -} - -#[derive(Copy, Clone)] -pub enum DirectoryOwnership { - Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs` - relative: Option, - }, - UnownedViaBlock, - UnownedViaMod(bool /* legacy warnings? */), -} - -// a bunch of utility functions of the form parse__from_ -// where includes crate, expr, item, stmt, tts, and one that -// uses a HOF to parse anything, and includes file and -// source_str. - -pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> { - let mut parser = new_parser_from_file(sess, input); - parser.parse_crate_mod() -} - -pub fn parse_crate_attrs_from_file<'a>(input: &Path, sess: &'a ParseSess) - -> PResult<'a, Vec> { - let mut parser = new_parser_from_file(sess, input); - parser.parse_inner_attributes() -} - -pub fn parse_crate_from_source_str(name: FileName, source: String, sess: &ParseSess) - -> PResult<'_, ast::Crate> { - new_parser_from_source_str(sess, name, source).parse_crate_mod() -} - -pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &ParseSess) - -> PResult<'_, Vec> { - new_parser_from_source_str(sess, name, source).parse_inner_attributes() -} - -pub fn parse_stream_from_source_str( - name: FileName, - source: String, - sess: &ParseSess, - override_span: Option, -) -> TokenStream { - let (stream, mut errors) = source_file_to_stream( - sess, - sess.source_map().new_source_file(name, source), - override_span, - ); - emit_unclosed_delims(&mut errors, &sess.span_diagnostic); - stream -} - -/// Creates a new parser from a source string. -pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(&sess.span_diagnostic, maybe_new_parser_from_source_str(sess, name, source)) -} - -/// Creates a new parser from a source string. Returns any buffered errors from lexing the initial -/// token stream. -pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) - -> Result, Vec> -{ - let mut parser = maybe_source_file_to_parser(sess, - sess.source_map().new_source_file(name, source))?; - parser.recurse_into_file_modules = false; - Ok(parser) -} - -/// Creates a new parser, handling errors as appropriate -/// if the file doesn't exist -pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> { - source_file_to_parser(sess, file_to_source_file(sess, path, None)) -} - -/// Creates a new parser, returning buffered diagnostics if the file doesn't -/// exist or from lexing the initial token stream. -pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) - -> Result, Vec> { - let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?; - maybe_source_file_to_parser(sess, file) -} - -/// Given a session, a crate config, a path, and a span, add -/// the file at the given path to the source_map, and return a parser. -/// On an error, use the given span as the source of the problem. -pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, - path: &Path, - directory_ownership: DirectoryOwnership, - module_name: Option, - sp: Span) -> Parser<'a> { - let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp))); - p.directory.ownership = directory_ownership; - p.root_module_name = module_name; - p -} - -/// Given a source_file and config, return a parser -fn source_file_to_parser(sess: &ParseSess, source_file: Lrc) -> Parser<'_> { - panictry_buffer!(&sess.span_diagnostic, - maybe_source_file_to_parser(sess, source_file)) -} - -/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the -/// initial token stream. -fn maybe_source_file_to_parser( - sess: &ParseSess, - source_file: Lrc, -) -> Result, Vec> { - let end_pos = source_file.end_pos; - let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?; - let mut parser = stream_to_parser(sess, stream, None); - parser.unclosed_delims = unclosed_delims; - if parser.token == token::Eof && parser.token.span.is_dummy() { - parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); - } - - Ok(parser) -} - -// must preserve old name for now, because quote! from the *existing* -// compiler expands into it -pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec) -> Parser<'_> { - stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS) -} - - -// base abstractions - -/// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's source_map and return the new source_file or -/// error when a file can't be read. -fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) - -> Result, Diagnostic> { - sess.source_map().load_file(path) - .map_err(|e| { - let msg = format!("couldn't read {}: {}", path.display(), e); - let mut diag = Diagnostic::new(Level::Fatal, &msg); - if let Some(sp) = spanopt { - diag.set_span(sp); - } - diag - }) -} - -/// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's `source_map` and return the new `source_file`. -fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) - -> Lrc { - match try_file_to_source_file(sess, path, spanopt) { - Ok(source_file) => source_file, - Err(d) => { - DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit(); - FatalError.raise(); - } - } -} - -/// Given a source_file, produces a sequence of token trees. -pub fn source_file_to_stream( - sess: &ParseSess, - source_file: Lrc, - override_span: Option, -) -> (TokenStream, Vec) { - panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span)) -} - -/// Given a source file, produces a sequence of token trees. Returns any buffered errors from -/// parsing the token stream. -pub fn maybe_file_to_stream( - sess: &ParseSess, - source_file: Lrc, - override_span: Option, -) -> Result<(TokenStream, Vec), Vec> { - let srdr = lexer::StringReader::new(sess, source_file, override_span); - let (token_trees, unmatched_braces) = srdr.into_token_trees(); - - match token_trees { - Ok(stream) => Ok((stream, unmatched_braces)), - Err(err) => { - let mut buffer = Vec::with_capacity(1); - err.buffer(&mut buffer); - // Not using `emit_unclosed_delims` to use `db.buffer` - for unmatched in unmatched_braces { - let mut db = sess.span_diagnostic.struct_span_err(unmatched.found_span, &format!( - "incorrect close delimiter: `{}`", - pprust::token_kind_to_string(&token::CloseDelim(unmatched.found_delim)), - )); - db.span_label(unmatched.found_span, "incorrect close delimiter"); - if let Some(sp) = unmatched.candidate_span { - db.span_label(sp, "close delimiter possibly meant for this"); - } - if let Some(sp) = unmatched.unclosed_span { - db.span_label(sp, "un-closed delimiter"); - } - db.buffer(&mut buffer); - } - Err(buffer) - } - } -} - -/// Given stream and the `ParseSess`, produces a parser. -pub fn stream_to_parser<'a>( - sess: &'a ParseSess, - stream: TokenStream, - subparser_name: Option<&'static str>, -) -> Parser<'a> { - Parser::new(sess, stream, None, true, false, subparser_name) -} - -/// Given stream, the `ParseSess` and the base directory, produces a parser. -/// -/// Use this function when you are creating a parser from the token stream -/// and also care about the current working directory of the parser (e.g., -/// you are trying to resolve modules defined inside a macro invocation). -/// -/// # Note -/// -/// The main usage of this function is outside of rustc, for those who uses -/// libsyntax as a library. Please do not remove this function while refactoring -/// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir<'a>( - sess: &'a ParseSess, - stream: TokenStream, - base_dir: Directory<'a>, -) -> Parser<'a> { - Parser::new(sess, stream, Some(base_dir), true, false, None) -} - -/// A sequence separator. -pub struct SeqSep { - /// The seperator token. - pub sep: Option, - /// `true` if a trailing separator is allowed. - pub trailing_sep_allowed: bool, -} - -impl SeqSep { - pub fn trailing_allowed(t: TokenKind) -> SeqSep { - SeqSep { - sep: Some(t), - trailing_sep_allowed: true, - } - } - - pub fn none() -> SeqSep { - SeqSep { - sep: None, - trailing_sep_allowed: false, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ast::{self, Name, PatKind}; - use crate::attr::first_attr_value_str_by_name; - use crate::ptr::P; - use crate::parse::token::Token; - use crate::print::pprust::item_to_string; - use crate::symbol::{kw, sym}; - use crate::tokenstream::{DelimSpan, TokenTree}; - use crate::util::parser_testing::string_to_stream; - use crate::util::parser_testing::{string_to_expr, string_to_item}; - use crate::with_default_globals; - use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION}; - - /// Parses an item. - /// - /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err` - /// when a syntax error occurred. - fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess) - -> PResult<'_, Option>> { - new_parser_from_source_str(sess, name, source).parse_item() - } - - // produce a syntax_pos::span - fn sp(a: u32, b: u32) -> Span { - Span::new(BytePos(a), BytePos(b), NO_EXPANSION) - } - - #[should_panic] - #[test] fn bad_path_expr_1() { - with_default_globals(|| { - string_to_expr("::abc::def::return".to_string()); - }) - } - - // check the token-tree-ization of macros - #[test] - fn string_to_tts_macro () { - with_default_globals(|| { - let tts: Vec<_> = - string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); - let tts: &[TokenTree] = &tts[..]; - - match tts { - [ - TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), - TokenTree::Token(Token { kind: token::Not, .. }), - TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), - TokenTree::Delimited(_, macro_delim, macro_tts) - ] - if name_macro_rules == &sym::macro_rules && name_zip.as_str() == "zip" => { - let tts = ¯o_tts.trees().collect::>(); - match &tts[..] { - [ - TokenTree::Delimited(_, first_delim, first_tts), - TokenTree::Token(Token { kind: token::FatArrow, .. }), - TokenTree::Delimited(_, second_delim, second_tts), - ] - if macro_delim == &token::Paren => { - let tts = &first_tts.trees().collect::>(); - match &tts[..] { - [ - TokenTree::Token(Token { kind: token::Dollar, .. }), - TokenTree::Token(Token { kind: token::Ident(name, false), .. }), - ] - if first_delim == &token::Paren && name.as_str() == "a" => {}, - _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), - } - let tts = &second_tts.trees().collect::>(); - match &tts[..] { - [ - TokenTree::Token(Token { kind: token::Dollar, .. }), - TokenTree::Token(Token { kind: token::Ident(name, false), .. }), - ] - if second_delim == &token::Paren && name.as_str() == "a" => {}, - _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), - } - }, - _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts), - } - }, - _ => panic!("value: {:?}",tts), - } - }) - } - - #[test] - fn string_to_tts_1() { - with_default_globals(|| { - let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); - - let expected = TokenStream::new(vec![ - TokenTree::token(token::Ident(kw::Fn, false), sp(0, 2)).into(), - TokenTree::token(token::Ident(Name::intern("a"), false), sp(3, 4)).into(), - TokenTree::Delimited( - DelimSpan::from_pair(sp(5, 6), sp(13, 14)), - token::DelimToken::Paren, - TokenStream::new(vec![ - TokenTree::token(token::Ident(Name::intern("b"), false), sp(6, 7)).into(), - TokenTree::token(token::Colon, sp(8, 9)).into(), - TokenTree::token(token::Ident(sym::i32, false), sp(10, 13)).into(), - ]).into(), - ).into(), - TokenTree::Delimited( - DelimSpan::from_pair(sp(15, 16), sp(20, 21)), - token::DelimToken::Brace, - TokenStream::new(vec![ - TokenTree::token(token::Ident(Name::intern("b"), false), sp(17, 18)).into(), - TokenTree::token(token::Semi, sp(18, 19)).into(), - ]).into(), - ).into() - ]); - - assert_eq!(tts, expected); - }) - } - - #[test] fn parse_use() { - with_default_globals(|| { - let use_s = "use foo::bar::baz;"; - let vitem = string_to_item(use_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], use_s); - - let use_s = "use foo::bar as baz;"; - let vitem = string_to_item(use_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], use_s); - }) - } - - #[test] fn parse_extern_crate() { - with_default_globals(|| { - let ex_s = "extern crate foo;"; - let vitem = string_to_item(ex_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], ex_s); - - let ex_s = "extern crate foo as bar;"; - let vitem = string_to_item(ex_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], ex_s); - }) - } - - fn get_spans_of_pat_idents(src: &str) -> Vec { - let item = string_to_item(src.to_string()).unwrap(); - - struct PatIdentVisitor { - spans: Vec - } - impl<'a> crate::visit::Visitor<'a> for PatIdentVisitor { - fn visit_pat(&mut self, p: &'a ast::Pat) { - match p.node { - PatKind::Ident(_ , ref spannedident, _) => { - self.spans.push(spannedident.span.clone()); - } - _ => { - crate::visit::walk_pat(self, p); - } - } - } - } - let mut v = PatIdentVisitor { spans: Vec::new() }; - crate::visit::walk_item(&mut v, &item); - return v.spans; - } - - #[test] fn span_of_self_arg_pat_idents_are_correct() { - with_default_globals(|| { - - let srcs = ["impl z { fn a (&self, &myarg: i32) {} }", - "impl z { fn a (&mut self, &myarg: i32) {} }", - "impl z { fn a (&'a self, &myarg: i32) {} }", - "impl z { fn a (self, &myarg: i32) {} }", - "impl z { fn a (self: Foo, &myarg: i32) {} }", - ]; - - for &src in &srcs { - let spans = get_spans_of_pat_idents(src); - let (lo, hi) = (spans[0].lo(), spans[0].hi()); - assert!("self" == &src[lo.to_usize()..hi.to_usize()], - "\"{}\" != \"self\". src=\"{}\"", - &src[lo.to_usize()..hi.to_usize()], src) - } - }) - } - - #[test] fn parse_exprs () { - with_default_globals(|| { - // just make sure that they parse.... - string_to_expr("3 + 4".to_string()); - string_to_expr("a::z.froob(b,&(987+3))".to_string()); - }) - } - - #[test] fn attrs_fix_bug () { - with_default_globals(|| { - string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) - -> Result, String> { - #[cfg(windows)] - fn wb() -> c_int { - (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int - } - - #[cfg(unix)] - fn wb() -> c_int { O_WRONLY as c_int } - - let mut fflags: c_int = wb(); -}".to_string()); - }) - } - - #[test] fn crlf_doc_comments() { - with_default_globals(|| { - let sess = ParseSess::new(FilePathMapping::empty()); - - let name_1 = FileName::Custom("crlf_source_1".to_string()); - let source = "/// doc comment\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_1, source, &sess) - .unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); - assert_eq!(doc.as_str(), "/// doc comment"); - - let name_2 = FileName::Custom("crlf_source_2".to_string()); - let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_2, source, &sess) - .unwrap().unwrap(); - let docs = item.attrs.iter().filter(|a| a.path == sym::doc) - .map(|a| a.value_str().unwrap().to_string()).collect::>(); - let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; - assert_eq!(&docs[..], b); - - let name_3 = FileName::Custom("clrf_source_3".to_string()); - let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap(); - assert_eq!(doc.as_str(), "/** doc comment\n * with CRLF */"); - }); - } - - #[test] - fn ttdelim_span() { - fn parse_expr_from_source_str( - name: FileName, source: String, sess: &ParseSess - ) -> PResult<'_, P> { - new_parser_from_source_str(sess, name, source).parse_expr() - } - - with_default_globals(|| { - let sess = ParseSess::new(FilePathMapping::empty()); - let expr = parse_expr_from_source_str(PathBuf::from("foo").into(), - "foo!( fn main() { body } )".to_string(), &sess).unwrap(); - - let tts: Vec<_> = match expr.node { - ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(), - _ => panic!("not a macro"), - }; - - let span = tts.iter().rev().next().unwrap().span(); - - match sess.source_map().span_to_snippet(span) { - Ok(s) => assert_eq!(&s[..], "{ body }"), - Err(_) => panic!("could not get snippet"), - } - }); - } - - // This tests that when parsing a string (rather than a file) we don't try - // and read in a file for a module declaration and just parse a stub. - // See `recurse_into_file_modules` in the parser. - #[test] - fn out_of_line_mod() { - with_default_globals(|| { - let sess = ParseSess::new(FilePathMapping::empty()); - let item = parse_item_from_source_str( - PathBuf::from("foo").into(), - "mod foo { struct S; mod this_does_not_exist; }".to_owned(), - &sess, - ).unwrap().unwrap(); - - if let ast::ItemKind::Mod(ref m) = item.node { - assert!(m.items.len() == 2); - } else { - panic!(); - } - }); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/parse/parser.rs b/gcc/rust/rustc_parser/libsyntax/parse/parser.rs deleted file mode 100644 index a95b689..0000000 --- a/gcc/rust/rustc_parser/libsyntax/parse/parser.rs +++ /dev/null @@ -1,7852 +0,0 @@ -// ignore-tidy-filelength - -use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; -use crate::ast::{GenericBound, TraitBoundModifier}; -use crate::ast::Unsafety; -use crate::ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; -use crate::ast::Block; -use crate::ast::{BlockCheckMode, CaptureBy, Movability}; -use crate::ast::{Constness, Crate}; -use crate::ast::Defaultness; -use crate::ast::EnumDef; -use crate::ast::{Expr, ExprKind, RangeLimits}; -use crate::ast::{Field, FnDecl, FnHeader}; -use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; -use crate::ast::{GenericParam, GenericParamKind}; -use crate::ast::GenericArg; -use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; -use crate::ast::{Label, Lifetime}; -use crate::ast::Local; -use crate::ast::MacStmtStyle; -use crate::ast::{Mac, Mac_, MacDelimiter}; -use crate::ast::{MutTy, Mutability}; -use crate::ast::{Pat, PatKind, PathSegment}; -use crate::ast::{PolyTraitRef, QSelf}; -use crate::ast::{Stmt, StmtKind}; -use crate::ast::{VariantData, StructField}; -use crate::ast::StrStyle; -use crate::ast::SelfKind; -use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use crate::ast::{Ty, TyKind, AssocTyConstraint, AssocTyConstraintKind, GenericBounds}; -use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; -use crate::ast::{UseTree, UseTreeKind}; -use crate::ast::{BinOpKind, UnOp}; -use crate::ast::{RangeEnd, RangeSyntax}; -use crate::{ast, attr}; -use crate::ext::base::DummyResult; -use crate::ext::hygiene::SyntaxContext; -use crate::source_map::{self, SourceMap, Spanned, respan}; -use crate::parse::{SeqSep, classify, literal, token}; -use crate::parse::lexer::UnmatchedBrace; -use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use crate::parse::token::{Token, TokenKind, DelimToken}; -use crate::parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; -use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; -use crate::print::pprust; -use crate::ptr::P; -use crate::parse::PResult; -use crate::ThinVec; -use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; -use crate::symbol::{kw, sym, Symbol}; -use crate::parse::diagnostics::{Error, dummy_arg}; - -use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; -use rustc_target::spec::abi::{self, Abi}; -use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; -use log::debug; - -use std::borrow::Cow; -use std::cmp; -use std::mem; -use std::path::{self, Path, PathBuf}; -use std::slice; - -#[derive(Debug)] -/// Whether the type alias or associated type is a concrete type or an existential type -pub enum AliasKind { - /// Just a new name for the same type - Weak(P), - /// Only trait impls of the type will be usable, not the actual type itself - Existential(GenericBounds), -} - -bitflags::bitflags! { - struct Restrictions: u8 { - const STMT_EXPR = 1 << 0; - const NO_STRUCT_LITERAL = 1 << 1; - } -} - -type ItemInfo = (Ident, ItemKind, Option>); - -/// Specifies how to parse a path. -#[derive(Copy, Clone, PartialEq)] -pub enum PathStyle { - /// In some contexts, notably in expressions, paths with generic arguments are ambiguous - /// with something else. For example, in expressions `segment < ....` can be interpreted - /// as a comparison and `segment ( ....` can be interpreted as a function call. - /// In all such contexts the non-path interpretation is preferred by default for practical - /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g. - /// `x` - comparisons, `x::` - unambiguously a path. - Expr, - /// In other contexts, notably in types, no ambiguity exists and paths can be written - /// without the disambiguator, e.g., `x` - unambiguously a path. - /// Paths with disambiguators are still accepted, `x::` - unambiguously a path too. - Type, - /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, - /// visibilities or attributes. - /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead - /// (paths in "mod" contexts have to be checked later for absence of generic arguments - /// anyway, due to macros), but it is used to avoid weird suggestions about expected - /// tokens when something goes wrong. - Mod, -} - -#[derive(Clone, Copy, PartialEq, Debug)] -crate enum SemiColonMode { - Break, - Ignore, - Comma, -} - -#[derive(Clone, Copy, PartialEq, Debug)] -crate enum BlockMode { - Break, - Ignore, -} - -/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression -/// dropped into the token stream, which happens while parsing the result of -/// macro expansion). Placement of these is not as complex as I feared it would -/// be. The important thing is to make sure that lookahead doesn't balk at -/// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr { - ($p:expr) => { - if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - $p.bump(); - return Ok(e); - } - token::NtPath(path) => { - let path = path.clone(); - $p.bump(); - return Ok($p.mk_expr( - $p.token.span, ExprKind::Path(None, path), ThinVec::new() - )); - } - token::NtBlock(block) => { - let block = block.clone(); - $p.bump(); - return Ok($p.mk_expr( - $p.token.span, ExprKind::Block(block, None), ThinVec::new() - )); - } - _ => {}, - }; - } - } -} - -/// As maybe_whole_expr, but for things other than expressions -macro_rules! maybe_whole { - ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { - if let token::Interpolated(nt) = &$p.token.kind { - if let token::$constructor(x) = &**nt { - let $x = x.clone(); - $p.bump(); - return Ok($e); - } - } - }; -} - -/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. -macro_rules! maybe_recover_from_interpolated_ty_qpath { - ($self: expr, $allow_qpath_recovery: expr) => { - if $allow_qpath_recovery && $self.look_ahead(1, |t| t == &token::ModSep) { - if let token::Interpolated(nt) = &$self.token.kind { - if let token::NtTy(ty) = &**nt { - let ty = ty.clone(); - $self.bump(); - return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_span, ty); - } - } - } - } -} - -fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs -} - -#[derive(Debug, Clone, Copy, PartialEq)] -enum PrevTokenKind { - DocComment, - Comma, - Plus, - Interpolated, - Eof, - Ident, - BitOr, - Other, -} - -// NOTE: `Ident`s are handled by `common.rs`. - -#[derive(Clone)] -pub struct Parser<'a> { - pub sess: &'a ParseSess, - /// The current normalized token. - /// "Normalized" means that some interpolated tokens - /// (`$i: ident` and `$l: lifetime` meta-variables) are replaced - /// with non-interpolated identifier and lifetime tokens they refer to. - /// Perhaps the normalized / non-normalized setup can be simplified somehow. - pub token: Token, - /// Span of the current non-normalized token. - meta_var_span: Option, - /// Span of the previous non-normalized token. - pub prev_span: Span, - /// Kind of the previous normalized token (in simplified form). - prev_token_kind: PrevTokenKind, - restrictions: Restrictions, - /// Used to determine the path to externally loaded source files. - crate directory: Directory<'a>, - /// `true` to parse sub-modules in other files. - pub recurse_into_file_modules: bool, - /// Name of the root module this parser originated from. If `None`, then the - /// name is not known. This does not change while the parser is descending - /// into modules, and sub-parsers have new values for this name. - pub root_module_name: Option, - crate expected_tokens: Vec, - crate token_cursor: TokenCursor, - desugar_doc_comments: bool, - /// `true` we should configure out of line modules as we parse. - pub cfg_mods: bool, - /// This field is used to keep track of how many left angle brackets we have seen. This is - /// required in order to detect extra leading left angle brackets (`<` characters) and error - /// appropriately. - /// - /// See the comments in the `parse_path_segment` function for more details. - crate unmatched_angle_bracket_count: u32, - crate max_angle_bracket_count: u32, - /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery - /// it gets removed from here. Every entry left at the end gets emitted as an independent - /// error. - crate unclosed_delims: Vec, - crate last_unexpected_token_span: Option, - /// If present, this `Parser` is not parsing Rust code but rather a macro call. - crate subparser_name: Option<&'static str>, -} - -impl<'a> Drop for Parser<'a> { - fn drop(&mut self) { - let diag = self.diagnostic(); - emit_unclosed_delims(&mut self.unclosed_delims, diag); - } -} - -#[derive(Clone)] -crate struct TokenCursor { - crate frame: TokenCursorFrame, - crate stack: Vec, -} - -#[derive(Clone)] -crate struct TokenCursorFrame { - crate delim: token::DelimToken, - crate span: DelimSpan, - crate open_delim: bool, - crate tree_cursor: tokenstream::Cursor, - crate close_delim: bool, - crate last_token: LastToken, -} - -/// This is used in `TokenCursorFrame` above to track tokens that are consumed -/// by the parser, and then that's transitively used to record the tokens that -/// each parse AST item is created with. -/// -/// Right now this has two states, either collecting tokens or not collecting -/// tokens. If we're collecting tokens we just save everything off into a local -/// `Vec`. This should eventually though likely save tokens from the original -/// token stream and just use slicing of token streams to avoid creation of a -/// whole new vector. -/// -/// The second state is where we're passively not recording tokens, but the last -/// token is still tracked for when we want to start recording tokens. This -/// "last token" means that when we start recording tokens we'll want to ensure -/// that this, the first token, is included in the output. -/// -/// You can find some more example usage of this in the `collect_tokens` method -/// on the parser. -#[derive(Clone)] -crate enum LastToken { - Collecting(Vec), - Was(Option), -} - -impl TokenCursorFrame { - fn new(span: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self { - TokenCursorFrame { - delim, - span, - open_delim: delim == token::NoDelim, - tree_cursor: tts.clone().into_trees(), - close_delim: delim == token::NoDelim, - last_token: LastToken::Was(None), - } - } -} - -impl TokenCursor { - fn next(&mut self) -> Token { - loop { - let tree = if !self.frame.open_delim { - self.frame.open_delim = true; - TokenTree::open_tt(self.frame.span.open, self.frame.delim) - } else if let Some(tree) = self.frame.tree_cursor.next() { - tree - } else if !self.frame.close_delim { - self.frame.close_delim = true; - TokenTree::close_tt(self.frame.span.close, self.frame.delim) - } else if let Some(frame) = self.stack.pop() { - self.frame = frame; - continue - } else { - return Token::new(token::Eof, DUMMY_SP); - }; - - match self.frame.last_token { - LastToken::Collecting(ref mut v) => v.push(tree.clone().into()), - LastToken::Was(ref mut t) => *t = Some(tree.clone().into()), - } - - match tree { - TokenTree::Token(token) => return token, - TokenTree::Delimited(sp, delim, tts) => { - let frame = TokenCursorFrame::new(sp, delim, &tts); - self.stack.push(mem::replace(&mut self.frame, frame)); - } - } - } - } - - fn next_desugared(&mut self) -> Token { - let (name, sp) = match self.next() { - Token { kind: token::DocComment(name), span } => (name, span), - tok => return tok, - }; - - let stripped = strip_doc_comment_decoration(&name.as_str()); - - // Searches for the occurrences of `"#*` and returns the minimum number of `#`s - // required to wrap the text. - let mut num_of_hashes = 0; - let mut count = 0; - for ch in stripped.chars() { - count = match ch { - '"' => 1, - '#' if count > 0 => count + 1, - _ => 0, - }; - num_of_hashes = cmp::max(num_of_hashes, count); - } - - let delim_span = DelimSpan::from_single(sp); - let body = TokenTree::Delimited( - delim_span, - token::Bracket, - [ - TokenTree::token(token::Ident(sym::doc, false), sp), - TokenTree::token(token::Eq, sp), - TokenTree::token(TokenKind::lit( - token::StrRaw(num_of_hashes), Symbol::intern(&stripped), None - ), sp), - ] - .iter().cloned().collect::().into(), - ); - - self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new( - delim_span, - token::NoDelim, - &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { - [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body] - .iter().cloned().collect::().into() - } else { - [TokenTree::token(token::Pound, sp), body] - .iter().cloned().collect::().into() - }, - ))); - - self.next() - } -} - -#[derive(Clone, PartialEq)] -crate enum TokenType { - Token(TokenKind), - Keyword(Symbol), - Operator, - Lifetime, - Ident, - Path, - Type, - Const, -} - -impl TokenType { - crate fn to_string(&self) -> String { - match *self { - TokenType::Token(ref t) => format!("`{}`", pprust::token_kind_to_string(t)), - TokenType::Keyword(kw) => format!("`{}`", kw), - TokenType::Operator => "an operator".to_string(), - TokenType::Lifetime => "lifetime".to_string(), - TokenType::Ident => "identifier".to_string(), - TokenType::Path => "path".to_string(), - TokenType::Type => "type".to_string(), - TokenType::Const => "const".to_string(), - } - } -} - -/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`, -/// `IDENT<::AssocTy>`. -/// -/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes -/// that `IDENT` is not the ident of a fn trait. -fn can_continue_type_after_non_fn_ident(t: &Token) -> bool { - t == &token::ModSep || t == &token::Lt || - t == &token::BinOp(token::Shl) -} - -/// Information about the path to a module. -pub struct ModulePath { - name: String, - path_exists: bool, - pub result: Result, -} - -pub struct ModulePathSuccess { - pub path: PathBuf, - pub directory_ownership: DirectoryOwnership, - warn: bool, -} - -#[derive(Debug)] -enum LhsExpr { - NotYetParsed, - AttributesParsed(ThinVec), - AlreadyParsed(P), -} - -impl From>> for LhsExpr { - fn from(o: Option>) -> Self { - if let Some(attrs) = o { - LhsExpr::AttributesParsed(attrs) - } else { - LhsExpr::NotYetParsed - } - } -} - -impl From> for LhsExpr { - fn from(expr: P) -> Self { - LhsExpr::AlreadyParsed(expr) - } -} - -#[derive(Copy, Clone, Debug)] -crate enum TokenExpectType { - Expect, - NoExpect, -} - -impl<'a> Parser<'a> { - pub fn new( - sess: &'a ParseSess, - tokens: TokenStream, - directory: Option>, - recurse_into_file_modules: bool, - desugar_doc_comments: bool, - subparser_name: Option<&'static str>, - ) -> Self { - let mut parser = Parser { - sess, - token: Token::dummy(), - prev_span: DUMMY_SP, - meta_var_span: None, - prev_token_kind: PrevTokenKind::Other, - restrictions: Restrictions::empty(), - recurse_into_file_modules, - directory: Directory { - path: Cow::from(PathBuf::new()), - ownership: DirectoryOwnership::Owned { relative: None } - }, - root_module_name: None, - expected_tokens: Vec::new(), - token_cursor: TokenCursor { - frame: TokenCursorFrame::new( - DelimSpan::dummy(), - token::NoDelim, - &tokens.into(), - ), - stack: Vec::new(), - }, - desugar_doc_comments, - cfg_mods: true, - unmatched_angle_bracket_count: 0, - max_angle_bracket_count: 0, - unclosed_delims: Vec::new(), - last_unexpected_token_span: None, - subparser_name, - }; - - parser.token = parser.next_tok(); - - if let Some(directory) = directory { - parser.directory = directory; - } else if !parser.token.span.is_dummy() { - if let FileName::Real(mut path) = - sess.source_map().span_to_unmapped_path(parser.token.span) { - path.pop(); - parser.directory.path = Cow::from(path); - } - } - - parser.process_potential_macro_variable(); - parser - } - - fn next_tok(&mut self) -> Token { - let mut next = if self.desugar_doc_comments { - self.token_cursor.next_desugared() - } else { - self.token_cursor.next() - }; - if next.span.is_dummy() { - // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = self.prev_span.with_ctxt(next.span.ctxt()); - } - next - } - - /// Converts the current token to a string using `self`'s reader. - pub fn this_token_to_string(&self) -> String { - pprust::token_to_string(&self.token) - } - - crate fn token_descr(&self) -> Option<&'static str> { - Some(match &self.token.kind { - _ if self.token.is_special_ident() => "reserved identifier", - _ if self.token.is_used_keyword() => "keyword", - _ if self.token.is_unused_keyword() => "reserved keyword", - token::DocComment(..) => "doc comment", - _ => return None, - }) - } - - crate fn this_token_descr(&self) -> String { - if let Some(prefix) = self.token_descr() { - format!("{} `{}`", prefix, self.this_token_to_string()) - } else { - format!("`{}`", self.this_token_to_string()) - } - } - - crate fn unexpected(&mut self) -> PResult<'a, T> { - match self.expect_one_of(&[], &[]) { - Err(e) => Err(e), - Ok(_) => unreachable!(), - } - } - - /// Expects and consumes the token `t`. Signals an error if the next token is not `t`. - pub fn expect(&mut self, t: &TokenKind) -> PResult<'a, bool /* recovered */> { - if self.expected_tokens.is_empty() { - if self.token == *t { - self.bump(); - Ok(false) - } else { - self.unexpected_try_recover(t) - } - } else { - self.expect_one_of(slice::from_ref(t), &[]) - } - } - - /// Expect next token to be edible or inedible token. If edible, - /// then consume it; if inedible, then return without consuming - /// anything. Signal a fatal error if next token is unexpected. - pub fn expect_one_of( - &mut self, - edible: &[TokenKind], - inedible: &[TokenKind], - ) -> PResult<'a, bool /* recovered */> { - if edible.contains(&self.token.kind) { - self.bump(); - Ok(false) - } else if inedible.contains(&self.token.kind) { - // leave it in the input - Ok(false) - } else if self.last_unexpected_token_span == Some(self.token.span) { - FatalError.raise(); - } else { - self.expected_one_of_not_found(edible, inedible) - } - } - - /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. - fn interpolated_or_expr_span( - &self, - expr: PResult<'a, P>, - ) -> PResult<'a, (Span, P)> { - expr.map(|e| { - if self.prev_token_kind == PrevTokenKind::Interpolated { - (self.prev_span, e) - } else { - (e.span, e) - } - }) - } - - pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { - self.parse_ident_common(true) - } - - fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { - match self.token.kind { - token::Ident(name, _) => { - if self.token.is_reserved_ident() { - let mut err = self.expected_ident_found(); - if recover { - err.emit(); - } else { - return Err(err); - } - } - let span = self.token.span; - self.bump(); - Ok(Ident::new(name, span)) - } - _ => { - Err(if self.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_err(self.prev_span, Error::UselessDocComment) - } else { - self.expected_ident_found() - }) - } - } - } - - /// Checks if the next token is `tok`, and returns `true` if so. - /// - /// This method will automatically add `tok` to `expected_tokens` if `tok` is not - /// encountered. - crate fn check(&mut self, tok: &TokenKind) -> bool { - let is_present = self.token == *tok; - if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } - is_present - } - - /// Consumes a token 'tok' if it exists. Returns whether the given token was present. - pub fn eat(&mut self, tok: &TokenKind) -> bool { - let is_present = self.check(tok); - if is_present { self.bump() } - is_present - } - - fn check_keyword(&mut self, kw: Symbol) -> bool { - self.expected_tokens.push(TokenType::Keyword(kw)); - self.token.is_keyword(kw) - } - - /// If the next token is the given keyword, eats it and returns - /// `true`. Otherwise, returns `false`. - pub fn eat_keyword(&mut self, kw: Symbol) -> bool { - if self.check_keyword(kw) { - self.bump(); - true - } else { - false - } - } - - fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool { - if self.token.is_keyword(kw) { - self.bump(); - true - } else { - false - } - } - - /// If the given word is not a keyword, signals an error. - /// If the next token is not the given word, signals an error. - /// Otherwise, eats it. - fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> { - if !self.eat_keyword(kw) { - self.unexpected() - } else { - Ok(()) - } - } - - crate fn check_ident(&mut self) -> bool { - if self.token.is_ident() { - true - } else { - self.expected_tokens.push(TokenType::Ident); - false - } - } - - fn check_path(&mut self) -> bool { - if self.token.is_path_start() { - true - } else { - self.expected_tokens.push(TokenType::Path); - false - } - } - - fn check_type(&mut self) -> bool { - if self.token.can_begin_type() { - true - } else { - self.expected_tokens.push(TokenType::Type); - false - } - } - - fn check_const_arg(&mut self) -> bool { - if self.token.can_begin_const_arg() { - true - } else { - self.expected_tokens.push(TokenType::Const); - false - } - } - - /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=` - /// and continues. If a `+` is not seen, returns `false`. - /// - /// This is used when token-splitting `+=` into `+`. - /// See issue #47856 for an example of when this may occur. - fn eat_plus(&mut self) -> bool { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); - match self.token.kind { - token::BinOp(token::Plus) => { - self.bump(); - true - } - token::BinOpEq(token::Plus) => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - self.bump_with(token::Eq, span); - true - } - _ => false, - } - } - - - /// Checks to see if the next token is either `+` or `+=`. - /// Otherwise returns `false`. - fn check_plus(&mut self) -> bool { - if self.token.is_like_plus() { - true - } - else { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); - false - } - } - - /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single - /// `&` and continues. If an `&` is not seen, signals an error. - fn expect_and(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::And))); - match self.token.kind { - token::BinOp(token::And) => { - self.bump(); - Ok(()) - } - token::AndAnd => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - Ok(self.bump_with(token::BinOp(token::And), span)) - } - _ => self.unexpected() - } - } - - /// Expects and consumes an `|`. If `||` is seen, replaces it with a single - /// `|` and continues. If an `|` is not seen, signals an error. - fn expect_or(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); - match self.token.kind { - token::BinOp(token::Or) => { - self.bump(); - Ok(()) - } - token::OrOr => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - Ok(self.bump_with(token::BinOp(token::Or), span)) - } - _ => self.unexpected() - } - } - - fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - literal::expect_no_suffix(&self.sess.span_diagnostic, sp, kind, suffix) - } - - /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single - /// `<` and continue. If `<-` is seen, replaces it with a single `<` - /// and continue. If a `<` is not seen, returns false. - /// - /// This is meant to be used when parsing generics on a path to get the - /// starting token. - fn eat_lt(&mut self) -> bool { - self.expected_tokens.push(TokenType::Token(token::Lt)); - let ate = match self.token.kind { - token::Lt => { - self.bump(); - true - } - token::BinOp(token::Shl) => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - self.bump_with(token::Lt, span); - true - } - token::LArrow => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - self.bump_with(token::BinOp(token::Minus), span); - true - } - _ => false, - }; - - if ate { - // See doc comment for `unmatched_angle_bracket_count`. - self.unmatched_angle_bracket_count += 1; - self.max_angle_bracket_count += 1; - debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count); - } - - ate - } - - fn expect_lt(&mut self) -> PResult<'a, ()> { - if !self.eat_lt() { - self.unexpected() - } else { - Ok(()) - } - } - - /// Expects and consumes a single `>` token. if a `>>` is seen, replaces it - /// with a single `>` and continues. If a `>` is not seen, signals an error. - fn expect_gt(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::Gt)); - let ate = match self.token.kind { - token::Gt => { - self.bump(); - Some(()) - } - token::BinOp(token::Shr) => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - Some(self.bump_with(token::Gt, span)) - } - token::BinOpEq(token::Shr) => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - Some(self.bump_with(token::Ge, span)) - } - token::Ge => { - let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1)); - Some(self.bump_with(token::Eq, span)) - } - _ => None, - }; - - match ate { - Some(_) => { - // See doc comment for `unmatched_angle_bracket_count`. - if self.unmatched_angle_bracket_count > 0 { - self.unmatched_angle_bracket_count -= 1; - debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count); - } - - Ok(()) - }, - None => self.unexpected(), - } - } - - /// Parses a sequence, including the closing delimiter. The function - /// `f` must consume tokens until reaching the next separator or - /// closing bracket. - pub fn parse_seq_to_end(&mut self, - ket: &TokenKind, - sep: SeqSep, - f: F) - -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; - if !recovered { - self.bump(); - } - Ok(val) - } - - /// Parses a sequence, not including the closing delimiter. The function - /// `f` must consume tokens until reaching the next separator or - /// closing bracket. - pub fn parse_seq_to_before_end( - &mut self, - ket: &TokenKind, - sep: SeqSep, - f: F, - ) -> PResult<'a, (Vec, bool)> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> - { - self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f) - } - - crate fn parse_seq_to_before_tokens( - &mut self, - kets: &[&TokenKind], - sep: SeqSep, - expect: TokenExpectType, - mut f: F, - ) -> PResult<'a, (Vec, bool /* recovered */)> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> - { - let mut first = true; - let mut recovered = false; - let mut v = vec![]; - while !kets.iter().any(|k| { - match expect { - TokenExpectType::Expect => self.check(k), - TokenExpectType::NoExpect => self.token == **k, - } - }) { - match self.token.kind { - token::CloseDelim(..) | token::Eof => break, - _ => {} - }; - if let Some(ref t) = sep.sep { - if first { - first = false; - } else { - match self.expect(t) { - Ok(false) => {} - Ok(true) => { - recovered = true; - break; - } - Err(mut e) => { - // Attempt to keep parsing if it was a similar separator - if let Some(ref tokens) = t.similar_tokens() { - if tokens.contains(&self.token.kind) { - self.bump(); - } - } - e.emit(); - // Attempt to keep parsing if it was an omitted separator - match f(self) { - Ok(t) => { - v.push(t); - continue; - }, - Err(mut e) => { - e.cancel(); - break; - } - } - } - } - } - } - if sep.trailing_sep_allowed && kets.iter().any(|k| { - match expect { - TokenExpectType::Expect => self.check(k), - TokenExpectType::NoExpect => self.token == **k, - } - }) { - break; - } - - let t = f(self)?; - v.push(t); - } - - Ok((v, recovered)) - } - - /// Parses a sequence, including the closing delimiter. The function - /// `f` must consume tokens until reaching the next separator or - /// closing bracket. - fn parse_unspanned_seq( - &mut self, - bra: &TokenKind, - ket: &TokenKind, - sep: SeqSep, - f: F, - ) -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - self.expect(bra)?; - let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; - if !recovered { - self.eat(ket); - } - Ok(result) - } - - /// Advance the parser by one token - pub fn bump(&mut self) { - if self.prev_token_kind == PrevTokenKind::Eof { - // Bumping after EOF is a bad sign, usually an infinite loop. - self.bug("attempted to bump the parser past EOF (may be stuck in a loop)"); - } - - self.prev_span = self.meta_var_span.take().unwrap_or(self.token.span); - - // Record last token kind for possible error recovery. - self.prev_token_kind = match self.token.kind { - token::DocComment(..) => PrevTokenKind::DocComment, - token::Comma => PrevTokenKind::Comma, - token::BinOp(token::Plus) => PrevTokenKind::Plus, - token::BinOp(token::Or) => PrevTokenKind::BitOr, - token::Interpolated(..) => PrevTokenKind::Interpolated, - token::Eof => PrevTokenKind::Eof, - token::Ident(..) => PrevTokenKind::Ident, - _ => PrevTokenKind::Other, - }; - - self.token = self.next_tok(); - self.expected_tokens.clear(); - // check after each token - self.process_potential_macro_variable(); - } - - /// Advance the parser using provided token as a next one. Use this when - /// consuming a part of a token. For example a single `<` from `<<`. - fn bump_with(&mut self, next: TokenKind, span: Span) { - self.prev_span = self.token.span.with_hi(span.lo()); - // It would be incorrect to record the kind of the current token, but - // fortunately for tokens currently using `bump_with`, the - // prev_token_kind will be of no use anyway. - self.prev_token_kind = PrevTokenKind::Other; - self.token = Token::new(next, span); - self.expected_tokens.clear(); - } - - pub fn look_ahead(&self, dist: usize, f: F) -> R where - F: FnOnce(&Token) -> R, - { - if dist == 0 { - return f(&self.token); - } - - let frame = &self.token_cursor.frame; - f(&match frame.tree_cursor.look_ahead(dist - 1) { - Some(tree) => match tree { - TokenTree::Token(token) => token, - TokenTree::Delimited(dspan, delim, _) => - Token::new(token::OpenDelim(delim), dspan.open), - } - None => Token::new(token::CloseDelim(frame.delim), frame.span.close) - }) - } - - /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. - fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { - self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) - } - - /// Is the current token one of the keywords that signals a bare function type? - fn token_is_bare_fn_keyword(&mut self) -> bool { - self.check_keyword(kw::Fn) || - self.check_keyword(kw::Unsafe) || - self.check_keyword(kw::Extern) - } - - /// Parses a `TyKind::BareFn` type. - fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'a, TyKind> { - /* - - [unsafe] [extern "ABI"] fn (S) -> T - ^~~~^ ^~~~^ ^~^ ^ - | | | | - | | | Return type - | | Argument types - | | - | ABI - Function Style - */ - - let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()?.unwrap_or(Abi::C) - } else { - Abi::Rust - }; - - self.expect_keyword(kw::Fn)?; - let (inputs, c_variadic) = self.parse_fn_args(false, true)?; - let ret_ty = self.parse_ret_ty(false)?; - let decl = P(FnDecl { - inputs, - output: ret_ty, - c_variadic, - }); - Ok(TyKind::BareFn(P(BareFnTy { - abi, - unsafety, - generic_params, - decl, - }))) - } - - /// Parses asyncness: `async` or nothing. - fn parse_asyncness(&mut self) -> IsAsync { - if self.eat_keyword(kw::Async) { - IsAsync::Async { - closure_id: ast::DUMMY_NODE_ID, - return_impl_trait_id: ast::DUMMY_NODE_ID, - } - } else { - IsAsync::NotAsync - } - } - - /// Parses unsafety: `unsafe` or nothing. - fn parse_unsafety(&mut self) -> Unsafety { - if self.eat_keyword(kw::Unsafe) { - Unsafety::Unsafe - } else { - Unsafety::Normal - } - } - - /// Parses the items in a trait declaration. - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { - maybe_whole!(self, NtTraitItem, |x| x); - let attrs = self.parse_outer_attributes()?; - let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_trait_item_(at_end, attrs); - unclosed_delims.append(&mut this.unclosed_delims); - item - })?; - self.unclosed_delims.append(&mut unclosed_delims); - // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - Ok(item) - } - - fn parse_trait_item_(&mut self, - at_end: &mut bool, - mut attrs: Vec) -> PResult<'a, TraitItem> { - let lo = self.token.span; - self.eat_bad_pub(); - let (name, node, generics) = if self.eat_keyword(kw::Type) { - self.parse_trait_item_assoc_ty()? - } else if self.is_const_item() { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let default = if self.eat(&token::Eq) { - let expr = self.parse_expr()?; - self.expect(&token::Semi)?; - Some(expr) - } else { - self.expect(&token::Semi)?; - None - }; - (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) - } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { - // trait item macro. - (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) - } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; - - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - - let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { - // This is somewhat dubious; We don't want to allow - // argument names to be left off if there is a - // definition... - - // We don't allow argument names to be left off in edition 2018. - let is_name_required = p.token.span.rust_2018(); - p.parse_arg_general(true, false, |_| is_name_required) - })?; - generics.where_clause = self.parse_where_clause()?; - - let sig = ast::MethodSig { - header: FnHeader { - unsafety, - constness, - abi, - asyncness, - }, - decl, - }; - - let body = match self.token.kind { - token::Semi => { - self.bump(); - *at_end = true; - debug!("parse_trait_methods(): parsing required method"); - None - } - token::OpenDelim(token::Brace) => { - debug!("parse_trait_methods(): parsing provided method"); - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - token::Interpolated(ref nt) => { - match **nt { - token::NtBlock(..) => { - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - _ => { - return self.expected_semi_or_open_brace(); - } - } - } - _ => { - return self.expected_semi_or_open_brace(); - } - }; - (ident, ast::TraitItemKind::Method(sig, body), generics) - }; - - Ok(TraitItem { - id: ast::DUMMY_NODE_ID, - ident: name, - attrs, - generics, - node, - span: lo.to(self.prev_span), - tokens: None, - }) - } - - /// Parses an optional return type `[ -> TY ]` in a function declaration. - fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { - if self.eat(&token::RArrow) { - Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?)) - } else { - Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo())) - } - } - - /// Parses a type. - pub fn parse_ty(&mut self) -> PResult<'a, P> { - self.parse_ty_common(true, true, false) - } - - /// Parses a type in restricted contexts where `+` is not permitted. - /// - /// Example 1: `&'a TYPE` - /// `+` is prohibited to maintain operator priority (P(+) < P(&)). - /// Example 2: `value1 as TYPE + value2` - /// `+` is prohibited to avoid interactions with expression grammar. - fn parse_ty_no_plus(&mut self) -> PResult<'a, P> { - self.parse_ty_common(false, true, false) - } - - fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, - allow_c_variadic: bool) -> PResult<'a, P> { - maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - maybe_whole!(self, NtTy, |x| x); - - let lo = self.token.span; - let mut impl_dyn_multi = false; - let node = if self.eat(&token::OpenDelim(token::Paren)) { - // `(TYPE)` is a parenthesized type. - // `(TYPE,)` is a tuple with a single field of type TYPE. - let mut ts = vec![]; - let mut last_comma = false; - while self.token != token::CloseDelim(token::Paren) { - ts.push(self.parse_ty()?); - if self.eat(&token::Comma) { - last_comma = true; - } else { - last_comma = false; - break; - } - } - let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus; - self.expect(&token::CloseDelim(token::Paren))?; - - if ts.len() == 1 && !last_comma { - let ty = ts.into_iter().nth(0).unwrap().into_inner(); - let maybe_bounds = allow_plus && self.token.is_like_plus(); - match ty.node { - // `(TY_BOUND_NOPAREN) + BOUND + ...`. - TyKind::Path(None, ref path) if maybe_bounds => { - self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)? - } - TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) - if maybe_bounds && bounds.len() == 1 && !trailing_plus => { - let path = match bounds[0] { - GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), - GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"), - }; - self.parse_remaining_bounds(Vec::new(), path, lo, true)? - } - // `(TYPE)` - _ => TyKind::Paren(P(ty)) - } - } else { - TyKind::Tup(ts) - } - } else if self.eat(&token::Not) { - // Never type `!` - TyKind::Never - } else if self.eat(&token::BinOp(token::Star)) { - // Raw pointer - TyKind::Ptr(self.parse_ptr()?) - } else if self.eat(&token::OpenDelim(token::Bracket)) { - // Array or slice - let t = self.parse_ty()?; - // Parse optional `; EXPR` in `[TYPE; EXPR]` - let t = match self.maybe_parse_fixed_length_of_vec()? { - None => TyKind::Slice(t), - Some(length) => TyKind::Array(t, AnonConst { - id: ast::DUMMY_NODE_ID, - value: length, - }), - }; - self.expect(&token::CloseDelim(token::Bracket))?; - t - } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) { - // Reference - self.expect_and()?; - self.parse_borrowed_pointee()? - } else if self.eat_keyword_noexpect(kw::Typeof) { - // `typeof(EXPR)` - // In order to not be ambiguous, the type must be surrounded by parens. - self.expect(&token::OpenDelim(token::Paren))?; - let e = AnonConst { - id: ast::DUMMY_NODE_ID, - value: self.parse_expr()?, - }; - self.expect(&token::CloseDelim(token::Paren))?; - TyKind::Typeof(e) - } else if self.eat_keyword(kw::Underscore) { - // A type to be inferred `_` - TyKind::Infer - } else if self.token_is_bare_fn_keyword() { - // Function pointer type - self.parse_ty_bare_fn(Vec::new())? - } else if self.check_keyword(kw::For) { - // Function pointer type or bound list (trait object type) starting with a poly-trait. - // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` - // `for<'lt> Trait1<'lt> + Trait2 + 'a` - let lo = self.token.span; - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - if self.token_is_bare_fn_keyword() { - self.parse_ty_bare_fn(lifetime_defs)? - } else { - let path = self.parse_path(PathStyle::Type)?; - let parse_plus = allow_plus && self.check_plus(); - self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? - } - } else if self.eat_keyword(kw::Impl) { - // Always parse bounds greedily for better error recovery. - let bounds = self.parse_generic_bounds(None)?; - impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) - } else if self.check_keyword(kw::Dyn) && - (self.token.span.rust_2018() || - self.look_ahead(1, |t| t.can_begin_bound() && - !can_continue_type_after_non_fn_ident(t))) { - self.bump(); // `dyn` - // Always parse bounds greedily for better error recovery. - let bounds = self.parse_generic_bounds(None)?; - impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) - } else if self.check(&token::Question) || - self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) { - // Bound list (trait object type) - TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?, - TraitObjectSyntax::None) - } else if self.eat_lt() { - // Qualified path - let (qself, path) = self.parse_qpath(PathStyle::Type)?; - TyKind::Path(Some(qself), path) - } else if self.token.is_path_start() { - // Simple path - let path = self.parse_path(PathStyle::Type)?; - if self.eat(&token::Not) { - // Macro invocation in type position - let (delim, tts) = self.expect_delimited_token_tree()?; - let node = Mac_ { path, tts, delim }; - TyKind::Mac(respan(lo.to(self.prev_span), node)) - } else { - // Just a type path or bound list (trait object type) starting with a trait. - // `Type` - // `Trait1 + Trait2 + 'a` - if allow_plus && self.check_plus() { - self.parse_remaining_bounds(Vec::new(), path, lo, true)? - } else { - TyKind::Path(None, path) - } - } - } else if self.check(&token::DotDotDot) { - if allow_c_variadic { - self.eat(&token::DotDotDot); - TyKind::CVarArgs - } else { - return Err(self.fatal( - "only foreign functions are allowed to be C-variadic" - )); - } - } else { - let msg = format!("expected type, found {}", self.this_token_descr()); - return Err(self.fatal(&msg)); - }; - - let span = lo.to(self.prev_span); - let ty = P(Ty { node, span, id: ast::DUMMY_NODE_ID }); - - // Try to recover from use of `+` with incorrect priority. - self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); - self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?; - self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery) - } - - fn parse_remaining_bounds(&mut self, generic_params: Vec, path: ast::Path, - lo: Span, parse_plus: bool) -> PResult<'a, TyKind> { - let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); - let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; - if parse_plus { - self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded - bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?); - } - Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) - } - - fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { - let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; - let mutbl = self.parse_mutability(); - let ty = self.parse_ty_no_plus()?; - return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })); - } - - fn parse_ptr(&mut self) -> PResult<'a, MutTy> { - let mutbl = if self.eat_keyword(kw::Mut) { - Mutability::Mutable - } else if self.eat_keyword(kw::Const) { - Mutability::Immutable - } else { - let span = self.prev_span; - let msg = "expected mut or const in raw pointer type"; - self.struct_span_err(span, msg) - .span_label(span, msg) - .help("use `*mut T` or `*const T` as appropriate") - .emit(); - Mutability::Immutable - }; - let t = self.parse_ty_no_plus()?; - Ok(MutTy { ty: t, mutbl }) - } - - fn is_named_argument(&self) -> bool { - let offset = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), - _ => 0, - } - token::BinOp(token::And) | token::AndAnd => 1, - _ if self.token.is_keyword(kw::Mut) => 1, - _ => 0, - }; - - self.look_ahead(offset, |t| t.is_ident()) && - self.look_ahead(offset + 1, |t| t == &token::Colon) - } - - /// Skips unexpected attributes and doc comments in this position and emits an appropriate - /// error. - /// This version of parse arg doesn't necessarily require identifier names. - fn parse_arg_general( - &mut self, - is_trait_item: bool, - allow_c_variadic: bool, - is_name_required: F, - ) -> PResult<'a, Arg> - where - F: Fn(&token::Token) -> bool - { - let attrs = self.parse_arg_attributes()?; - if let Ok(Some(mut arg)) = self.parse_self_arg() { - arg.attrs = attrs.into(); - return self.recover_bad_self_arg(arg, is_trait_item); - } - - let is_name_required = is_name_required(&self.token); - let (pat, ty) = if is_name_required || self.is_named_argument() { - debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required); - - let pat = self.parse_pat(Some("argument name"))?; - if let Err(mut err) = self.expect(&token::Colon) { - if let Some(ident) = self.argument_without_type( - &mut err, - pat, - is_name_required, - is_trait_item, - ) { - err.emit(); - return Ok(dummy_arg(ident)); - } else { - return Err(err); - } - } - - self.eat_incorrect_doc_comment_for_arg_type(); - (pat, self.parse_ty_common(true, true, allow_c_variadic)?) - } else { - debug!("parse_arg_general ident_to_pat"); - let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_arg_type(); - let mut ty = self.parse_ty_common(true, true, allow_c_variadic); - if ty.is_ok() && self.token != token::Comma && - self.token != token::CloseDelim(token::Paren) { - // This wasn't actually a type, but a pattern looking like a type, - // so we are going to rollback and re-parse for recovery. - ty = self.unexpected(); - } - match ty { - Ok(ty) => { - let ident = Ident::new(kw::Invalid, self.prev_span); - let pat = P(Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident( - BindingMode::ByValue(Mutability::Immutable), ident, None), - span: ty.span, - }); - (pat, ty) - } - Err(mut err) => { - // If this is a C-variadic argument and we hit an error, return the - // error. - if self.token == token::DotDotDot { - return Err(err); - } - // Recover from attempting to parse the argument as a type without pattern. - err.cancel(); - mem::replace(self, parser_snapshot_before_ty); - self.recover_arg_parse()? - } - } - }; - - Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, ty }) - } - - /// Parses an argument in a lambda header (e.g., `|arg, arg|`). - fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { - let attrs = self.parse_arg_attributes()?; - let pat = self.parse_pat(Some("argument name"))?; - let t = if self.eat(&token::Colon) { - self.parse_ty()? - } else { - P(Ty { - id: ast::DUMMY_NODE_ID, - node: TyKind::Infer, - span: self.prev_span, - }) - }; - Ok(Arg { - attrs: attrs.into(), - ty: t, - pat, - id: ast::DUMMY_NODE_ID - }) - } - - fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option>> { - if self.eat(&token::Semi) { - Ok(Some(self.parse_expr()?)) - } else { - Ok(None) - } - } - - /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). - crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - maybe_whole_expr!(self); - - let minus_lo = self.token.span; - let minus_present = self.eat(&token::BinOp(token::Minus)); - let lo = self.token.span; - let literal = self.parse_lit()?; - let hi = self.prev_span; - let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new()); - - if minus_present { - let minus_hi = self.prev_span; - let unary = self.mk_unary(UnOp::Neg, expr); - Ok(self.mk_expr(minus_lo.to(minus_hi), unary, ThinVec::new())) - } else { - Ok(expr) - } - } - - fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> { - match self.token.kind { - token::Ident(name, _) if name.is_path_segment_keyword() => { - let span = self.token.span; - self.bump(); - Ok(Ident::new(name, span)) - } - _ => self.parse_ident(), - } - } - - fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { - match self.token.kind { - token::Ident(name, false) if name == kw::Underscore => { - let span = self.token.span; - self.bump(); - Ok(Ident::new(name, span)) - } - _ => self.parse_ident(), - } - } - - /// Parses a qualified path. - /// Assumes that the leading `<` has been parsed already. - /// - /// `qualified_path = ::path` - /// - /// # Examples - /// `::default` - /// `::a` - /// `::F::a` (without disambiguator) - /// `::F::a::` (with disambiguator) - fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> { - let lo = self.prev_span; - let ty = self.parse_ty()?; - - // `path` will contain the prefix of the path up to the `>`, - // if any (e.g., `U` in the `::*` examples - // above). `path_span` has the span of that path, or an empty - // span in the case of something like `::Bar`. - let (mut path, path_span); - if self.eat_keyword(kw::As) { - let path_lo = self.token.span; - path = self.parse_path(PathStyle::Type)?; - path_span = path_lo.to(self.prev_span); - } else { - path_span = self.token.span.to(self.token.span); - path = ast::Path { segments: Vec::new(), span: path_span }; - } - - // See doc comment for `unmatched_angle_bracket_count`. - self.expect(&token::Gt)?; - if self.unmatched_angle_bracket_count > 0 { - self.unmatched_angle_bracket_count -= 1; - debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count); - } - - self.expect(&token::ModSep)?; - - let qself = QSelf { ty, path_span, position: path.segments.len() }; - self.parse_path_segments(&mut path.segments, style)?; - - Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) })) - } - - /// Parses simple paths. - /// - /// `path = [::] segment+` - /// `segment = ident | ident[::] | ident[::](args) [-> type]` - /// - /// # Examples - /// `a::b::C` (without disambiguator) - /// `a::b::C::` (with disambiguator) - /// `Fn(Args)` (without disambiguator) - /// `Fn::(Args)` (with disambiguator) - pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - maybe_whole!(self, NtPath, |path| { - if style == PathStyle::Mod && - path.segments.iter().any(|segment| segment.args.is_some()) { - self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); - } - path - }); - - let lo = self.meta_var_span.unwrap_or(self.token.span); - let mut segments = Vec::new(); - let mod_sep_ctxt = self.token.span.ctxt(); - if self.eat(&token::ModSep) { - segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); - } - self.parse_path_segments(&mut segments, style)?; - - Ok(ast::Path { segments, span: lo.to(self.prev_span) }) - } - - /// Like `parse_path`, but also supports parsing `Word` meta items into paths for - /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]` - /// attributes. - pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - let meta_ident = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtMeta(ref meta) => match meta.node { - ast::MetaItemKind::Word => Some(meta.path.clone()), - _ => None, - }, - _ => None, - }, - _ => None, - }; - if let Some(path) = meta_ident { - self.bump(); - return Ok(path); - } - self.parse_path(style) - } - - crate fn parse_path_segments(&mut self, - segments: &mut Vec, - style: PathStyle) - -> PResult<'a, ()> { - loop { - let segment = self.parse_path_segment(style)?; - if style == PathStyle::Expr { - // In order to check for trailing angle brackets, we must have finished - // recursing (`parse_path_segment` can indirectly call this function), - // that is, the next token must be the highlighted part of the below example: - // - // `Foo::>::Qux` - // ^ here - // - // As opposed to the below highlight (if we had only finished the first - // recursion): - // - // `Foo::>::Qux` - // ^ here - // - // `PathStyle::Expr` is only provided at the root invocation and never in - // `parse_path_segment` to recurse and therefore can be checked to maintain - // this invariant. - self.check_trailing_angle_brackets(&segment, token::ModSep); - } - segments.push(segment); - - if self.is_import_coupler() || !self.eat(&token::ModSep) { - return Ok(()); - } - } - } - - fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { - let ident = self.parse_path_segment_ident()?; - - let is_args_start = |token: &Token| match token.kind { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) - | token::LArrow => true, - _ => false, - }; - let check_args_start = |this: &mut Self| { - this.expected_tokens.extend_from_slice( - &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))] - ); - is_args_start(&this.token) - }; - - Ok(if style == PathStyle::Type && check_args_start(self) || - style != PathStyle::Mod && self.check(&token::ModSep) - && self.look_ahead(1, |t| is_args_start(t)) { - // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If - // it isn't, then we reset the unmatched angle bracket count as we're about to start - // parsing a new path. - if style == PathStyle::Expr { - self.unmatched_angle_bracket_count = 0; - self.max_angle_bracket_count = 0; - } - - // Generic arguments are found - `<`, `(`, `::<` or `::(`. - self.eat(&token::ModSep); - let lo = self.token.span; - let args = if self.eat_lt() { - // `<'a, T, A = U>` - let (args, constraints) = - self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; - self.expect_gt()?; - let span = lo.to(self.prev_span); - AngleBracketedArgs { args, constraints, span }.into() - } else { - // `(T, U) -> R` - self.bump(); // `(` - let (inputs, recovered) = self.parse_seq_to_before_tokens( - &[&token::CloseDelim(token::Paren)], - SeqSep::trailing_allowed(token::Comma), - TokenExpectType::Expect, - |p| p.parse_ty())?; - if !recovered { - self.bump(); // `)` - } - let span = lo.to(self.prev_span); - let output = if self.eat(&token::RArrow) { - Some(self.parse_ty_common(false, false, false)?) - } else { - None - }; - ParenthesizedArgs { inputs, output, span }.into() - }; - - PathSegment { ident, args, id: ast::DUMMY_NODE_ID } - } else { - // Generic arguments are not found. - PathSegment::from_ident(ident) - }) - } - - crate fn check_lifetime(&mut self) -> bool { - self.expected_tokens.push(TokenType::Lifetime); - self.token.is_lifetime() - } - - /// Parses a single lifetime `'a` or panics. - crate fn expect_lifetime(&mut self) -> Lifetime { - if let Some(ident) = self.token.lifetime() { - let span = self.token.span; - self.bump(); - Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID } - } else { - self.span_bug(self.token.span, "not a lifetime") - } - } - - fn eat_label(&mut self) -> Option

This is some text

- - - ); -} - -enum HTMLFragment { - tag(~str, ~[HTMLFragment]), - text(~str), -} diff --git a/gcc/testsuite/rust.test/hygiene-dodging-1.rs b/gcc/testsuite/rust.test/hygiene-dodging-1.rs deleted file mode 100644 index 3969394..0000000 --- a/gcc/testsuite/rust.test/hygiene-dodging-1.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod x { - pub fn g() -> uint {14} -} - -pub fn main(){ - // should *not* shadow the module x: - let x = 9; - // use it to avoid warnings: - x+3; - assert_eq!(x::g(),14); -} diff --git a/gcc/testsuite/rust.test/i32-sub.rs b/gcc/testsuite/rust.test/i32-sub.rs deleted file mode 100644 index af3b724..0000000 --- a/gcc/testsuite/rust.test/i32-sub.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { let mut x: i32 = -400_i32; x = 0_i32 - x; assert!((x == 400_i32)); } diff --git a/gcc/testsuite/rust.test/i8-incr.rs b/gcc/testsuite/rust.test/i8-incr.rs deleted file mode 100644 index 799910a..0000000 --- a/gcc/testsuite/rust.test/i8-incr.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let mut x: i8 = -12i8; - let y: i8 = -12i8; - x = x + 1i8; - x = x - 1i8; - assert_eq!(x, y); -} diff --git a/gcc/testsuite/rust.test/if-bot.rs b/gcc/testsuite/rust.test/if-bot.rs deleted file mode 100644 index 768f343..0000000 --- a/gcc/testsuite/rust.test/if-bot.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let i: int = if false { fail2!() } else { 5 }; - info2!("{:?}", i); -} diff --git a/gcc/testsuite/rust.test/if-check.rs b/gcc/testsuite/rust.test/if-check.rs deleted file mode 100644 index 0fd5fc0..0000000 --- a/gcc/testsuite/rust.test/if-check.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn even(x: uint) -> bool { - if x < 2u { - return false; - } else if x == 2u { return true; } else { return even(x - 2u); } -} - -fn foo(x: uint) { - if even(x) { - info2!("{}", x); - } else { - fail2!(); - } -} - -pub fn main() { foo(2u); } diff --git a/gcc/testsuite/rust.test/if-ret.rs b/gcc/testsuite/rust.test/if-ret.rs deleted file mode 100644 index b589c08..0000000 --- a/gcc/testsuite/rust.test/if-ret.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo() { if (return) { } } - -pub fn main() { foo(); } diff --git a/gcc/testsuite/rust.test/ifmt.rs b/gcc/testsuite/rust.test/ifmt.rs deleted file mode 100644 index 75d11ed..0000000 --- a/gcc/testsuite/rust.test/ifmt.rs +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -#[feature(macro_rules)]; -#[deny(warnings)]; - -use std::fmt; -use std::rt::io::Decorator; -use std::rt::io::mem::MemWriter; -use std::rt::io; -use std::rt::io::Writer; -use std::str; - -struct A; -struct B; - -#[fmt="foo"] -impl fmt::Signed for A { - fn fmt(_: &A, f: &mut fmt::Formatter) { f.buf.write("aloha".as_bytes()); } -} -impl fmt::Signed for B { - fn fmt(_: &B, f: &mut fmt::Formatter) { f.buf.write("adios".as_bytes()); } -} - -macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a, $b.to_owned()) }) - -pub fn main() { - - // Make sure there's a poly formatter that takes anything - t!(format!("{:?}", 1), "1"); - t!(format!("{:?}", A), "A"); - t!(format!("{:?}", ()), "()"); - t!(format!("{:?}", @(~1, "foo")), "@(~1, \"foo\")"); - - // Various edge cases without formats - t!(format!(""), ""); - t!(format!("hello"), "hello"); - t!(format!("hello \\{"), "hello {"); - - // default formatters should work - t!(format!("{}", 1i), "1"); - t!(format!("{}", 1i8), "1"); - t!(format!("{}", 1i16), "1"); - t!(format!("{}", 1i32), "1"); - t!(format!("{}", 1i64), "1"); - t!(format!("{}", 1u), "1"); - t!(format!("{}", 1u8), "1"); - t!(format!("{}", 1u16), "1"); - t!(format!("{}", 1u32), "1"); - t!(format!("{}", 1u64), "1"); - t!(format!("{}", 1.0f32), "1"); - t!(format!("{}", 1.0f64), "1"); - t!(format!("{}", "a"), "a"); - t!(format!("{}", ~"a"), "a"); - t!(format!("{}", @"a"), "a"); - t!(format!("{}", false), "false"); - t!(format!("{}", 'a'), "a"); - - // At least exercise all the formats - t!(format!("{:b}", true), "true"); - t!(format!("{:c}", '☃'), "☃"); - t!(format!("{:d}", 10), "10"); - t!(format!("{:i}", 10), "10"); - t!(format!("{:u}", 10u), "10"); - t!(format!("{:o}", 10u), "12"); - t!(format!("{:x}", 10u), "a"); - t!(format!("{:X}", 10u), "A"); - t!(format!("{:s}", "foo"), "foo"); - t!(format!("{:s}", ~"foo"), "foo"); - t!(format!("{:s}", @"foo"), "foo"); - t!(format!("{:p}", 0x1234 as *int), "0x1234"); - t!(format!("{:p}", 0x1234 as *mut int), "0x1234"); - t!(format!("{:d}", A), "aloha"); - t!(format!("{:d}", B), "adios"); - t!(format!("foo {:s} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); - t!(format!("{1} {0}", 0, 1), "1 0"); - t!(format!("{foo} {bar}", foo=0, bar=1), "0 1"); - t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0"); - t!(format!("{} {0}", "a"), "a a"); - t!(format!("{foo_bar}", foo_bar=1), "1"); - - // Methods should probably work - t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 0u), "c0"); - t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 1u), "a1"); - t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 2u), "b2"); - t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 3u), "d3"); - t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "a"), "aa"); - t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "b"), "bb"); - t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "c"), "cc"); - t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "d"), "dd"); - t!(format!("{1, select, a{#{0:s}} other{#}}", "b", "a"), "ab"); - t!(format!("{1, select, a{#{0}} other{#}}", "c", "b"), "b"); - - // Formatting strings and their arguments - t!(format!("{:s}", "a"), "a"); - t!(format!("{:4s}", "a"), "a "); - t!(format!("{:>4s}", "a"), " a"); - t!(format!("{:<4s}", "a"), "a "); - t!(format!("{:.4s}", "a"), "a"); - t!(format!("{:4.4s}", "a"), "a "); - t!(format!("{:4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:<4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>10.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:2.4s}", "aaaaa"), "aaaa"); - t!(format!("{:2.4s}", "aaaa"), "aaaa"); - t!(format!("{:2.4s}", "aaa"), "aaa"); - t!(format!("{:2.4s}", "aa"), "aa"); - t!(format!("{:2.4s}", "a"), "a "); - t!(format!("{:0>2s}", "a"), "0a"); - t!(format!("{:.*s}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:.1$s}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); - t!(format!("{:.a$s}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa"); - t!(format!("{:1$s}", "a", 4), "a "); - t!(format!("{1:0$s}", 4, "a"), "a "); - t!(format!("{:a$s}", "a", a=4), "a "); - t!(format!("{:-#s}", "a"), "a"); - t!(format!("{:+#s}", "a"), "a"); - - // Formatting integers should select the right implementation based off the - // type of the argument. Also, hex/octal/binary should be defined for - // integers, but they shouldn't emit the negative sign. - t!(format!("{:d}", -1i), "-1"); - t!(format!("{:d}", -1i8), "-1"); - t!(format!("{:d}", -1i16), "-1"); - t!(format!("{:d}", -1i32), "-1"); - t!(format!("{:d}", -1i64), "-1"); - t!(format!("{:t}", 1i), "1"); - t!(format!("{:t}", 1i8), "1"); - t!(format!("{:t}", 1i16), "1"); - t!(format!("{:t}", 1i32), "1"); - t!(format!("{:t}", 1i64), "1"); - t!(format!("{:x}", 1i), "1"); - t!(format!("{:x}", 1i8), "1"); - t!(format!("{:x}", 1i16), "1"); - t!(format!("{:x}", 1i32), "1"); - t!(format!("{:x}", 1i64), "1"); - t!(format!("{:X}", 1i), "1"); - t!(format!("{:X}", 1i8), "1"); - t!(format!("{:X}", 1i16), "1"); - t!(format!("{:X}", 1i32), "1"); - t!(format!("{:X}", 1i64), "1"); - t!(format!("{:o}", 1i), "1"); - t!(format!("{:o}", 1i8), "1"); - t!(format!("{:o}", 1i16), "1"); - t!(format!("{:o}", 1i32), "1"); - t!(format!("{:o}", 1i64), "1"); - - t!(format!("{:u}", 1u), "1"); - t!(format!("{:u}", 1u8), "1"); - t!(format!("{:u}", 1u16), "1"); - t!(format!("{:u}", 1u32), "1"); - t!(format!("{:u}", 1u64), "1"); - t!(format!("{:t}", 1u), "1"); - t!(format!("{:t}", 1u8), "1"); - t!(format!("{:t}", 1u16), "1"); - t!(format!("{:t}", 1u32), "1"); - t!(format!("{:t}", 1u64), "1"); - t!(format!("{:x}", 1u), "1"); - t!(format!("{:x}", 1u8), "1"); - t!(format!("{:x}", 1u16), "1"); - t!(format!("{:x}", 1u32), "1"); - t!(format!("{:x}", 1u64), "1"); - t!(format!("{:X}", 1u), "1"); - t!(format!("{:X}", 1u8), "1"); - t!(format!("{:X}", 1u16), "1"); - t!(format!("{:X}", 1u32), "1"); - t!(format!("{:X}", 1u64), "1"); - t!(format!("{:o}", 1u), "1"); - t!(format!("{:o}", 1u8), "1"); - t!(format!("{:o}", 1u16), "1"); - t!(format!("{:o}", 1u32), "1"); - t!(format!("{:o}", 1u64), "1"); - - // Test the flags for formatting integers - t!(format!("{:3d}", 1), " 1"); - t!(format!("{:>3d}", 1), " 1"); - t!(format!("{:>+3d}", 1), " +1"); - t!(format!("{:<3d}", 1), "1 "); - t!(format!("{:#d}", 1), "1"); - t!(format!("{:#x}", 10), "0xa"); - t!(format!("{:#X}", 10), "0xA"); - t!(format!("{:#5x}", 10), " 0xa"); - t!(format!("{:#o}", 10), "0o12"); - t!(format!("{:08x}", 10), "0000000a"); - t!(format!("{:8x}", 10), " a"); - t!(format!("{:<8x}", 10), "a "); - t!(format!("{:>8x}", 10), " a"); - t!(format!("{:#08x}", 10), "0x00000a"); - t!(format!("{:08d}", -10), "-0000010"); - t!(format!("{:x}", -1u8), "ff"); - t!(format!("{:X}", -1u8), "FF"); - t!(format!("{:t}", -1u8), "11111111"); - t!(format!("{:o}", -1u8), "377"); - t!(format!("{:#x}", -1u8), "0xff"); - t!(format!("{:#X}", -1u8), "0xFF"); - t!(format!("{:#t}", -1u8), "0b11111111"); - t!(format!("{:#o}", -1u8), "0o377"); - - // Signed combinations - t!(format!("{:+5d}", 1), " +1"); - t!(format!("{:+5d}", -1), " -1"); - t!(format!("{:05d}", 1), "00001"); - t!(format!("{:05d}", -1), "-0001"); - t!(format!("{:+05d}", 1), "+0001"); - t!(format!("{:+05d}", -1), "-0001"); - - // Some float stuff - t!(format!("{:f}", 1.0f32), "1"); - t!(format!("{:f}", 1.0f64), "1"); - t!(format!("{:.3f}", 1.0f64), "1.000"); - t!(format!("{:10.3f}", 1.0f64), " 1.000"); - t!(format!("{:+10.3f}", 1.0f64), " +1.000"); - t!(format!("{:+10.3f}", -1.0f64), " -1.000"); - - // Escaping - t!(format!("\\{"), "{"); - t!(format!("\\}"), "}"); - t!(format!("\\#"), "#"); - t!(format!("\\\\"), "\\"); - - test_write(); - test_print(); - - // make sure that format! doesn't move out of local variables - let a = ~3; - format!("{:?}", a); - format!("{:?}", a); - - // make sure that format! doesn't cause spurious unused-unsafe warnings when - // it's inside of an outer unsafe block - unsafe { - let a: int = ::std::cast::transmute(3u); - format!("{}", a); - } - - test_format_args(); - - // test that trailing commas are acceptable - format!("{}", "test",); - format!("{foo}", foo="test",); -} - -// Basic test to make sure that we can invoke the `write!` macro with an -// io::Writer instance. -fn test_write() { - let mut buf = MemWriter::new(); - write!(&mut buf as &mut io::Writer, "{}", 3); - { - let w = &mut buf as &mut io::Writer; - write!(w, "{foo}", foo=4); - write!(w, "{:s}", "hello"); - writeln!(w, "{}", "line"); - writeln!(w, "{foo}", foo="bar"); - } - - let s = str::from_utf8_owned(buf.inner()); - t!(s, "34helloline\nbar\n"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -fn test_print() { - print!("hi"); - print!("{:?}", ~[0u8]); - println!("hello"); - println!("this is a {}", "test"); - println!("{foo}", foo="bar"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -fn test_format_args() { - let mut buf = MemWriter::new(); - { - let w = &mut buf as &mut io::Writer; - format_args!(|args| { fmt::write(w, args) }, "{}", 1); - format_args!(|args| { fmt::write(w, args) }, "test"); - format_args!(|args| { fmt::write(w, args) }, "{test}", test=3); - } - let s = str::from_utf8_owned(buf.inner()); - t!(s, "1test3"); - - let s = format_args!(fmt::format, "hello {}", "world"); - t!(s, "hello world"); -} diff --git a/gcc/testsuite/rust.test/impl-implicit-trait.rs b/gcc/testsuite/rust.test/impl-implicit-trait.rs deleted file mode 100644 index a33fc4f..0000000 --- a/gcc/testsuite/rust.test/impl-implicit-trait.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum option_ { - none_, - some_(T), -} - -impl option_ { - pub fn foo(&self) -> bool { true } -} - -enum option__ { - none__, - some__(int) -} - -impl option__ { - pub fn foo(&self) -> bool { true } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/impl-privacy-xc-1.rs b/gcc/testsuite/rust.test/impl-privacy-xc-1.rs deleted file mode 100644 index 19d3caf..0000000 --- a/gcc/testsuite/rust.test/impl-privacy-xc-1.rs +++ /dev/null @@ -1,9 +0,0 @@ -// aux-build:impl_privacy_xc_1.rs -// xfail-fast - -extern mod impl_privacy_xc_1; - -pub fn main() { - let fish = impl_privacy_xc_1::Fish { x: 1 }; - fish.swim(); -} diff --git a/gcc/testsuite/rust.test/impl-privacy-xc-2.rs b/gcc/testsuite/rust.test/impl-privacy-xc-2.rs deleted file mode 100644 index b3e4a4e..0000000 --- a/gcc/testsuite/rust.test/impl-privacy-xc-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -// aux-build:impl_privacy_xc_2.rs -// xfail-fast - -extern mod impl_privacy_xc_2; - -pub fn main() { - let fish1 = impl_privacy_xc_2::Fish { x: 1 }; - let fish2 = impl_privacy_xc_2::Fish { x: 2 }; - println(if fish1.eq(&fish2) { "yes" } else { "no " }); -} diff --git a/gcc/testsuite/rust.test/import-from.rs b/gcc/testsuite/rust.test/import-from.rs deleted file mode 100644 index 5cc51a6..0000000 --- a/gcc/testsuite/rust.test/import-from.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use spam::{ham, eggs}; - -mod spam { - pub fn ham() { } - pub fn eggs() { } -} - -pub fn main() { ham(); eggs(); } diff --git a/gcc/testsuite/rust.test/import-glob-0.rs b/gcc/testsuite/rust.test/import-glob-0.rs deleted file mode 100644 index 1da6172..0000000 --- a/gcc/testsuite/rust.test/import-glob-0.rs +++ /dev/null @@ -1,41 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -use module_of_many_things::*; -use dug::too::greedily::and::too::deep::*; - -mod module_of_many_things { - pub fn f1() { info2!("f1"); } - pub fn f2() { info2!("f2"); } - fn f3() { info2!("f3"); } - pub fn f4() { info2!("f4"); } -} - -mod dug { - pub mod too { - pub mod greedily { - pub mod and { - pub mod too { - pub mod deep { - pub fn nameless_fear() { info2!("Boo!"); } - pub fn also_redstone() { info2!("Whatever."); } - } - } - } - } - } -} - - -pub fn main() { f1(); f2(); f4(); nameless_fear(); also_redstone(); } diff --git a/gcc/testsuite/rust.test/import-glob-crate.rs b/gcc/testsuite/rust.test/import-glob-crate.rs deleted file mode 100644 index b3c8ffb..0000000 --- a/gcc/testsuite/rust.test/import-glob-crate.rs +++ /dev/null @@ -1,23 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; -#[allow(dead_assignment)]; - -extern mod extra; -use std::vec::*; - -pub fn main() { - let mut v = from_elem(0u, 0); - v = append(v, [4, 2]); - assert_eq!(from_fn(2, |i| 2*(i+1)), ~[2, 4]); -} diff --git a/gcc/testsuite/rust.test/import-in-block.rs b/gcc/testsuite/rust.test/import-in-block.rs deleted file mode 100644 index 0d53965..0000000 --- a/gcc/testsuite/rust.test/import-in-block.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -pub fn main() { - use std::util::replace; - let mut x = 5; - replace(&mut x, 6); - { - use std::util::*; - let mut y = 6; - swap(&mut x, &mut y); - } -} diff --git a/gcc/testsuite/rust.test/import-trailing-comma.rs b/gcc/testsuite/rust.test/import-trailing-comma.rs deleted file mode 100644 index dcd843e..0000000 --- a/gcc/testsuite/rust.test/import-trailing-comma.rs +++ /dev/null @@ -1,22 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use foo::bar::{baz, quux,}; - -mod foo { - pub mod bar { - pub fn baz() { } - pub fn quux() { } - } -} - -pub fn main() { baz(); quux(); } diff --git a/gcc/testsuite/rust.test/import.rs b/gcc/testsuite/rust.test/import.rs deleted file mode 100644 index eff085e..0000000 --- a/gcc/testsuite/rust.test/import.rs +++ /dev/null @@ -1,23 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod foo { - pub fn x(y: int) { info2!("{:?}", y); } -} - -mod bar { - use foo::x; - use z = foo::x; - pub fn thing() { x(10); z(10); } -} - -pub fn main() { bar::thing(); } diff --git a/gcc/testsuite/rust.test/import2.rs b/gcc/testsuite/rust.test/import2.rs deleted file mode 100644 index 3ca64ce..0000000 --- a/gcc/testsuite/rust.test/import2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use zed::bar; - -mod zed { - pub fn bar() { info2!("bar"); } -} - -pub fn main() { bar(); } diff --git a/gcc/testsuite/rust.test/import3.rs b/gcc/testsuite/rust.test/import3.rs deleted file mode 100644 index 10f6d87..0000000 --- a/gcc/testsuite/rust.test/import3.rs +++ /dev/null @@ -1,24 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_imports)]; - -use baz::zed; -use baz::zed::bar; - -mod baz { - pub mod zed { - pub fn bar() { info2!("bar2"); } - } -} - -pub fn main() { bar(); } diff --git a/gcc/testsuite/rust.test/import4.rs b/gcc/testsuite/rust.test/import4.rs deleted file mode 100644 index d453306..0000000 --- a/gcc/testsuite/rust.test/import4.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use zed::bar; - -mod zed { - pub fn bar() { info2!("bar"); } -} - -pub fn main() { let _zed = 42; bar(); } diff --git a/gcc/testsuite/rust.test/import5.rs b/gcc/testsuite/rust.test/import5.rs deleted file mode 100644 index 00c5f35..0000000 --- a/gcc/testsuite/rust.test/import5.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use foo::bar; -mod foo { - pub use foo::zed::bar; - pub mod zed { - pub fn bar() { info2!("foo"); } - } -} - -pub fn main() { bar(); } diff --git a/gcc/testsuite/rust.test/import6.rs b/gcc/testsuite/rust.test/import6.rs deleted file mode 100644 index 150a89f..0000000 --- a/gcc/testsuite/rust.test/import6.rs +++ /dev/null @@ -1,26 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_imports)]; - -use foo::zed; -use bar::baz; - -mod foo { - pub mod zed { - pub fn baz() { info2!("baz"); } - } -} -mod bar { - pub use foo::zed::baz; -} -pub fn main() { baz(); } diff --git a/gcc/testsuite/rust.test/import7.rs b/gcc/testsuite/rust.test/import7.rs deleted file mode 100644 index e924188..0000000 --- a/gcc/testsuite/rust.test/import7.rs +++ /dev/null @@ -1,29 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_imports)]; - -use foo::zed; -use bar::baz; - -mod foo { - pub mod zed { - pub fn baz() { info2!("baz"); } - } -} -mod bar { - pub use foo::zed::baz; - pub mod foo { - pub mod zed {} - } -} -pub fn main() { baz(); } diff --git a/gcc/testsuite/rust.test/import8.rs b/gcc/testsuite/rust.test/import8.rs deleted file mode 100644 index 9b0c512..0000000 --- a/gcc/testsuite/rust.test/import8.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use foo::x; -use z = foo::x; - -mod foo { - pub fn x(y: int) { info2!("{}", y); } -} - -pub fn main() { x(10); z(10); } diff --git a/gcc/testsuite/rust.test/infer-fn-tail-expr.rs b/gcc/testsuite/rust.test/infer-fn-tail-expr.rs deleted file mode 100644 index eb86013..0000000 --- a/gcc/testsuite/rust.test/infer-fn-tail-expr.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// issue #680 - -fn f() -> ~[int] { ~[] } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/inferred-suffix-in-pattern-range.rs b/gcc/testsuite/rust.test/inferred-suffix-in-pattern-range.rs deleted file mode 100644 index 447ee2c..0000000 --- a/gcc/testsuite/rust.test/inferred-suffix-in-pattern-range.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = 2; - let x_message = match x { - 0 .. 1 => { ~"not many" } - _ => { ~"lots" } - }; - assert_eq!(x_message, ~"lots"); - - let y = 2i; - let y_message = match y { - 0 .. 1 => { ~"not many" } - _ => { ~"lots" } - }; - assert_eq!(y_message, ~"lots"); - - let z = 1u64; - let z_message = match z { - 0 .. 1 => { ~"not many" } - _ => { ~"lots" } - }; - assert_eq!(z_message, ~"not many"); -} diff --git a/gcc/testsuite/rust.test/infinite-loops.rs b/gcc/testsuite/rust.test/infinite-loops.rs deleted file mode 100644 index dea0df2..0000000 --- a/gcc/testsuite/rust.test/infinite-loops.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - A simple way to make sure threading works. This should use all the - CPU cycles an any machines that we're likely to see for a while. -*/ -// xfail-test - -extern mod extra; - -fn loopy(n: int) { - if n > 0 { do spawn { loopy(n - 1) }; do spawn { loopy(n - 1) }; } - loop { } -} - -pub fn main() { - // Commenting this out, as this will hang forever otherwise. - // Even after seeing the comment above, I'm not sure what the - // intention of this test is. - // do spawn { loopy(5) }; -} diff --git a/gcc/testsuite/rust.test/init-res-into-things.rs b/gcc/testsuite/rust.test/init-res-into-things.rs deleted file mode 100644 index fb62048..0000000 --- a/gcc/testsuite/rust.test/init-res-into-things.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Resources can't be copied, but storing into data structures counts -// as a move unless the stored thing is used afterwards. - -struct r { - i: @mut int, -} - -struct Box { x: r } - -#[unsafe_destructor] -impl Drop for r { - fn drop(&mut self) { - *(self.i) = *(self.i) + 1; - } -} - -fn r(i: @mut int) -> r { - r { - i: i - } -} - -fn test_box() { - let i = @mut 0; - { - let _a = @r(i); - } - assert_eq!(*i, 1); -} - -fn test_rec() { - let i = @mut 0; - { - let _a = Box {x: r(i)}; - } - assert_eq!(*i, 1); -} - -fn test_tag() { - enum t { - t0(r), - } - - let i = @mut 0; - { - let _a = t0(r(i)); - } - assert_eq!(*i, 1); -} - -fn test_tup() { - let i = @mut 0; - { - let _a = (r(i), 0); - } - assert_eq!(*i, 1); -} - -fn test_unique() { - let i = @mut 0; - { - let _a = ~r(i); - } - assert_eq!(*i, 1); -} - -fn test_box_rec() { - let i = @mut 0; - { - let _a = @Box { - x: r(i) - }; - } - assert_eq!(*i, 1); -} - -pub fn main() { - test_box(); - test_rec(); - test_tag(); - test_tup(); - test_unique(); - test_box_rec(); -} diff --git a/gcc/testsuite/rust.test/inner-module.rs b/gcc/testsuite/rust.test/inner-module.rs deleted file mode 100644 index 7e3547b..0000000 --- a/gcc/testsuite/rust.test/inner-module.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -mod inner { - pub mod inner2 { - pub fn hello() { info2!("hello, modular world"); } - } - pub fn hello() { inner2::hello(); } -} - -pub fn main() { inner::hello(); inner::inner2::hello(); } diff --git a/gcc/testsuite/rust.test/inner-static.rs b/gcc/testsuite/rust.test/inner-static.rs deleted file mode 100644 index 3bd806a..0000000 --- a/gcc/testsuite/rust.test/inner-static.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:inner_static.rs -// xfail-fast - -extern mod inner_static; - -pub fn main() { - let a = inner_static::A::<()>; - let b = inner_static::B::<()>; - let c = inner_static::test::A::<()>; - assert_eq!(a.bar(), 2); - assert_eq!(b.bar(), 4); - assert_eq!(c.bar(), 6); -} diff --git a/gcc/testsuite/rust.test/instantiable.rs b/gcc/testsuite/rust.test/instantiable.rs deleted file mode 100644 index 41ddce7..0000000 --- a/gcc/testsuite/rust.test/instantiable.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; - -// check that we do not report a type like this as uninstantiable, -// even though it would be if the nxt field had type @foo: -struct foo(X); - -struct X { x: uint, nxt: *foo } - -pub fn main() { - let _x = foo(X {x: 0, nxt: ptr::null()}); -} diff --git a/gcc/testsuite/rust.test/int-conversion-coherence.rs b/gcc/testsuite/rust.test/int-conversion-coherence.rs deleted file mode 100644 index 7ef4f6e..0000000 --- a/gcc/testsuite/rust.test/int-conversion-coherence.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// -// Problem here is that transactions aren't implemented for integer literal -// inference. - -trait plus { - fn plus() -> int; -} - -impl foo of plus for uint { fn plus() -> int { self as int + 20 } } -impl foo of plus for int { fn plus() -> int { self + 10 } } - -pub fn main() { - assert_eq!(10.plus(), 20); -} diff --git a/gcc/testsuite/rust.test/int.rs b/gcc/testsuite/rust.test/int.rs deleted file mode 100644 index c6632f8..0000000 --- a/gcc/testsuite/rust.test/int.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { let _x: int = 10; } diff --git a/gcc/testsuite/rust.test/integer-literal-suffix-inference.rs b/gcc/testsuite/rust.test/integer-literal-suffix-inference.rs deleted file mode 100644 index 542efe3..0000000 --- a/gcc/testsuite/rust.test/integer-literal-suffix-inference.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - fn id_i8(n: i8) -> i8 { n } - fn id_i16(n: i16) -> i16 { n } - fn id_i32(n: i32) -> i32 { n } - fn id_i64(n: i64) -> i64 { n } - - fn id_uint(n: uint) -> uint { n } - fn id_u8(n: u8) -> u8 { n } - fn id_u16(n: u16) -> u16 { n } - fn id_u32(n: u32) -> u32 { n } - fn id_u64(n: u64) -> u64 { n } - - let _i: i8 = -128; - let j = -128; - id_i8(j); - id_i8(-128); - - let _i: i16 = -32_768; - let j = -32_768; - id_i16(j); - id_i16(-32_768); - - let _i: i32 = -2_147_483_648; - let j = -2_147_483_648; - id_i32(j); - id_i32(-2_147_483_648); - - let _i: i64 = -9_223_372_036_854_775_808; - let j = -9_223_372_036_854_775_808; - id_i64(j); - id_i64(-9_223_372_036_854_775_808); - - let _i: uint = 1; - let j = 1; - id_uint(j); - id_uint(1); - - let _i: u8 = 255; - let j = 255; - id_u8(j); - id_u8(255); - - let _i: u16 = 65_535; - let j = 65_535; - id_u16(j); - id_u16(65_535); - - let _i: u32 = 4_294_967_295; - let j = 4_294_967_295; - id_u32(j); - id_u32(4_294_967_295); - - let _i: u64 = 18_446_744_073_709_551_615; - let j = 18_446_744_073_709_551_615; - id_u64(j); - id_u64(18_446_744_073_709_551_615); -} diff --git a/gcc/testsuite/rust.test/integral-indexing.rs b/gcc/testsuite/rust.test/integral-indexing.rs deleted file mode 100644 index 05032dd..0000000 --- a/gcc/testsuite/rust.test/integral-indexing.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// This is a testcase for issue #94. -pub fn main() { - let v: ~[int] = ~[0, 1, 2, 3, 4, 5]; - let s: ~str = ~"abcdef"; - assert_eq!(v[3u], 3); - assert_eq!(v[3u8], 3); - assert_eq!(v[3i8], 3); - assert_eq!(v[3u32], 3); - assert_eq!(v[3i32], 3); - info2!("{}", v[3u8]); - assert_eq!(s[3u], 'd' as u8); - assert_eq!(s[3u8], 'd' as u8); - assert_eq!(s[3i8], 'd' as u8); - assert_eq!(s[3u32], 'd' as u8); - assert_eq!(s[3i32], 'd' as u8); - info2!("{}", s[3u8]); -} diff --git a/gcc/testsuite/rust.test/intrinsic-alignment.rs b/gcc/testsuite/rust.test/intrinsic-alignment.rs deleted file mode 100644 index 051f92b..0000000 --- a/gcc/testsuite/rust.test/intrinsic-alignment.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast Does not work with main in a submodule - -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; - } -} - -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -mod m { - #[main] - #[cfg(target_arch = "x86")] - pub fn main() { - unsafe { - assert_eq!(::rusti::pref_align_of::(), 8u); - assert_eq!(::rusti::min_align_of::(), 4u); - } - } - - #[main] - #[cfg(target_arch = "x86_64")] - pub fn main() { - unsafe { - assert_eq!(::rusti::pref_align_of::(), 8u); - assert_eq!(::rusti::min_align_of::(), 8u); - } - } -} - -#[cfg(target_os = "win32")] -mod m { - #[main] - #[cfg(target_arch = "x86")] - pub fn main() { - unsafe { - assert_eq!(::rusti::pref_align_of::(), 8u); - assert_eq!(::rusti::min_align_of::(), 8u); - } - } -} - -#[cfg(target_os = "android")] -mod m { - #[main] - #[cfg(target_arch = "arm")] - pub fn main() { - unsafe { - assert_eq!(::rusti::pref_align_of::(), 8u); - assert_eq!(::rusti::min_align_of::(), 8u); - } - } -} diff --git a/gcc/testsuite/rust.test/intrinsic-atomics-cc.rs b/gcc/testsuite/rust.test/intrinsic-atomics-cc.rs deleted file mode 100644 index a55149b..0000000 --- a/gcc/testsuite/rust.test/intrinsic-atomics-cc.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_intrinsic.rs - -extern mod cci_intrinsic; -use cci_intrinsic::atomic_xchg; - -pub fn main() { - let mut x = 1; - atomic_xchg(&mut x, 5); - assert_eq!(x, 5); -} diff --git a/gcc/testsuite/rust.test/intrinsic-atomics.rs b/gcc/testsuite/rust.test/intrinsic-atomics.rs deleted file mode 100644 index 2ec91ee..0000000 --- a/gcc/testsuite/rust.test/intrinsic-atomics.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - extern "rust-intrinsic" { - pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int; - pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int; - pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; - - pub fn atomic_load(src: &int) -> int; - pub fn atomic_load_acq(src: &int) -> int; - - pub fn atomic_store(dst: &mut int, val: int); - pub fn atomic_store_rel(dst: &mut int, val: int); - - pub fn atomic_xchg(dst: &mut int, src: int) -> int; - pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int; - pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int; - - pub fn atomic_xadd(dst: &mut int, src: int) -> int; - pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int; - pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int; - - pub fn atomic_xsub(dst: &mut int, src: int) -> int; - pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int; - pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int; - } -} - -pub fn main() { - unsafe { - let mut x = ~1; - - assert_eq!(rusti::atomic_load(x), 1); - *x = 5; - assert_eq!(rusti::atomic_load_acq(x), 5); - - rusti::atomic_store(x,3); - assert_eq!(*x, 3); - rusti::atomic_store_rel(x,1); - assert_eq!(*x, 1); - - assert_eq!(rusti::atomic_cxchg(x, 1, 2), 1); - assert_eq!(*x, 2); - - assert_eq!(rusti::atomic_cxchg_acq(x, 1, 3), 2); - assert_eq!(*x, 2); - - assert_eq!(rusti::atomic_cxchg_rel(x, 2, 1), 2); - assert_eq!(*x, 1); - - assert_eq!(rusti::atomic_xchg(x, 0), 1); - assert_eq!(*x, 0); - - assert_eq!(rusti::atomic_xchg_acq(x, 1), 0); - assert_eq!(*x, 1); - - assert_eq!(rusti::atomic_xchg_rel(x, 0), 1); - assert_eq!(*x, 0); - - assert_eq!(rusti::atomic_xadd(x, 1), 0); - assert_eq!(rusti::atomic_xadd_acq(x, 1), 1); - assert_eq!(rusti::atomic_xadd_rel(x, 1), 2); - assert_eq!(*x, 3); - - assert_eq!(rusti::atomic_xsub(x, 1), 3); - assert_eq!(rusti::atomic_xsub_acq(x, 1), 2); - assert_eq!(rusti::atomic_xsub_rel(x, 1), 1); - assert_eq!(*x, 0); - } -} diff --git a/gcc/testsuite/rust.test/intrinsic-frame-address.rs b/gcc/testsuite/rust.test/intrinsic-frame-address.rs deleted file mode 100644 index c7b2379..0000000 --- a/gcc/testsuite/rust.test/intrinsic-frame-address.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -mod rusti { - extern "rust-intrinsic" { - pub fn frame_address(f: &fn(*u8)); - } -} - -pub fn main() { - unsafe { - do rusti::frame_address |addr| { - assert!(addr.is_not_null()); - } - } -} diff --git a/gcc/testsuite/rust.test/intrinsic-move-val.rs b/gcc/testsuite/rust.test/intrinsic-move-val.rs deleted file mode 100644 index f328c48..0000000 --- a/gcc/testsuite/rust.test/intrinsic-move-val.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - extern "rust-intrinsic" { - pub fn move_val_init(dst: &mut T, src: T); - pub fn move_val(dst: &mut T, src: T); - } -} - -pub fn main() { - unsafe { - let x = @1; - let mut y = @2; - rusti::move_val(&mut y, x); - assert_eq!(*y, 1); - } -} diff --git a/gcc/testsuite/rust.test/intrinsic-uninit.rs b/gcc/testsuite/rust.test/intrinsic-uninit.rs deleted file mode 100644 index ab69049..0000000 --- a/gcc/testsuite/rust.test/intrinsic-uninit.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - extern "rust-intrinsic" { - pub fn uninit() -> T; - } -} -pub fn main() { - let _a : int = unsafe {rusti::uninit()}; -} diff --git a/gcc/testsuite/rust.test/intrinsics-integer.rs b/gcc/testsuite/rust.test/intrinsics-integer.rs deleted file mode 100644 index e454726..0000000 --- a/gcc/testsuite/rust.test/intrinsics-integer.rs +++ /dev/null @@ -1,123 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -extern mod extra; - -mod rusti { - extern "rust-intrinsic" { - pub fn ctpop8(x: i8) -> i8; - pub fn ctpop16(x: i16) -> i16; - pub fn ctpop32(x: i32) -> i32; - pub fn ctpop64(x: i64) -> i64; - - pub fn ctlz8(x: i8) -> i8; - pub fn ctlz16(x: i16) -> i16; - pub fn ctlz32(x: i32) -> i32; - pub fn ctlz64(x: i64) -> i64; - - pub fn cttz8(x: i8) -> i8; - pub fn cttz16(x: i16) -> i16; - pub fn cttz32(x: i32) -> i32; - pub fn cttz64(x: i64) -> i64; - - pub fn bswap16(x: i16) -> i16; - pub fn bswap32(x: i32) -> i32; - pub fn bswap64(x: i64) -> i64; - } -} - -pub fn main() { - unsafe { - use rusti::*; - - assert_eq!(ctpop8(0i8), 0i8); - assert_eq!(ctpop16(0i16), 0i16); - assert_eq!(ctpop32(0i32), 0i32); - assert_eq!(ctpop64(0i64), 0i64); - - assert_eq!(ctpop8(1i8), 1i8); - assert_eq!(ctpop16(1i16), 1i16); - assert_eq!(ctpop32(1i32), 1i32); - assert_eq!(ctpop64(1i64), 1i64); - - assert_eq!(ctpop8(10i8), 2i8); - assert_eq!(ctpop16(10i16), 2i16); - assert_eq!(ctpop32(10i32), 2i32); - assert_eq!(ctpop64(10i64), 2i64); - - assert_eq!(ctpop8(100i8), 3i8); - assert_eq!(ctpop16(100i16), 3i16); - assert_eq!(ctpop32(100i32), 3i32); - assert_eq!(ctpop64(100i64), 3i64); - - assert_eq!(ctpop8(-1i8), 8i8); - assert_eq!(ctpop16(-1i16), 16i16); - assert_eq!(ctpop32(-1i32), 32i32); - assert_eq!(ctpop64(-1i64), 64i64); - - assert_eq!(ctlz8(0i8), 8i8); - assert_eq!(ctlz16(0i16), 16i16); - assert_eq!(ctlz32(0i32), 32i32); - assert_eq!(ctlz64(0i64), 64i64); - - assert_eq!(ctlz8(1i8), 7i8); - assert_eq!(ctlz16(1i16), 15i16); - assert_eq!(ctlz32(1i32), 31i32); - assert_eq!(ctlz64(1i64), 63i64); - - assert_eq!(ctlz8(10i8), 4i8); - assert_eq!(ctlz16(10i16), 12i16); - assert_eq!(ctlz32(10i32), 28i32); - assert_eq!(ctlz64(10i64), 60i64); - - assert_eq!(ctlz8(100i8), 1i8); - assert_eq!(ctlz16(100i16), 9i16); - assert_eq!(ctlz32(100i32), 25i32); - assert_eq!(ctlz64(100i64), 57i64); - - assert_eq!(cttz8(-1i8), 0i8); - assert_eq!(cttz16(-1i16), 0i16); - assert_eq!(cttz32(-1i32), 0i32); - assert_eq!(cttz64(-1i64), 0i64); - - assert_eq!(cttz8(0i8), 8i8); - assert_eq!(cttz16(0i16), 16i16); - assert_eq!(cttz32(0i32), 32i32); - assert_eq!(cttz64(0i64), 64i64); - - assert_eq!(cttz8(1i8), 0i8); - assert_eq!(cttz16(1i16), 0i16); - assert_eq!(cttz32(1i32), 0i32); - assert_eq!(cttz64(1i64), 0i64); - - assert_eq!(cttz8(10i8), 1i8); - assert_eq!(cttz16(10i16), 1i16); - assert_eq!(cttz32(10i32), 1i32); - assert_eq!(cttz64(10i64), 1i64); - - assert_eq!(cttz8(100i8), 2i8); - assert_eq!(cttz16(100i16), 2i16); - assert_eq!(cttz32(100i32), 2i32); - assert_eq!(cttz64(100i64), 2i64); - - assert_eq!(cttz8(-1i8), 0i8); - assert_eq!(cttz16(-1i16), 0i16); - assert_eq!(cttz32(-1i32), 0i32); - assert_eq!(cttz64(-1i64), 0i64); - - assert_eq!(bswap16(0x0A0Bi16), 0x0B0Ai16); - assert_eq!(bswap32(0x0ABBCC0Di32), 0x0DCCBB0Ai32); - assert_eq!(bswap64(0x0122334455667708i64), 0x0877665544332201i64); - } -} diff --git a/gcc/testsuite/rust.test/intrinsics-math.rs b/gcc/testsuite/rust.test/intrinsics-math.rs deleted file mode 100644 index 085ce65..0000000 --- a/gcc/testsuite/rust.test/intrinsics-math.rs +++ /dev/null @@ -1,107 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -mod rusti { - extern "rust-intrinsic" { - pub fn sqrtf32(x: f32) -> f32; - pub fn sqrtf64(x: f64) -> f64; - pub fn powif32(a: f32, x: i32) -> f32; - pub fn powif64(a: f64, x: i32) -> f64; - pub fn sinf32(x: f32) -> f32; - pub fn sinf64(x: f64) -> f64; - pub fn cosf32(x: f32) -> f32; - pub fn cosf64(x: f64) -> f64; - pub fn powf32(a: f32, x: f32) -> f32; - pub fn powf64(a: f64, x: f64) -> f64; - pub fn expf32(x: f32) -> f32; - pub fn expf64(x: f64) -> f64; - pub fn exp2f32(x: f32) -> f32; - pub fn exp2f64(x: f64) -> f64; - pub fn logf32(x: f32) -> f32; - pub fn logf64(x: f64) -> f64; - pub fn log10f32(x: f32) -> f32; - pub fn log10f64(x: f64) -> f64; - pub fn log2f32(x: f32) -> f32; - pub fn log2f64(x: f64) -> f64; - pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; - pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; - pub fn fabsf32(x: f32) -> f32; - pub fn fabsf64(x: f64) -> f64; - pub fn floorf32(x: f32) -> f32; - pub fn floorf64(x: f64) -> f64; - pub fn ceilf32(x: f32) -> f32; - pub fn ceilf64(x: f64) -> f64; - pub fn truncf32(x: f32) -> f32; - pub fn truncf64(x: f64) -> f64; - } -} - -pub fn main() { - unsafe { - use rusti::*; - - use std::f32; - use std::f64; - - assert!((sqrtf32(64f32).approx_eq(&8f32))); - assert!((sqrtf64(64f64).approx_eq(&8f64))); - - assert!((powif32(25f32, -2i32).approx_eq(&0.0016f32))); - assert!((powif64(23.2f64, 2i32).approx_eq(&538.24f64))); - - assert!((sinf32(0f32).approx_eq(&0f32))); - assert!((sinf64(f64::consts::pi / 2f64).approx_eq(&1f64))); - - assert!((cosf32(0f32).approx_eq(&1f32))); - assert!((cosf64(f64::consts::pi * 2f64).approx_eq(&1f64))); - - assert!((powf32(25f32, -2f32).approx_eq(&0.0016f32))); - assert!((powf64(400f64, 0.5f64).approx_eq(&20f64))); - - assert!((fabsf32(expf32(1f32) - f32::consts::e).approx_eq(&0f32))); - assert!((expf64(1f64).approx_eq(&f64::consts::e))); - - assert!((exp2f32(10f32).approx_eq(&1024f32))); - assert!((exp2f64(50f64).approx_eq(&1125899906842624f64))); - - assert!((fabsf32(logf32(f32::consts::e) - 1f32).approx_eq(&0f32))); - assert!((logf64(1f64).approx_eq(&0f64))); - - assert!((log10f32(10f32).approx_eq(&1f32))); - assert!((log10f64(f64::consts::e).approx_eq(&f64::consts::log10_e))); - - assert!((log2f32(8f32).approx_eq(&3f32))); - assert!((log2f64(f64::consts::e).approx_eq(&f64::consts::log2_e))); - - assert!((fmaf32(1.0f32, 2.0f32, 5.0f32).approx_eq(&7.0f32))); - assert!((fmaf64(0.0f64, -2.0f64, f64::consts::e).approx_eq(&f64::consts::e))); - - assert!((fabsf32(-1.0f32).approx_eq(&1.0f32))); - assert!((fabsf64(34.2f64).approx_eq(&34.2f64))); - - assert!((floorf32(3.8f32).approx_eq(&3.0f32))); - assert!((floorf64(-1.1f64).approx_eq(&-2.0f64))); - - // Causes linker error - // undefined reference to llvm.ceil.f32/64 - //assert!((ceilf32(-2.3f32) == -2.0f32)); - //assert!((ceilf64(3.8f64) == 4.0f64)); - - // Causes linker error - // undefined reference to llvm.trunc.f32/64 - //assert!((truncf32(0.1f32) == 0.0f32)); - //assert!((truncf64(-0.1f64) == 0.0f64)); - } - -} diff --git a/gcc/testsuite/rust.test/invoke-external-foreign.rs b/gcc/testsuite/rust.test/invoke-external-foreign.rs deleted file mode 100644 index 1736428..0000000 --- a/gcc/testsuite/rust.test/invoke-external-foreign.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:foreign_lib.rs - -// The purpose of this test is to check that we can -// successfully (and safely) invoke external, cdecl -// functions from outside the crate. - -extern mod foreign_lib; - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let _foo = foreign_lib::rustrt::rust_get_test_int(); - } -} diff --git a/gcc/testsuite/rust.test/irrefutable-unit.rs b/gcc/testsuite/rust.test/irrefutable-unit.rs deleted file mode 100644 index 51adeea..0000000 --- a/gcc/testsuite/rust.test/irrefutable-unit.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let ((),()) = ((),()); -} diff --git a/gcc/testsuite/rust.test/issue-1112.rs b/gcc/testsuite/rust.test/issue-1112.rs deleted file mode 100644 index 22c88c8..0000000 --- a/gcc/testsuite/rust.test/issue-1112.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #1112 -// Alignment of interior pointers to dynamic-size types - -struct X { - a: T, - b: u8, - c: bool, - d: u8, - e: u16, - f: u8, - g: u8 -} - -pub fn main() { - let x: X = X { - a: 12345678, - b: 9u8, - c: true, - d: 10u8, - e: 11u16, - f: 12u8, - g: 13u8 - }; - bar(x); -} - -fn bar(x: X) { - assert_eq!(x.b, 9u8); - assert_eq!(x.c, true); - assert_eq!(x.d, 10u8); - assert_eq!(x.e, 11u16); - assert_eq!(x.f, 12u8); - assert_eq!(x.g, 13u8); -} diff --git a/gcc/testsuite/rust.test/issue-1251.rs b/gcc/testsuite/rust.test/issue-1251.rs deleted file mode 100644 index a78a10e..0000000 --- a/gcc/testsuite/rust.test/issue-1251.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[link(name = "rust_get_test_int")]; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-1257.rs b/gcc/testsuite/rust.test/issue-1257.rs deleted file mode 100644 index 9acdd92..0000000 --- a/gcc/testsuite/rust.test/issue-1257.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main () { - let mut line = ~""; - let mut i = 0; - while line != ~"exit" { - line = if i == 9 { ~"exit" } else { ~"notexit" }; - i += 1; - } -} diff --git a/gcc/testsuite/rust.test/issue-1458.rs b/gcc/testsuite/rust.test/issue-1458.rs deleted file mode 100644 index e22f382..0000000 --- a/gcc/testsuite/rust.test/issue-1458.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn plus_one(f: &fn() -> int) -> int { - return f() + 1; -} - -fn ret_plus_one() -> extern fn(&fn() -> int) -> int { - return plus_one; -} - -pub fn main() { - let z = do (ret_plus_one()) || { 2 }; - assert_eq!(z, 3); -} diff --git a/gcc/testsuite/rust.test/issue-1460.rs b/gcc/testsuite/rust.test/issue-1460.rs deleted file mode 100644 index 44465fe..0000000 --- a/gcc/testsuite/rust.test/issue-1460.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -pub fn main() { - {|i| if 1 == i { }}; -} diff --git a/gcc/testsuite/rust.test/issue-1516.rs b/gcc/testsuite/rust.test/issue-1516.rs deleted file mode 100644 index 17444e6..0000000 --- a/gcc/testsuite/rust.test/issue-1516.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let early_error: &'static fn(&str) -> ! = |_msg| { fail2!() }; -} diff --git a/gcc/testsuite/rust.test/issue-1660.rs b/gcc/testsuite/rust.test/issue-1660.rs deleted file mode 100644 index 5c8b4be..0000000 --- a/gcc/testsuite/rust.test/issue-1660.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - static _x: int = 1<<2; -} diff --git a/gcc/testsuite/rust.test/issue-1696.rs b/gcc/testsuite/rust.test/issue-1696.rs deleted file mode 100644 index de62c57..0000000 --- a/gcc/testsuite/rust.test/issue-1696.rs +++ /dev/null @@ -1,19 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -pub fn main() { - let mut m = HashMap::new(); - m.insert("foo".as_bytes().to_owned(), "bar".as_bytes().to_owned()); - error2!("{:?}", m); -} diff --git a/gcc/testsuite/rust.test/issue-1701.rs b/gcc/testsuite/rust.test/issue-1701.rs deleted file mode 100644 index 4f3d0db..0000000 --- a/gcc/testsuite/rust.test/issue-1701.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum pattern { tabby, tortoiseshell, calico } -enum breed { beagle, rottweiler, pug } -type name = ~str; -enum ear_kind { lop, upright } -enum animal { cat(pattern), dog(breed), rabbit(name, ear_kind), tiger } - -fn noise(a: animal) -> Option<~str> { - match a { - cat(*) => { Some(~"meow") } - dog(*) => { Some(~"woof") } - rabbit(*) => { None } - tiger(*) => { Some(~"roar") } - } -} - -pub fn main() { - assert_eq!(noise(cat(tabby)), Some(~"meow")); - assert_eq!(noise(dog(pug)), Some(~"woof")); - assert_eq!(noise(rabbit(~"Hilbert", upright)), None); - assert_eq!(noise(tiger), Some(~"roar")); -} diff --git a/gcc/testsuite/rust.test/issue-1821.rs b/gcc/testsuite/rust.test/issue-1821.rs deleted file mode 100644 index 92f0bea..0000000 --- a/gcc/testsuite/rust.test/issue-1821.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #1821 - Don't recurse trying to typecheck this -enum t { - foo(~[t]) -} -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-1866.rs b/gcc/testsuite/rust.test/issue-1866.rs deleted file mode 100644 index 037c7b8..0000000 --- a/gcc/testsuite/rust.test/issue-1866.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod a { - pub type rust_task = uint; - pub mod rustrt { - use super::rust_task; - extern { - pub fn rust_task_is_unwinding(rt: *rust_task) -> bool; - } - } -} - -mod b { - pub type rust_task = bool; - pub mod rustrt { - use super::rust_task; - extern { - pub fn rust_task_is_unwinding(rt: *rust_task) -> bool; - } - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-1974.rs b/gcc/testsuite/rust.test/issue-1974.rs deleted file mode 100644 index 90646b0..0000000 --- a/gcc/testsuite/rust.test/issue-1974.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue 1974 -// Don't double free the condition allocation -pub fn main() { - let s = ~"hej"; - while s != ~"" { - return; - } -} diff --git a/gcc/testsuite/rust.test/issue-2185.rs b/gcc/testsuite/rust.test/issue-2185.rs deleted file mode 100644 index fdf88f4..0000000 --- a/gcc/testsuite/rust.test/issue-2185.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// does the second one subsume the first? -// xfail-test -// xfail-fast - -// notes on this test case: -// On Thu, Apr 18, 2013 at 6:30 PM, John Clements wrote: -// the "issue-2185.rs" test was xfailed with a ref to #2263. Issue #2263 is now fixed, so I tried it again, and after adding some &self parameters, I got this error: -// -// Running /usr/local/bin/rustc: -// issue-2185.rs:24:0: 26:1 error: conflicting implementations for a trait -// issue-2185.rs:24 impl iterable for &'static fn(&fn(uint)) { -// issue-2185.rs:25 fn iter(&self, blk: &fn(v: uint)) { self( |i| blk(i) ) } -// issue-2185.rs:26 } -// issue-2185.rs:20:0: 22:1 note: note conflicting implementation here -// issue-2185.rs:20 impl iterable for &'static fn(&fn(A)) { -// issue-2185.rs:21 fn iter(&self, blk: &fn(A)) { self(blk); } -// issue-2185.rs:22 } -// -// … so it looks like it's just not possible to implement both the generic iterable and iterable for the type iterable. Is it okay if I just remove this test? -// -// but Niko responded: -// think it's fine to remove this test, just because it's old and cruft and not hard to reproduce. *However* it should eventually be possible to implement the same interface for the same type multiple times with different type parameters, it's just that our current trait implementation has accidental limitations. - -// so I'm leaving it in. -// actually, it looks like this is related to bug #3429. I'll rename this bug. - -// This test had to do with an outdated version of the iterable trait. -// However, the condition it was testing seemed complex enough to -// warrant still having a test, so I inlined the old definitions. - -trait iterable { - fn iter(&self, blk: &fn(A)); -} - -impl iterable for &'static fn(&fn(A)) { - fn iter(&self, blk: &fn(A)) { self(blk); } -} - -impl iterable for &'static fn(&fn(uint)) { - fn iter(&self, blk: &fn(v: uint)) { self( |i| blk(i) ) } -} - -fn filter>(self: IA, - prd: &'static fn(A) -> bool, - blk: &fn(A)) { - do self.iter |a| { - if prd(a) { blk(a) } - } -} - -fn foldl>(self: IA, b0: B, blk: &fn(B, A) -> B) -> B { - let mut b = b0; - do self.iter |a| { - b = blk(b, a); - } - b -} - -fn range(lo: uint, hi: uint, it: &fn(uint)) { - let mut i = lo; - while i < hi { - it(i); - i += 1u; - } -} - -pub fn main() { - let range: &'static fn(&fn(uint)) = |a| range(0u, 1000u, a); - let filt: &'static fn(&fn(v: uint)) = |a| filter( - range, - |&&n: uint| n % 3u != 0u && n % 5u != 0u, - a); - let sum = foldl(filt, 0u, |accum, &&n: uint| accum + n ); - - println!("{}", sum); -} diff --git a/gcc/testsuite/rust.test/issue-2190-1.rs b/gcc/testsuite/rust.test/issue-2190-1.rs deleted file mode 100644 index f3a8177..0000000 --- a/gcc/testsuite/rust.test/issue-2190-1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -static generations: uint = 1024+256+128+49; - -fn child_no(x: uint) -> ~fn() { - || { - if x < generations { - task::spawn(child_no(x+1)); - } - } -} - -pub fn main() { - task::spawn(child_no(0)); -} diff --git a/gcc/testsuite/rust.test/issue-2190-2.rs b/gcc/testsuite/rust.test/issue-2190-2.rs deleted file mode 100644 index d5ee712..0000000 --- a/gcc/testsuite/rust.test/issue-2190-2.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test FIXME #2190 -mod a { - fn foo(f: &fn()) { f() } - fn bar() {} - pub fn main() { foo(||bar()); } -} - -mod b { - fn foo(f: Option<&fn()>) { f.iter(|x|x()) } - fn bar() {} - pub fn main() { foo(Some(bar)); } -} - -mod c { - fn foo(f: Option<&fn()>) { f.iter(|x|x()) } - fn bar() {} - pub fn main() { foo(Some(||bar())); } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-2190.rs b/gcc/testsuite/rust.test/issue-2190.rs deleted file mode 100644 index 0586995..0000000 --- a/gcc/testsuite/rust.test/issue-2190.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -type t = { - f: ~fn() -}; - -pub fn main() { - let _t: t = { f: {||()} }; -} diff --git a/gcc/testsuite/rust.test/issue-2214.rs b/gcc/testsuite/rust.test/issue-2214.rs deleted file mode 100644 index 9eebf66..0000000 --- a/gcc/testsuite/rust.test/issue-2214.rs +++ /dev/null @@ -1,47 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; -use std::libc::{c_double, c_int}; - -fn to_c_int(v: &mut int) -> &mut c_int { - unsafe { - cast::transmute_copy(&v) - } -} - -#[fixed_stack_segment] #[inline(never)] -fn lgamma(n: c_double, value: &mut int) -> c_double { - unsafe { - return m::lgamma(n, to_c_int(value)); - } -} - -mod m { - use std::libc::{c_double, c_int}; - - #[link_name = "m"] - extern { - #[cfg(unix)] - #[link_name="lgamma_r"] - pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; - #[cfg(windows)] - #[link_name="__lgamma_r"] - pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; - } -} - -pub fn main() { - let mut y: int = 5; - let x: &mut int = &mut y; - assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double); -} diff --git a/gcc/testsuite/rust.test/issue-2216.rs b/gcc/testsuite/rust.test/issue-2216.rs deleted file mode 100644 index f51a49e..0000000 --- a/gcc/testsuite/rust.test/issue-2216.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut x = 0; - - 'foo: loop { - 'bar: loop { - 'quux: loop { - if 1 == 2 { - break 'foo; - } - else { - break 'bar; - } - } - continue 'foo; - } - x = 42; - break; - } - - error2!("{:?}", x); - assert_eq!(x, 42); -} diff --git a/gcc/testsuite/rust.test/issue-2284.rs b/gcc/testsuite/rust.test/issue-2284.rs deleted file mode 100644 index b8c9ada..0000000 --- a/gcc/testsuite/rust.test/issue-2284.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Send { - fn f(&self); -} - -fn f(t: T) { - t.f(); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-2288.rs b/gcc/testsuite/rust.test/issue-2288.rs deleted file mode 100644 index 57d6fed04..0000000 --- a/gcc/testsuite/rust.test/issue-2288.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait clam { - fn chowder(&self, y: A); -} -struct foo { - x: A, -} - -impl clam for foo { - fn chowder(&self, _y: A) { - } -} - -fn foo(b: A) -> foo { - foo { - x: b - } -} - -fn f(x: @clam, a: A) { - x.chowder(a); -} - -pub fn main() { - - let c = foo(42); - let d: @clam = @c as @clam; - f(d, c.x); -} diff --git a/gcc/testsuite/rust.test/issue-2311-2.rs b/gcc/testsuite/rust.test/issue-2311-2.rs deleted file mode 100644 index cf8d3dc..0000000 --- a/gcc/testsuite/rust.test/issue-2311-2.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait clam { } -struct foo { - x: A, -} - -impl foo { - pub fn bar>(&self, _c: C) -> B { - fail2!(); - } -} - -fn foo(b: A) -> foo { - foo { - x: b - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-2311.rs b/gcc/testsuite/rust.test/issue-2311.rs deleted file mode 100644 index dc873ed..0000000 --- a/gcc/testsuite/rust.test/issue-2311.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait clam { } -trait foo { - fn bar>(&self, c: C) -> B; -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-2312.rs b/gcc/testsuite/rust.test/issue-2312.rs deleted file mode 100644 index 54a8730..0000000 --- a/gcc/testsuite/rust.test/issue-2312.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing that the B's are resolved - -trait clam { } - -struct foo(int); - -impl foo { - pub fn bar>(&self, _c: C) -> B { fail2!(); } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-2316-c.rs b/gcc/testsuite/rust.test/issue-2316-c.rs deleted file mode 100644 index c9dc6a5..0000000 --- a/gcc/testsuite/rust.test/issue-2316-c.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:issue_2316_a.rs -// aux-build:issue_2316_b.rs - -extern mod issue_2316_b; -use issue_2316_b::cloth; - -pub fn main() { - let _c: cloth::fabric = cloth::calico; -} diff --git a/gcc/testsuite/rust.test/issue-2380-b.rs b/gcc/testsuite/rust.test/issue-2380-b.rs deleted file mode 100644 index d61622e..0000000 --- a/gcc/testsuite/rust.test/issue-2380-b.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue-2380.rs - -extern mod a; - -pub fn main() { - a::f::<()>(); -} diff --git a/gcc/testsuite/rust.test/issue-2383.rs b/gcc/testsuite/rust.test/issue-2383.rs deleted file mode 100644 index 0314c7f..0000000 --- a/gcc/testsuite/rust.test/issue-2383.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; -use extra::ringbuf::RingBuf; -use extra::container::Deque; - -pub fn main() { - let mut q = RingBuf::new(); - q.push_back(10); -} diff --git a/gcc/testsuite/rust.test/issue-2414-c.rs b/gcc/testsuite/rust.test/issue-2414-c.rs deleted file mode 100644 index 1bc88e7..0000000 --- a/gcc/testsuite/rust.test/issue-2414-c.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue-2414-a.rs -// aux-build:issue-2414-b.rs - -extern mod b; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2428.rs b/gcc/testsuite/rust.test/issue-2428.rs deleted file mode 100644 index 4e73be8..0000000 --- a/gcc/testsuite/rust.test/issue-2428.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _foo = 100; - static quux: int = 5; - - enum Stuff { - Bar = quux - } - - assert_eq!(Bar as int, quux); -} diff --git a/gcc/testsuite/rust.test/issue-2445-b.rs b/gcc/testsuite/rust.test/issue-2445-b.rs deleted file mode 100644 index 91f76fc..0000000 --- a/gcc/testsuite/rust.test/issue-2445-b.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct c1 { - x: T, -} - -impl c1 { - pub fn f1(&self, _x: int) { - } -} - -fn c1(x: T) -> c1 { - c1 { - x: x - } -} - -impl c1 { - pub fn f2(&self, _x: int) { - } -} - - -pub fn main() { - c1::(3).f1(4); - c1::(3).f2(4); -} diff --git a/gcc/testsuite/rust.test/issue-2445.rs b/gcc/testsuite/rust.test/issue-2445.rs deleted file mode 100644 index 6356c87..0000000 --- a/gcc/testsuite/rust.test/issue-2445.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct c1 { - x: T, -} - -impl c1 { - pub fn f1(&self, _x: T) {} -} - -fn c1(x: T) -> c1 { - c1 { - x: x - } -} - -impl c1 { - pub fn f2(&self, _x: T) {} -} - - -pub fn main() { - c1::(3).f1(4); - c1::(3).f2(4); -} diff --git a/gcc/testsuite/rust.test/issue-2463.rs b/gcc/testsuite/rust.test/issue-2463.rs deleted file mode 100644 index 051ebd1..0000000 --- a/gcc/testsuite/rust.test/issue-2463.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair { f: int, g: int } - -pub fn main() { - - let x = Pair { - f: 0, - g: 0, - }; - - let _y = Pair { - f: 1, - g: 1, - .. x - }; - - let _z = Pair { - f: 1, - .. x - }; - -} diff --git a/gcc/testsuite/rust.test/issue-2472.rs b/gcc/testsuite/rust.test/issue-2472.rs deleted file mode 100644 index db116cd..0000000 --- a/gcc/testsuite/rust.test/issue-2472.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue_2472_b.rs -// xfail-fast - -extern mod issue_2472_b; - -use issue_2472_b::{S, T}; - -pub fn main() { - let s = S(()); - s.foo(); - s.bar(); -} diff --git a/gcc/testsuite/rust.test/issue-2487-a.rs b/gcc/testsuite/rust.test/issue-2487-a.rs deleted file mode 100644 index c12325e..0000000 --- a/gcc/testsuite/rust.test/issue-2487-a.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct socket { - sock: int, - -} - -impl Drop for socket { - fn drop(&mut self) {} -} - -impl socket { - pub fn set_identity(&self) { - do closure { - setsockopt_bytes(self.sock.clone()) - } - } -} - -fn socket() -> socket { - socket { - sock: 1 - } -} - -fn closure(f: &fn()) { f() } - -fn setsockopt_bytes(_sock: int) { } - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2502.rs b/gcc/testsuite/rust.test/issue-2502.rs deleted file mode 100644 index c26fef4..0000000 --- a/gcc/testsuite/rust.test/issue-2502.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct font<'self> { - fontbuf: &'self ~[u8], -} - -impl<'self> font<'self> { - pub fn buf(&self) -> &'self ~[u8] { - self.fontbuf - } -} - -fn font<'r>(fontbuf: &'r ~[u8]) -> font<'r> { - font { - fontbuf: fontbuf - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-2526-a.rs b/gcc/testsuite/rust.test/issue-2526-a.rs deleted file mode 100644 index e9df42b..0000000 --- a/gcc/testsuite/rust.test/issue-2526-a.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue-2526.rs - -#[feature(globs)]; -#[allow(unused_imports)]; - -extern mod issue_2526; -use issue_2526::*; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2550.rs b/gcc/testsuite/rust.test/issue-2550.rs deleted file mode 100644 index 99c6882..0000000 --- a/gcc/testsuite/rust.test/issue-2550.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct C { - x: uint, -} - -fn C(x: uint) -> C { - C { - x: x - } -} - -fn f(_x: T) { -} - -pub fn main() { - f(C(1u)); -} diff --git a/gcc/testsuite/rust.test/issue-2611-3.rs b/gcc/testsuite/rust.test/issue-2611-3.rs deleted file mode 100644 index 5882edf..0000000 --- a/gcc/testsuite/rust.test/issue-2611-3.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that impls are allowed to have looser, more permissive bounds -// than the traits require. - -trait A { - fn b(x: C) -> C; -} - -struct E { - f: int -} - -impl A for E { - fn b(_x: F) -> F { fail2!() } - //~^ ERROR in method `b`, type parameter 0 has 1 bound, but -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2631-b.rs b/gcc/testsuite/rust.test/issue-2631-b.rs deleted file mode 100644 index 71aa110..0000000 --- a/gcc/testsuite/rust.test/issue-2631-b.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue-2631-a.rs - -extern mod req; - -use req::request; -use std::hashmap::HashMap; - -pub fn main() { - let v = ~[@~"hi"]; - let mut m: req::header_map = HashMap::new(); - m.insert(~"METHOD", @mut v); - request::(&m); -} diff --git a/gcc/testsuite/rust.test/issue-2633-2.rs b/gcc/testsuite/rust.test/issue-2633-2.rs deleted file mode 100644 index 71a491b..0000000 --- a/gcc/testsuite/rust.test/issue-2633-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn a_val(x: ~int, y: ~int) -> int { - *x + *y -} - -pub fn main() { - let z = ~22; - a_val(z.clone(), z.clone()); -} diff --git a/gcc/testsuite/rust.test/issue-2633.rs b/gcc/testsuite/rust.test/issue-2633.rs deleted file mode 100644 index e905c89..0000000 --- a/gcc/testsuite/rust.test/issue-2633.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - meow: extern "Rust" fn(), -} - -fn meow() { - error2!("meow") -} - -fn cat() -> cat { - cat { - meow: meow, - } -} - -struct KittyInfo {kitty: cat} - -// Code compiles and runs successfully if we add a + before the first arg -fn nyan(kitty: cat, _kitty_info: KittyInfo) { - (kitty.meow)(); -} - -pub fn main() { - let kitty = cat(); - nyan(kitty, KittyInfo {kitty: kitty}); -} diff --git a/gcc/testsuite/rust.test/issue-2642.rs b/gcc/testsuite/rust.test/issue-2642.rs deleted file mode 100644 index dc60155..0000000 --- a/gcc/testsuite/rust.test/issue-2642.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() { - let _x: uint = loop { loop { break; } }; -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-2708.rs b/gcc/testsuite/rust.test/issue-2708.rs deleted file mode 100644 index 1fce8e5..0000000 --- a/gcc/testsuite/rust.test/issue-2708.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Font { - fontbuf: uint, - cairo_font: uint, - font_dtor: uint, - -} - -impl Drop for Font { - fn drop(&mut self) {} -} - -fn Font() -> Font { - Font { - fontbuf: 0, - cairo_font: 0, - font_dtor: 0 - } -} - -pub fn main() { - let _f = @Font(); -} diff --git a/gcc/testsuite/rust.test/issue-2718.rs b/gcc/testsuite/rust.test/issue-2718.rs deleted file mode 100644 index 617f98c..0000000 --- a/gcc/testsuite/rust.test/issue-2718.rs +++ /dev/null @@ -1,327 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub type Task = int; - -// tjc: I don't know why -pub mod pipes { - use super::Task; - use std::cast::{forget, transmute}; - use std::cast; - use std::task; - use std::util; - - pub struct Stuff { - state: state, - blocked_task: Option, - payload: Option - } - - #[deriving(Eq)] - pub enum state { - empty, - full, - blocked, - terminated - } - - pub struct packet { - state: state, - blocked_task: Option, - payload: Option - } - - pub fn packet() -> *packet { - unsafe { - let p: *packet = cast::transmute(~Stuff{ - state: empty, - blocked_task: None::, - payload: None:: - }); - p - } - } - - mod rusti { - pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail2!(); } - pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail2!(); } - pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail2!(); } - } - - // We should consider moving this to ::std::unsafe, although I - // suspect graydon would want us to use void pointers instead. - pub unsafe fn uniquify(x: *T) -> ~T { - cast::transmute(x) - } - - pub fn swap_state_acq(dst: &mut state, src: state) -> state { - unsafe { - transmute(rusti::atomic_xchg_acq(transmute(dst), src as int)) - } - } - - pub fn swap_state_rel(dst: &mut state, src: state) -> state { - unsafe { - transmute(rusti::atomic_xchg_rel(transmute(dst), src as int)) - } - } - - pub fn send(mut p: send_packet, payload: T) { - let p = p.unwrap(); - let mut p = unsafe { uniquify(p) }; - assert!((*p).payload.is_none()); - (*p).payload = Some(payload); - let old_state = swap_state_rel(&mut (*p).state, full); - match old_state { - empty => { - // Yay, fastpath. - - // The receiver will eventually clean this up. - unsafe { forget(p); } - } - full => { fail2!("duplicate send") } - blocked => { - - // The receiver will eventually clean this up. - unsafe { forget(p); } - } - terminated => { - // The receiver will never receive this. Rely on drop_glue - // to clean everything up. - } - } - } - - pub fn recv(mut p: recv_packet) -> Option { - let p = p.unwrap(); - let mut p = unsafe { uniquify(p) }; - loop { - let old_state = swap_state_acq(&mut (*p).state, - blocked); - match old_state { - empty | blocked => { task::deschedule(); } - full => { - let payload = util::replace(&mut p.payload, None); - return Some(payload.unwrap()) - } - terminated => { - assert_eq!(old_state, terminated); - return None; - } - } - } - } - - pub fn sender_terminate(p: *packet) { - let mut p = unsafe { uniquify(p) }; - match swap_state_rel(&mut (*p).state, terminated) { - empty | blocked => { - // The receiver will eventually clean up. - unsafe { forget(p) } - } - full => { - // This is impossible - fail2!("you dun goofed") - } - terminated => { - // I have to clean up, use drop_glue - } - } - } - - pub fn receiver_terminate(p: *packet) { - let mut p = unsafe { uniquify(p) }; - match swap_state_rel(&mut (*p).state, terminated) { - empty => { - // the sender will clean up - unsafe { forget(p) } - } - blocked => { - // this shouldn't happen. - fail2!("terminating a blocked packet") - } - terminated | full => { - // I have to clean up, use drop_glue - } - } - } - - pub struct send_packet { - p: Option<*packet>, - } - - #[unsafe_destructor] - impl Drop for send_packet { - fn drop(&mut self) { - unsafe { - if self.p != None { - let self_p: &mut Option<*packet> = - cast::transmute(&self.p); - let p = util::replace(self_p, None); - sender_terminate(p.unwrap()) - } - } - } - } - - impl send_packet { - pub fn unwrap(&mut self) -> *packet { - util::replace(&mut self.p, None).unwrap() - } - } - - pub fn send_packet(p: *packet) -> send_packet { - send_packet { - p: Some(p) - } - } - - pub struct recv_packet { - p: Option<*packet>, - } - - #[unsafe_destructor] - impl Drop for recv_packet { - fn drop(&mut self) { - unsafe { - if self.p != None { - let self_p: &mut Option<*packet> = - cast::transmute(&self.p); - let p = util::replace(self_p, None); - receiver_terminate(p.unwrap()) - } - } - } - } - - impl recv_packet { - pub fn unwrap(&mut self) -> *packet { - util::replace(&mut self.p, None).unwrap() - } - } - - pub fn recv_packet(p: *packet) -> recv_packet { - recv_packet { - p: Some(p) - } - } - - pub fn entangle() -> (send_packet, recv_packet) { - let p = packet(); - (send_packet(p), recv_packet(p)) - } -} - -pub mod pingpong { - use std::cast; - - pub struct ping(::pipes::send_packet); - pub struct pong(::pipes::send_packet); - - pub fn liberate_ping(p: ping) -> ::pipes::send_packet { - unsafe { - let _addr : *::pipes::send_packet = match &p { - &ping(ref x) => { cast::transmute(x) } - }; - fail2!() - } - } - - pub fn liberate_pong(p: pong) -> ::pipes::send_packet { - unsafe { - let _addr : *::pipes::send_packet = match &p { - &pong(ref x) => { cast::transmute(x) } - }; - fail2!() - } - } - - pub fn init() -> (client::ping, server::ping) { - ::pipes::entangle() - } - - pub mod client { - use pingpong; - - pub type ping = ::pipes::send_packet; - pub type pong = ::pipes::recv_packet; - - pub fn do_ping(c: ping) -> pong { - let (sp, rp) = ::pipes::entangle(); - - ::pipes::send(c, pingpong::ping(sp)); - rp - } - - pub fn do_pong(c: pong) -> (ping, ()) { - let packet = ::pipes::recv(c); - if packet.is_none() { - fail2!("sender closed the connection") - } - (pingpong::liberate_pong(packet.unwrap()), ()) - } - } - - pub mod server { - use pingpong; - - pub type ping = ::pipes::recv_packet; - pub type pong = ::pipes::send_packet; - - pub fn do_ping(c: ping) -> (pong, ()) { - let packet = ::pipes::recv(c); - if packet.is_none() { - fail2!("sender closed the connection") - } - (pingpong::liberate_ping(packet.unwrap()), ()) - } - - pub fn do_pong(c: pong) -> ping { - let (sp, rp) = ::pipes::entangle(); - ::pipes::send(c, pingpong::pong(sp)); - rp - } - } -} - -fn client(chan: pingpong::client::ping) { - let chan = pingpong::client::do_ping(chan); - error2!("Sent ping"); - let (_chan, _data) = pingpong::client::do_pong(chan); - error2!("Received pong"); -} - -fn server(chan: pingpong::server::ping) { - let (chan, _data) = pingpong::server::do_ping(chan); - error2!("Received ping"); - let _chan = pingpong::server::do_pong(chan); - error2!("Sent pong"); -} - -pub fn main() { - /* -// Commented out because of option::get error - - let (client_, server_) = pingpong::init(); - let client_ = Cell::new(client_); - let server_ = Cell::new(server_); - - task::spawn {|client_| - let client__ = client_.take(); - client(client__); - }; - task::spawn {|server_| - let server__ = server_.take(); - server(server_ˊ); - }; - */ -} diff --git a/gcc/testsuite/rust.test/issue-2723-b.rs b/gcc/testsuite/rust.test/issue-2723-b.rs deleted file mode 100644 index 8c13ffe..0000000 --- a/gcc/testsuite/rust.test/issue-2723-b.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: aux-build not compatible with fast -// aux-build:issue_2723_a.rs - -extern mod issue_2723_a; -use issue_2723_a::f; - -pub fn main() { - unsafe { - f(~[2]); - } -} diff --git a/gcc/testsuite/rust.test/issue-2734.rs b/gcc/testsuite/rust.test/issue-2734.rs deleted file mode 100644 index 319146d..0000000 --- a/gcc/testsuite/rust.test/issue-2734.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait hax { } -impl hax for A { } - -fn perform_hax(x: @T) -> @hax { - @x as @hax -} - -fn deadcode() { - perform_hax(@~"deadcode"); -} - -pub fn main() { - let _ = perform_hax(@42); -} diff --git a/gcc/testsuite/rust.test/issue-2735-2.rs b/gcc/testsuite/rust.test/issue-2735-2.rs deleted file mode 100644 index 3be634c..0000000 --- a/gcc/testsuite/rust.test/issue-2735-2.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test should behave exactly like issue-2735-3 -struct defer { - b: @mut bool, -} - -#[unsafe_destructor] -impl Drop for defer { - fn drop(&mut self) { - *self.b = true; - } -} - -fn defer(b: @mut bool) -> defer { - defer { - b: b - } -} - -pub fn main() { - let dtor_ran = @mut false; - let _ = defer(dtor_ran); - assert!(*dtor_ran); -} diff --git a/gcc/testsuite/rust.test/issue-2735-3.rs b/gcc/testsuite/rust.test/issue-2735-3.rs deleted file mode 100644 index 8999ffd..0000000 --- a/gcc/testsuite/rust.test/issue-2735-3.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test should behave exactly like issue-2735-2 -struct defer { - b: @mut bool, -} - -#[unsafe_destructor] -impl Drop for defer { - fn drop(&mut self) { - *self.b = true; - } -} - -fn defer(b: @mut bool) -> defer { - defer { - b: b - } -} - -pub fn main() { - let dtor_ran = @mut false; - defer(dtor_ran); - assert!(*dtor_ran); -} diff --git a/gcc/testsuite/rust.test/issue-2735.rs b/gcc/testsuite/rust.test/issue-2735.rs deleted file mode 100644 index 9a5a366..0000000 --- a/gcc/testsuite/rust.test/issue-2735.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait hax { } -impl hax for A { } - -fn perform_hax(x: @T) -> @hax { - @x as @hax -} - -fn deadcode() { - perform_hax(@~"deadcode"); -} - -pub fn main() { - perform_hax(@42); -} diff --git a/gcc/testsuite/rust.test/issue-2748-a.rs b/gcc/testsuite/rust.test/issue-2748-a.rs deleted file mode 100644 index 63807de..0000000 --- a/gcc/testsuite/rust.test/issue-2748-a.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct CMap<'self> { - buf: &'self [u8], -} - -fn CMap<'r>(buf: &'r [u8]) -> CMap<'r> { - CMap { - buf: buf - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-2748-b.rs b/gcc/testsuite/rust.test/issue-2748-b.rs deleted file mode 100644 index 3ca8d49..0000000 --- a/gcc/testsuite/rust.test/issue-2748-b.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn thing<'r>(x: &'r [int]) -> &'r [int] { x } - -pub fn main() { - let x = &[1,2,3]; - let y = x; - let z = thing(x); - assert_eq!(z[2], x[2]); - assert_eq!(z[1], y[1]); -} diff --git a/gcc/testsuite/rust.test/issue-2804-2.rs b/gcc/testsuite/rust.test/issue-2804-2.rs deleted file mode 100644 index 8fad80c..0000000 --- a/gcc/testsuite/rust.test/issue-2804-2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Minimized version of issue-2804.rs. Both check that callee IDs don't -// clobber the previous node ID in a macro expr - -use std::hashmap::HashMap; - -fn add_interfaces(managed_ip: ~str, device: HashMap<~str, int>) { - error2!("{}, {:?}", managed_ip, device.get(&~"interfaces")); -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2804.rs b/gcc/testsuite/rust.test/issue-2804.rs deleted file mode 100644 index efcdbaa..0000000 --- a/gcc/testsuite/rust.test/issue-2804.rs +++ /dev/null @@ -1,75 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use extra::json; -use std::hashmap::HashMap; -use std::option; - -enum object { - bool_value(bool), - int_value(i64), -} - -fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str -{ - match table.find(&key) { - option::Some(&extra::json::String(ref s)) => { - (*s).clone() - } - option::Some(value) => { - error2!("{} was expected to be a string but is a {:?}", key, value); - default - } - option::None => { - default - } - } -} - -fn add_interface(_store: int, managed_ip: ~str, data: extra::json::Json) -> (~str, object) -{ - match &data { - &extra::json::Object(ref interface) => { - let name = lookup((*interface).clone(), ~"ifDescr", ~""); - let label = format!("{}-{}", managed_ip, name); - - (label, bool_value(false)) - } - _ => { - error2!("Expected dict for {} interfaces but found {:?}", managed_ip, data); - (~"gnos:missing-interface", bool_value(true)) - } - } -} - -fn add_interfaces(store: int, managed_ip: ~str, device: HashMap<~str, extra::json::Json>) -> ~[(~str, object)] -{ - match device.get(&~"interfaces") - { - &extra::json::List(ref interfaces) => - { - do interfaces.map |interface| { - add_interface(store, managed_ip.clone(), (*interface).clone()) - } - } - _ => - { - error2!("Expected list for {} interfaces but found {:?}", managed_ip, - device.get(&~"interfaces")); - ~[] - } - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2895.rs b/gcc/testsuite/rust.test/issue-2895.rs deleted file mode 100644 index 1e1db39..0000000 --- a/gcc/testsuite/rust.test/issue-2895.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -struct Cat { - x: int -} - -struct Kitty { - x: int, -} - -impl Drop for Kitty { - fn drop(&mut self) {} -} - -#[cfg(target_arch = "x86_64")] -pub fn main() { - assert_eq!(mem::size_of::(), 8 as uint); - assert_eq!(mem::size_of::(), 16 as uint); -} - -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "arm")] -pub fn main() { - assert_eq!(mem::size_of::(), 4 as uint); - assert_eq!(mem::size_of::(), 8 as uint); -} diff --git a/gcc/testsuite/rust.test/issue-2904.rs b/gcc/testsuite/rust.test/issue-2904.rs deleted file mode 100644 index f2a4692..0000000 --- a/gcc/testsuite/rust.test/issue-2904.rs +++ /dev/null @@ -1,87 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Map representation - -extern mod extra; - -use std::io::ReaderUtil; -use std::io; -use std::to_str; - -enum square { - bot, - wall, - rock, - lambda, - closed_lift, - open_lift, - earth, - empty -} - -impl to_str::ToStr for square { - fn to_str(&self) -> ~str { - match *self { - bot => { ~"R" } - wall => { ~"#" } - rock => { ~"*" } - lambda => { ~"\\" } - closed_lift => { ~"L" } - open_lift => { ~"O" } - earth => { ~"." } - empty => { ~" " } - } - } -} - -fn square_from_char(c: char) -> square { - match c { - 'R' => { bot } - '#' => { wall } - '*' => { rock } - '\\' => { lambda } - 'L' => { closed_lift } - 'O' => { open_lift } - '.' => { earth } - ' ' => { empty } - _ => { - error2!("invalid square: {:?}", c); - fail2!() - } - } -} - -fn read_board_grid(input: rdr) -> ~[~[square]] { - let input = @input as @io::Reader; - let mut grid = ~[]; - do input.each_line |line| { - let mut row = ~[]; - for c in line.iter() { - row.push(square_from_char(c)) - } - grid.push(row); - true - }; - let width = grid[0].len(); - for row in grid.iter() { assert!(row.len() == width) } - grid -} - -mod test { - #[test] - pub fn trivial_to_str() { - assert!(lambda.to_str() == "\\") - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-2935.rs b/gcc/testsuite/rust.test/issue-2935.rs deleted file mode 100644 index fff8938..0000000 --- a/gcc/testsuite/rust.test/issue-2935.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//type t = { a: int }; -// type t = { a: bool }; -type t = bool; - -trait it { - fn f(&self); -} - -impl it for t { - fn f(&self) { } -} - -pub fn main() { - // let x = ({a: 4i} as it); - // let y = @({a: 4i}); - // let z = @({a: 4i} as it); - // let z = @({a: true} as it); - let z = @(@true as @it); - // x.f(); - // y.f(); - // (*z).f(); - error2!("ok so far..."); - z.f(); //segfault -} diff --git a/gcc/testsuite/rust.test/issue-2936.rs b/gcc/testsuite/rust.test/issue-2936.rs deleted file mode 100644 index 183eb6e..0000000 --- a/gcc/testsuite/rust.test/issue-2936.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait bar { - fn get_bar(&self) -> T; -} - -fn foo>(b: U) -> T { - b.get_bar() -} - -struct cbar { - x: int, -} - -impl bar for cbar { - fn get_bar(&self) -> int { - self.x - } -} - -fn cbar(x: int) -> cbar { - cbar { - x: x - } -} - -pub fn main() { - let x: int = foo::(cbar(5)); - assert_eq!(x, 5); -} diff --git a/gcc/testsuite/rust.test/issue-2989.rs b/gcc/testsuite/rust.test/issue-2989.rs deleted file mode 100644 index 9b667ab..0000000 --- a/gcc/testsuite/rust.test/issue-2989.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::vec; - -trait methods { - fn to_bytes(&self) -> ~[u8]; -} - -impl methods for () { - fn to_bytes(&self) -> ~[u8] { - vec::from_elem(0, 0u8) - } -} - -// the position of this function is significant! - if it comes before methods -// then it works, if it comes after it then it doesn't! -fn to_bools(bitv: Storage) -> ~[bool] { - vec::from_fn(8, |i| { - let w = i / 64; - let b = i % 64; - let x = 1u64 & (bitv.storage[w] >> b); - x == 1u64 - }) -} - -struct Storage { storage: ~[u64] } - -pub fn main() { - let bools = ~[false, false, true, false, false, true, true, false]; - let bools2 = to_bools(Storage{storage: ~[0b01100100]}); - - for i in range(0u, 8) { - println!("{} => {} vs {}", i, bools[i], bools2[i]); - } - - assert_eq!(bools, bools2); -} diff --git a/gcc/testsuite/rust.test/issue-3012-2.rs b/gcc/testsuite/rust.test/issue-3012-2.rs deleted file mode 100644 index c572575..0000000 --- a/gcc/testsuite/rust.test/issue-3012-2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue-3012-1.rs -extern mod socketlib; - -use socketlib::socket; -use std::libc; - -pub fn main() { - let fd: libc::c_int = 1 as libc::c_int; - let _sock = @socket::socket_handle(fd); -} diff --git a/gcc/testsuite/rust.test/issue-3026.rs b/gcc/testsuite/rust.test/issue-3026.rs deleted file mode 100644 index ce471e5..0000000 --- a/gcc/testsuite/rust.test/issue-3026.rs +++ /dev/null @@ -1,19 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -pub fn main() { - let mut buggy_map: HashMap = HashMap::new(); - let x = ~1; - buggy_map.insert(42, &*x); -} diff --git a/gcc/testsuite/rust.test/issue-3037.rs b/gcc/testsuite/rust.test/issue-3037.rs deleted file mode 100644 index ef403a6c..0000000 --- a/gcc/testsuite/rust.test/issue-3037.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum what { } - -fn what_to_str(x: what) -> ~str -{ - match x { - } -} - -pub fn main() -{ -} diff --git a/gcc/testsuite/rust.test/issue-3052.rs b/gcc/testsuite/rust.test/issue-3052.rs deleted file mode 100644 index cb1ffc3..0000000 --- a/gcc/testsuite/rust.test/issue-3052.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -type Connection = &'static fn(~[u8]); - -fn f() -> Option { - let mock_connection: Connection = |_| {}; - Some(mock_connection) -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-3091.rs b/gcc/testsuite/rust.test/issue-3091.rs deleted file mode 100644 index c4c2c2b..0000000 --- a/gcc/testsuite/rust.test/issue-3091.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = 1; - let y = 1; - assert_eq!(&x, &y); -} diff --git a/gcc/testsuite/rust.test/issue-3109.rs b/gcc/testsuite/rust.test/issue-3109.rs deleted file mode 100644 index 76cb182..0000000 --- a/gcc/testsuite/rust.test/issue-3109.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - error2!("{:?}", ("hi there!", "you")); -} diff --git a/gcc/testsuite/rust.test/issue-3121.rs b/gcc/testsuite/rust.test/issue-3121.rs deleted file mode 100644 index 206dc38..0000000 --- a/gcc/testsuite/rust.test/issue-3121.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum side { mayo, catsup, vinegar } -enum order { hamburger, fries(side), shake } -enum meal { to_go(order), for_here(order) } - -fn foo(m: @meal, cond: bool) { - match *m { - to_go(_) => { } - for_here(_) if cond => {} - for_here(hamburger) => {} - for_here(fries(_s)) => {} - for_here(shake) => {} - } -} - -pub fn main() { - foo(@for_here(hamburger), true) -} diff --git a/gcc/testsuite/rust.test/issue-3149.rs b/gcc/testsuite/rust.test/issue-3149.rs deleted file mode 100644 index ab64fb4..0000000 --- a/gcc/testsuite/rust.test/issue-3149.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn Matrix4(m11: T, m12: T, m13: T, m14: T, - m21: T, m22: T, m23: T, m24: T, - m31: T, m32: T, m33: T, m34: T, - m41: T, m42: T, m43: T, m44: T) - -> Matrix4 { - Matrix4 { - m11: m11, m12: m12, m13: m13, m14: m14, - m21: m21, m22: m22, m23: m23, m24: m24, - m31: m31, m32: m32, m33: m33, m34: m34, - m41: m41, m42: m42, m43: m43, m44: m44 - } -} - -struct Matrix4 { - m11: T, m12: T, m13: T, m14: T, - m21: T, m22: T, m23: T, m24: T, - m31: T, m32: T, m33: T, m34: T, - m41: T, m42: T, m43: T, m44: T, -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3168.rs b/gcc/testsuite/rust.test/issue-3168.rs deleted file mode 100644 index 978cd58..0000000 --- a/gcc/testsuite/rust.test/issue-3168.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test linked failure -// xfail-fast - -use std::comm; -use std::task; - -pub fn main() { - let (p,c) = comm::stream(); - do task::try || { - let (p2,c2) = comm::stream(); - do task::spawn || { - p2.recv(); - error!("sibling fails"); - fail!(); - } - let (p3,c3) = comm::stream(); - c.send(c3); - c2.send(()); - error!("child blocks"); - p3.recv(); - }; - error!("parent tries"); - assert!(!p.recv().try_send(())); - error!("all done!"); -} diff --git a/gcc/testsuite/rust.test/issue-3186.rs b/gcc/testsuite/rust.test/issue-3186.rs deleted file mode 100644 index 6b35cd7..0000000 --- a/gcc/testsuite/rust.test/issue-3186.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum y { x } - -enum x {} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3211.rs b/gcc/testsuite/rust.test/issue-3211.rs deleted file mode 100644 index 5e89cb2..0000000 --- a/gcc/testsuite/rust.test/issue-3211.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub fn main() { - let mut x = 0; - do 4096.times { - x += 1; - } - assert_eq!(x, 4096); - println!("x = {}", x); -} diff --git a/gcc/testsuite/rust.test/issue-3220.rs b/gcc/testsuite/rust.test/issue-3220.rs deleted file mode 100644 index 9c44a7c..0000000 --- a/gcc/testsuite/rust.test/issue-3220.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct thing { x: int, } - -impl Drop for thing { - fn drop(&mut self) {} -} - -fn thing() -> thing { - thing { - x: 0 - } -} - -impl thing { - pub fn f(self) {} -} - -pub fn main() { - let z = thing(); - (z).f(); -} diff --git a/gcc/testsuite/rust.test/issue-3250.rs b/gcc/testsuite/rust.test/issue-3250.rs deleted file mode 100644 index 0a93b89..0000000 --- a/gcc/testsuite/rust.test/issue-3250.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[auto_serialize] - -type t = (uint, uint); - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-3290.rs b/gcc/testsuite/rust.test/issue-3290.rs deleted file mode 100644 index 5cdc423..0000000 --- a/gcc/testsuite/rust.test/issue-3290.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test FIXME #3290 -fn main() { - let mut x = ~3; - x = x; - assert_eq!(*x, 3); -} diff --git a/gcc/testsuite/rust.test/issue-333.rs b/gcc/testsuite/rust.test/issue-333.rs deleted file mode 100644 index 1217f32..0000000 --- a/gcc/testsuite/rust.test/issue-333.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn quux(x: T) -> T { let f = id::; return f(x); } - -fn id(x: T) -> T { return x; } - -pub fn main() { assert!((quux(10) == 10)); } diff --git a/gcc/testsuite/rust.test/issue-3389.rs b/gcc/testsuite/rust.test/issue-3389.rs deleted file mode 100644 index 5bb88df..0000000 --- a/gcc/testsuite/rust.test/issue-3389.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct trie_node { - content: ~[~str], - children: ~[trie_node], -} - -fn print_str_vector(vector: ~[~str]) { - for string in vector.iter() { - println(*string); - } -} - -pub fn main() { - let mut node: trie_node = trie_node { - content: ~[], - children: ~[] - }; - let v = ~[~"123", ~"abc"]; - node.content = ~[~"123", ~"abc"]; - print_str_vector(v); - print_str_vector(node.content.clone()); - -} diff --git a/gcc/testsuite/rust.test/issue-3424.rs b/gcc/testsuite/rust.test/issue-3424.rs deleted file mode 100644 index f860426..0000000 --- a/gcc/testsuite/rust.test/issue-3424.rs +++ /dev/null @@ -1,30 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// rustc --test ignores2.rs && ./ignores2 -extern mod extra; - -use std::path::{Path}; -use std::path; -use std::result; - -type rsrc_loader = ~fn(path: &Path) -> result::Result<~str, ~str>; - -fn tester() -{ - let loader: rsrc_loader = |_path| {result::Ok(~"more blah")}; - - let path = path::Path::new("blah"); - assert!(loader(&path).is_ok()); -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3429.rs b/gcc/testsuite/rust.test/issue-3429.rs deleted file mode 100644 index fc49348..0000000 --- a/gcc/testsuite/rust.test/issue-3429.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = 1; - let y: &fn() -> int = || x; - let _z = y(); -} diff --git a/gcc/testsuite/rust.test/issue-3447.rs b/gcc/testsuite/rust.test/issue-3447.rs deleted file mode 100644 index 64483ab..0000000 --- a/gcc/testsuite/rust.test/issue-3447.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static S: &'static str = "str"; - -struct list { - element: T, - next: Option<@mut list> -} - -impl list { - pub fn addEnd(&mut self, element: T) { - let newList = list { - element: element, - next: None - }; - - self.next = Some(@mut newList); - } -} - -pub fn main() { - let ls = list { - element: S, - next: None - }; - println(ls.element); -} diff --git a/gcc/testsuite/rust.test/issue-3461.rs b/gcc/testsuite/rust.test/issue-3461.rs deleted file mode 100644 index dae35d7..0000000 --- a/gcc/testsuite/rust.test/issue-3461.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -pub fn main() { - - fn foo() { } - - let bar: ~fn() = ~foo; -} diff --git a/gcc/testsuite/rust.test/issue-3500.rs b/gcc/testsuite/rust.test/issue-3500.rs deleted file mode 100644 index 99def54..0000000 --- a/gcc/testsuite/rust.test/issue-3500.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = &Some(1); - match x { - &Some(_) => (), - &None => (), - } -} diff --git a/gcc/testsuite/rust.test/issue-3556.rs b/gcc/testsuite/rust.test/issue-3556.rs deleted file mode 100644 index f058a5c..0000000 --- a/gcc/testsuite/rust.test/issue-3556.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::io::WriterUtil; -use std::io; - -enum Token { - Text(@~str), - ETag(@~[~str], @~str), - UTag(@~[~str], @~str), - Section(@~[~str], bool, @~[Token], @~str, @~str, @~str, @~str, @~str), - IncompleteSection(@~[~str], bool, @~str, bool), - Partial(@~str, @~str, @~str), -} - -fn check_strs(actual: &str, expected: &str) -> bool -{ - if actual != expected - { - io::stderr().write_line(format!("Found {}, but expected {}", actual, - expected)); - return false; - } - return true; -} - -pub fn main() -{ - // assert!(check_strs(fmt!("%?", Text(@~"foo")), "Text(@~\"foo\")")); - // assert!(check_strs(fmt!("%?", ETag(@~[~"foo"], @~"bar")), "ETag(@~[ ~\"foo\" ], @~\"bar\")")); - - let t = Text(@~"foo"); - let u = Section(@~[~"alpha"], true, @~[t], @~"foo", @~"foo", @~"foo", @~"foo", @~"foo"); - let v = format!("{:?}", u); // this is the line that causes the seg fault - assert!(v.len() > 0); -} diff --git a/gcc/testsuite/rust.test/issue-3559.rs b/gcc/testsuite/rust.test/issue-3559.rs deleted file mode 100644 index 9665da1..0000000 --- a/gcc/testsuite/rust.test/issue-3559.rs +++ /dev/null @@ -1,36 +0,0 @@ -// xfail-test #4276 - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// rustc --test map_to_str.rs && ./map_to_str -extern mod extra; - -use std::io::{WriterUtil}; - -fn check_strs(actual: &str, expected: &str) -> bool -{ - if actual != expected - { - io::stderr().write_line(fmt!("Found %s, but expected %s", actual, expected)); - return false; - } - return true; -} - -fn tester() -{ - let mut table = std::hashmap::HashMap::new(); - table.insert(@~"one", 1); - table.insert(@~"two", 2); - assert!(check_strs(table.to_str(), ~"xxx")); // not sure what expected should be -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3563-2.rs b/gcc/testsuite/rust.test/issue-3563-2.rs deleted file mode 100644 index e688b95..0000000 --- a/gcc/testsuite/rust.test/issue-3563-2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Canvas { - fn add_point(&self, point: &int); - fn add_points(&self, shapes: &[int]) { - for pt in shapes.iter() { - self.add_point(pt) - } - } - -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3563-3.rs b/gcc/testsuite/rust.test/issue-3563-3.rs deleted file mode 100644 index 55273f7..0000000 --- a/gcc/testsuite/rust.test/issue-3563-3.rs +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ASCII art shape renderer. -// Demonstrates traits, impls, operator overloading, non-copyable struct, unit testing. -// To run execute: rustc --test shapes.rs && ./shapes - -// Rust's std library is tightly bound to the language itself so it is automatically linked in. -// However the extra library is designed to be optional (for code that must run on constrained -// environments like embedded devices or special environments like kernel code) so it must -// be explicitly linked in. -extern mod extra; - -// Extern mod controls linkage. Use controls the visibility of names to modules that are -// already linked in. Using WriterUtil allows us to use the write_line method. -use std::io::WriterUtil; -use std::io; -use std::str; -use std::vec; - -// Represents a position on a canvas. -struct Point { - x: int, - y: int, -} - -// Represents an offset on a canvas. (This has the same structure as a Point. -// but different semantics). -struct Size { - width: int, - height: int, -} - -struct Rect { - top_left: Point, - size: Size, -} - -// TODO: operators - -// Contains the information needed to do shape rendering via ASCII art. -struct AsciiArt { - width: uint, - height: uint, - priv fill: char, - priv lines: ~[~[char]], - - // This struct can be quite large so we'll disable copying: developers need - // to either pass these structs around via borrowed pointers or move them. -} - -impl Drop for AsciiArt { - fn drop(&mut self) {} -} - -// It's common to define a constructor sort of function to create struct instances. -// If there is a canonical constructor it is typically named the same as the type. -// Other constructor sort of functions are typically named from_foo, from_bar, etc. -fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt { - // Use an anonymous function to build a vector of vectors containing - // blank characters for each position in our canvas. - let lines = do vec::build(Some(height)) |push| { - do height.times { - push(vec::from_elem(width, '.')); - } - }; - - // Rust code often returns values by omitting the trailing semi-colon - // instead of using an explicit return statement. - AsciiArt {width: width, height: height, fill: fill, lines: lines} -} - -// Methods particular to the AsciiArt struct. -impl AsciiArt { - fn add_pt(&mut self, x: int, y: int) { - if x >= 0 && x < self.width as int { - if y >= 0 && y < self.height as int { - // Note that numeric types don't implicitly convert to each other. - let v = y as uint; - let h = x as uint; - - // Vector subscripting will normally copy the element, but &v[i] - // will return a reference which is what we need because the - // element is: - // 1) potentially large - // 2) needs to be modified - let row = &mut self.lines[v]; - row[h] = self.fill; - } - } - } -} - -// Allows AsciiArt to be converted to a string using the libcore ToStr trait. -// Note that the %s fmt! specifier will not call this automatically. -impl ToStr for AsciiArt { - fn to_str(&self) -> ~str { - // Convert each line into a string. - let lines = do self.lines.map |line| {str::from_chars(*line)}; - - // Concatenate the lines together using a new-line. - lines.connect("\n") - } -} - -// This is similar to an interface in other languages: it defines a protocol which -// developers can implement for arbitrary concrete types. -trait Canvas { - fn add_point(&mut self, shape: Point); - fn add_rect(&mut self, shape: Rect); - - // Unlike interfaces traits support default implementations. - // Got an ICE as soon as I added this method. - fn add_points(&mut self, shapes: &[Point]) { - for pt in shapes.iter() {self.add_point(*pt)}; - } -} - -// Here we provide an implementation of the Canvas methods for AsciiArt. -// Other implementations could also be provided (e.g. for PDF or Apple's Quartz) -// and code can use them polymorphically via the Canvas trait. -impl Canvas for AsciiArt { - fn add_point(&mut self, shape: Point) { - self.add_pt(shape.x, shape.y); - } - - fn add_rect(&mut self, shape: Rect) { - // Add the top and bottom lines. - for x in range(shape.top_left.x, shape.top_left.x + shape.size.width) { - self.add_pt(x, shape.top_left.y); - self.add_pt(x, shape.top_left.y + shape.size.height - 1); - } - - // Add the left and right lines. - for y in range(shape.top_left.y, shape.top_left.y + shape.size.height) { - self.add_pt(shape.top_left.x, y); - self.add_pt(shape.top_left.x + shape.size.width - 1, y); - } - } -} - -// Rust's unit testing framework is currently a bit under-developed so we'll use -// this little helper. -pub fn check_strs(actual: &str, expected: &str) -> bool { - if actual != expected { - io::stderr().write_line(format!("Found:\n{}\nbut expected\n{}", actual, expected)); - return false; - } - return true; -} - - -fn test_ascii_art_ctor() { - let art = AsciiArt(3, 3, '*'); - assert!(check_strs(art.to_str(), "...\n...\n...")); -} - - -fn test_add_pt() { - let mut art = AsciiArt(3, 3, '*'); - art.add_pt(0, 0); - art.add_pt(0, -10); - art.add_pt(1, 2); - assert!(check_strs(art.to_str(), "*..\n...\n.*.")); -} - - -fn test_shapes() { - let mut art = AsciiArt(4, 4, '*'); - art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}}); - art.add_point(Point {x: 2, y: 2}); - assert!(check_strs(art.to_str(), "****\n*..*\n*.**\n****")); -} - -pub fn main() { - test_ascii_art_ctor(); - test_add_pt(); - test_shapes(); -} diff --git a/gcc/testsuite/rust.test/issue-3574.rs b/gcc/testsuite/rust.test/issue-3574.rs deleted file mode 100644 index eb59b3e..0000000 --- a/gcc/testsuite/rust.test/issue-3574.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unnecessary_allocation)]; - -// rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs -extern mod extra; - -fn compare(x: &str, y: &str) -> bool -{ - match x - { - "foo" => y == "foo", - _ => y == "bar", - } -} - -pub fn main() -{ - assert!(compare("foo", "foo")); - assert!(compare(~"foo", ~"foo")); - assert!(compare(@"foo", @"foo")); -} diff --git a/gcc/testsuite/rust.test/issue-3609.rs b/gcc/testsuite/rust.test/issue-3609.rs deleted file mode 100644 index fdd2647..0000000 --- a/gcc/testsuite/rust.test/issue-3609.rs +++ /dev/null @@ -1,28 +0,0 @@ -extern mod extra; - -use std::comm::Chan; -use std::task; - -type RingBuffer = ~[f64]; -type SamplesFn = ~fn(samples: &RingBuffer); - -enum Msg -{ - GetSamples(~str, SamplesFn), // sample set name, callback which receives samples -} - -fn foo(name: ~str, samples_chan: Chan) { - do task::spawn - { - let callback: SamplesFn = - |buffer| - { - for i in range(0u, buffer.len()) { - error2!("{}: {}", i, buffer[i]) - } - }; - samples_chan.send(GetSamples(name.clone(), callback)); - }; -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3656.rs b/gcc/testsuite/rust.test/issue-3656.rs deleted file mode 100644 index 668f3f8..0000000 --- a/gcc/testsuite/rust.test/issue-3656.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast Can't redeclare malloc with wrong signature because bugs -// Issue #3656 -// Incorrect struct size computation in the FFI, because of not taking -// the alignment of elements into account. - -use std::libc::{c_uint, uint32_t, c_void}; - -struct KEYGEN { - hash_algorithm: [c_uint, ..2], - count: uint32_t, - salt: *c_void, - salt_size: uint32_t, -} - -extern { - // Bogus signature, just need to test if it compiles. - pub fn malloc(data: KEYGEN); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-3683.rs b/gcc/testsuite/rust.test/issue-3683.rs deleted file mode 100644 index aa7fa0c..0000000 --- a/gcc/testsuite/rust.test/issue-3683.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait Foo { - fn a(&self) -> int; - fn b(&self) -> int { - self.a() + 2 - } -} - -impl Foo for int { - fn a(&self) -> int { - 3 - } -} - -pub fn main() { - assert_eq!(3.b(), 5); -} diff --git a/gcc/testsuite/rust.test/issue-3702.rs b/gcc/testsuite/rust.test/issue-3702.rs deleted file mode 100644 index 7d65d6e..0000000 --- a/gcc/testsuite/rust.test/issue-3702.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - trait Text { - fn to_str(&self) -> ~str; - } - - fn to_string(t: @Text) { - println(t.to_str()); - } - -} diff --git a/gcc/testsuite/rust.test/issue-3743.rs b/gcc/testsuite/rust.test/issue-3743.rs deleted file mode 100644 index 13455bd..0000000 --- a/gcc/testsuite/rust.test/issue-3743.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Vec2 { - x: f64, - y: f64 -} - -// methods we want to export as methods as well as operators -impl Vec2 { -#[inline(always)] - fn vmul(self, other: f64) -> Vec2 { - Vec2 { x: self.x * other, y: self.y * other } - } -} - -// Right-hand-side operator visitor pattern -trait RhsOfVec2Mul { fn mul_vec2_by(&self, lhs: &Vec2) -> Result; } - -// Vec2's implementation of Mul "from the other side" using the above trait -impl> Mul for Vec2 { - fn mul(&self, rhs: &Rhs) -> Res { rhs.mul_vec2_by(self) } -} - -// Implementation of 'f64 as right-hand-side of Vec2::Mul' -impl RhsOfVec2Mul for f64 { - fn mul_vec2_by(&self, lhs: &Vec2) -> Vec2 { lhs.vmul(*self) } -} - -// Usage with failing inference -pub fn main() { - let a = Vec2 { x: 3.0, y: 4.0 }; - - // the following compiles and works properly - let v1: Vec2 = a * 3.0; - println!("{} {}", v1.x, v1.y); - - // the following compiles but v2 will not be Vec2 yet and - // using it later will cause an error that the type of v2 - // must be known - let v2 = a * 3.0; - println!("{} {}", v2.x, v2.y); // error regarding v2's type -} diff --git a/gcc/testsuite/rust.test/issue-3753.rs b/gcc/testsuite/rust.test/issue-3753.rs deleted file mode 100644 index 49759f3..0000000 --- a/gcc/testsuite/rust.test/issue-3753.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #3656 -// Issue Name: pub method preceeded by attribute can't be parsed -// Abstract: Visibility parsing failed when compiler parsing - -use std::f64; - -struct Point { - x: f64, - y: f64 -} - -pub enum Shape { - Circle(Point, f64), - Rectangle(Point, Point) -} - -impl Shape { - pub fn area(&self, sh: Shape) -> f64 { - match sh { - Circle(_, size) => f64::consts::pi * size * size, - Rectangle(Point {x, y}, Point {x: x2, y: y2}) => (x2 - x) * (y2 - y) - } - } -} - -pub fn main(){ - let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0); - println!("{}", s.area(s)); -} diff --git a/gcc/testsuite/rust.test/issue-3794.rs b/gcc/testsuite/rust.test/issue-3794.rs deleted file mode 100644 index 61e6bd2..0000000 --- a/gcc/testsuite/rust.test/issue-3794.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait T { - fn print(&self); -} - -struct S { - s: int, -} - -impl T for S { - fn print(&self) { - println!("{:?}", self); - } -} - -fn print_t(t: &T) { - t.print(); -} - -fn print_s(s: &S) { - s.print(); -} - -pub fn main() { - let s: @S = @S { s: 5 }; - print_s(s); - let t: @T = s as @T; - print_t(t); - -} diff --git a/gcc/testsuite/rust.test/issue-3796.rs b/gcc/testsuite/rust.test/issue-3796.rs deleted file mode 100644 index 5f44093..0000000 --- a/gcc/testsuite/rust.test/issue-3796.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test FIXME #3796 -#[deny(dead_assignment)]; -fn main() { - let mut x = 1; - let f: &fn() -> int = || { x + 20 }; - assert_eq!(f(), 21); - x += 1; - assert_eq!(f(), 22); -} diff --git a/gcc/testsuite/rust.test/issue-3847.rs b/gcc/testsuite/rust.test/issue-3847.rs deleted file mode 100644 index b5f41dd..0000000 --- a/gcc/testsuite/rust.test/issue-3847.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod buildings { - pub struct Tower { height: uint } -} - -pub fn main() { - let sears = buildings::Tower { height: 1451 }; - let h: uint = match sears { - buildings::Tower { height: h } => { h } - }; - - println(h.to_str()); -} diff --git a/gcc/testsuite/rust.test/issue-3860.rs b/gcc/testsuite/rust.test/issue-3860.rs deleted file mode 100644 index ee9516e..0000000 --- a/gcc/testsuite/rust.test/issue-3860.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { x: int } - -impl Foo { - pub fn stuff<'a>(&'a mut self) -> &'a mut Foo { - return self; - } -} - -pub fn main() { - let x = @mut Foo { x: 3 }; - // Neither of the next two lines should cause an error - let _ = x.stuff(); - x.stuff(); -} diff --git a/gcc/testsuite/rust.test/issue-3874.rs b/gcc/testsuite/rust.test/issue-3874.rs deleted file mode 100644 index ea1242a..0000000 --- a/gcc/testsuite/rust.test/issue-3874.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum PureCounter { PureCounter(uint) } - -fn each(thing: PureCounter, blk: &fn(v: &uint)) { - let PureCounter(ref x) = thing; - blk(x); -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3878.rs b/gcc/testsuite/rust.test/issue-3878.rs deleted file mode 100644 index 0db4e6e..0000000 --- a/gcc/testsuite/rust.test/issue-3878.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(path_statement)]; - -pub fn main() { - let y = ~1; - y; -} diff --git a/gcc/testsuite/rust.test/issue-3888-2.rs b/gcc/testsuite/rust.test/issue-3888-2.rs deleted file mode 100644 index c9f6733..0000000 --- a/gcc/testsuite/rust.test/issue-3888-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] { - v.slice(1, 5) -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3895.rs b/gcc/testsuite/rust.test/issue-3895.rs deleted file mode 100644 index ef9cab8..0000000 --- a/gcc/testsuite/rust.test/issue-3895.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - enum State { BadChar, BadSyntax } - - match BadChar { - _ if true => BadChar, - BadChar | BadSyntax => fail2!() , - }; -} diff --git a/gcc/testsuite/rust.test/issue-3904.rs b/gcc/testsuite/rust.test/issue-3904.rs deleted file mode 100644 index 6b678ff..0000000 --- a/gcc/testsuite/rust.test/issue-3904.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -type ErrPrinter = &fn(&str, &str); - -fn example_err(prog: &str, arg: &str) { - println!("{}: {}", prog, arg) -} - -fn exit(+print: ErrPrinter, prog: &str, arg: &str) { - print(prog, arg); -} - -struct X { - err: ErrPrinter -} - -impl X { - pub fn boom() { - exit(self.err, "prog", "arg"); - } -} - -pub fn main(){ - let val = &X{ - err: example_err, - }; - val.boom(); -} diff --git a/gcc/testsuite/rust.test/issue-3907-2.rs b/gcc/testsuite/rust.test/issue-3907-2.rs deleted file mode 100644 index 8599caa..0000000 --- a/gcc/testsuite/rust.test/issue-3907-2.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// aux-build:issue_3907_1.rs -extern mod issue_3907_1; - -type Foo = issue_3907_1::Foo; - -struct S { - name: int -} - -impl Foo for S { - fn bar() { } -} - -fn main() { - let s = S { - name: 0 - }; - s.bar(); -} diff --git a/gcc/testsuite/rust.test/issue-3935.rs b/gcc/testsuite/rust.test/issue-3935.rs deleted file mode 100644 index af1538c..0000000 --- a/gcc/testsuite/rust.test/issue-3935.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Bike { - name: ~str, -} - -pub fn main() { - let town_bike = Bike { name: ~"schwinn" }; - let my_bike = Bike { name: ~"surly" }; - - assert!(town_bike != my_bike); -} diff --git a/gcc/testsuite/rust.test/issue-3979-2.rs b/gcc/testsuite/rust.test/issue-3979-2.rs deleted file mode 100644 index 39e9f5d..0000000 --- a/gcc/testsuite/rust.test/issue-3979-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait A { - fn a_method(&self); -} - -trait B: A { - fn b_method(&self); -} - -trait C: B { - fn c_method(&self) { - self.a_method(); - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-3979-generics.rs b/gcc/testsuite/rust.test/issue-3979-generics.rs deleted file mode 100644 index 86cdd61..0000000 --- a/gcc/testsuite/rust.test/issue-3979-generics.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Positioned { - fn SetX(&mut self, S); - fn X(&self) -> S; -} - -trait Movable>: Positioned { - fn translate(&mut self, dx: S) { - let x = self.X() + dx; - self.SetX(x); - } -} - -struct Point { x: int, y: int } - -impl Positioned for Point { - fn SetX(&mut self, x: int) { - self.x = x; - } - fn X(&self) -> int { - self.x - } -} - -impl Movable for Point {} - -pub fn main() { - let mut p = Point{ x: 1, y: 2}; - p.translate(3); - assert_eq!(p.X(), 4); -} diff --git a/gcc/testsuite/rust.test/issue-3979-xcrate.rs b/gcc/testsuite/rust.test/issue-3979-xcrate.rs deleted file mode 100644 index a6294da..0000000 --- a/gcc/testsuite/rust.test/issue-3979-xcrate.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:issue_3979_traits.rs -extern mod issue_3979_traits; -use issue_3979_traits::{Positioned, Movable}; - -struct Point { x: int, y: int } - -impl Positioned for Point { - fn SetX(&mut self, x: int) { - self.x = x; - } - fn X(&self) -> int { - self.x - } -} - -impl Movable for Point {} - -pub fn main() { - let mut p = Point{ x: 1, y: 2}; - p.translate(3); - assert_eq!(p.X(), 4); -} diff --git a/gcc/testsuite/rust.test/issue-3979.rs b/gcc/testsuite/rust.test/issue-3979.rs deleted file mode 100644 index 4f693428..0000000 --- a/gcc/testsuite/rust.test/issue-3979.rs +++ /dev/null @@ -1,41 +0,0 @@ - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Positioned { - fn SetX(&mut self, int); - fn X(&self) -> int; -} - -trait Movable: Positioned { - fn translate(&mut self, dx: int) { - let x = self.X(); - self.SetX(x + dx); - } -} - -struct Point { x: int, y: int } - -impl Positioned for Point { - fn SetX(&mut self, x: int) { - self.x = x; - } - fn X(&self) -> int { - self.x - } -} - -impl Movable for Point {} - -pub fn main() { - let mut p = Point{ x: 1, y: 2}; - p.translate(3); - assert_eq!(p.X(), 4); -} diff --git a/gcc/testsuite/rust.test/issue-3991.rs b/gcc/testsuite/rust.test/issue-3991.rs deleted file mode 100644 index d5dd090..0000000 --- a/gcc/testsuite/rust.test/issue-3991.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct HasNested { - nest: ~[~[int]], -} - -impl HasNested { - fn method_push_local(&mut self) { - self.nest[0].push(0); - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-4016.rs b/gcc/testsuite/rust.test/issue-4016.rs deleted file mode 100644 index 98b6a9c..0000000 --- a/gcc/testsuite/rust.test/issue-4016.rs +++ /dev/null @@ -1,26 +0,0 @@ -// xfail-fast -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use extra::json; -use extra::serialize::Decodable; - -trait JD : Decodable { } - -fn exec() { - let doc = json::from_str("").unwrap(); - let mut decoder = json::Decoder(doc); - let _v: T = Decodable::decode(&mut decoder); - fail2!() -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-4025.rs b/gcc/testsuite/rust.test/issue-4025.rs deleted file mode 100644 index 4a5cf15..0000000 --- a/gcc/testsuite/rust.test/issue-4025.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -# if b { x } else { y } requires identical types for x and y -*/ - -fn print1(b: bool, s1: &str, s2: &str) { - println(if b { s1 } else { s2 }); -} -fn print2<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) { - println(if b { s1 } else { s2 }); -} -fn print3(b: bool, s1: &str, s2: &str) { - let mut s: &str; - if b { s = s1; } else { s = s2; } - println(s); -} -fn print4<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) { - let mut s: &str; - if b { s = s1; } else { s = s2; } - println(s); -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-4036.rs b/gcc/testsuite/rust.test/issue-4036.rs deleted file mode 100644 index ad82071..0000000 --- a/gcc/testsuite/rust.test/issue-4036.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #4036: Test for an issue that arose around fixing up type inference -// byproducts in vtable records. - -extern mod extra; -use self::extra::json; -use self::extra::serialize; - -pub fn main() { - let json = json::from_str("[1]").unwrap(); - let mut decoder = json::Decoder(json); - let _x: ~[int] = serialize::Decodable::decode(&mut decoder); -} diff --git a/gcc/testsuite/rust.test/issue-4092.rs b/gcc/testsuite/rust.test/issue-4092.rs deleted file mode 100644 index 919c1f7..0000000 --- a/gcc/testsuite/rust.test/issue-4092.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -pub fn main() { - let mut x = HashMap::new(); - x.insert((@"abc", 0), 0); -} diff --git a/gcc/testsuite/rust.test/issue-4107.rs b/gcc/testsuite/rust.test/issue-4107.rs deleted file mode 100644 index 2ed662e..0000000 --- a/gcc/testsuite/rust.test/issue-4107.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _id: &Mat2 = &Matrix::identity(); -} - -pub trait Index { } -pub trait Dimensional: Index { } - -pub struct Mat2 { x: () } -pub struct Vec2 { x: () } - -impl Dimensional> for Mat2 { } -impl Index> for Mat2 { } - -impl Dimensional for Vec2 { } -impl Index for Vec2 { } - -pub trait Matrix: Dimensional { - fn identity() -> Self; -} - -impl Matrix> for Mat2 { - fn identity() -> Mat2 { Mat2{ x: () } } -} diff --git a/gcc/testsuite/rust.test/issue-4120.rs b/gcc/testsuite/rust.test/issue-4120.rs deleted file mode 100644 index deb8e0a..0000000 --- a/gcc/testsuite/rust.test/issue-4120.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-test - -// XFAIL'd due to Valgrind complaining about TLS loss. - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() -{ - unsafe { - libc::exit(0); - } - error!("ack"); -} diff --git a/gcc/testsuite/rust.test/issue-4208.rs b/gcc/testsuite/rust.test/issue-4208.rs deleted file mode 100644 index 4328dc7..0000000 --- a/gcc/testsuite/rust.test/issue-4208.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue-4208-cc.rs -// xfail-fast - Windows hates cross-crate tests - -extern mod numeric; -use numeric::{sin, Angle}; - -fn foo>(theta: A) -> T { sin(&theta) } - -fn main() {} diff --git a/gcc/testsuite/rust.test/issue-4228.rs b/gcc/testsuite/rust.test/issue-4228.rs deleted file mode 100644 index 8cae8dd..0000000 --- a/gcc/testsuite/rust.test/issue-4228.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo; - -impl Foo { - fn first() {} -} -impl Foo { - fn second() {} -} - -pub fn main() { - Foo::first(); - Foo::second(); -} diff --git a/gcc/testsuite/rust.test/issue-4241.rs b/gcc/testsuite/rust.test/issue-4241.rs deleted file mode 100644 index b53036d..0000000 --- a/gcc/testsuite/rust.test/issue-4241.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// xfail-test needs networking - -extern mod extra; - -use extra::net::tcp::TcpSocketBuf; - -use std::io; -use std::int; - -use std::io::{ReaderUtil,WriterUtil}; - -enum Result { - Nil, - Int(int), - Data(~[u8]), - List(~[Result]), - Error(~str), - Status(~str) -} - -priv fn parse_data(len: uint, io: @io::Reader) -> Result { - let res = - if (len > 0) { - let bytes = io.read_bytes(len as uint); - assert_eq!(bytes.len(), len); - Data(bytes) - } else { - Data(~[]) - }; - assert_eq!(io.read_char(), '\r'); - assert_eq!(io.read_char(), '\n'); - return res; -} - -priv fn parse_list(len: uint, io: @io::Reader) -> Result { - let mut list: ~[Result] = ~[]; - do len.times { - let v = - match io.read_char() { - '$' => parse_bulk(io), - ':' => parse_int(io), - _ => fail!() - }; - list.push(v); - } - return List(list); -} - -priv fn chop(s: ~str) -> ~str { - s.slice(0, s.len() - 1).to_owned() -} - -priv fn parse_bulk(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { - None => fail!(), - Some(-1) => Nil, - Some(len) if len >= 0 => parse_data(len as uint, io), - Some(_) => fail!() - } -} - -priv fn parse_multi(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { - None => fail!(), - Some(-1) => Nil, - Some(0) => List(~[]), - Some(len) if len >= 0 => parse_list(len as uint, io), - Some(_) => fail!() - } -} - -priv fn parse_int(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { - None => fail!(), - Some(i) => Int(i) - } -} - -priv fn parse_response(io: @io::Reader) -> Result { - match io.read_char() { - '$' => parse_bulk(io), - '*' => parse_multi(io), - '+' => Status(chop(io.read_line())), - '-' => Error(chop(io.read_line())), - ':' => parse_int(io), - _ => fail!() - } -} - -priv fn cmd_to_str(cmd: ~[~str]) -> ~str { - let mut res = ~"*"; - res.push_str(cmd.len().to_str()); - res.push_str("\r\n"); - for s in cmd.iter() { - res.push_str([~"$", s.len().to_str(), ~"\r\n", - (*s).clone(), ~"\r\n"].concat() ); - } - res -} - -fn query(cmd: ~[~str], sb: TcpSocketBuf) -> Result { - let cmd = cmd_to_str(cmd); - //io::println(cmd); - sb.write_str(cmd); - let res = parse_response(@sb as @io::Reader); - res -} - -fn query2(cmd: ~[~str]) -> Result { - let _cmd = cmd_to_str(cmd); - do io::with_str_reader(~"$3\r\nXXX\r\n") |sb| { - let res = parse_response(@sb as @io::Reader); - println!("{:?}", res); - res - } -} - - -fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-4252.rs b/gcc/testsuite/rust.test/issue-4252.rs deleted file mode 100644 index c7ba345..0000000 --- a/gcc/testsuite/rust.test/issue-4252.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test - -trait X { - fn call(&self); -} - -struct Y; - -struct Z { - x: T -} - -impl X for Y { - fn call(&self) { - } -} - -impl Drop for Z { - fn drop(&mut self) { - self.x.call(); // Adding this statement causes an ICE. - } -} - -fn main() { - let y = Y; - let _z = Z{x: y}; -} diff --git a/gcc/testsuite/rust.test/issue-4333.rs b/gcc/testsuite/rust.test/issue-4333.rs deleted file mode 100644 index ebf29be..0000000 --- a/gcc/testsuite/rust.test/issue-4333.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io; - -pub fn main() { - let stdout = &io::stdout() as &io::WriterUtil; - stdout.write_line("Hello!"); -} diff --git a/gcc/testsuite/rust.test/issue-4387.rs b/gcc/testsuite/rust.test/issue-4387.rs deleted file mode 100644 index f297325..0000000 --- a/gcc/testsuite/rust.test/issue-4387.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _foo = [0, ..2*4]; -} diff --git a/gcc/testsuite/rust.test/issue-4401.rs b/gcc/testsuite/rust.test/issue-4401.rs deleted file mode 100644 index ab38d76..0000000 --- a/gcc/testsuite/rust.test/issue-4401.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub fn main() { - let mut count = 0; - do 999_999.times() { - count += 1; - } - assert_eq!(count, 999_999); - println!("{}", count); -} diff --git a/gcc/testsuite/rust.test/issue-4446.rs b/gcc/testsuite/rust.test/issue-4446.rs deleted file mode 100644 index ddcb544..0000000 --- a/gcc/testsuite/rust.test/issue-4446.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let (port, chan) = stream(); - - do spawn { - println(port.recv()); - } - - chan.send("hello, world"); -} diff --git a/gcc/testsuite/rust.test/issue-4448.rs b/gcc/testsuite/rust.test/issue-4448.rs deleted file mode 100644 index 212406f..0000000 --- a/gcc/testsuite/rust.test/issue-4448.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::comm; -use std::task; - -pub fn main() { - let (port, chan) = comm::stream::<&'static str>(); - - do task::spawn { - assert_eq!(port.recv(), "hello, world"); - } - - chan.send("hello, world"); -} diff --git a/gcc/testsuite/rust.test/issue-4464.rs b/gcc/testsuite/rust.test/issue-4464.rs deleted file mode 100644 index 529f8ec..0000000 --- a/gcc/testsuite/rust.test/issue-4464.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn broken<'r>(v: &'r [u8], i: uint, j: uint) -> &'r [u8] { v.slice(i, j) } - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-4541.rs b/gcc/testsuite/rust.test/issue-4541.rs deleted file mode 100644 index 7b80974..0000000 --- a/gcc/testsuite/rust.test/issue-4541.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io; - -fn parse_args() -> ~str { - let args = ::std::os::args(); - let mut n = 0; - - while n < args.len() { - match args[n].clone() { - ~"-v" => (), - s => { - return s; - } - } - n += 1; - } - - return ~"" -} - -pub fn main() { - io::println(parse_args()); -} diff --git a/gcc/testsuite/rust.test/issue-4542.rs b/gcc/testsuite/rust.test/issue-4542.rs deleted file mode 100644 index e6a3d2f..0000000 --- a/gcc/testsuite/rust.test/issue-4542.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::os; - -pub fn main() { - let x = os::args(); - for arg in x.iter() { - match arg.clone() { - _s => { } - } - } -} diff --git a/gcc/testsuite/rust.test/issue-4545.rs b/gcc/testsuite/rust.test/issue-4545.rs deleted file mode 100644 index 834e098..0000000 --- a/gcc/testsuite/rust.test/issue-4545.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like aux-build -// aux-build:issue-4545.rs - -extern mod somelib(name = "issue-4545"); -fn main() { somelib::mk::(); } diff --git a/gcc/testsuite/rust.test/issue-4735.rs b/gcc/testsuite/rust.test/issue-4735.rs deleted file mode 100644 index b28ba68..0000000 --- a/gcc/testsuite/rust.test/issue-4735.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use std::cast::transmute; -use std::libc::c_void; - -struct NonCopyable(*c_void); - -impl Drop for NonCopyable { - fn drop(&mut self) { - let p = **self; - let _v = unsafe { transmute::<*c_void, ~int>(p) }; - } -} - -pub fn main() { - let t = ~0; - let p = unsafe { transmute::<~int, *c_void>(t) }; - let _z = NonCopyable(p); -} diff --git a/gcc/testsuite/rust.test/issue-4759-1.rs b/gcc/testsuite/rust.test/issue-4759-1.rs deleted file mode 100644 index ad8ee98..0000000 --- a/gcc/testsuite/rust.test/issue-4759-1.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait U { fn f(self); } -impl U for int { fn f(self) {} } -pub fn main() { 4.f(); } diff --git a/gcc/testsuite/rust.test/issue-4759.rs b/gcc/testsuite/rust.test/issue-4759.rs deleted file mode 100644 index 4591203..0000000 --- a/gcc/testsuite/rust.test/issue-4759.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct T { a: ~int } - -trait U { - fn f(self); -} - -impl U for ~int { - fn f(self) { } -} - -pub fn main() { - let T { a: a } = T { a: ~0 }; - a.f(); -} - diff --git a/gcc/testsuite/rust.test/issue-4830.rs b/gcc/testsuite/rust.test/issue-4830.rs deleted file mode 100644 index e8147a2..0000000 --- a/gcc/testsuite/rust.test/issue-4830.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub struct Scheduler { - /// The event loop used to drive the scheduler and perform I/O - priv event_loop: ~int -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-4875.rs b/gcc/testsuite/rust.test/issue-4875.rs deleted file mode 100644 index 8194779..0000000 --- a/gcc/testsuite/rust.test/issue-4875.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// regression test for issue 4875 - -pub struct Foo { - data: T, -} - -fn foo(Foo{_}: Foo) { -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/issue-5008-borrowed-traitobject-method-call.rs b/gcc/testsuite/rust.test/issue-5008-borrowed-traitobject-method-call.rs deleted file mode 100644 index ac4b665..0000000 --- a/gcc/testsuite/rust.test/issue-5008-borrowed-traitobject-method-call.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - -#5008 cast to &Trait causes code to segfault on method call - -It fixes itself if the &Trait is changed to @Trait. -*/ - -trait Debuggable { - fn debug_name(&self) -> ~str; -} - -#[deriving(Clone)] -struct Thing { -name: ~str, -} - -impl Thing { - fn new() -> Thing { Thing { name: ~"dummy" } } -} - -impl Debuggable for Thing { - fn debug_name(&self) -> ~str { self.name.clone() } -} - -fn print_name(x: &Debuggable) -{ - println!("debug_name = {}", x.debug_name()); -} - -pub fn main() { - let thing = Thing::new(); - print_name(&thing as &Debuggable); -} diff --git a/gcc/testsuite/rust.test/issue-5060.rs b/gcc/testsuite/rust.test/issue-5060.rs deleted file mode 100644 index e7d0cc0..0000000 --- a/gcc/testsuite/rust.test/issue-5060.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -use std::io; - -macro_rules! print_hd_tl ( - ($field_hd:ident, $($field_tl:ident),+) => ({ - io::print(stringify!($field_hd)); - io::print("::["); - $( - io::print(stringify!($field_tl)); - io::print(", "); - )+ - io::print("]\n"); - }) -) - -pub fn main() { - print_hd_tl!(x, y, z, w) -} - diff --git a/gcc/testsuite/rust.test/issue-5192.rs b/gcc/testsuite/rust.test/issue-5192.rs deleted file mode 100644 index 202a3cb..0000000 --- a/gcc/testsuite/rust.test/issue-5192.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait EventLoop { -} - -pub struct UvEventLoop { - uvio: int -} - -impl UvEventLoop { - pub fn new() -> UvEventLoop { - UvEventLoop { - uvio: 0 - } - } -} - -impl EventLoop for UvEventLoop { -} - -pub struct Scheduler { - event_loop: ~EventLoop, -} - -impl Scheduler { - - pub fn new(event_loop: ~EventLoop) -> Scheduler { - Scheduler { - event_loop: event_loop, - } - } -} - -pub fn main() { - let _sched = Scheduler::new(~UvEventLoop::new() as ~EventLoop); -} diff --git a/gcc/testsuite/rust.test/issue-5239-2.rs b/gcc/testsuite/rust.test/issue-5239-2.rs deleted file mode 100644 index ba70fac..0000000 --- a/gcc/testsuite/rust.test/issue-5239-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #5239 - -pub fn main() { - let _f: &fn(int) -> int = |ref x: int| { *x }; - let foo = 10; - assert!(_f(foo) == 10); -} diff --git a/gcc/testsuite/rust.test/issue-5243.rs b/gcc/testsuite/rust.test/issue-5243.rs deleted file mode 100644 index 1fc5196..0000000 --- a/gcc/testsuite/rust.test/issue-5243.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that merely having lifetime parameters is not -// enough for trans to consider this as non-monomorphic, -// which led to various assertions and failures in turn. - -struct S<'self> { - v: &'self int -} - -fn f<'lt>(_s: &'lt S<'lt>) {} - -pub fn main() { - f(& S { v: &42 }); -} diff --git a/gcc/testsuite/rust.test/issue-5275.rs b/gcc/testsuite/rust.test/issue-5275.rs deleted file mode 100644 index b0560b4..0000000 --- a/gcc/testsuite/rust.test/issue-5275.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #5275 - -fn foo(self_: &A) -> int { - if true { - fail2!() - } else { - *bar(self_.bar) - } -} - -fn bar<'r>(_: &'r mut int) -> &'r int { - fail2!() -} - -struct A { - bar: @mut int, -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-5280.rs b/gcc/testsuite/rust.test/issue-5280.rs deleted file mode 100644 index 16fd45a..0000000 --- a/gcc/testsuite/rust.test/issue-5280.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -type FontTableTag = u32; - -trait FontTableTagConversions { - fn tag_to_str(self); -} - -impl FontTableTagConversions for FontTableTag { - fn tag_to_str(self) { - &self; - } -} - -pub fn main() { - 5.tag_to_str(); -} diff --git a/gcc/testsuite/rust.test/issue-5315.rs b/gcc/testsuite/rust.test/issue-5315.rs deleted file mode 100644 index 1d2e7b7..0000000 --- a/gcc/testsuite/rust.test/issue-5315.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct A(bool); - -pub fn main() { - let f = A; - f(true); -} diff --git a/gcc/testsuite/rust.test/issue-5321-immediates-with-bare-self.rs b/gcc/testsuite/rust.test/issue-5321-immediates-with-bare-self.rs deleted file mode 100644 index 3f1dc2f..0000000 --- a/gcc/testsuite/rust.test/issue-5321-immediates-with-bare-self.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Fooable { - fn yes(self); -} - -impl Fooable for uint { - fn yes(self) { - do self.times { - println("yes"); - } - } -} - -pub fn main() { - 2.yes(); -} diff --git a/gcc/testsuite/rust.test/issue-5353.rs b/gcc/testsuite/rust.test/issue-5353.rs deleted file mode 100644 index cf11b9a..0000000 --- a/gcc/testsuite/rust.test/issue-5353.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static INVALID_ENUM : u32 = 0; -static INVALID_VALUE : u32 = 1; - -fn gl_err_str(err: u32) -> ~str -{ - match err - { - INVALID_ENUM => { ~"Invalid enum" }, - INVALID_VALUE => { ~"Invalid value" }, - _ => { ~"Unknown error" } - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-5517.rs b/gcc/testsuite/rust.test/issue-5517.rs deleted file mode 100644 index d63d8b1..0000000 --- a/gcc/testsuite/rust.test/issue-5517.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let box1 = @mut 42; - let _x = *(&mut *box1) == 42 || *(&mut *box1) == 31337; -} diff --git a/gcc/testsuite/rust.test/issue-5530.rs b/gcc/testsuite/rust.test/issue-5530.rs deleted file mode 100644 index 68287a3..0000000 --- a/gcc/testsuite/rust.test/issue-5530.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum Enum { - Foo { foo: uint }, - Bar { bar: uint } -} - -fn fun1(e1: &Enum, e2: &Enum) -> uint { - match (e1, e2) { - (&Foo { foo: _ }, &Foo { foo: _ }) => 0, - (&Foo { foo: _ }, &Bar { bar: _ }) => 1, - (&Bar { bar: _ }, &Bar { bar: _ }) => 2, - (&Bar { bar: _ }, &Foo { foo: _ }) => 3, - } -} - -fn fun2(e1: &Enum, e2: &Enum) -> uint { - match (e1, e2) { - (&Foo { foo: _ }, &Foo { foo: _ }) => 0, - (&Foo { foo: _ }, _ ) => 1, - (&Bar { bar: _ }, &Bar { bar: _ }) => 2, - (&Bar { bar: _ }, _ ) => 3, - } -} - -pub fn main() { - let foo = Foo { foo: 1 }; - let bar = Bar { bar: 1 }; - - assert_eq!(fun1(&foo, &foo), 0); - assert_eq!(fun1(&foo, &bar), 1); - assert_eq!(fun1(&bar, &bar), 2); - assert_eq!(fun1(&bar, &foo), 3); - - assert_eq!(fun2(&foo, &foo), 0); - assert_eq!(fun2(&foo, &bar), 1); // fun2 returns 0 - assert_eq!(fun2(&bar, &bar), 2); - assert_eq!(fun2(&bar, &foo), 3); // fun2 returns 2 -} diff --git a/gcc/testsuite/rust.test/issue-5550.rs b/gcc/testsuite/rust.test/issue-5550.rs deleted file mode 100644 index d68766d..0000000 --- a/gcc/testsuite/rust.test/issue-5550.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let s: ~str = ~"foobar"; - let mut t: &str = s; - t = t.slice(0, 3); // for master: str::view(t, 0, 3) maybe -} diff --git a/gcc/testsuite/rust.test/issue-5554.rs b/gcc/testsuite/rust.test/issue-5554.rs deleted file mode 100644 index e4ef20a..0000000 --- a/gcc/testsuite/rust.test/issue-5554.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -use std::num::Zero; - -pub struct X { - a: T -} - -// reordering these bounds stops the ICE -impl - Zero for X { - fn zero() -> X { - X { a: Zero::zero() } - } - fn is_zero(&self) -> bool { - self.a.is_zero() - } -} - -macro_rules! constants { - () => { - let _0 : X = Zero::zero(); - } -} - - -pub fn main() { - constants!(); -} diff --git a/gcc/testsuite/rust.test/issue-5572.rs b/gcc/testsuite/rust.test/issue-5572.rs deleted file mode 100644 index d1a1fbf..0000000 --- a/gcc/testsuite/rust.test/issue-5572.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn foo(_t: T) { } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-5666.rs b/gcc/testsuite/rust.test/issue-5666.rs deleted file mode 100644 index eeccac9..0000000 --- a/gcc/testsuite/rust.test/issue-5666.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Dog { - name : ~str -} - -trait Barks { - fn bark(&self) -> ~str; -} - -impl Barks for Dog { - fn bark(&self) -> ~str { - return format!("woof! (I'm {})", self.name); - } -} - - -pub fn main() { - let snoopy = ~Dog{name: ~"snoopy"}; - let bubbles = ~Dog{name: ~"bubbles"}; - let barker = [snoopy as ~Barks, bubbles as ~Barks]; - - for pup in barker.iter() { - println!("{}", pup.bark()); - } -} - diff --git a/gcc/testsuite/rust.test/issue-5688.rs b/gcc/testsuite/rust.test/issue-5688.rs deleted file mode 100644 index 869374d..0000000 --- a/gcc/testsuite/rust.test/issue-5688.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -# Corrupted initialization in the static struct - -...should print &[1, 2, 3] but instead prints something like -&[4492532864, 24]. It is pretty evident that the compiler messed up -with the representation of [int, ..n] and [int] somehow, or at least -failed to typecheck correctly. -*/ - -struct X { vec: &'static [int] } -static V: &'static [X] = &[X { vec: &[1, 2, 3] }]; -pub fn main() { - for &v in V.iter() { - println!("{:?}", v.vec); - } -} diff --git a/gcc/testsuite/rust.test/issue-5708.rs b/gcc/testsuite/rust.test/issue-5708.rs deleted file mode 100644 index 918e43d..0000000 --- a/gcc/testsuite/rust.test/issue-5708.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -# ICE when returning struct with borrowed pointer to trait - -A function which takes a borrowed pointer to a trait and returns a -struct with that borrowed pointer results in an ICE. - -This does not occur with concrete types, only with borrowed pointers -to traits. -*/ - -// original -trait Inner { - fn print(&self); -} - -impl Inner for int { - fn print(&self) { print(format!("Inner: {}\n", *self)); } -} - -struct Outer<'self> { - inner: &'self Inner -} - -impl<'self> Outer<'self> { - fn new<'r>(inner: &'r Inner) -> Outer<'r> { - Outer { - inner: inner - } - } -} - -pub fn main() { - let inner = 5; - let outer = Outer::new(&inner as &Inner); - outer.inner.print(); -} - - -// minimal -trait MyTrait { } - -pub struct MyContainer<'self, T> { - foos: ~[&'self MyTrait], -} - -impl<'self, T> MyContainer<'self, T> { - pub fn add (&mut self, foo: &'self MyTrait) { - self.foos.push(foo); - } -} diff --git a/gcc/testsuite/rust.test/issue-5741.rs b/gcc/testsuite/rust.test/issue-5741.rs deleted file mode 100644 index 46ec686..0000000 --- a/gcc/testsuite/rust.test/issue-5741.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unreachable_code)]; - -use std::io; - -pub fn main() { - return; - while io::stdin().read_line() != ~"quit" { }; -} diff --git a/gcc/testsuite/rust.test/issue-5754.rs b/gcc/testsuite/rust.test/issue-5754.rs deleted file mode 100644 index b2eeedf..0000000 --- a/gcc/testsuite/rust.test/issue-5754.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct TwoDoubles { - r: f64, - i: f64 -} - -extern "C" { - fn rust_dbg_extern_identity_TwoDoubles(arg1: TwoDoubles) -> TwoDoubles; -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-5791.rs b/gcc/testsuite/rust.test/issue-5791.rs deleted file mode 100644 index 251ae2f3..0000000 --- a/gcc/testsuite/rust.test/issue-5791.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -extern { - #[link_name = "malloc"] - fn malloc1(len: libc::c_int) -> *libc::c_void; - #[link_name = "malloc"] - fn malloc2(len: libc::c_int, foo: libc::c_int) -> *libc::c_void; -} - -pub fn main () {} diff --git a/gcc/testsuite/rust.test/issue-5884.rs b/gcc/testsuite/rust.test/issue-5884.rs deleted file mode 100644 index 519211b..0000000 --- a/gcc/testsuite/rust.test/issue-5884.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub struct Foo { - a: int, -} - -struct Bar<'self> { - a: ~Option, - b: &'self Foo, -} - -fn check(a: @Foo) { - let _ic = Bar{ b: a, a: ~None }; -} - -pub fn main(){} diff --git a/gcc/testsuite/rust.test/issue-5917.rs b/gcc/testsuite/rust.test/issue-5917.rs deleted file mode 100644 index 6fb5c25..0000000 --- a/gcc/testsuite/rust.test/issue-5917.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct T (&'static [int]); -static t : T = T (&'static [5, 4, 3]); -pub fn main () { - assert_eq!(t[0], 5); -} diff --git a/gcc/testsuite/rust.test/issue-5926.rs b/gcc/testsuite/rust.test/issue-5926.rs deleted file mode 100644 index dbaa546..0000000 --- a/gcc/testsuite/rust.test/issue-5926.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_mut)]; - -pub fn main() { - let mut your_favorite_numbers = @[1,2,3]; - let mut my_favorite_numbers = @[4,5,6]; - let f = your_favorite_numbers + my_favorite_numbers; - println!("The third favorite number is {:?}.", f) -} - diff --git a/gcc/testsuite/rust.test/issue-6117.rs b/gcc/testsuite/rust.test/issue-6117.rs deleted file mode 100644 index 73e9391..0000000 --- a/gcc/testsuite/rust.test/issue-6117.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - match Left(@17) { - Right(()) => {} - _ => {} - } -} diff --git a/gcc/testsuite/rust.test/issue-6128.rs b/gcc/testsuite/rust.test/issue-6128.rs deleted file mode 100644 index 51c7ed8..0000000 --- a/gcc/testsuite/rust.test/issue-6128.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -trait Graph { - fn f(&self, Edge); - -} - -impl Graph for HashMap { - fn f(&self, _e: E) { - fail2!(); - } -} - -pub fn main() { - let g : ~HashMap = ~HashMap::new(); - let _g2 : ~Graph = g as ~Graph; -} diff --git a/gcc/testsuite/rust.test/issue-6130.rs b/gcc/testsuite/rust.test/issue-6130.rs deleted file mode 100644 index d883974..0000000 --- a/gcc/testsuite/rust.test/issue-6130.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deny(type_limits)]; - -pub fn main() { - let i: uint = 0; - assert!(i <= 0xFFFF_FFFF_u); - - let i: int = 0; - assert!(i >= -0x8000_0000_i); - assert!(i <= 0x7FFF_FFFF_i); -} diff --git a/gcc/testsuite/rust.test/issue-6141-leaking-owned-fn.rs b/gcc/testsuite/rust.test/issue-6141-leaking-owned-fn.rs deleted file mode 100644 index 98d2ca5d..0000000 --- a/gcc/testsuite/rust.test/issue-6141-leaking-owned-fn.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn run(f: &fn()) { - f() -} - -pub fn main() { - let f: ~fn() = || (); - run(f); -} diff --git a/gcc/testsuite/rust.test/issue-6153.rs b/gcc/testsuite/rust.test/issue-6153.rs deleted file mode 100644 index 668d6f3..0000000 --- a/gcc/testsuite/rust.test/issue-6153.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn swap(f: &fn(~[int]) -> ~[int]) -> ~[int] { - let x = ~[1, 2, 3]; - f(x) -} - -pub fn main() { - let v = swap(|mut x| { x.push(4); x }); - let w = do swap |mut x| { x.push(4); x }; - assert_eq!(v, w); -} diff --git a/gcc/testsuite/rust.test/issue-6318.rs b/gcc/testsuite/rust.test/issue-6318.rs deleted file mode 100644 index 00a94c0..0000000 --- a/gcc/testsuite/rust.test/issue-6318.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub enum Thing { - A(~Foo) -} - -pub trait Foo {} - -pub struct Struct; - -impl Foo for Struct {} - -pub fn main() { - match A(~Struct as ~Foo) { - A(_a) => 0, - }; -} - diff --git a/gcc/testsuite/rust.test/issue-6341.rs b/gcc/testsuite/rust.test/issue-6341.rs deleted file mode 100644 index 3859d15..0000000 --- a/gcc/testsuite/rust.test/issue-6341.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct A { x: uint } - -impl Drop for A { - fn drop(&mut self) {} -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-6344-let.rs b/gcc/testsuite/rust.test/issue-6344-let.rs deleted file mode 100644 index 2d70f26..0000000 --- a/gcc/testsuite/rust.test/issue-6344-let.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -struct A { x: uint } - -impl Drop for A { - fn drop(&mut self) {} -} - -pub fn main() { - let a = A { x: 0 }; - - let A { x: ref x } = a; - info2!("{:?}", x) -} diff --git a/gcc/testsuite/rust.test/issue-6344-match.rs b/gcc/testsuite/rust.test/issue-6344-match.rs deleted file mode 100644 index 465e413..0000000 --- a/gcc/testsuite/rust.test/issue-6344-match.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -struct A { x: uint } - -impl Drop for A { - fn drop(&mut self) {} -} - -pub fn main() { - let a = A { x: 0 }; - - match a { - A { x : ref x } => { - info2!("{:?}", x) - } - } -} diff --git a/gcc/testsuite/rust.test/issue-6470.rs b/gcc/testsuite/rust.test/issue-6470.rs deleted file mode 100644 index a161084..0000000 --- a/gcc/testsuite/rust.test/issue-6470.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub mod Bar { - pub struct Foo { - v: int, - } - - extern { - #[rust_stack] - pub fn foo(v: *Foo) -> Foo; - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/issue-6557.rs b/gcc/testsuite/rust.test/issue-6557.rs deleted file mode 100644 index 5722461..0000000 --- a/gcc/testsuite/rust.test/issue-6557.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(~(_x, _y): ~(int, int)) {} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-6898.rs b/gcc/testsuite/rust.test/issue-6898.rs deleted file mode 100644 index 48a0206..0000000 --- a/gcc/testsuite/rust.test/issue-6898.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable::intrinsics; - -/// Returns the size of a type -pub fn size_of() -> uint { - TypeInfo::size_of(None::) -} - -/// Returns the size of the type that `val` points to -pub fn size_of_val(val: &T) -> uint { - val.size_of_val() -} - -pub trait TypeInfo { - fn size_of(_lame_type_hint: Option) -> uint; - fn size_of_val(&self) -> uint; -} - -impl TypeInfo for T { - /// The size of the type in bytes. - fn size_of(_lame_type_hint: Option) -> uint { - unsafe { intrinsics::size_of::() } - } - - /// Returns the size of the type of `self` in bytes. - fn size_of_val(&self) -> uint { - TypeInfo::size_of(None::) - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-6919.rs b/gcc/testsuite/rust.test/issue-6919.rs deleted file mode 100644 index f63811f..0000000 --- a/gcc/testsuite/rust.test/issue-6919.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:iss.rs -// xfail-fast - -extern mod iss ( name = "iss6919_3" ); - -pub fn main() { - iss::D.k; -} - diff --git a/gcc/testsuite/rust.test/issue-7012.rs b/gcc/testsuite/rust.test/issue-7012.rs deleted file mode 100644 index 696197a..0000000 --- a/gcc/testsuite/rust.test/issue-7012.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -# Comparison of static arrays - -The expected behaviour would be that test==test1, therefore 'true' -would be printed, however the below prints false. -*/ - -struct signature<'self> { pattern : &'self [u32] } - -static test1: signature<'static> = signature { - pattern: &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32] -}; - -pub fn main() { - let test = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32]; - println(format!("{}",test==test1.pattern)); -} diff --git a/gcc/testsuite/rust.test/issue-7222.rs b/gcc/testsuite/rust.test/issue-7222.rs deleted file mode 100644 index 5db170f..0000000 --- a/gcc/testsuite/rust.test/issue-7222.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - static FOO: f64 = 10.0; - - match 0.0 { - 0.0 .. FOO => (), - _ => () - } -} - diff --git a/gcc/testsuite/rust.test/issue-7344.rs b/gcc/testsuite/rust.test/issue-7344.rs deleted file mode 100644 index 9b1643b..0000000 --- a/gcc/testsuite/rust.test/issue-7344.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unreachable_code)]; - -fn foo() -> bool { false } - -fn bar() { - return; - !foo(); -} - -fn baz() { - return; - if "" == "" {} -} - -pub fn main() { - bar(); - baz(); -} diff --git a/gcc/testsuite/rust.test/issue-7519-match-unit-in-arg.rs b/gcc/testsuite/rust.test/issue-7519-match-unit-in-arg.rs deleted file mode 100644 index 7512324..0000000 --- a/gcc/testsuite/rust.test/issue-7519-match-unit-in-arg.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -#7519 ICE pattern matching unit in function argument -*/ - -fn foo(():()) { } - -pub fn main() { - foo(()); -} diff --git a/gcc/testsuite/rust.test/issue-7563.rs b/gcc/testsuite/rust.test/issue-7563.rs deleted file mode 100644 index 348a455..0000000 --- a/gcc/testsuite/rust.test/issue-7563.rs +++ /dev/null @@ -1,25 +0,0 @@ -trait IDummy { - fn do_nothing(&self); -} - -struct A { a: int } -struct B<'self> { b: int, pa: &'self A } - - impl IDummy for A { - fn do_nothing(&self) { - println("A::do_nothing() is called"); - } - } - -impl<'self> B<'self> { - fn get_pa(&self) -> &'self IDummy { self.pa as &'self IDummy } -} - -pub fn main() { - let sa = A { a: 100 }; - let sb = B { b: 200, pa: &sa }; - - debug2!("sa is {:?}", sa); - debug2!("sb is {:?}", sb); - debug2!("sb.pa is {:?}", sb.get_pa()); -} diff --git a/gcc/testsuite/rust.test/issue-7673-cast-generically-implemented-trait.rs b/gcc/testsuite/rust.test/issue-7673-cast-generically-implemented-trait.rs deleted file mode 100644 index af8b453..0000000 --- a/gcc/testsuite/rust.test/issue-7673-cast-generically-implemented-trait.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - -#7673 Polymorphically creating traits barely works - -*/ - -pub fn main() {} - -trait A {} -impl A for T {} - -fn owned1(a: T) { ~a as ~A:; } /* note `:` */ -fn owned2(a: ~T) { a as ~A:; } -fn owned3(a: ~T) { ~a as ~A:; } - -fn managed1(a: T) { @a as @A; } -fn managed2(a: @T) { a as @A; } -fn managed3(a: @T) { @a as @A; } diff --git a/gcc/testsuite/rust.test/issue-7712.rs b/gcc/testsuite/rust.test/issue-7712.rs deleted file mode 100644 index fa7d68c..0000000 --- a/gcc/testsuite/rust.test/issue-7712.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-Z debug-info - -pub trait TraitWithDefaultMethod { - fn method(self) { - () - } -} - -struct MyStruct; - -impl TraitWithDefaultMethod for MyStruct { } - -pub fn main() { - MyStruct.method(); -} diff --git a/gcc/testsuite/rust.test/issue-8044.rs b/gcc/testsuite/rust.test/issue-8044.rs deleted file mode 100644 index d8e0085..0000000 --- a/gcc/testsuite/rust.test/issue-8044.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like aux-build -// aux-build:issue-8044.rs - -extern mod minimal(name= "issue-8044"); -use minimal::{BTree, leaf}; - -fn main() { - BTree:: { node: leaf(1) }; -} diff --git a/gcc/testsuite/rust.test/issue-8171-default-method-self-inherit-builtin-trait.rs b/gcc/testsuite/rust.test/issue-8171-default-method-self-inherit-builtin-trait.rs deleted file mode 100644 index aaf2ecb..0000000 --- a/gcc/testsuite/rust.test/issue-8171-default-method-self-inherit-builtin-trait.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - -#8171 Self is not recognised as implementing kinds in default method implementations - -*/ - -fn require_send(_: T){} - -trait TragicallySelfIsNotSend: Send { - fn x(self) { - require_send(self); - } -} - -pub fn main(){} diff --git a/gcc/testsuite/rust.test/issue-8248.rs b/gcc/testsuite/rust.test/issue-8248.rs deleted file mode 100644 index 377b9ce..0000000 --- a/gcc/testsuite/rust.test/issue-8248.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait A {} -struct B; -impl A for B {} - -fn foo(_: &mut A) {} - -pub fn main() { - let mut b = B; - foo(&mut b as &mut A); -} - diff --git a/gcc/testsuite/rust.test/issue-8249.rs b/gcc/testsuite/rust.test/issue-8249.rs deleted file mode 100644 index bfc1d94..0000000 --- a/gcc/testsuite/rust.test/issue-8249.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait A {} -struct B; -impl A for B {} - -struct C<'self> { - foo: &'self mut A, -} - -fn foo(a: &mut A) { - C{ foo: a }; -} - -pub fn main() { -} - diff --git a/gcc/testsuite/rust.test/issue-8351-1.rs b/gcc/testsuite/rust.test/issue-8351-1.rs deleted file mode 100644 index 44e1005..0000000 --- a/gcc/testsuite/rust.test/issue-8351-1.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum E { - Foo{f: int}, - Bar, -} - -pub fn main() { - let e = Foo{f: 0}; - match e { - Foo{f: 1} => fail2!(), - Foo{_} => (), - _ => fail2!(), - } -} diff --git a/gcc/testsuite/rust.test/issue-8351-2.rs b/gcc/testsuite/rust.test/issue-8351-2.rs deleted file mode 100644 index 4c31921..0000000 --- a/gcc/testsuite/rust.test/issue-8351-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum E { - Foo{f: int, b: bool}, - Bar, -} - -pub fn main() { - let e = Foo{f: 0, b: false}; - match e { - Foo{f: 1, b: true} => fail2!(), - Foo{b: false, f: 0} => (), - _ => fail2!(), - } -} diff --git a/gcc/testsuite/rust.test/issue-8398.rs b/gcc/testsuite/rust.test/issue-8398.rs deleted file mode 100644 index 31ac2c4..0000000 --- a/gcc/testsuite/rust.test/issue-8398.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::rt::io; - -fn foo(a: &mut io::Writer) { - a.write([]) -} - -pub fn main(){} - diff --git a/gcc/testsuite/rust.test/issue-8401.rs b/gcc/testsuite/rust.test/issue-8401.rs deleted file mode 100644 index cf78683..0000000 --- a/gcc/testsuite/rust.test/issue-8401.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue_8401.rs -// xfail-fast - -extern mod issue_8401; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-8498.rs b/gcc/testsuite/rust.test/issue-8498.rs deleted file mode 100644 index 40f9835..0000000 --- a/gcc/testsuite/rust.test/issue-8498.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -use std::io; - -fn main() { -// This is ok - match &[(~5,~7)] { - ps => { - let (ref y, _) = ps[0]; - io::println(fmt!("1. y = %d", **y)); - assert!(**y == 5); - } - } - -// This is not entirely ok - match Some(&[(~5,)]) { - Some(ps) => { - let (ref y,) = ps[0]; - io::println(fmt!("2. y = %d", **y)); - if **y != 5 { io::println("sadness"); } - } - None => () - } - -// This is not ok - match Some(&[(~5,~7)]) { - Some(ps) => { - let (ref y, ref z) = ps[0]; - io::println(fmt!("3. y = %d z = %d", **y, **z)); - assert!(**y == 5); - } - None => () - } -} - diff --git a/gcc/testsuite/rust.test/issue-868.rs b/gcc/testsuite/rust.test/issue-868.rs deleted file mode 100644 index 2a82f55..0000000 --- a/gcc/testsuite/rust.test/issue-868.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(g: &fn() -> T) -> T { g() } - -pub fn main() { - let _x = f( | | { 10 }); - // used to be: cannot determine a type for this expression - f(| | { }); - // ditto - f( | | { ()}); - // always worked - let _: () = f(| | { }); - // empty block with no type info should compile too - let _ = f(||{}); - let _ = (||{}); -} diff --git a/gcc/testsuite/rust.test/issue-8898.rs b/gcc/testsuite/rust.test/issue-8898.rs deleted file mode 100644 index 0773102..0000000 --- a/gcc/testsuite/rust.test/issue-8898.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -fn assert_repr_eq(obj : T, expected : ~str) { - - assert_eq!(expected, format!("{:?}", obj)); -} - -pub fn main() { - let abc = [1, 2, 3]; - let tf = [true, false]; - let x = [(), ()]; - let y = ~[(), ()]; - let slice = x.slice(0,1); - let z = @x; - - assert_repr_eq(abc, ~"[1, 2, 3]"); - assert_repr_eq(tf, ~"[true, false]"); - assert_repr_eq(x, ~"[(), ()]"); - assert_repr_eq(y, ~"~[(), ()]"); - assert_repr_eq(slice, ~"&[()]"); - assert_repr_eq(&x, ~"&[(), ()]"); - assert_repr_eq(z, ~"@[(), ()]"); -} diff --git a/gcc/testsuite/rust.test/issue-9047.rs b/gcc/testsuite/rust.test/issue-9047.rs deleted file mode 100644 index 053d6aa..0000000 --- a/gcc/testsuite/rust.test/issue-9047.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn decode() -> ~str { - 'outer: loop { - let mut ch_start: uint; - break 'outer; - } - ~"" -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-9110.rs b/gcc/testsuite/rust.test/issue-9110.rs deleted file mode 100644 index dad9b53..0000000 --- a/gcc/testsuite/rust.test/issue-9110.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -macro_rules! silly_macro( - () => ( - pub mod Qux { - pub struct Foo { x : u8 } - pub fn bar(_foo : Foo) {} - } - ); -) - -silly_macro!() - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-912.rs b/gcc/testsuite/rust.test/issue-912.rs deleted file mode 100644 index d2c51df..0000000 --- a/gcc/testsuite/rust.test/issue-912.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -fn find(_f: &fn(@T) -> bool, _v: [@T]) {} - -pub fn main() { - let x = 10, arr = []; - find({|f| f.id == x}, arr); - arr += [{id: 20}]; // This assigns a type to arr -} diff --git a/gcc/testsuite/rust.test/issue-9123.rs b/gcc/testsuite/rust.test/issue-9123.rs deleted file mode 100644 index 73a14de..0000000 --- a/gcc/testsuite/rust.test/issue-9123.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like aux-build -// aux-build:issue_9123.rs - -extern mod issue_9123; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue-9188.rs b/gcc/testsuite/rust.test/issue-9188.rs deleted file mode 100644 index 7cfa230..0000000 --- a/gcc/testsuite/rust.test/issue-9188.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue_9188.rs -// xfail-fast windows doesn't like aux-build - -extern mod issue_9188; - -fn main() { - let a = issue_9188::bar(); - let b = issue_9188::foo::(); - assert_eq!(*a, *b); -} - diff --git a/gcc/testsuite/rust.test/issue-9394-inherited-trait-calls.rs b/gcc/testsuite/rust.test/issue-9394-inherited-trait-calls.rs deleted file mode 100644 index f2ee920..0000000 --- a/gcc/testsuite/rust.test/issue-9394-inherited-trait-calls.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Base: Base2 + Base3{ - fn foo(&self) -> ~str; - fn foo1(&self) -> ~str; - fn foo2(&self) -> ~str{ - ~"base foo2" - } -} - -trait Base2: Base3{ - fn baz(&self) -> ~str; -} - -trait Base3{ - fn root(&self) -> ~str; -} - -trait Super: Base{ - fn bar(&self) -> ~str; -} - -struct X; - -impl Base for X { - fn foo(&self) -> ~str{ - ~"base foo" - } - fn foo1(&self) -> ~str{ - ~"base foo1" - } - -} - -impl Base2 for X { - fn baz(&self) -> ~str{ - ~"base2 baz" - } -} - -impl Base3 for X { - fn root(&self) -> ~str{ - ~"base3 root" - } -} - -impl Super for X { - fn bar(&self) -> ~str{ - ~"super bar" - } -} - -pub fn main() { - let n = X; - let s = &n as &Super; - assert_eq!(s.bar(),~"super bar"); - assert_eq!(s.foo(),~"base foo"); - assert_eq!(s.foo1(),~"base foo1"); - assert_eq!(s.foo2(),~"base foo2"); - assert_eq!(s.baz(),~"base2 baz"); - assert_eq!(s.root(),~"base3 root"); -} diff --git a/gcc/testsuite/rust.test/issue-9446.rs b/gcc/testsuite/rust.test/issue-9446.rs deleted file mode 100644 index 542d1e6..0000000 --- a/gcc/testsuite/rust.test/issue-9446.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Wrapper(~str); - -impl Wrapper { - pub fn new(wrapped: ~str) -> Wrapper { - Wrapper(wrapped) - } - - pub fn say_hi(&self) { - println!("hello {}", **self); - } -} - -impl Drop for Wrapper { - fn drop(&mut self) {} -} - -pub fn main() { - { - // This runs without complaint. - let x = Wrapper::new(~"Bob"); - x.say_hi(); - } - { - // This fails to compile, circa 0.8-89-gc635fba. - // error: internal compiler error: drop_ty_immediate: non-box ty - Wrapper::new(~"Bob").say_hi(); - } -} diff --git a/gcc/testsuite/rust.test/issue-979.rs b/gcc/testsuite/rust.test/issue-979.rs deleted file mode 100644 index 4c4f19d..0000000 --- a/gcc/testsuite/rust.test/issue-979.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct r { - b: @mut int, -} - -#[unsafe_destructor] -impl Drop for r { - fn drop(&mut self) { - *(self.b) += 1; - } -} - -fn r(b: @mut int) -> r { - r { - b: b - } -} - -pub fn main() { - let b = @mut 0; - { - let _p = Some(r(b)); - } - - assert_eq!(*b, 1); -} diff --git a/gcc/testsuite/rust.test/issue-980.rs b/gcc/testsuite/rust.test/issue-980.rs deleted file mode 100644 index e2e5dfc..0000000 --- a/gcc/testsuite/rust.test/issue-980.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum maybe_pointy { - no_pointy, - yes_pointy(@mut Pointy), -} - -struct Pointy { - x : maybe_pointy -} - -pub fn main() { - let m = @mut Pointy { x : no_pointy }; - m.x = yes_pointy(m); -} diff --git a/gcc/testsuite/rust.test/issue2170exe.rs b/gcc/testsuite/rust.test/issue2170exe.rs deleted file mode 100644 index 64b6593..0000000 --- a/gcc/testsuite/rust.test/issue2170exe.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fail fast doesn't under aux-build -// aux-build:issue2170lib.rs -extern mod issue2170lib; - -pub fn main() { - // let _ = issue2170lib::rsrc(2i32); -} diff --git a/gcc/testsuite/rust.test/issue2378c.rs b/gcc/testsuite/rust.test/issue2378c.rs deleted file mode 100644 index ade1926..0000000 --- a/gcc/testsuite/rust.test/issue2378c.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue2378a.rs -// aux-build:issue2378b.rs -// xfail-fast - check-fast doesn't understand aux-build - -extern mod issue2378a; -extern mod issue2378b; - -use issue2378a::{just}; -use issue2378b::{two_maybes}; - -pub fn main() { - let x = two_maybes{a: just(3), b: just(5)}; - assert_eq!(x[0u], (3, 5)); -} diff --git a/gcc/testsuite/rust.test/issue_3136_b.rs b/gcc/testsuite/rust.test/issue_3136_b.rs deleted file mode 100644 index b1d28a1..0000000 --- a/gcc/testsuite/rust.test/issue_3136_b.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:issue_3136_a.rc - -extern mod issue_3136_a; -pub fn main() {} diff --git a/gcc/testsuite/rust.test/issue_9155.rs b/gcc/testsuite/rust.test/issue_9155.rs deleted file mode 100644 index ba92a0c..0000000 --- a/gcc/testsuite/rust.test/issue_9155.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:issue_9155.rs -// xfail-fast windows doesn't like the aux-build - -extern mod issue_9155; - -struct Baz; - -fn main() { - issue_9155::Foo::new(Baz); -} diff --git a/gcc/testsuite/rust.test/istr.rs b/gcc/testsuite/rust.test/istr.rs deleted file mode 100644 index a02edba..0000000 --- a/gcc/testsuite/rust.test/istr.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test_stack_assign() { - let s: ~str = ~"a"; - info2!("{}", s.clone()); - let t: ~str = ~"a"; - assert!(s == t); - let u: ~str = ~"b"; - assert!((s != u)); -} - -fn test_heap_lit() { ~"a big string"; } - -fn test_heap_assign() { - let s: ~str = ~"a big ol' string"; - let t: ~str = ~"a big ol' string"; - assert!(s == t); - let u: ~str = ~"a bad ol' string"; - assert!((s != u)); -} - -fn test_heap_log() { let s = ~"a big ol' string"; info2!("{}", s); } - -fn test_stack_add() { - assert_eq!(~"a" + "b", ~"ab"); - let s: ~str = ~"a"; - assert_eq!(s + s, ~"aa"); - assert_eq!(~"" + "", ~""); -} - -fn test_stack_heap_add() { assert!((~"a" + "bracadabra" == ~"abracadabra")); } - -fn test_heap_add() { - assert_eq!(~"this should" + " totally work", ~"this should totally work"); -} - -fn test_append() { - let mut s = ~""; - s.push_str("a"); - assert_eq!(s, ~"a"); - - let mut s = ~"a"; - s.push_str("b"); - info2!("{}", s.clone()); - assert_eq!(s, ~"ab"); - - let mut s = ~"c"; - s.push_str("offee"); - assert!(s == ~"coffee"); - - s.push_str("&tea"); - assert!(s == ~"coffee&tea"); -} - -pub fn main() { - test_stack_assign(); - test_heap_lit(); - test_heap_assign(); - test_heap_log(); - test_stack_add(); - test_stack_heap_add(); - test_heap_add(); - test_append(); -} diff --git a/gcc/testsuite/rust.test/item-attributes.rs b/gcc/testsuite/rust.test/item-attributes.rs deleted file mode 100644 index 22f0f1f..0000000 --- a/gcc/testsuite/rust.test/item-attributes.rs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// These are attributes of the implicit crate. Really this just needs to parse -// for completeness since .rs files linked from .rc files support this -// notation to specify their module's attributes -#[attr1 = "val"]; -#[attr2 = "val"]; -#[attr3]; -#[attr4(attr5)]; - -// Special linkage attributes for the crate -#[link(name = "extra", - vers = "0.1", - uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", - url = "http://rust-lang.org/src/extra")]; - -// These are attributes of the following mod -#[attr1 = "val"] -#[attr2 = "val"] -mod test_first_item_in_file_mod {} - -mod test_single_attr_outer { - #[attr = "val"] - pub static x: int = 10; - - #[attr = "val"] - pub fn f() { } - - #[attr = "val"] - pub mod mod1 {} - - pub mod rustrt { - #[attr = "val"] - extern {} - } -} - -mod test_multi_attr_outer { - #[attr1 = "val"] - #[attr2 = "val"] - pub static x: int = 10; - - #[attr1 = "val"] - #[attr2 = "val"] - pub fn f() { } - - #[attr1 = "val"] - #[attr2 = "val"] - pub mod mod1 {} - - pub mod rustrt { - #[attr1 = "val"] - #[attr2 = "val"] - extern {} - } - - #[attr1 = "val"] - #[attr2 = "val"] - struct t {x: int} -} - -mod test_stmt_single_attr_outer { - pub fn f() { - #[attr = "val"] - static x: int = 10; - - #[attr = "val"] - fn f() { } - - #[attr = "val"] - mod mod1 { - } - - mod rustrt { - #[attr = "val"] - extern { - } - } - } -} - -mod test_stmt_multi_attr_outer { - pub fn f() { - - #[attr1 = "val"] - #[attr2 = "val"] - static x: int = 10; - - #[attr1 = "val"] - #[attr2 = "val"] - fn f() { } - - /* FIXME: Issue #493 - #[attr1 = "val"] - #[attr2 = "val"] - mod mod1 { - } - - pub mod rustrt { - #[attr1 = "val"] - #[attr2 = "val"] - extern { - } - } - */ - } -} - -mod test_attr_inner { - pub mod m { - // This is an attribute of mod m - #[attr = "val"]; - } -} - -mod test_attr_inner_then_outer { - pub mod m { - // This is an attribute of mod m - #[attr = "val"]; - // This is an attribute of fn f - #[attr = "val"] - fn f() { } - } -} - -mod test_attr_inner_then_outer_multi { - pub mod m { - // This is an attribute of mod m - #[attr1 = "val"]; - #[attr2 = "val"]; - // This is an attribute of fn f - #[attr1 = "val"] - #[attr2 = "val"] - fn f() { } - } -} - -mod test_distinguish_syntax_ext { - extern mod extra; - - pub fn f() { - format!("test{}", "s"); - #[attr = "val"] - fn g() { } - } -} - -mod test_other_forms { - #[attr] - #[attr(word)] - #[attr(attr(word))] - #[attr(key1 = "val", key2 = "val", attr)] - pub fn f() { } -} - -mod test_foreign_items { - pub mod rustrt { - use std::libc; - - extern { - #[attr]; - - #[attr] - fn rust_get_test_int() -> libc::intptr_t; - } - } -} - -mod test_literals { - #[str = "s"]; - #[char = 'c']; - #[int = 100]; - #[uint = 100u]; - #[mach_int = 100u32]; - #[float = 1.0]; - #[mach_float = 1.0f32]; - #[nil = ()]; - #[bool = true]; - mod m {} -} - -fn test_fn_inner() { - #[inner_fn_attr]; -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/item-name-overload.rs b/gcc/testsuite/rust.test/item-name-overload.rs deleted file mode 100644 index c6b777d..0000000 --- a/gcc/testsuite/rust.test/item-name-overload.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -mod foo { - pub fn baz() { } -} - -mod bar { - pub fn baz() { } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/iter-range.rs b/gcc/testsuite/rust.test/iter-range.rs deleted file mode 100644 index 8216320..0000000 --- a/gcc/testsuite/rust.test/iter-range.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn range_(a: int, b: int, it: &fn(int)) { - assert!((a < b)); - let mut i: int = a; - while i < b { it(i); i += 1; } -} - -pub fn main() { - let mut sum: int = 0; - range_(0, 100, |x| sum += x ); - info2!("{}", sum); -} diff --git a/gcc/testsuite/rust.test/ivec-add.rs b/gcc/testsuite/rust.test/ivec-add.rs deleted file mode 100644 index ecf530f..0000000 --- a/gcc/testsuite/rust.test/ivec-add.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn double(a: T) -> ~[T] { return ~[a.clone()] + ~[a]; } - -fn double_int(a: int) -> ~[int] { return ~[a] + ~[a]; } - -pub fn main() { - let mut d = double(1); - assert_eq!(d[0], 1); - assert_eq!(d[1], 1); - - d = double_int(1); - assert_eq!(d[0], 1); - assert_eq!(d[1], 1); -} diff --git a/gcc/testsuite/rust.test/ivec-pass-by-value.rs b/gcc/testsuite/rust.test/ivec-pass-by-value.rs deleted file mode 100644 index 4a82e68..0000000 --- a/gcc/testsuite/rust.test/ivec-pass-by-value.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(_a: ~[int]) { } -pub fn main() { f(~[1, 2, 3, 4, 5]); } diff --git a/gcc/testsuite/rust.test/ivec-tag.rs b/gcc/testsuite/rust.test/ivec-tag.rs deleted file mode 100644 index 4b76f2f..0000000 --- a/gcc/testsuite/rust.test/ivec-tag.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::task; - -fn producer(c: &Chan<~[u8]>) { - c.send( - ~[1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8, - 13u8]); -} - -pub fn main() { - let (p, ch) = stream::<~[u8]>(); - let _prod = task::spawn(|| producer(&ch) ); - - let _data: ~[u8] = p.recv(); -} diff --git a/gcc/testsuite/rust.test/keyword-changes-2012-07-31.rs b/gcc/testsuite/rust.test/keyword-changes-2012-07-31.rs deleted file mode 100644 index ff568b7..0000000 --- a/gcc/testsuite/rust.test/keyword-changes-2012-07-31.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// return -> return -// mod -> module -// match -> match - -pub fn main() { -} - -mod foo { -} - -fn bar() -> int { - match 0 { - _ => { 0 } - } -} diff --git a/gcc/testsuite/rust.test/kindck-owned-trait-contains-1.rs b/gcc/testsuite/rust.test/kindck-owned-trait-contains-1.rs deleted file mode 100644 index 29a89a6..0000000 --- a/gcc/testsuite/rust.test/kindck-owned-trait-contains-1.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait repeat { fn get(&self) -> A; } - -impl repeat for @A { - fn get(&self) -> A { - (**self).clone() - } -} - -fn repeater(v: @A) -> @repeat: { - // Note: owned kind is not necessary as A appears in the trait type - @v as @repeat: // No -} - -pub fn main() { - let x = 3; - let y = repeater(@x); - assert_eq!(x, y.get()); -} diff --git a/gcc/testsuite/rust.test/labeled-break.rs b/gcc/testsuite/rust.test/labeled-break.rs deleted file mode 100644 index d7d210c..0000000 --- a/gcc/testsuite/rust.test/labeled-break.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - 'foo: loop { - loop { - break 'foo; - } - } - - 'bar: for _ in range(0, 100) { - loop { - break 'bar; - } - } -} diff --git a/gcc/testsuite/rust.test/lambda-infer-unresolved.rs b/gcc/testsuite/rust.test/lambda-infer-unresolved.rs deleted file mode 100644 index 0a6393d..0000000 --- a/gcc/testsuite/rust.test/lambda-infer-unresolved.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This should typecheck even though the type of e is not fully -// resolved when we finish typechecking the &fn. - - -struct Refs { refs: ~[int], n: int } - -pub fn main() { - let e = @mut Refs{refs: ~[], n: 0}; - let _f: &fn() = || error2!("{}", e.n); - e.refs.push(1); -} diff --git a/gcc/testsuite/rust.test/large-records.rs b/gcc/testsuite/rust.test/large-records.rs deleted file mode 100644 index 788d9cf..0000000 --- a/gcc/testsuite/rust.test/large-records.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -struct Large {a: int, - b: int, - c: int, - d: int, - e: int, - f: int, - g: int, - h: int, - i: int, - j: int, - k: int, - l: int} -fn f() { - let _foo: Large = - Large {a: 0, - b: 0, - c: 0, - d: 0, - e: 0, - f: 0, - g: 0, - h: 0, - i: 0, - j: 0, - k: 0, - l: 0}; -} - -pub fn main() { f(); } diff --git a/gcc/testsuite/rust.test/last-use-in-block.rs b/gcc/testsuite/rust.test/last-use-in-block.rs deleted file mode 100644 index 2f7f0f2..0000000 --- a/gcc/testsuite/rust.test/last-use-in-block.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #1818 - -fn lp(s: ~str, f: &fn(~str) -> T) -> T { - while false { - let r = f(s); - return (r); - } - fail2!(); -} - -fn apply(s: ~str, f: &fn(~str) -> T) -> T { - fn g(s: ~str, f: &fn(~str) -> T) -> T {f(s)} - g(s, |v| { let r = f(v); r }) -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/last-use-in-cap-clause.rs b/gcc/testsuite/rust.test/last-use-in-cap-clause.rs deleted file mode 100644 index d014a3c..0000000 --- a/gcc/testsuite/rust.test/last-use-in-cap-clause.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure #1399 stays fixed - -struct A { a: ~int } - -fn foo() -> &'static fn() -> int { - let k = ~22; - let _u = A {a: k.clone()}; - let result: &'static fn() -> int = || 22; - result -} - -pub fn main() { - assert_eq!(foo()(), 22); -} diff --git a/gcc/testsuite/rust.test/last-use-is-capture.rs b/gcc/testsuite/rust.test/last-use-is-capture.rs deleted file mode 100644 index a6beed6..0000000 --- a/gcc/testsuite/rust.test/last-use-is-capture.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure #1399 stays fixed - -struct A { a: ~int } - -pub fn main() { - fn invoke(f: &fn()) { f(); } - let k = ~22; - let _u = A {a: k.clone()}; - invoke(|| error2!("{:?}", k.clone()) ) -} diff --git a/gcc/testsuite/rust.test/lazy-and-or.rs b/gcc/testsuite/rust.test/lazy-and-or.rs deleted file mode 100644 index c821f58..0000000 --- a/gcc/testsuite/rust.test/lazy-and-or.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn incr(x: &mut int) -> bool { *x += 1; assert!((false)); return false; } - -pub fn main() { - let x = 1 == 2 || 3 == 3; - assert!((x)); - let mut y: int = 10; - info2!("{:?}", x || incr(&mut y)); - assert_eq!(y, 10); - if true && x { assert!((true)); } else { assert!((false)); } -} diff --git a/gcc/testsuite/rust.test/lazy-init.rs b/gcc/testsuite/rust.test/lazy-init.rs deleted file mode 100644 index 53edb3d..0000000 --- a/gcc/testsuite/rust.test/lazy-init.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn foo(x: int) { info2!("{}", x); } - -pub fn main() { let mut x: int; if 1 > 2 { x = 12; } else { x = 10; } foo(x); } diff --git a/gcc/testsuite/rust.test/leak-box-as-tydesc.rs b/gcc/testsuite/rust.test/leak-box-as-tydesc.rs deleted file mode 100644 index 0e266c2..0000000 --- a/gcc/testsuite/rust.test/leak-box-as-tydesc.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn leaky(_t: T) { } - -pub fn main() { let x = @10; leaky::<@int>(x); } diff --git a/gcc/testsuite/rust.test/leak-tag-copy.rs b/gcc/testsuite/rust.test/leak-tag-copy.rs deleted file mode 100644 index 93e2fcd..0000000 --- a/gcc/testsuite/rust.test/leak-tag-copy.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -enum t { a, b(@int), } - -pub fn main() { let mut x = b(@10); x = a; } diff --git a/gcc/testsuite/rust.test/leak-unique-as-tydesc.rs b/gcc/testsuite/rust.test/leak-unique-as-tydesc.rs deleted file mode 100644 index ab186d9..0000000 --- a/gcc/testsuite/rust.test/leak-unique-as-tydesc.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn leaky(_t: T) { } - -pub fn main() { let x = ~10; leaky::<~int>(x); } diff --git a/gcc/testsuite/rust.test/let-assignability.rs b/gcc/testsuite/rust.test/let-assignability.rs deleted file mode 100644 index 2a34147..0000000 --- a/gcc/testsuite/rust.test/let-assignability.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() { - let a = ~"hello"; - let b: &str = a; - println(b); -} - -pub fn main() { - f(); -} diff --git a/gcc/testsuite/rust.test/let-destruct-fresh-mem.rs b/gcc/testsuite/rust.test/let-destruct-fresh-mem.rs deleted file mode 100644 index 13c12a7..0000000 --- a/gcc/testsuite/rust.test/let-destruct-fresh-mem.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -struct X { x: int, y: @A } -struct A { a: int } - -pub fn main() { - let u = X {x: 10, y: @A {a: 20}}; - let X {x: x, y: @A {a: a}} = u; - let mut x = x; - let mut a = a; - x = 100; - a = 100; - assert_eq!(x, 100); - assert_eq!(a, 100); - assert_eq!(u.x, 10); - assert_eq!(u.y.a, 20); -} diff --git a/gcc/testsuite/rust.test/let-destruct-ref.rs b/gcc/testsuite/rust.test/let-destruct-ref.rs deleted file mode 100644 index fdb2805..0000000 --- a/gcc/testsuite/rust.test/let-destruct-ref.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn main() { - let x = ~"hello"; - let ref y = x; - assert_eq!(x.slice(0, x.len()), y.slice(0, y.len())); -} diff --git a/gcc/testsuite/rust.test/let-destruct.rs b/gcc/testsuite/rust.test/let-destruct.rs deleted file mode 100644 index aab19b3..0000000 --- a/gcc/testsuite/rust.test/let-destruct.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct xx(int); - -struct X { x: xx, y: int } - -pub fn main() { - let @X {x: xx(x), y: y} = @X{x: xx(10), y: 20}; - assert_eq!(x + y, 30); -} diff --git a/gcc/testsuite/rust.test/let-var-hygiene.rs b/gcc/testsuite/rust.test/let-var-hygiene.rs deleted file mode 100644 index ce49492..0000000 --- a/gcc/testsuite/rust.test/let-var-hygiene.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -// shouldn't affect evaluation of $ex: -macro_rules! bad_macro (($ex:expr) => ({let _x = 9; $ex})) -pub fn main() { - let _x = 8; - assert_eq!(bad_macro!(_x),8) -} diff --git a/gcc/testsuite/rust.test/linear-for-loop.rs b/gcc/testsuite/rust.test/linear-for-loop.rs deleted file mode 100644 index db27a47..0000000 --- a/gcc/testsuite/rust.test/linear-for-loop.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = ~[1, 2, 3]; - let mut y = 0; - for i in x.iter() { info2!("{:?}", *i); y += *i; } - info2!("{:?}", y); - assert_eq!(y, 6); - let s = ~"hello there"; - let mut i: int = 0; - for c in s.byte_iter() { - if i == 0 { assert!((c == 'h' as u8)); } - if i == 1 { assert!((c == 'e' as u8)); } - if i == 2 { assert!((c == 'l' as u8)); } - if i == 3 { assert!((c == 'l' as u8)); } - if i == 4 { assert!((c == 'o' as u8)); } - // ... - - i += 1; - info2!("{:?}", i); - info2!("{:?}", c); - } - assert_eq!(i, 11); -} diff --git a/gcc/testsuite/rust.test/link-section.rs b/gcc/testsuite/rust.test/link-section.rs deleted file mode 100644 index 0a1d28b..0000000 --- a/gcc/testsuite/rust.test/link-section.rs +++ /dev/null @@ -1,34 +0,0 @@ -#[cfg(not(target_os = "macos"))] -#[link_section=".moretext"] -fn i_live_in_more_text() -> &'static str { - "knock knock" -} - -#[cfg(not(target_os = "macos"))] -#[link_section=".imm"] -static magic: uint = 42; - -#[cfg(not(target_os = "macos"))] -#[link_section=".mut"] -static mut frobulator: uint = 0xdeadbeef; - -#[cfg(target_os = "macos")] -#[link_section="__TEXT,__moretext"] -fn i_live_in_more_text() -> &'static str { - "knock knock" -} - -#[cfg(target_os = "macos")] -#[link_section="__RODATA,__imm"] -static magic: uint = 42; - -#[cfg(target_os = "macos")] -#[link_section="__DATA,__mut"] -static mut frobulator: uint = 0xdeadbeef; - -pub fn main() { - unsafe { - frobulator = 0xcafebabe; - println!("{} {} {}", i_live_in_more_text(), magic, frobulator); - } -} diff --git a/gcc/testsuite/rust.test/lint-cstack.rs b/gcc/testsuite/rust.test/lint-cstack.rs deleted file mode 100644 index 8090147..0000000 --- a/gcc/testsuite/rust.test/lint-cstack.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -extern { - fn rust_get_test_int() -> libc::intptr_t; -} - -trait A { - #[fixed_stack_segment] - fn foo() { - unsafe { - rust_get_test_int(); - } - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/lint-non-camel-case-types-non-uppercase-statics-unicode.rs b/gcc/testsuite/rust.test/lint-non-camel-case-types-non-uppercase-statics-unicode.rs deleted file mode 100644 index e3a0c84..0000000 --- a/gcc/testsuite/rust.test/lint-non-camel-case-types-non-uppercase-statics-unicode.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[forbid(non_camel_case_types)]; -#[forbid(non_uppercase_statics)]; - -// Some scripts (e.g. hiragana) don't have a concept of -// upper/lowercase - -struct ヒ; - -static ラ: uint = 0; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/lint-non-camel-case-with-trailing-underscores.rs b/gcc/testsuite/rust.test/lint-non-camel-case-with-trailing-underscores.rs deleted file mode 100644 index f51312b..0000000 --- a/gcc/testsuite/rust.test/lint-non-camel-case-with-trailing-underscores.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This is ok because we often use the trailing underscore to mean 'prime' - -#[forbid(non_camel_case_types)] -type Foo_ = int; - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/lint-non-uppercase-statics-lowercase-mut-statics.rs b/gcc/testsuite/rust.test/lint-non-uppercase-statics-lowercase-mut-statics.rs deleted file mode 100644 index cf66402..0000000 --- a/gcc/testsuite/rust.test/lint-non-uppercase-statics-lowercase-mut-statics.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -#[forbid(non_camel_case_types)]; -#[forbid(non_uppercase_statics)]; - -static mut bar: int = 2; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/list.rs b/gcc/testsuite/rust.test/list.rs deleted file mode 100644 index b8a9d2e..0000000 --- a/gcc/testsuite/rust.test/list.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -enum list { cons(int, @list), nil, } - -pub fn main() { cons(10, @cons(11, @cons(12, @nil))); } diff --git a/gcc/testsuite/rust.test/liveness-assign-imm-local-after-loop.rs b/gcc/testsuite/rust.test/liveness-assign-imm-local-after-loop.rs deleted file mode 100644 index a2f0c81..0000000 --- a/gcc/testsuite/rust.test/liveness-assign-imm-local-after-loop.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unreachable_code)]; -#[allow(unused_variable)]; - -fn test(_cond: bool) { - let v: int; - v = 1; - loop { } // loop never terminates, so no error is reported - v = 2; -} - -pub fn main() { - // note: don't call test()... :) -} diff --git a/gcc/testsuite/rust.test/liveness-assign-imm-local-after-ret.rs b/gcc/testsuite/rust.test/liveness-assign-imm-local-after-ret.rs deleted file mode 100644 index fe70573..0000000 --- a/gcc/testsuite/rust.test/liveness-assign-imm-local-after-ret.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unreachable_code)]; - -fn test() { - let _v: int; - _v = 1; - return; - _v = 2; //~ WARNING: unreachable statement -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/liveness-loop-break.rs b/gcc/testsuite/rust.test/liveness-loop-break.rs deleted file mode 100644 index 103a344..0000000 --- a/gcc/testsuite/rust.test/liveness-loop-break.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test() { - let v; - loop { - v = 3; - break; - } - info2!("{}", v); -} - -pub fn main() { - test(); -} diff --git a/gcc/testsuite/rust.test/liveness-move-in-loop.rs b/gcc/testsuite/rust.test/liveness-move-in-loop.rs deleted file mode 100644 index d910ac9..0000000 --- a/gcc/testsuite/rust.test/liveness-move-in-loop.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn take(x: int) -> int {x} - -fn the_loop() { - let mut list = ~[]; - loop { - let x = 5; - if x > 3 { - list.push(take(x)); - } else { - break; - } - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/log-err-phi.rs b/gcc/testsuite/rust.test/log-err-phi.rs deleted file mode 100644 index 399ef25..0000000 --- a/gcc/testsuite/rust.test/log-err-phi.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { if false { error2!("{}", ~"foo" + "bar"); } } diff --git a/gcc/testsuite/rust.test/log-knows-the-names-of-variants-in-std.rs b/gcc/testsuite/rust.test/log-knows-the-names-of-variants-in-std.rs deleted file mode 100644 index 77bac4d..0000000 --- a/gcc/testsuite/rust.test/log-knows-the-names-of-variants-in-std.rs +++ /dev/null @@ -1,32 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; -use extra::list; - -#[deriving(Clone)] -enum foo { - a(uint), - b(~str), -} - -fn check_log(exp: ~str, v: T) { - assert_eq!(exp, format!("{:?}", v)); -} - -pub fn main() { - let x = list::from_vec([a(22u), b(~"hi")]); - let exp = ~"@Cons(a(22u), @Cons(b(~\"hi\"), @Nil))"; - let act = format!("{:?}", x); - assert!(act == exp); - check_log(exp, x); -} diff --git a/gcc/testsuite/rust.test/log-knows-the-names-of-variants.rs b/gcc/testsuite/rust.test/log-knows-the-names-of-variants.rs deleted file mode 100644 index 2e0b857..0000000 --- a/gcc/testsuite/rust.test/log-knows-the-names-of-variants.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum foo { - a(uint), - b(~str), - c, -} - -enum bar { - d, e, f -} - -pub fn main() { - assert_eq!(~"a(22u)", format!("{:?}", a(22u))); - assert_eq!(~"b(~\"hi\")", format!("{:?}", b(~"hi"))); - assert_eq!(~"c", format!("{:?}", c)); - assert_eq!(~"d", format!("{:?}", d)); -} diff --git a/gcc/testsuite/rust.test/log-linearized.rs b/gcc/testsuite/rust.test/log-linearized.rs deleted file mode 100644 index 393b5c3..0000000 --- a/gcc/testsuite/rust.test/log-linearized.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that shapes respect linearize_ty_params(). - -enum option { - none, - some(T), -} - -struct Smallintmap {v: ~[option]} - -struct V { v: ~[option] } - -fn mk() -> @mut Smallintmap { - let v: ~[option] = ~[]; - return @mut Smallintmap {v: v}; -} - -fn f() { - let sim = mk::(); - error2!("{:?}", sim); -} - -pub fn main() { - f::(); -} diff --git a/gcc/testsuite/rust.test/log-poly.rs b/gcc/testsuite/rust.test/log-poly.rs deleted file mode 100644 index 5cd4561..0000000 --- a/gcc/testsuite/rust.test/log-poly.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Numbers { - Three -} - -pub fn main() { - info2!("{}", 1); - info2!("{}", 2.0); - warn2!("{:?}", Three); - error2!("{:?}", ~[4]); -} diff --git a/gcc/testsuite/rust.test/log-str.rs b/gcc/testsuite/rust.test/log-str.rs deleted file mode 100644 index a8914de..0000000 --- a/gcc/testsuite/rust.test/log-str.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::sys; - -pub fn main() { - let act = sys::log_str(&~[1, 2, 3]); - assert_eq!(~"~[1, 2, 3]", act); - - let act = format!("{:?}/{:6?}", ~[1, 2, 3], ~"hi"); - assert_eq!(act, ~"~[1, 2, 3]/~\"hi\" "); -} diff --git a/gcc/testsuite/rust.test/logging-right-crate.rs b/gcc/testsuite/rust.test/logging-right-crate.rs deleted file mode 100644 index 21b45ce..0000000 --- a/gcc/testsuite/rust.test/logging-right-crate.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:logging_right_crate.rs -// xfail-fast -// exec-env:RUST_LOG=logging-right-crate=debug - -// This is a test for issue #3046 to make sure that when we monomorphize a -// function from one crate to another the right top-level logging name is -// preserved. -// -// It used to be the case that if logging were turned on for this crate, all -// monomorphized functions from other crates had logging turned on (their -// logging module names were all incorrect). This test ensures that this no -// longer happens by enabling logging for *this* crate and then invoking a -// function in an external crate which will fail when logging is enabled. - -extern mod logging_right_crate; - -fn main() { - // this function fails if logging is turned on - logging_right_crate::foo::(); -} diff --git a/gcc/testsuite/rust.test/logging_before_rt_started.rs b/gcc/testsuite/rust.test/logging_before_rt_started.rs deleted file mode 100644 index cdf3882..0000000 --- a/gcc/testsuite/rust.test/logging_before_rt_started.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_LOG=std::ptr -// xfail-fast this would cause everything to print forever on windows... - -// In issue #9487, it was realized that std::ptr was invoking the logging -// infrastructure, and when std::ptr was used during runtime initialization, -// this caused some serious problems. The problems have since been fixed, but -// this test will trigger "output during runtime initialization" to make sure -// that the bug isn't re-introduced. - -fn main() {} diff --git a/gcc/testsuite/rust.test/long-while.rs b/gcc/testsuite/rust.test/long-while.rs deleted file mode 100644 index 2b1fb3b..0000000 --- a/gcc/testsuite/rust.test/long-while.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_variable)]; - -pub fn main() { - let mut i: int = 0; - while i < 1000000 { - i += 1; - let x = 3; - } -} diff --git a/gcc/testsuite/rust.test/loop-break-cont-1.rs b/gcc/testsuite/rust.test/loop-break-cont-1.rs deleted file mode 100644 index 3b7e03a..0000000 --- a/gcc/testsuite/rust.test/loop-break-cont-1.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _i = 0u; - loop { - break; - } - assert!(true); -} diff --git a/gcc/testsuite/rust.test/loop-break-cont.rs b/gcc/testsuite/rust.test/loop-break-cont.rs deleted file mode 100644 index 812089f..0000000 --- a/gcc/testsuite/rust.test/loop-break-cont.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i = 0u; - loop { - error2!("a"); - i += 1u; - if i == 10u { - break; - } - } - assert_eq!(i, 10u); - let mut is_even = false; - loop { - if i == 21u { - break; - } - error2!("b"); - is_even = false; - i += 1u; - if i % 2u != 0u { - continue; - } - is_even = true; - } - assert!(!is_even); - loop { - error2!("c"); - if i == 22u { - break; - } - is_even = false; - i += 1u; - if i % 2u != 0u { - continue; - } - is_even = true; - } - assert!(is_even); -} diff --git a/gcc/testsuite/rust.test/loop-diverges.rs b/gcc/testsuite/rust.test/loop-diverges.rs deleted file mode 100644 index 9c46ba2..0000000 --- a/gcc/testsuite/rust.test/loop-diverges.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* Make sure a loop{} can be the tailexpr in the body -of a diverging function */ - -fn forever() -> ! { - loop{} -} - -pub fn main() { - if (1 == 2) { forever(); } -} diff --git a/gcc/testsuite/rust.test/loop-scope.rs b/gcc/testsuite/rust.test/loop-scope.rs deleted file mode 100644 index 436bdf2..0000000 --- a/gcc/testsuite/rust.test/loop-scope.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = ~[10, 20, 30]; - let mut sum = 0; - for x in x.iter() { sum += *x; } - assert_eq!(sum, 60); -} diff --git a/gcc/testsuite/rust.test/lots-a-fail.rs b/gcc/testsuite/rust.test/lots-a-fail.rs deleted file mode 100644 index b91dadc..0000000 --- a/gcc/testsuite/rust.test/lots-a-fail.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test linked failure -extern mod extra; - -use std::task; - -fn die() { - fail!(); -} - -fn iloop() { - task::spawn(|| die() ); -} - -pub fn main() { - for _ in range(0u, 100u) { - task::spawn_unlinked(|| iloop() ); - } -} diff --git a/gcc/testsuite/rust.test/macro-2.rs b/gcc/testsuite/rust.test/macro-2.rs deleted file mode 100644 index faf8301..0000000 --- a/gcc/testsuite/rust.test/macro-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty - token trees can't pretty print - -#[feature(macro_rules)]; - -pub fn main() { - - macro_rules! mylambda_tt( - ($x:ident, $body:expr) => ({ - fn f($x: int) -> int { return $body; }; - f - }) - ) - - assert!(mylambda_tt!(y, y * 2)(8) == 16) -} diff --git a/gcc/testsuite/rust.test/macro-attributes.rs b/gcc/testsuite/rust.test/macro-attributes.rs deleted file mode 100644 index 7cbc8ef..0000000 --- a/gcc/testsuite/rust.test/macro-attributes.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty - token trees can't pretty print - -#[feature(macro_rules)]; - -macro_rules! compiles_fine { - ($at:attr) => { - // test that the different types of attributes work - #[attribute] - /// Documentation! - $at - - // check that the attributes are recognised by requiring this - // to be removed to avoid a compile error - #[cfg(always_remove)] - static MISTYPED: () = "foo"; - } -} - -// item -compiles_fine!(#[foo]) - -pub fn main() { - // statement - compiles_fine!(#[bar]); -} diff --git a/gcc/testsuite/rust.test/macro-interpolation.rs b/gcc/testsuite/rust.test/macro-interpolation.rs deleted file mode 100644 index 0741d74..0000000 --- a/gcc/testsuite/rust.test/macro-interpolation.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -macro_rules! overly_complicated ( - ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => - ({ - fn $fnname($arg: $ty) -> Option<$ty> $body - match $fnname($val) { - Some($pat) => { - $res - } - _ => { fail2!(); } - } - }) - -) -pub fn main() { - assert!(overly_complicated!(f, x, Option, { return Some(x); }, - Some(8u), Some(y), y) == 8u) - -} diff --git a/gcc/testsuite/rust.test/macro-local-data-key.rs b/gcc/testsuite/rust.test/macro-local-data-key.rs deleted file mode 100644 index e03256b..0000000 --- a/gcc/testsuite/rust.test/macro-local-data-key.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::local_data; - -local_data_key!(foo: int) - -mod bar { - local_data_key!(pub baz: f64) -} - -pub fn main() { - local_data::get(foo, |x| assert!(x.is_none())); - local_data::get(bar::baz, |y| assert!(y.is_none())); - - local_data::set(foo, 3); - local_data::set(bar::baz, -10.0); - - local_data::get(foo, |x| assert_eq!(*x.unwrap(), 3)); - local_data::get(bar::baz, |y| assert_eq!(*y.unwrap(), -10.0)); -} diff --git a/gcc/testsuite/rust.test/macro-path.rs b/gcc/testsuite/rust.test/macro-path.rs deleted file mode 100644 index 9740982..0000000 --- a/gcc/testsuite/rust.test/macro-path.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -mod m { - pub type t = int; -} - -macro_rules! foo { - ($p:path) => ({ - fn f() -> $p { 10 }; - f() - }) -} - -pub fn main() { - assert_eq!(foo!(m::t), 10); -} diff --git a/gcc/testsuite/rust.test/macro-stmt.rs b/gcc/testsuite/rust.test/macro-stmt.rs deleted file mode 100644 index 28e0f6f..0000000 --- a/gcc/testsuite/rust.test/macro-stmt.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty - token trees can't pretty print - -#[feature(macro_rules)]; - -macro_rules! myfn( - ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( - fn $f( $( $x : int),* ) -> int $body - ) -) - -myfn!(add, (a,b), { return a+b; } ) - -pub fn main() { - - macro_rules! mylet( - ($x:ident, $val:expr) => ( - let $x = $val; - ) - ); - - mylet!(y, 8*2); - assert_eq!(y, 16); - - myfn!(mult, (a,b), { a*b } ); - - assert_eq!(mult(2, add(4,4)), 16); - - macro_rules! actually_an_expr_macro ( - () => ( 16 ) - ) - - assert_eq!({ actually_an_expr_macro!() }, 16); - -} diff --git a/gcc/testsuite/rust.test/macro-with-attrs1.rs b/gcc/testsuite/rust.test/macro-with-attrs1.rs deleted file mode 100644 index 1e49e4a..0000000 --- a/gcc/testsuite/rust.test/macro-with-attrs1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like compile-flags -// compile-flags: --cfg foo - -#[feature(macro_rules)]; - -#[cfg(foo)] -macro_rules! foo( () => (1) ) - -#[cfg(not(foo))] -macro_rules! foo( () => (2) ) - -fn main() { - assert_eq!(foo!(), 1); -} diff --git a/gcc/testsuite/rust.test/macro-with-attrs2.rs b/gcc/testsuite/rust.test/macro-with-attrs2.rs deleted file mode 100644 index 742769f..0000000 --- a/gcc/testsuite/rust.test/macro-with-attrs2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -#[cfg(foo)] -macro_rules! foo( () => (1) ) - -#[cfg(not(foo))] -macro_rules! foo( () => (2) ) - -pub fn main() { - assert_eq!(foo!(), 2); -} - diff --git a/gcc/testsuite/rust.test/match-borrowed_str.rs b/gcc/testsuite/rust.test/match-borrowed_str.rs deleted file mode 100644 index acff2de..0000000 --- a/gcc/testsuite/rust.test/match-borrowed_str.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unnecessary_allocation)]; - -fn f1(ref_string: &str) -> ~str { - match ref_string { - "a" => ~"found a", - "b" => ~"found b", - _ => ~"not found" - } -} - -fn f2(ref_string: &str) -> ~str { - match ref_string { - "a" => ~"found a", - "b" => ~"found b", - s => format!("not found ({})", s) - } -} - -fn g1(ref_1: &str, ref_2: &str) -> ~str { - match (ref_1, ref_2) { - ("a", "b") => ~"found a,b", - ("b", "c") => ~"found b,c", - _ => ~"not found" - } -} - -fn g2(ref_1: &str, ref_2: &str) -> ~str { - match (ref_1, ref_2) { - ("a", "b") => ~"found a,b", - ("b", "c") => ~"found b,c", - (s1, s2) => format!("not found ({}, {})", s1, s2) - } -} - -pub fn main() { - assert_eq!(f1(@"a"), ~"found a"); - assert_eq!(f1(~"b"), ~"found b"); - assert_eq!(f1(&"c"), ~"not found"); - assert_eq!(f1("d"), ~"not found"); - assert_eq!(f2(@"a"), ~"found a"); - assert_eq!(f2(~"b"), ~"found b"); - assert_eq!(f2(&"c"), ~"not found (c)"); - assert_eq!(f2("d"), ~"not found (d)"); - assert_eq!(g1(@"a", @"b"), ~"found a,b"); - assert_eq!(g1(~"b", ~"c"), ~"found b,c"); - assert_eq!(g1(&"c", &"d"), ~"not found"); - assert_eq!(g1("d", "e"), ~"not found"); - assert_eq!(g2(@"a", @"b"), ~"found a,b"); - assert_eq!(g2(~"b", ~"c"), ~"found b,c"); - assert_eq!(g2(&"c", &"d"), ~"not found (c, d)"); - assert_eq!(g2("d", "e"), ~"not found (d, e)"); -} diff --git a/gcc/testsuite/rust.test/match-bot-2.rs b/gcc/testsuite/rust.test/match-bot-2.rs deleted file mode 100644 index 3abc443..0000000 --- a/gcc/testsuite/rust.test/match-bot-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// n.b. This was only ever failing with optimization disabled. -fn a() -> int { match return 1 { 2 => 3, _ => fail2!() } } -pub fn main() { a(); } diff --git a/gcc/testsuite/rust.test/match-bot.rs b/gcc/testsuite/rust.test/match-bot.rs deleted file mode 100644 index fd26dbf..0000000 --- a/gcc/testsuite/rust.test/match-bot.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -pub fn main() { - let i: int = - match Some::(3) { None:: => { fail2!() } Some::(_) => { 5 } }; - info2!("{}", i); -} diff --git a/gcc/testsuite/rust.test/match-drop-strs-issue-4541.rs b/gcc/testsuite/rust.test/match-drop-strs-issue-4541.rs deleted file mode 100644 index e90d6b2..0000000 --- a/gcc/testsuite/rust.test/match-drop-strs-issue-4541.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Tests a tricky scenario involving string matching, -// copying, and moving to ensure that we don't segfault -// or double-free, as we were wont to do in the past. - -use std::io; -use std::os; - -fn parse_args() -> ~str { - let args = os::args(); - let mut n = 0; - - while n < args.len() { - match args[n].clone() { - ~"-v" => (), - s => { - return s; - } - } - n += 1; - } - - return ~"" -} - -pub fn main() { - io::println(parse_args()); -} diff --git a/gcc/testsuite/rust.test/match-enum-struct-0.rs b/gcc/testsuite/rust.test/match-enum-struct-0.rs deleted file mode 100644 index f5e4cf6..0000000 --- a/gcc/testsuite/rust.test/match-enum-struct-0.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// regression test for issue #5625 - -#[feature(struct_variant)]; - -enum E { - Foo{f : int}, - Bar -} - -pub fn main() { - let e = Bar; - match e { - Foo{f: _f} => fail2!(), - _ => (), - } -} diff --git a/gcc/testsuite/rust.test/match-enum-struct-1.rs b/gcc/testsuite/rust.test/match-enum-struct-1.rs deleted file mode 100644 index 0f853cf..0000000 --- a/gcc/testsuite/rust.test/match-enum-struct-1.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum E { - Foo{f : int}, - Bar -} - -pub fn main() { - let e = Foo{f: 1}; - match e { - Foo{_} => (), - _ => fail2!(), - } - match e { - Foo{f: _f} => (), - _ => fail2!(), - } -} diff --git a/gcc/testsuite/rust.test/match-implicit-copy-unique.rs b/gcc/testsuite/rust.test/match-implicit-copy-unique.rs deleted file mode 100644 index 2307489..0000000 --- a/gcc/testsuite/rust.test/match-implicit-copy-unique.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair { a: ~int, b: ~int } - -pub fn main() { - let mut x = ~Pair {a: ~10, b: ~20}; - match x { - ~Pair {a: ref mut a, b: ref mut _b} => { - assert!(**a == 10); *a = ~30; assert!(**a == 30); - } - } -} diff --git a/gcc/testsuite/rust.test/match-in-macro.rs b/gcc/testsuite/rust.test/match-in-macro.rs deleted file mode 100644 index b364c8d..0000000 --- a/gcc/testsuite/rust.test/match-in-macro.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules, struct_variant)]; - -enum Foo { - B { b1: int, bb1: int}, -} - -macro_rules! match_inside_expansion( - () => ( - match B { b1:29 , bb1: 100} { - B { b1:b2 , bb1:bb2 } => b2+bb2 - } - ) -) - -pub fn main() { - assert_eq!(match_inside_expansion!(),129); -} diff --git a/gcc/testsuite/rust.test/match-join.rs b/gcc/testsuite/rust.test/match-join.rs deleted file mode 100644 index e733197..0000000 --- a/gcc/testsuite/rust.test/match-join.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -extern mod extra; - -fn foo(y: Option) { - let mut x: int; - let mut rs: ~[int] = ~[]; - /* tests that x doesn't get put in the precondition for the - entire if expression */ - - if true { - } else { - match y { - None:: => x = 17, - _ => x = 42 - } - rs.push(x); - } - return; -} - -pub fn main() { info2!("hello"); foo::(Some::(5)); } diff --git a/gcc/testsuite/rust.test/match-naked-record-expr.rs b/gcc/testsuite/rust.test/match-naked-record-expr.rs deleted file mode 100644 index 433cf23..0000000 --- a/gcc/testsuite/rust.test/match-naked-record-expr.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct X { x: int } - -pub fn main() { - let _x = match 0 { - _ => X { - x: 0 - }.x - }; -} diff --git a/gcc/testsuite/rust.test/match-naked-record.rs b/gcc/testsuite/rust.test/match-naked-record.rs deleted file mode 100644 index fe12b7c..0000000 --- a/gcc/testsuite/rust.test/match-naked-record.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct X { x: int } - -pub fn main() { - let _x = match 0 { - _ => X { - x: 0 - } - }; -} diff --git a/gcc/testsuite/rust.test/match-path.rs b/gcc/testsuite/rust.test/match-path.rs deleted file mode 100644 index 3da6bb9..0000000 --- a/gcc/testsuite/rust.test/match-path.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -mod m1 { - pub enum foo { foo1, foo2, } -} - -fn bar(x: m1::foo) { match x { m1::foo1 => { } m1::foo2 => { } } } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/match-pattern-drop.rs b/gcc/testsuite/rust.test/match-pattern-drop.rs deleted file mode 100644 index 416c932..0000000 --- a/gcc/testsuite/rust.test/match-pattern-drop.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- -enum t { make_t(@int), clam, } - -fn foo(s: @int) { - info2!("{:?}", ::std::managed::refcount(s)); - let count = ::std::managed::refcount(s); - let x: t = make_t(s); // ref up - assert_eq!(::std::managed::refcount(s), count + 1u); - info2!("{:?}", ::std::managed::refcount(s)); - - match x { - make_t(y) => { - info2!("{:?}", y); // ref up then down - - } - _ => { info2!("?"); fail2!(); } - } - info2!("{:?}", ::std::managed::refcount(s)); - assert_eq!(::std::managed::refcount(s), count + 1u); - let _ = ::std::managed::refcount(s); // don't get bitten by last-use. -} - -pub fn main() { - let s: @int = @0; // ref up - - let count = ::std::managed::refcount(s); - - foo(s); // ref up then down - - info2!("{}", ::std::managed::refcount(s)); - let count2 = ::std::managed::refcount(s); - assert_eq!(count, count2); -} diff --git a/gcc/testsuite/rust.test/match-pattern-lit.rs b/gcc/testsuite/rust.test/match-pattern-lit.rs deleted file mode 100644 index 9493b8d..0000000 --- a/gcc/testsuite/rust.test/match-pattern-lit.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn altlit(f: int) -> int { - match f { - 10 => { info2!("case 10"); return 20; } - 11 => { info2!("case 11"); return 22; } - _ => fail2!("the impossible happened") - } -} - -pub fn main() { assert!((altlit(10) == 20)); assert!((altlit(11) == 22)); } diff --git a/gcc/testsuite/rust.test/match-pattern-no-type-params.rs b/gcc/testsuite/rust.test/match-pattern-no-type-params.rs deleted file mode 100644 index 6ef3f75..0000000 --- a/gcc/testsuite/rust.test/match-pattern-no-type-params.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum maybe { nothing, just(T), } - -fn foo(x: maybe) { - match x { - nothing => { error2!("A"); } - just(_a) => { error2!("B"); } - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/match-pattern-simple.rs b/gcc/testsuite/rust.test/match-pattern-simple.rs deleted file mode 100644 index 92a7539..0000000 --- a/gcc/testsuite/rust.test/match-pattern-simple.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn altsimple(f: int) { match f { _x => () } } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/match-phi.rs b/gcc/testsuite/rust.test/match-phi.rs deleted file mode 100644 index c25f573..0000000 --- a/gcc/testsuite/rust.test/match-phi.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -enum thing { a, b, c, } - -fn foo(it: &fn(int)) { it(10); } - -pub fn main() { - let mut x = true; - match a { - a => { x = true; foo(|_i| { } ) } - b => { x = false; } - c => { x = false; } - } -} diff --git a/gcc/testsuite/rust.test/match-pipe-binding.rs b/gcc/testsuite/rust.test/match-pipe-binding.rs deleted file mode 100644 index 7083254..0000000 --- a/gcc/testsuite/rust.test/match-pipe-binding.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test1() { - // from issue 6338 - match ((1, ~"a"), (2, ~"b")) { - ((1, a), (2, b)) | ((2, b), (1, a)) => { - assert_eq!(a, ~"a"); - assert_eq!(b, ~"b"); - }, - _ => fail2!(), - } -} - -fn test2() { - match (1, 2, 3) { - (1, a, b) | (2, b, a) => { - assert_eq!(a, 2); - assert_eq!(b, 3); - }, - _ => fail2!(), - } -} - -fn test3() { - match (1, 2, 3) { - (1, ref a, ref b) | (2, ref b, ref a) => { - assert_eq!(*a, 2); - assert_eq!(*b, 3); - }, - _ => fail2!(), - } -} - -fn test4() { - match (1, 2, 3) { - (1, a, b) | (2, b, a) if a == 2 => { - assert_eq!(a, 2); - assert_eq!(b, 3); - }, - _ => fail2!(), - } -} - -fn test5() { - match (1, 2, 3) { - (1, ref a, ref b) | (2, ref b, ref a) if *a == 2 => { - assert_eq!(*a, 2); - assert_eq!(*b, 3); - }, - _ => fail2!(), - } -} - -pub fn main() { - test1(); - test2(); - test3(); - test4(); - test5(); -} diff --git a/gcc/testsuite/rust.test/match-range-static.rs b/gcc/testsuite/rust.test/match-range-static.rs deleted file mode 100644 index 0bf0d6e..0000000 --- a/gcc/testsuite/rust.test/match-range-static.rs +++ /dev/null @@ -1,9 +0,0 @@ -static s: int = 1; -static e: int = 42; - -pub fn main() { - match 7 { - s..e => (), - _ => (), - } -} diff --git a/gcc/testsuite/rust.test/match-range.rs b/gcc/testsuite/rust.test/match-range.rs deleted file mode 100644 index a95c4e5..0000000 --- a/gcc/testsuite/rust.test/match-range.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - match 5u { - 1u..5u => {} - _ => fail2!("should match range"), - } - match 5u { - 6u..7u => fail2!("shouldn't match range"), - _ => {} - } - match 5u { - 1u => fail2!("should match non-first range"), - 2u..6u => {} - _ => fail2!("math is broken") - } - match 'c' { - 'a'..'z' => {} - _ => fail2!("should suppport char ranges") - } - match -3 { - -7..5 => {} - _ => fail2!("should match signed range") - } - match 3.0 { - 1.0..5.0 => {} - _ => fail2!("should match float range") - } - match -1.5 { - -3.6..3.6 => {} - _ => fail2!("should match negative float range") - } -} diff --git a/gcc/testsuite/rust.test/match-ref-binding-in-guard-3256.rs b/gcc/testsuite/rust.test/match-ref-binding-in-guard-3256.rs deleted file mode 100644 index 74a3f25..0000000 --- a/gcc/testsuite/rust.test/match-ref-binding-in-guard-3256.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable; - -pub fn main() { - unsafe { - let x = Some(unstable::sync::Exclusive::new(true)); - match x { - Some(ref z) if z.with(|b| *b) => { - do z.with |b| { assert!(*b); } - }, - _ => fail2!() - } - } -} diff --git a/gcc/testsuite/rust.test/match-ref-binding-mut-option.rs b/gcc/testsuite/rust.test/match-ref-binding-mut-option.rs deleted file mode 100644 index 8d1e483..0000000 --- a/gcc/testsuite/rust.test/match-ref-binding-mut-option.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut v = Some(22); - match v { - None => {} - Some(ref mut p) => { *p += 1; } - } - assert_eq!(v, Some(23)); -} diff --git a/gcc/testsuite/rust.test/match-ref-binding-mut.rs b/gcc/testsuite/rust.test/match-ref-binding-mut.rs deleted file mode 100644 index 266f7cd..0000000 --- a/gcc/testsuite/rust.test/match-ref-binding-mut.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Rec { - f: int -} - -fn destructure(x: &mut Rec) { - match *x { - Rec {f: ref mut f} => *f += 1 - } -} - -pub fn main() { - let mut v = Rec {f: 22}; - destructure(&mut v); - assert_eq!(v.f, 23); -} diff --git a/gcc/testsuite/rust.test/match-ref-binding.rs b/gcc/testsuite/rust.test/match-ref-binding.rs deleted file mode 100644 index 0b613df..0000000 --- a/gcc/testsuite/rust.test/match-ref-binding.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn destructure(x: Option) -> int { - match x { - None => 0, - Some(ref v) => *v - } -} - -pub fn main() { - assert_eq!(destructure(Some(22)), 22); -} diff --git a/gcc/testsuite/rust.test/match-static-const-rename.rs b/gcc/testsuite/rust.test/match-static-const-rename.rs deleted file mode 100644 index df62ba7..0000000 --- a/gcc/testsuite/rust.test/match-static-const-rename.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #7526: lowercase static constants in patterns look like bindings - -// This is similar to compile-fail/match-static-const-lc, except it -// shows the expected usual workaround (choosing a different name for -// the static definition) and also demonstrates that one can work -// around this problem locally by renaming the constant in the `use` -// form to an uppercase identifier that placates the lint. - -#[deny(non_uppercase_pattern_statics)]; - -pub static A : int = 97; - -fn f() { - let r = match (0,0) { - (0, A) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 1); - let r = match (0,97) { - (0, A) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 0); -} - -mod m { - pub static aha : int = 7; -} - -fn g() { - use AHA = self::m::aha; - let r = match (0,0) { - (0, AHA) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 1); - let r = match (0,7) { - (0, AHA) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 0); -} - -fn h() { - let r = match (0,0) { - (0, self::m::aha) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 1); - let r = match (0,7) { - (0, self::m::aha) => 0, - (x, y) => 1 + x + y, - }; - assert!(r == 0); -} - -pub fn main () { - f(); - g(); - h(); -} diff --git a/gcc/testsuite/rust.test/match-str.rs b/gcc/testsuite/rust.test/match-str.rs deleted file mode 100644 index ecec003..0000000 --- a/gcc/testsuite/rust.test/match-str.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #53 - -pub fn main() { - match ~"test" { ~"not-test" => fail2!(), ~"test" => (), _ => fail2!() } - - enum t { tag1(~str), tag2, } - - - match tag1(~"test") { - tag2 => fail2!(), - tag1(~"not-test") => fail2!(), - tag1(~"test") => (), - _ => fail2!() - } - - let x = match ~"a" { ~"a" => 1, ~"b" => 2, _ => fail2!() }; - assert_eq!(x, 1); - - match ~"a" { ~"a" => { } ~"b" => { }, _ => fail2!() } - -} diff --git a/gcc/testsuite/rust.test/match-struct-0.rs b/gcc/testsuite/rust.test/match-struct-0.rs deleted file mode 100644 index 215b05a..0000000 --- a/gcc/testsuite/rust.test/match-struct-0.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo{ - f : int, -} - -pub fn main() { - let f = Foo{f: 1}; - match f { - Foo{f: 0} => fail2!(), - Foo{_} => (), - } - match f { - Foo{f: 0} => fail2!(), - Foo{f: _f} => (), - } - match f { - Foo{f: 0} => fail2!(), - _ => (), - } -} diff --git a/gcc/testsuite/rust.test/match-tag.rs b/gcc/testsuite/rust.test/match-tag.rs deleted file mode 100644 index 9eeb12d..0000000 --- a/gcc/testsuite/rust.test/match-tag.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -enum color { - rgb(int, int, int), - rgba(int, int, int, int), - hsl(int, int, int), -} - -fn process(c: color) -> int { - let mut x: int; - match c { - rgb(r, _, _) => { x = r; } - rgba(_, _, _, a) => { x = a; } - hsl(_, s, _) => { x = s; } - } - return x; -} - -pub fn main() { - let gray: color = rgb(127, 127, 127); - let clear: color = rgba(50, 150, 250, 0); - let red: color = hsl(0, 255, 255); - assert_eq!(process(gray), 127); - assert_eq!(process(clear), 0); - assert_eq!(process(red), 255); -} diff --git a/gcc/testsuite/rust.test/match-unique-bind.rs b/gcc/testsuite/rust.test/match-unique-bind.rs deleted file mode 100644 index 7f2af90..0000000 --- a/gcc/testsuite/rust.test/match-unique-bind.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - match ~100 { - ~x => { - info2!("{:?}", x); - assert_eq!(x, 100); - } - } -} diff --git a/gcc/testsuite/rust.test/match-value-binding-in-guard-3291.rs b/gcc/testsuite/rust.test/match-value-binding-in-guard-3291.rs deleted file mode 100644 index 33785b2..0000000 --- a/gcc/testsuite/rust.test/match-value-binding-in-guard-3291.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: Option<~int>, b: bool) -> int { - match x { - None => { 1 } - Some(ref x) if b => { *x.clone() } - Some(_) => { 0 } - } -} - -pub fn main() { - foo(Some(~22), true); - foo(Some(~22), false); - foo(None, true); - foo(None, false); -} diff --git a/gcc/testsuite/rust.test/match-vec-rvalue.rs b/gcc/testsuite/rust.test/match-vec-rvalue.rs deleted file mode 100644 index a6e61fb..0000000 --- a/gcc/testsuite/rust.test/match-vec-rvalue.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Tests that matching rvalues with drops does not crash. - -pub fn main() { - match ~[1, 2, 3] { - x => { - assert_eq!(x.len(), 3); - assert_eq!(x[0], 1); - assert_eq!(x[1], 2); - assert_eq!(x[2], 3); - } - } -} diff --git a/gcc/testsuite/rust.test/match-with-ret-arm.rs b/gcc/testsuite/rust.test/match-with-ret-arm.rs deleted file mode 100644 index 2476d440..0000000 --- a/gcc/testsuite/rust.test/match-with-ret-arm.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::uint; - -pub fn main() { - // sometimes we have had trouble finding - // the right type for f, as we unified - // bot and u32 here - let f = match from_str::("1234") { - None => return (), - Some(num) => num as u32 - }; - assert_eq!(f, 1234u32); - error2!("{}", f) -} diff --git a/gcc/testsuite/rust.test/max-min-classes.rs b/gcc/testsuite/rust.test/max-min-classes.rs deleted file mode 100644 index e3c375f..0000000 --- a/gcc/testsuite/rust.test/max-min-classes.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Product { - fn product(&self) -> int; -} - -struct Foo { - x: int, - y: int, -} - -impl Foo { - pub fn sum(&self) -> int { - self.x + self.y - } -} - -impl Product for Foo { - fn product(&self) -> int { - self.x * self.y - } -} - -fn Foo(x: int, y: int) -> Foo { - Foo { x: x, y: y } -} - -pub fn main() { - let foo = Foo(3, 20); - println!("{} {}", foo.sum(), foo.product()); -} diff --git a/gcc/testsuite/rust.test/method-attributes.rs b/gcc/testsuite/rust.test/method-attributes.rs deleted file mode 100644 index db74407..0000000 --- a/gcc/testsuite/rust.test/method-attributes.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact - Make sure we print all the attributes - -#[frobable] -trait frobable { - #[frob_attr] - fn frob(&self); - #[defrob_attr] - fn defrob(&self); -} - -#[int_frobable] -impl frobable for int { - #[frob_attr1] - fn frob(&self) { - #[frob_attr2]; - } - - #[defrob_attr1] - fn defrob(&self) { - #[defrob_attr2]; - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/mid-path-type-params.rs b/gcc/testsuite/rust.test/mid-path-type-params.rs deleted file mode 100644 index bc4f427..0000000 --- a/gcc/testsuite/rust.test/mid-path-type-params.rs +++ /dev/null @@ -1,33 +0,0 @@ -struct S { - contents: T, -} - -impl S { - fn new(x: T, _: U) -> S { - S { - contents: x, - } - } -} - -trait Trait { - fn new(x: T, y: U) -> Self; -} - -struct S2 { - contents: int, -} - -impl Trait for S2 { - fn new(x: int, _: U) -> S2 { - S2 { - contents: x, - } - } -} - -pub fn main() { - let _ = S::::new::(1, 1.0); - let _: S2 = Trait::::new::(1, 1.0); -} - diff --git a/gcc/testsuite/rust.test/mlist-cycle.rs b/gcc/testsuite/rust.test/mlist-cycle.rs deleted file mode 100644 index cb33fee..0000000 --- a/gcc/testsuite/rust.test/mlist-cycle.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// -*- rust -*- -extern mod std; -use std::gc; -use std::gc::rustrt; - -struct cell {c: @list} - -enum list { link(@mut cell), nil, } - -pub fn main() { - let first: @cell = @mut cell{c: @nil()}; - let second: @cell = @mut cell{c: @link(first)}; - first._0 = @link(second); - rustrt::gc(); - let third: @cell = @mut cell{c: @nil()}; -} diff --git a/gcc/testsuite/rust.test/mlist.rs b/gcc/testsuite/rust.test/mlist.rs deleted file mode 100644 index cfb1db4..0000000 --- a/gcc/testsuite/rust.test/mlist.rs +++ /dev/null @@ -1,14 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum mlist { cons(int, @mlist), nil, } - -pub fn main() { cons(10, @cons(11, @cons(12, @nil))); } diff --git a/gcc/testsuite/rust.test/mod-inside-fn.rs b/gcc/testsuite/rust.test/mod-inside-fn.rs deleted file mode 100644 index 388d2e4..0000000 --- a/gcc/testsuite/rust.test/mod-inside-fn.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() -> int { - mod m { - pub fn g() -> int { 720 } - } - - m::g() -} - -pub fn main() { - assert_eq!(f(), 720); -} diff --git a/gcc/testsuite/rust.test/mod-view-items.rs b/gcc/testsuite/rust.test/mod-view-items.rs deleted file mode 100644 index 21e841b..0000000 --- a/gcc/testsuite/rust.test/mod-view-items.rs +++ /dev/null @@ -1,24 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test view items inside non-file-level mods - -// This is a regression test for an issue where we were failing to -// pretty-print such view items. If that happens again, this should -// begin failing. - -mod m { - use std::vec; - pub fn f() -> ~[int] { vec::from_elem(1u, 0) } -} - -pub fn main() { let _x = m::f(); } diff --git a/gcc/testsuite/rust.test/mod_dir_implicit.rs b/gcc/testsuite/rust.test/mod_dir_implicit.rs deleted file mode 100644 index eb5f72e..0000000 --- a/gcc/testsuite/rust.test/mod_dir_implicit.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -mod mod_dir_implicit_aux; - -pub fn main() { - assert_eq!(mod_dir_implicit_aux::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_path.rs b/gcc/testsuite/rust.test/mod_dir_path.rs deleted file mode 100644 index a356a0a..0000000 --- a/gcc/testsuite/rust.test/mod_dir_path.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -mod mod_dir_simple { - #[path = "test.rs"] - pub mod syrup; -} - -pub fn main() { - assert_eq!(mod_dir_simple::syrup::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_path2.rs b/gcc/testsuite/rust.test/mod_dir_path2.rs deleted file mode 100644 index 6119e96..0000000 --- a/gcc/testsuite/rust.test/mod_dir_path2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -#[path = "mod_dir_simple"] -mod pancakes { - #[path = "test.rs"] - pub mod syrup; -} - -pub fn main() { - assert_eq!(pancakes::syrup::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_path3.rs b/gcc/testsuite/rust.test/mod_dir_path3.rs deleted file mode 100644 index 0028265..0000000 --- a/gcc/testsuite/rust.test/mod_dir_path3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -#[path = "mod_dir_simple"] -mod pancakes { - pub mod test; -} - -pub fn main() { - assert_eq!(pancakes::test::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_path_multi.rs b/gcc/testsuite/rust.test/mod_dir_path_multi.rs deleted file mode 100644 index 4766d33..0000000 --- a/gcc/testsuite/rust.test/mod_dir_path_multi.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -#[path = "mod_dir_simple"] -mod biscuits { - pub mod test; -} - -#[path = "mod_dir_simple"] -mod gravy { - pub mod test; -} - -pub fn main() { - assert_eq!(biscuits::test::foo(), 10); - assert_eq!(gravy::test::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_recursive.rs b/gcc/testsuite/rust.test/mod_dir_recursive.rs deleted file mode 100644 index a39d4141..0000000 --- a/gcc/testsuite/rust.test/mod_dir_recursive.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -// Testing that the parser for each file tracks its modules -// and paths independently. The load_another_mod module should -// not try to reuse the 'mod_dir_simple' path. - -mod mod_dir_simple { - pub mod load_another_mod; -} - -pub fn main() { - assert_eq!(mod_dir_simple::load_another_mod::test::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_dir_simple.rs b/gcc/testsuite/rust.test/mod_dir_simple.rs deleted file mode 100644 index fbc522f..0000000 --- a/gcc/testsuite/rust.test/mod_dir_simple.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty -// xfail-fast - -mod mod_dir_simple { - pub mod test; -} - -pub fn main() { - assert_eq!(mod_dir_simple::test::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_file.rs b/gcc/testsuite/rust.test/mod_file.rs deleted file mode 100644 index b2dd931..0000000 --- a/gcc/testsuite/rust.test/mod_file.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty - -// Testing that a plain .rs file can load modules from other source files - -mod mod_file_aux; - -pub fn main() { - assert_eq!(mod_file_aux::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/mod_file_aux.rs b/gcc/testsuite/rust.test/mod_file_aux.rs deleted file mode 100644 index a336cad..0000000 --- a/gcc/testsuite/rust.test/mod_file_aux.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test Not a test. Used by other tests - -pub fn foo() -> int { 10 } diff --git a/gcc/testsuite/rust.test/mod_file_with_path_attr.rs b/gcc/testsuite/rust.test/mod_file_with_path_attr.rs deleted file mode 100644 index 8455b66..0000000 --- a/gcc/testsuite/rust.test/mod_file_with_path_attr.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-pretty - -// Testing that a plain .rs file can load modules from other source files - -#[path = "mod_file_aux.rs"] -mod m; - -pub fn main() { - assert_eq!(m::foo(), 10); -} diff --git a/gcc/testsuite/rust.test/module-qualified-struct-destructure.rs b/gcc/testsuite/rust.test/module-qualified-struct-destructure.rs deleted file mode 100644 index 5655ff8..0000000 --- a/gcc/testsuite/rust.test/module-qualified-struct-destructure.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod m { - pub struct S { - x: int, - y: int - } -} - -pub fn main() { - let x = m::S { x: 1, y: 2 }; - let m::S { x: _a, y: _b } = x; -} diff --git a/gcc/testsuite/rust.test/monad.rs b/gcc/testsuite/rust.test/monad.rs deleted file mode 100644 index 8baf15c..0000000 --- a/gcc/testsuite/rust.test/monad.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -trait vec_monad { - fn bind(&self, f: &fn(&A) -> ~[B]) -> ~[B]; -} - -impl vec_monad for ~[A] { - fn bind(&self, f: &fn(&A) -> ~[B]) -> ~[B] { - let mut r = ~[]; - for elt in self.iter() { - r.push_all_move(f(elt)); - } - r - } -} - -trait option_monad { - fn bind(&self, f: &fn(&A) -> Option) -> Option; -} - -impl option_monad for Option { - fn bind(&self, f: &fn(&A) -> Option) -> Option { - match *self { - Some(ref a) => { f(a) } - None => { None } - } - } -} - -fn transform(x: Option) -> Option<~str> { - x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_str()) ) -} - -pub fn main() { - assert_eq!(transform(Some(10)), Some(~"11")); - assert_eq!(transform(None), None); - assert!((~[~"hi"]) - .bind(|x| ~[x.clone(), *x + "!"] ) - .bind(|x| ~[x.clone(), *x + "?"] ) == - ~[~"hi", ~"hi?", ~"hi!", ~"hi!?"]); -} diff --git a/gcc/testsuite/rust.test/monomorphize-abi-alignment.rs b/gcc/testsuite/rust.test/monomorphize-abi-alignment.rs deleted file mode 100644 index f9c8fe0..0000000 --- a/gcc/testsuite/rust.test/monomorphize-abi-alignment.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, - * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment - * of any field. (Also, u64 has 8-byte ABI alignment; this is not always true). - * - * On such platforms, if monomorphize uses the "preferred" alignment, then it will unify - * `A` and `B`, even though `S` and `S` have the field `t` at different offsets, - * and apply the wrong instance of the method `unwrap`. - */ - -struct S { i:u8, t:T } -impl S { fn unwrap(self) -> T { self.t } } -struct A((u32, u32)); -struct B(u64); - -pub fn main() { - static Ca: S = S { i: 0, t: A((13, 104)) }; - static Cb: S = S { i: 0, t: B(31337) }; - assert_eq!(*(Ca.unwrap()), (13, 104)); - assert_eq!(*(Cb.unwrap()), 31337); -} diff --git a/gcc/testsuite/rust.test/monomorphized-callees-with-ty-params-3314.rs b/gcc/testsuite/rust.test/monomorphized-callees-with-ty-params-3314.rs deleted file mode 100644 index 3146c2a..0000000 --- a/gcc/testsuite/rust.test/monomorphized-callees-with-ty-params-3314.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::io; - -trait Serializer { -} - -trait Serializable { - fn serialize(&self, s: S); -} - -impl Serializable for int { - fn serialize(&self, _s: S) { } -} - -struct F { a: A } - -impl Serializable for F { - fn serialize(&self, s: S) { - self.a.serialize(s); - } -} - -impl Serializer for @io::Writer { -} - -pub fn main() { - do io::with_str_writer |wr| { - let foo = F { a: 1 }; - foo.serialize(wr); - - let bar = F { a: F {a: 1 } }; - bar.serialize(wr); - }; -} diff --git a/gcc/testsuite/rust.test/morestack-address.rs b/gcc/testsuite/rust.test/morestack-address.rs deleted file mode 100644 index ad8b328..0000000 --- a/gcc/testsuite/rust.test/morestack-address.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - #[nolink] - extern "rust-intrinsic" { - pub fn morestack_addr() -> *(); - } -} - -pub fn main() { - unsafe { - let addr = rusti::morestack_addr(); - assert!(addr.is_not_null()); - error2!("{}", addr); - } -} diff --git a/gcc/testsuite/rust.test/morestack1.rs b/gcc/testsuite/rust.test/morestack1.rs deleted file mode 100644 index e1a5c8c..0000000 --- a/gcc/testsuite/rust.test/morestack1.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -fn getbig(i: int) { - if i != 0 { - getbig(i - 1); - } -} - -pub fn main() { - getbig(100000); -} diff --git a/gcc/testsuite/rust.test/morestack2.rs b/gcc/testsuite/rust.test/morestack2.rs deleted file mode 100644 index cf42af0..0000000 --- a/gcc/testsuite/rust.test/morestack2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -fn getbig(i: int) -> int { - let m = if i >= 0 { - let j = getbig(i - 1); - let k = getbig(j - 1); - k - } else { - 0 - }; - m -} - -pub fn main() { - getbig(10000); -} diff --git a/gcc/testsuite/rust.test/morestack3.rs b/gcc/testsuite/rust.test/morestack3.rs deleted file mode 100644 index b24afa1..0000000 --- a/gcc/testsuite/rust.test/morestack3.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -// Here we're testing that all of the argument registers, argument -// stack slots, and return value are preserved across split stacks. -fn getbig(a0: int, - a1: int, - a2: int, - a3: int, - a4: int, - a5: int, - a6: int, - a7: int, - a8: int, - a9: int) -> int { - - assert_eq!(a0 + 1, a1); - assert_eq!(a1 + 1, a2); - assert_eq!(a2 + 1, a3); - assert_eq!(a3 + 1, a4); - assert_eq!(a4 + 1, a5); - assert_eq!(a5 + 1, a6); - assert_eq!(a6 + 1, a7); - assert_eq!(a7 + 1, a8); - assert_eq!(a8 + 1, a9); - if a0 != 0 { - let j = getbig(a0 - 1, - a1 - 1, - a2 - 1, - a3 - 1, - a4 - 1, - a5 - 1, - a6 - 1, - a7 - 1, - a8 - 1, - a9 - 1); - assert_eq!(j, a0 - 1); - } - return a0; -} - -pub fn main() { - let a = 1000; - getbig(a, a+1, a+2, a+3, a+4, a+5, a+6, a+7, a+8, a+9); -} diff --git a/gcc/testsuite/rust.test/morestack4.rs b/gcc/testsuite/rust.test/morestack4.rs deleted file mode 100644 index bd4f516..0000000 --- a/gcc/testsuite/rust.test/morestack4.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -// This is testing for stack frames greater than 256 bytes, -// for which function prologues are generated differently - -struct Biggy { - a00: u64, - a01: u64, - a02: u64, - a03: u64, - a04: u64, - a05: u64, - a06: u64, - a07: u64, - a08: u64, - a09: u64, - a10: u64, - a11: u64, - a12: u64, - a13: u64, - a14: u64, - a15: u64, - a16: u64, - a17: u64, - a18: u64, - a19: u64, - a20: u64, - a21: u64, - a22: u64, - a23: u64, - a24: u64, - a25: u64, - a26: u64, - a27: u64, - a28: u64, - a29: u64, - a30: u64, - a31: u64, - a32: u64, - a33: u64, - a34: u64, - a35: u64, - a36: u64, - a37: u64, - a38: u64, - a39: u64, -} - - -fn getbig(i: Biggy) { - if i.a00 != 0u64 { - getbig(Biggy{a00: i.a00 - 1u64,.. i}); - } -} - -pub fn main() { - getbig(Biggy { - a00: 10000u64, - a01: 10000u64, - a02: 10000u64, - a03: 10000u64, - a04: 10000u64, - a05: 10000u64, - a06: 10000u64, - a07: 10000u64, - a08: 10000u64, - a09: 10000u64, - a10: 10000u64, - a11: 10000u64, - a12: 10000u64, - a13: 10000u64, - a14: 10000u64, - a15: 10000u64, - a16: 10000u64, - a17: 10000u64, - a18: 10000u64, - a19: 10000u64, - a20: 10000u64, - a21: 10000u64, - a22: 10000u64, - a23: 10000u64, - a24: 10000u64, - a25: 10000u64, - a26: 10000u64, - a27: 10000u64, - a28: 10000u64, - a29: 10000u64, - a30: 10000u64, - a31: 10000u64, - a32: 10000u64, - a33: 10000u64, - a34: 10000u64, - a35: 10000u64, - a36: 10000u64, - a37: 10000u64, - a38: 10000u64, - a39: 10000u64, - }); -} diff --git a/gcc/testsuite/rust.test/morestack5.rs b/gcc/testsuite/rust.test/morestack5.rs deleted file mode 100644 index ec8ed77..0000000 --- a/gcc/testsuite/rust.test/morestack5.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -// This test will call __morestack with various minimum stack sizes - -extern mod extra; - -use std::task; - -fn getbig(i: int) { - if i != 0 { - getbig(i - 1); - } -} - -pub fn main() { - let mut sz = 400u; - while sz < 500u { - task::try(|| getbig(200) ); - sz += 1u; - } -} diff --git a/gcc/testsuite/rust.test/morestack6.rs b/gcc/testsuite/rust.test/morestack6.rs deleted file mode 100644 index a5a67ed..0000000 --- a/gcc/testsuite/rust.test/morestack6.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test newsched transition - -// This test attempts to force the dynamic linker to resolve -// external symbols as close to the red zone as possible. - -use std::rand; -use std::task; - -mod rustrt { - use std::libc; - - extern { - pub fn debug_get_stk_seg() -> *u8; - - pub fn rust_get_sched_id() -> libc::intptr_t; - pub fn rust_get_argc() -> libc::c_int; - pub fn get_task_id() -> libc::intptr_t; - pub fn rust_get_task(); - } -} - -fn calllink01() { unsafe { rustrt::rust_get_sched_id(); } } -fn calllink02() { unsafe { rustrt::rust_get_argc(); } } -fn calllink08() { unsafe { rustrt::get_task_id(); } } -fn calllink10() { unsafe { rustrt::rust_get_task(); } } - -fn runtest(f: extern fn(), frame_backoff: u32) { - runtest2(f, frame_backoff, 0 as *u8); -} - -fn runtest2(f: extern fn(), frame_backoff: u32, last_stk: *u8) -> u32 { - unsafe { - let curr_stk = rustrt::debug_get_stk_seg(); - if (last_stk != curr_stk && last_stk != 0 as *u8) { - // We switched stacks, go back and try to hit the dynamic linker - frame_backoff - } else { - let frame_backoff = runtest2(f, frame_backoff, curr_stk); - if frame_backoff > 1u32 { - frame_backoff - 1u32 - } else if frame_backoff == 1u32 { - f(); - 0u32 - } else { - 0u32 - } - } - } -} - -pub fn main() { - use std::rand::Rng; - let fns = ~[ - calllink01, - calllink02, - calllink08, - calllink10 - ]; - let mut rng = rand::rng(); - for f in fns.iter() { - let f = *f; - let sz = rng.gen::() % 256u32 + 256u32; - let frame_backoff = rng.gen::() % 10u32 + 1u32; - task::try(|| runtest(f, frame_backoff) ); - } -} diff --git a/gcc/testsuite/rust.test/move-1-unique.rs b/gcc/testsuite/rust.test/move-1-unique.rs deleted file mode 100644 index ac6dfa0..0000000 --- a/gcc/testsuite/rust.test/move-1-unique.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone)] -struct Triple { - x: int, - y: int, - z: int, -} - -fn test(x: bool, foo: ~Triple) -> int { - let bar = foo; - let mut y: ~Triple; - if x { y = bar; } else { y = ~Triple{x: 4, y: 5, z: 6}; } - return y.y; -} - -pub fn main() { - let x = ~Triple{x: 1, y: 2, z: 3}; - assert_eq!(test(true, x.clone()), 2); - assert_eq!(test(true, x.clone()), 2); - assert_eq!(test(true, x.clone()), 2); - assert_eq!(test(false, x), 5); -} diff --git a/gcc/testsuite/rust.test/move-1.rs b/gcc/testsuite/rust.test/move-1.rs deleted file mode 100644 index 5d3b25e..0000000 --- a/gcc/testsuite/rust.test/move-1.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Triple { x: int, y: int, z: int } - -fn test(x: bool, foo: @Triple) -> int { - let bar = foo; - let mut y: @Triple; - if x { y = bar; } else { y = @Triple{x: 4, y: 5, z: 6}; } - return y.y; -} - -pub fn main() { - let x = @Triple {x: 1, y: 2, z: 3}; - assert_eq!(test(true, x), 2); - assert_eq!(test(true, x), 2); - assert_eq!(test(true, x), 2); - assert_eq!(test(false, x), 5); -} diff --git a/gcc/testsuite/rust.test/move-2-unique.rs b/gcc/testsuite/rust.test/move-2-unique.rs deleted file mode 100644 index e3595d4..0000000 --- a/gcc/testsuite/rust.test/move-2-unique.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -struct X { x: int, y: int, z: int } - -pub fn main() { let x = ~X{x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); } diff --git a/gcc/testsuite/rust.test/move-2.rs b/gcc/testsuite/rust.test/move-2.rs deleted file mode 100644 index fb5f3e1..0000000 --- a/gcc/testsuite/rust.test/move-2.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -struct X { x: int, y: int, z: int } - -pub fn main() { let x = @X {x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); } diff --git a/gcc/testsuite/rust.test/move-3-unique.rs b/gcc/testsuite/rust.test/move-3-unique.rs deleted file mode 100644 index 46308e0..0000000 --- a/gcc/testsuite/rust.test/move-3-unique.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -#[deriving(Clone)] -struct Triple { - x: int, - y: int, - z: int, -} - -fn test(x: bool, foo: ~Triple) -> int { - let bar = foo; - let mut y: ~Triple; - if x { y = bar; } else { y = ~Triple {x: 4, y: 5, z: 6}; } - return y.y; -} - -pub fn main() { - let x = ~Triple{x: 1, y: 2, z: 3}; - for _ in range(0u, 10000u) { - assert_eq!(test(true, x.clone()), 2); - } - assert_eq!(test(false, x), 5); -} diff --git a/gcc/testsuite/rust.test/move-3.rs b/gcc/testsuite/rust.test/move-3.rs deleted file mode 100644 index c9e480d..0000000 --- a/gcc/testsuite/rust.test/move-3.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -struct Triple { x: int, y: int, z: int } - -fn test(x: bool, foo: @Triple) -> int { - let bar = foo; - let mut y: @Triple; - if x { y = bar; } else { y = @Triple{x: 4, y: 5, z: 6}; } - return y.y; -} - -pub fn main() { - let x = @Triple{x: 1, y: 2, z: 3}; - for _i in range(0u, 10000u) { - assert_eq!(test(true, x), 2); - } - assert_eq!(test(false, x), 5); -} diff --git a/gcc/testsuite/rust.test/move-4-unique.rs b/gcc/testsuite/rust.test/move-4-unique.rs deleted file mode 100644 index 48621cf..0000000 --- a/gcc/testsuite/rust.test/move-4-unique.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -struct Triple {a: int, b: int, c: int} - -fn test(foo: ~Triple) -> ~Triple { - let foo = foo; - let bar = foo; - let baz = bar; - let quux = baz; - return quux; -} - -pub fn main() { let x = ~Triple{a: 1, b: 2, c: 3}; let y = test(x); assert!((y.c == 3)); } diff --git a/gcc/testsuite/rust.test/move-4.rs b/gcc/testsuite/rust.test/move-4.rs deleted file mode 100644 index 2f0f256..0000000 --- a/gcc/testsuite/rust.test/move-4.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -extern mod extra; - -struct Triple { a: int, b: int, c: int } - -fn test(foo: @Triple) -> @Triple { - let foo = foo; - let bar = foo; - let baz = bar; - let quux = baz; - return quux; -} - -pub fn main() { - let x = @Triple{a: 1, b: 2, c: 3}; - let y = test(x); - assert_eq!(y.c, 3); -} diff --git a/gcc/testsuite/rust.test/move-arg-2-unique.rs b/gcc/testsuite/rust.test/move-arg-2-unique.rs deleted file mode 100644 index ed3cdc8..0000000 --- a/gcc/testsuite/rust.test/move-arg-2-unique.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test(foo: ~~[int]) { assert!((foo[0] == 10)); } - -pub fn main() { - let x = ~~[10]; - // Test forgetting a local by move-in - test(x); - - // Test forgetting a temporary by move-in. - test(~~[10]); -} diff --git a/gcc/testsuite/rust.test/move-arg-2.rs b/gcc/testsuite/rust.test/move-arg-2.rs deleted file mode 100644 index fc909da..0000000 --- a/gcc/testsuite/rust.test/move-arg-2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test(foo: @~[int]) { assert!((foo[0] == 10)); } - -pub fn main() { - let x = @~[10]; - // Test forgetting a local by move-in - test(x); - - // Test forgetting a temporary by move-in. - test(@~[10]); -} diff --git a/gcc/testsuite/rust.test/move-arg.rs b/gcc/testsuite/rust.test/move-arg.rs deleted file mode 100644 index 87db5cb..0000000 --- a/gcc/testsuite/rust.test/move-arg.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test(foo: int) { assert!((foo == 10)); } - -pub fn main() { let x = 10; test(x); } diff --git a/gcc/testsuite/rust.test/move-nullary-fn.rs b/gcc/testsuite/rust.test/move-nullary-fn.rs deleted file mode 100644 index 87281c2..0000000 --- a/gcc/testsuite/rust.test/move-nullary-fn.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #922 -fn f2(_thing: &fn()) { } - -fn f(thing: &fn()) { - f2(thing); -} - -pub fn main() { - f(|| {}); -} diff --git a/gcc/testsuite/rust.test/move-out-of-field.rs b/gcc/testsuite/rust.test/move-out-of-field.rs deleted file mode 100644 index 6cf207e..0000000 --- a/gcc/testsuite/rust.test/move-out-of-field.rs +++ /dev/null @@ -1,21 +0,0 @@ -struct StringBuffer { - s: ~str -} - -impl StringBuffer { - pub fn append(&mut self, v: &str) { - self.s.push_str(v); - } -} - -fn to_str(sb: StringBuffer) -> ~str { - sb.s -} - -pub fn main() { - let mut sb = StringBuffer {s: ~""}; - sb.append("Hello, "); - sb.append("World!"); - let str = to_str(sb); - assert_eq!(str, ~"Hello, World!"); -} diff --git a/gcc/testsuite/rust.test/move-scalar.rs b/gcc/testsuite/rust.test/move-scalar.rs deleted file mode 100644 index 845cb8a..0000000 --- a/gcc/testsuite/rust.test/move-scalar.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - - let y: int = 42; - let mut x: int; - x = y; - assert_eq!(x, 42); -} diff --git a/gcc/testsuite/rust.test/move-self.rs b/gcc/testsuite/rust.test/move-self.rs deleted file mode 100644 index 55a7edb..0000000 --- a/gcc/testsuite/rust.test/move-self.rs +++ /dev/null @@ -1,18 +0,0 @@ -struct S { - x: ~str -} - -impl S { - pub fn foo(self) { - self.bar(); - } - - pub fn bar(self) { - println(self.x); - } -} - -pub fn main() { - let x = S { x: ~"Hello!" }; - x.foo(); -} diff --git a/gcc/testsuite/rust.test/moves-based-on-type-capture-clause.rs b/gcc/testsuite/rust.test/moves-based-on-type-capture-clause.rs deleted file mode 100644 index 349be13..0000000 --- a/gcc/testsuite/rust.test/moves-based-on-type-capture-clause.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::task; - -pub fn main() { - let x = ~"Hello world!"; - do task::spawn { - println(x); - } -} diff --git a/gcc/testsuite/rust.test/moves-based-on-type-cross-crate.rs b/gcc/testsuite/rust.test/moves-based-on-type-cross-crate.rs deleted file mode 100644 index 1103869..0000000 --- a/gcc/testsuite/rust.test/moves-based-on-type-cross-crate.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:moves_based_on_type_lib.rs - -extern mod moves_based_on_type_lib; -use moves_based_on_type_lib::f; - -pub fn main() { - f(); -} diff --git a/gcc/testsuite/rust.test/multi-let.rs b/gcc/testsuite/rust.test/multi-let.rs deleted file mode 100644 index eb1444b..0000000 --- a/gcc/testsuite/rust.test/multi-let.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = 10; - let y = x; - assert!((y == 10)); -} diff --git a/gcc/testsuite/rust.test/multibyte.rs b/gcc/testsuite/rust.test/multibyte.rs deleted file mode 100644 index a28008f3..0000000 --- a/gcc/testsuite/rust.test/multibyte.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that multibyte characters don't crash the compiler -pub fn main() { - println("마이너스 사인이 없으면"); -} diff --git a/gcc/testsuite/rust.test/multiline-comment.rs b/gcc/testsuite/rust.test/multiline-comment.rs deleted file mode 100644 index 08fd933..0000000 --- a/gcc/testsuite/rust.test/multiline-comment.rs +++ /dev/null @@ -1,16 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -/* - * This is a multi-line oldcomment. - */ -pub fn main() { } diff --git a/gcc/testsuite/rust.test/multiple-trait-bounds.rs b/gcc/testsuite/rust.test/multiple-trait-bounds.rs deleted file mode 100644 index cdfa93d..0000000 --- a/gcc/testsuite/rust.test/multiple-trait-bounds.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn f(_: T) { -} - -pub fn main() { - f(3); -} diff --git a/gcc/testsuite/rust.test/mut-function-arguments.rs b/gcc/testsuite/rust.test/mut-function-arguments.rs deleted file mode 100644 index 0fa89ba..0000000 --- a/gcc/testsuite/rust.test/mut-function-arguments.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(mut y: ~int) { - *y = 5; - assert_eq!(*y, 5); -} - -fn g() { - let frob: &fn(~int) = |mut q| { *q = 2; assert!(*q == 2); }; - let w = ~37; - frob(w); - -} - -pub fn main() { - let z = ~17; - f(z); - g(); -} diff --git a/gcc/testsuite/rust.test/mut-vstore-expr.rs b/gcc/testsuite/rust.test/mut-vstore-expr.rs deleted file mode 100644 index a276e90..0000000 --- a/gcc/testsuite/rust.test/mut-vstore-expr.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x: &mut [int] = &mut [ 1, 2, 3 ]; -} diff --git a/gcc/testsuite/rust.test/mutability-inherits-through-fixed-length-vec.rs b/gcc/testsuite/rust.test/mutability-inherits-through-fixed-length-vec.rs deleted file mode 100644 index 855c77e..0000000 --- a/gcc/testsuite/rust.test/mutability-inherits-through-fixed-length-vec.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test1() { - let mut ints = [0, ..32]; - ints[0] += 1; - assert_eq!(ints[0], 1); -} - -fn test2() { - let mut ints = [0, ..32]; - for i in ints.mut_iter() { *i += 22; } - for i in ints.iter() { assert!(*i == 22); } -} - -pub fn main() { - test1(); - test2(); -} diff --git a/gcc/testsuite/rust.test/mutable-alias-vec.rs b/gcc/testsuite/rust.test/mutable-alias-vec.rs deleted file mode 100644 index 9ec91d9..0000000 --- a/gcc/testsuite/rust.test/mutable-alias-vec.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// -*- rust -*- -extern mod extra; - -fn grow(v: &mut ~[int]) { - v.push(1); -} - -pub fn main() { - let mut v: ~[int] = ~[]; - grow(&mut v); - grow(&mut v); - grow(&mut v); - let len = v.len(); - info2!("{}", len); - assert_eq!(len, 3 as uint); -} diff --git a/gcc/testsuite/rust.test/mutable-vec-drop.rs b/gcc/testsuite/rust.test/mutable-vec-drop.rs deleted file mode 100644 index 5e05722..0000000 --- a/gcc/testsuite/rust.test/mutable-vec-drop.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_mut)]; - -struct Pair { a: int, b: int} - -pub fn main() { - // This just tests whether the vec leaks its members. - let mut _pvec: ~[@Pair] = - ~[@Pair{a: 1, b: 2}, @Pair{a: 3, b: 4}, @Pair{a: 5, b: 6}]; -} diff --git a/gcc/testsuite/rust.test/mutual-recursion-group.rs b/gcc/testsuite/rust.test/mutual-recursion-group.rs deleted file mode 100644 index cf007e9..0000000 --- a/gcc/testsuite/rust.test/mutual-recursion-group.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -enum colour { red, green, blue, } - -enum tree { children(@list), leaf(colour), } - -enum list { cons(@tree, @list), nil, } - -enum small_list { kons(int, @small_list), neel, } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/negative.rs b/gcc/testsuite/rust.test/negative.rs deleted file mode 100644 index a435f2c..0000000 --- a/gcc/testsuite/rust.test/negative.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - match -5 { - -5 => {} - _ => { fail2!() } - } -} diff --git a/gcc/testsuite/rust.test/nested-class.rs b/gcc/testsuite/rust.test/nested-class.rs deleted file mode 100644 index 6ab9856..0000000 --- a/gcc/testsuite/rust.test/nested-class.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - struct b { - i: int, - } - - impl b { - pub fn do_stuff(&self) -> int { return 37; } - } - - fn b(i:int) -> b { - b { - i: i - } - } - - // fn b(x:int) -> int { fail!(); } - - let z = b(42); - assert_eq!(z.i, 42); - assert_eq!(z.do_stuff(), 37); -} diff --git a/gcc/testsuite/rust.test/nested-enum-same-names.rs b/gcc/testsuite/rust.test/nested-enum-same-names.rs deleted file mode 100644 index 33c4ed6..0000000 --- a/gcc/testsuite/rust.test/nested-enum-same-names.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - -#7770 ICE with sibling methods containing same-name-enum containing - same-name-member - -If you have two methods in an impl block, each containing an enum -(with the same name), each containing at least one value with the same -name, rustc gives the same LLVM symbol for the two of them and fails, -as it does not include the method name in the symbol name. - -*/ - -pub struct Foo; -impl Foo { - pub fn foo() { - enum Panic { Common }; - } - pub fn bar() { - enum Panic { Common }; - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/nested-exhaustive-match.rs b/gcc/testsuite/rust.test/nested-exhaustive-match.rs deleted file mode 100644 index e5ecd82..0000000 --- a/gcc/testsuite/rust.test/nested-exhaustive-match.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { foo: bool, bar: Option, baz: int } - -pub fn main() { - match @Foo{foo: true, bar: Some(10), baz: 20} { - @Foo{foo: true, bar: Some(_), _} => {} - @Foo{foo: false, bar: None, _} => {} - @Foo{foo: true, bar: None, _} => {} - @Foo{foo: false, bar: Some(_), _} => {} - } -} diff --git a/gcc/testsuite/rust.test/nested-function-names-issue-8587.rs b/gcc/testsuite/rust.test/nested-function-names-issue-8587.rs deleted file mode 100644 index f697f0b..0000000 --- a/gcc/testsuite/rust.test/nested-function-names-issue-8587.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure nested functions are separate, even if they have -// equal name. -// -// Issue #8587 - -pub struct X; - -impl X { - fn f(&self) -> int { - #[inline(never)] - fn inner() -> int { - 0 - } - inner() - } - - fn g(&self) -> int { - #[inline(never)] - fn inner_2() -> int { - 1 - } - inner_2() - } - - fn h(&self) -> int { - #[inline(never)] - fn inner() -> int { - 2 - } - inner() - } -} - -pub fn main() { - let n = X; - assert_eq!(n.f(), 0); - assert_eq!(n.g(), 1); - // This test `h` used to fail. - assert_eq!(n.h(), 2); -} diff --git a/gcc/testsuite/rust.test/nested-matchs.rs b/gcc/testsuite/rust.test/nested-matchs.rs deleted file mode 100644 index 9c72819..0000000 --- a/gcc/testsuite/rust.test/nested-matchs.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -fn baz() -> ! { fail2!(); } - -fn foo() { - match Some::(5) { - Some::(_x) => { - let mut bar; - match None:: { None:: => { bar = 5; } _ => { baz(); } } - info2!("{:?}", bar); - } - None:: => { info2!("hello"); } - } -} - -pub fn main() { foo(); } diff --git a/gcc/testsuite/rust.test/nested-pattern.rs b/gcc/testsuite/rust.test/nested-pattern.rs deleted file mode 100644 index cc8436e..0000000 --- a/gcc/testsuite/rust.test/nested-pattern.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// a bug was causing this to complain about leaked memory on exit - -enum t { foo(int, uint), bar(int, Option), } - -fn nested(o: t) { - match o { - bar(_i, Some::(_)) => { error2!("wrong pattern matched"); fail2!(); } - _ => { error2!("succeeded"); } - } -} - -pub fn main() { nested(bar(1, None::)); } diff --git a/gcc/testsuite/rust.test/nested-patterns.rs b/gcc/testsuite/rust.test/nested-patterns.rs deleted file mode 100644 index b979518..0000000 --- a/gcc/testsuite/rust.test/nested-patterns.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct A { a: int, b: @int } -struct B { a: int, b: C } -struct D { a: int, d: C } -struct C { c: int } - -pub fn main() { - match A {a: 10, b: @20} { - x@A {a, b: @20} => { assert!(x.a == 10); assert!(a == 10); } - A {b: _b, _} => { fail2!(); } - } - let mut x@B {b, _} = B {a: 10, b: C {c: 20}}; - x.b.c = 30; - assert_eq!(b.c, 20); - let mut y@D {d, _} = D {a: 10, d: C {c: 20}}; - y.d.c = 30; - assert_eq!(d.c, 20); -} diff --git a/gcc/testsuite/rust.test/nested_item_main.rs b/gcc/testsuite/rust.test/nested_item_main.rs deleted file mode 100644 index 5ce05fe..0000000 --- a/gcc/testsuite/rust.test/nested_item_main.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:nested_item.rs -// xfail-fast - -extern mod nested_item; - -pub fn main() { - assert_eq!(2, nested_item::foo::<()>()); - assert_eq!(2, nested_item::foo::()); -} diff --git a/gcc/testsuite/rust.test/new-impl-syntax.rs b/gcc/testsuite/rust.test/new-impl-syntax.rs deleted file mode 100644 index bc2c147..0000000 --- a/gcc/testsuite/rust.test/new-impl-syntax.rs +++ /dev/null @@ -1,25 +0,0 @@ -struct Thingy { - x: int, - y: int -} - -impl ToStr for Thingy { - fn to_str(&self) -> ~str { - format!("\\{ x: {}, y: {} \\}", self.x, self.y) - } -} - -struct PolymorphicThingy { - x: T -} - -impl ToStr for PolymorphicThingy { - fn to_str(&self) -> ~str { - self.x.to_str() - } -} - -pub fn main() { - println(Thingy { x: 1, y: 2 }.to_str()); - println(PolymorphicThingy { x: Thingy { x: 1, y: 2 } }.to_str()); -} diff --git a/gcc/testsuite/rust.test/new-import-syntax.rs b/gcc/testsuite/rust.test/new-import-syntax.rs deleted file mode 100644 index c7497bf..0000000 --- a/gcc/testsuite/rust.test/new-import-syntax.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::println; - -pub fn main() { - println("Hello world!"); -} diff --git a/gcc/testsuite/rust.test/new-style-constants.rs b/gcc/testsuite/rust.test/new-style-constants.rs deleted file mode 100644 index e240208..0000000 --- a/gcc/testsuite/rust.test/new-style-constants.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::println; - -static FOO: int = 3; - -pub fn main() { - println!("{}", FOO); -} diff --git a/gcc/testsuite/rust.test/new-style-fixed-length-vec.rs b/gcc/testsuite/rust.test/new-style-fixed-length-vec.rs deleted file mode 100644 index a689fb0..0000000 --- a/gcc/testsuite/rust.test/new-style-fixed-length-vec.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static FOO: [int, ..3] = [1, 2, 3]; - -pub fn main() { - println!("{} {} {}", FOO[0], FOO[1], FOO[2]); -} diff --git a/gcc/testsuite/rust.test/new-vstore-mut-box-syntax.rs b/gcc/testsuite/rust.test/new-vstore-mut-box-syntax.rs deleted file mode 100644 index 4792caf..0000000 --- a/gcc/testsuite/rust.test/new-vstore-mut-box-syntax.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x: @mut [int] = @mut [ 1, 2, 3 ]; - -} diff --git a/gcc/testsuite/rust.test/newlambdas-ret-infer.rs b/gcc/testsuite/rust.test/newlambdas-ret-infer.rs deleted file mode 100644 index 6d67578..0000000 --- a/gcc/testsuite/rust.test/newlambdas-ret-infer.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that the lambda kind is inferred correctly as a return -// expression - -fn unique() -> ~fn() { return || (); } - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/newlambdas-ret-infer2.rs b/gcc/testsuite/rust.test/newlambdas-ret-infer2.rs deleted file mode 100644 index 17ff8ce..0000000 --- a/gcc/testsuite/rust.test/newlambdas-ret-infer2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that the lambda kind is inferred correctly as a return -// expression - -fn unique() -> ~fn() { || () } - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/newlambdas.rs b/gcc/testsuite/rust.test/newlambdas.rs deleted file mode 100644 index d9d0daa..0000000 --- a/gcc/testsuite/rust.test/newlambdas.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests for the new |args| expr lambda syntax - -fn f(i: int, f: &fn(int) -> int) -> int { f(i) } - -fn g(_g: &fn()) { } - -pub fn main() { - assert_eq!(f(10, |a| a), 10); - g(||()); - assert_eq!(do f(10) |a| { a }, 10); - do g() { } -} diff --git a/gcc/testsuite/rust.test/newtype-polymorphic.rs b/gcc/testsuite/rust.test/newtype-polymorphic.rs deleted file mode 100644 index 694773f..0000000 --- a/gcc/testsuite/rust.test/newtype-polymorphic.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone)] -struct myvec(~[X]); - -fn myvec_deref(mv: myvec) -> ~[X] { return (*mv).clone(); } - -fn myvec_elt(mv: myvec) -> X { return mv[0]; } - -pub fn main() { - let mv = myvec(~[1, 2, 3]); - assert_eq!(myvec_deref(mv.clone())[1], 2); - assert_eq!(myvec_elt(mv.clone()), 1); - assert_eq!(mv[2], 3); -} diff --git a/gcc/testsuite/rust.test/newtype-struct-drop-run.rs b/gcc/testsuite/rust.test/newtype-struct-drop-run.rs deleted file mode 100644 index 54c4c06..0000000 --- a/gcc/testsuite/rust.test/newtype-struct-drop-run.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure the destructor is run for newtype structs. - -struct Foo(@mut int); - -#[unsafe_destructor] -impl Drop for Foo { - fn drop(&mut self) { - ***self = 23; - } -} - -pub fn main() { - let y = @mut 32; - { - let _x = Foo(y); - } - assert_eq!(*y, 23); -} diff --git a/gcc/testsuite/rust.test/newtype-struct-with-dtor.rs b/gcc/testsuite/rust.test/newtype-struct-with-dtor.rs deleted file mode 100644 index 37b9b5f..0000000 --- a/gcc/testsuite/rust.test/newtype-struct-with-dtor.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::libc::c_int; -use std::libc; - -pub struct Fd(c_int); - -impl Drop for Fd { - #[fixed_stack_segment] #[inline(never)] - fn drop(&mut self) { - unsafe { - libc::close(**self); - } - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/newtype-struct-xc-2.rs b/gcc/testsuite/rust.test/newtype-struct-xc-2.rs deleted file mode 100644 index cedf1d4..0000000 --- a/gcc/testsuite/rust.test/newtype-struct-xc-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -// xfail-fast -// aux-build:newtype_struct_xc.rs - -extern mod newtype_struct_xc; -use newtype_struct_xc::Au; - -fn f() -> Au { - Au(2) -} - -pub fn main() { - let _ = f(); -} diff --git a/gcc/testsuite/rust.test/newtype-struct-xc.rs b/gcc/testsuite/rust.test/newtype-struct-xc.rs deleted file mode 100644 index 2280b33..0000000 --- a/gcc/testsuite/rust.test/newtype-struct-xc.rs +++ /dev/null @@ -1,8 +0,0 @@ -// xfail-fast -// aux-build:newtype_struct_xc.rs - -extern mod newtype_struct_xc; - -pub fn main() { - let _ = newtype_struct_xc::Au(2); -} diff --git a/gcc/testsuite/rust.test/newtype-temporary.rs b/gcc/testsuite/rust.test/newtype-temporary.rs deleted file mode 100644 index 03e5d92..0000000 --- a/gcc/testsuite/rust.test/newtype-temporary.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(uint); - -fn foo() -> Foo { - Foo(42) -} - -pub fn main() { - assert_eq!(*foo(), 42); -} diff --git a/gcc/testsuite/rust.test/newtype.rs b/gcc/testsuite/rust.test/newtype.rs deleted file mode 100644 index f7c8797..0000000 --- a/gcc/testsuite/rust.test/newtype.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct mytype(Mytype); - -struct Mytype {compute: extern fn(mytype) -> int, val: int} - -fn compute(i: mytype) -> int { return i.val + 20; } - -pub fn main() { - let myval = mytype(Mytype{compute: compute, val: 30}); - println!("{}", compute(myval)); - assert_eq!((myval.compute)(myval), 50); -} diff --git a/gcc/testsuite/rust.test/nil-decl-in-foreign.rs b/gcc/testsuite/rust.test/nil-decl-in-foreign.rs deleted file mode 100644 index 15795f9..0000000 --- a/gcc/testsuite/rust.test/nil-decl-in-foreign.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #901 -mod libc { - #[nolink] - extern { - pub fn printf(x: ()); - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/nil-pattern.rs b/gcc/testsuite/rust.test/nil-pattern.rs deleted file mode 100644 index 329590b..0000000 --- a/gcc/testsuite/rust.test/nil-pattern.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { let x = (); match x { () => { } } } diff --git a/gcc/testsuite/rust.test/no-std-xcrate.rs b/gcc/testsuite/rust.test/no-std-xcrate.rs deleted file mode 100644 index f69f53c..0000000 --- a/gcc/testsuite/rust.test/no-std-xcrate.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #9839 -// aux-build:no_std_crate.rs - -// This tests that crates which link to std can also be linked to crates with -// #[no_std] that have no lang items. - -extern mod no_std_crate; - -fn main() { - no_std_crate::foo(); -} diff --git a/gcc/testsuite/rust.test/no-std-xcrate2.rs b/gcc/testsuite/rust.test/no-std-xcrate2.rs deleted file mode 100644 index e393eb3..0000000 --- a/gcc/testsuite/rust.test/no-std-xcrate2.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test: this has weird linking problems on linux, and it probably needs a -// solution along the lines of disabling segmented stacks and/or the -// stack checks. -// aux-build:no_std_crate.rs - -// This tests that libraries built with #[no_std] can be linked to crates with -// #[no_std] and actually run. - -#[no_std]; - -extern mod no_std_crate; - -// This is an unfortunate thing to have to do on linux :( -#[cfg(target_os = "linux")] -#[doc(hidden)] -pub mod linkhack { - #[link_args="-lrustrt -lrt"] - extern {} -} - -#[start] -fn main(_: int, _: **u8, _: *u8) -> int { - no_std_crate::foo(); - 0 -} diff --git a/gcc/testsuite/rust.test/non-boolean-pure-fns.rs b/gcc/testsuite/rust.test/non-boolean-pure-fns.rs deleted file mode 100644 index ed54345..0000000 --- a/gcc/testsuite/rust.test/non-boolean-pure-fns.rs +++ /dev/null @@ -1,34 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use extra::list::{List, Cons, Nil, head, is_empty}; - -fn pure_length_go(ls: @List, acc: uint) -> uint { - match *ls { Nil => { acc } Cons(_, tl) => { pure_length_go(tl, acc + 1u) } } -} - -fn pure_length(ls: @List) -> uint { pure_length_go(ls, 0u) } - -fn nonempty_list(ls: @List) -> bool { pure_length(ls) > 0u } - -fn safe_head(ls: @List) -> T { - assert!(!is_empty(ls)); - return head(ls); -} - -pub fn main() { - let mylist = @Cons(@1u, @Nil); - assert!((nonempty_list(mylist))); - assert_eq!(*safe_head(mylist), 1u); -} diff --git a/gcc/testsuite/rust.test/non-legacy-modes.rs b/gcc/testsuite/rust.test/non-legacy-modes.rs deleted file mode 100644 index 642686e..0000000 --- a/gcc/testsuite/rust.test/non-legacy-modes.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct X { - repr: int -} - -fn apply(x: T, f: &fn(T)) { - f(x); -} - -fn check_int(x: int) { - assert_eq!(x, 22); -} - -fn check_struct(x: X) { - check_int(x.repr); -} - -pub fn main() { - apply(22, check_int); - apply(X {repr: 22}, check_struct); -} diff --git a/gcc/testsuite/rust.test/nul-characters.rs b/gcc/testsuite/rust.test/nul-characters.rs deleted file mode 100644 index 2a301d0..0000000 --- a/gcc/testsuite/rust.test/nul-characters.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() -{ - let all_nuls1 = "\0\x00\u0000\U00000000"; - let all_nuls2 = "\U00000000\u0000\x00\0"; - let all_nuls3 = "\u0000\U00000000\x00\0"; - let all_nuls4 = "\x00\u0000\0\U00000000"; - - // sizes for two should suffice - assert_eq!(all_nuls1.len(), 4); - assert_eq!(all_nuls2.len(), 4); - - // string equality should pass between the strings - assert_eq!(all_nuls1, all_nuls2); - assert_eq!(all_nuls2, all_nuls3); - assert_eq!(all_nuls3, all_nuls4); - - // all extracted characters in all_nuls are equivalent to each other - for c1 in all_nuls1.iter() - { - for c2 in all_nuls1.iter() - { - assert_eq!(c1,c2); - } - } - - // testing equality between explicit character literals - assert_eq!('\0', '\x00'); - assert_eq!('\u0000', '\x00'); - assert_eq!('\u0000', '\U00000000'); - - // NUL characters should make a difference - assert!("Hello World" != "Hello \0World"); - assert!("Hello World" != "Hello World\0"); -} diff --git a/gcc/testsuite/rust.test/nullable-pointer-iotareduction.rs b/gcc/testsuite/rust.test/nullable-pointer-iotareduction.rs deleted file mode 100644 index 62bd54e..0000000 --- a/gcc/testsuite/rust.test/nullable-pointer-iotareduction.rs +++ /dev/null @@ -1,90 +0,0 @@ -// xfail-test - -// xfail'd due to a bug in move detection for macros. - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::{option, cast}; - -// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, -// which "says that a destructor applied to an object built from a constructor -// behaves as expected". -- http://coq.inria.fr/doc/Reference-Manual006.html -// -// It's a little more complicated here, because of pointers and regions and -// trying to get assert failure messages that at least identify which case -// failed. - -enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } -impl E { - fn is_none(&self) -> bool { - match *self { - Thing(*) => false, - Nothing(*) => true - } - } - fn get_ref<'r>(&'r self) -> (int, &'r T) { - match *self { - Nothing(*) => fail!("E::get_ref(Nothing::<%s>)", stringify!($T)), - Thing(x, ref y) => (x, y) - } - } -} - -macro_rules! check_option { - ($e:expr: $T:ty) => {{ - check_option!($e: $T, |ptr| assert!(*ptr == $e)); - }}; - ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ - assert!(option::None::<$T>.is_none()); - let e = $e; - let s_ = option::Some::<$T>(e); - let $v = s_.get_ref(); - $chk - }} -} - -macro_rules! check_fancy { - ($e:expr: $T:ty) => {{ - check_fancy!($e: $T, |ptr| assert!(*ptr == $e)); - }}; - ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ - assert!(Nothing::<$T>((), ((), ()), [23i8, ..0]).is_none()); - let e = $e; - let t_ = Thing::<$T>(23, e); - match t_.get_ref() { - (23, $v) => { $chk } - _ => fail!("Thing::<%s>(23, %s).get_ref() != (23, _)", - stringify!($T), stringify!($e)) - } - }} -} - -macro_rules! check_type { - ($($a:tt)*) => {{ - check_option!($($a)*); - check_fancy!($($a)*); - }} -} - -pub fn main() { - check_type!(&17: &int); - check_type!(~18: ~int); - check_type!(@19: @int); - check_type!(~"foo": ~str); - check_type!(@"bar": @str); - check_type!(~[20, 22]: ~[int]); - check_type!(@[]: @[int]); - check_type!(@[24, 26]: @[int]); - let mint: uint = unsafe { cast::transmute(main) }; - check_type!(main: extern fn(), |pthing| { - assert!(mint == unsafe { cast::transmute(*pthing) }) - }); -} diff --git a/gcc/testsuite/rust.test/nullable-pointer-size.rs b/gcc/testsuite/rust.test/nullable-pointer-size.rs deleted file mode 100644 index 228b91a..0000000 --- a/gcc/testsuite/rust.test/nullable-pointer-size.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(macro_rules)]; - -use std::mem; - -enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } -struct S(int, T); - -// These are macros so we get useful assert messages. - -macro_rules! check_option { - ($T:ty) => { - assert_eq!(mem::size_of::>(), mem::size_of::<$T>()); - } -} - -macro_rules! check_fancy { - ($T:ty) => { - assert_eq!(mem::size_of::>(), mem::size_of::>()); - } -} - -macro_rules! check_type { - ($T:ty) => {{ - check_option!($T); - check_fancy!($T); - }} -} - -pub fn main() { - check_type!(&'static int); - check_type!(~int); - check_type!(@int); - check_type!(~str); - check_type!(@str); - check_type!(~[int]); - check_type!(@[int]); - check_type!(extern fn()); -} diff --git a/gcc/testsuite/rust.test/nullary-or-pattern.rs b/gcc/testsuite/rust.test/nullary-or-pattern.rs deleted file mode 100644 index 8e932c4..0000000 --- a/gcc/testsuite/rust.test/nullary-or-pattern.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum blah { a, b, } - -fn or_alt(q: blah) -> int { - match q { a | b => { 42 } } -} - -pub fn main() { - assert_eq!(or_alt(a), 42); - assert_eq!(or_alt(b), 42); -} diff --git a/gcc/testsuite/rust.test/numeric-method-autoexport.rs b/gcc/testsuite/rust.test/numeric-method-autoexport.rs deleted file mode 100644 index 1422f93..0000000 --- a/gcc/testsuite/rust.test/numeric-method-autoexport.rs +++ /dev/null @@ -1,41 +0,0 @@ -// xfail-pretty - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This file is intended to test only that methods are automatically -// reachable for each numeric type, for each exported impl, with no imports -// necessary. Testing the methods of the impls is done within the source -// file for each numeric type. -pub fn main() { -// ints - // num - assert_eq!(15i.add(&6), 21); - assert_eq!(15i8.add(&6i8), 21i8); - assert_eq!(15i16.add(&6i16), 21i16); - assert_eq!(15i32.add(&6i32), 21i32); - assert_eq!(15i64.add(&6i64), 21i64); - -// uints - // num - assert_eq!(15u.add(&6u), 21u); - assert_eq!(15u8.add(&6u8), 21u8); - assert_eq!(15u16.add(&6u16), 21u16); - assert_eq!(15u32.add(&6u32), 21u32); - assert_eq!(15u64.add(&6u64), 21u64); - - // times - 15u.times(|| {}); - -// floats - // num - assert_eq!(10f32.to_int().unwrap(), 10); - assert_eq!(10f64.to_int().unwrap(), 10); -} diff --git a/gcc/testsuite/rust.test/objects-coerce-freeze-borrored.rs b/gcc/testsuite/rust.test/objects-coerce-freeze-borrored.rs deleted file mode 100644 index 0bdc367..0000000 --- a/gcc/testsuite/rust.test/objects-coerce-freeze-borrored.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that we can coerce an `@Object` to an `&Object` - -trait Foo { - fn foo(&self) -> uint; - fn bar(&mut self) -> uint; -} - -impl Foo for uint { - fn foo(&self) -> uint { - *self - } - - fn bar(&mut self) -> uint { - *self += 1; - *self - } -} - -fn do_it_mut(obj: &mut Foo) { - let x = obj.bar(); - let y = obj.foo(); - assert_eq!(x, y); - - do_it_imm(obj, y); -} - -fn do_it_imm(obj: &Foo, v: uint) { - let y = obj.foo(); - assert_eq!(v, y); -} - -pub fn main() { - let mut x = 22_u; - let obj = &mut x as &mut Foo; - do_it_mut(obj); - do_it_imm(obj, 23u); - do_it_mut(obj); -} diff --git a/gcc/testsuite/rust.test/objects-coerce-from-managed-to-borrowed.rs b/gcc/testsuite/rust.test/objects-coerce-from-managed-to-borrowed.rs deleted file mode 100644 index 40c8548..0000000 --- a/gcc/testsuite/rust.test/objects-coerce-from-managed-to-borrowed.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that we can coerce an `@Object` to an `&Object` - -trait Foo { - fn foo(&self) -> uint; - fn bar(&mut self) -> uint; -} - -impl Foo for uint { - fn foo(&self) -> uint { - *self - } - - fn bar(&mut self) -> uint { - *self += 1; - *self - } -} - -fn do_it_mut(obj: &mut Foo) { - let x = obj.bar(); - let y = obj.foo(); - assert_eq!(x, y); -} - -fn do_it_imm(obj: &Foo, v: uint) { - let y = obj.foo(); - assert_eq!(v, y); -} - -pub fn main() { - let x = @mut 22u as @mut Foo; - do_it_mut(x); - do_it_imm(x, 23u); -} diff --git a/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-header.rs b/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-header.rs deleted file mode 100644 index baef209..0000000 --- a/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-header.rs +++ /dev/null @@ -1,41 +0,0 @@ -// xfail-pretty - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test invoked `&self` methods on owned objects where the values -// closed over contain managed values. This implies that the ~ boxes -// will have headers that must be skipped over. - -trait FooTrait { - fn foo(&self) -> uint; -} - -struct BarStruct { - x: @uint -} - -impl FooTrait for BarStruct { - fn foo(&self) -> uint { - *self.x - } -} - -pub fn main() { - let foos: ~[ ~FooTrait: ] = ~[ - ~BarStruct{ x: @0 } as ~FooTrait:, - ~BarStruct{ x: @1 } as ~FooTrait:, - ~BarStruct{ x: @2 } as ~FooTrait: - ]; - - for i in range(0u, foos.len()) { - assert_eq!(i, foos[i].foo()); - } -} diff --git a/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-headerless.rs b/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-headerless.rs deleted file mode 100644 index 72ae7cf..0000000 --- a/gcc/testsuite/rust.test/objects-owned-object-borrowed-method-headerless.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test invoked `&self` methods on owned objects where the values -// closed over do not contain managed values, and thus the ~ boxes do -// not have headers. - -trait FooTrait { - fn foo(&self) -> uint; -} - -struct BarStruct { - x: uint -} - -impl FooTrait for BarStruct { - fn foo(&self) -> uint { - self.x - } -} - -pub fn main() { - let foos: ~[ ~FooTrait ] = ~[ - ~BarStruct{ x: 0 } as ~FooTrait, - ~BarStruct{ x: 1 } as ~FooTrait, - ~BarStruct{ x: 2 } as ~FooTrait - ]; - - for i in range(0u, foos.len()) { - assert_eq!(i, foos[i].foo()); - } -} diff --git a/gcc/testsuite/rust.test/objects-owned-object-owned-method.rs b/gcc/testsuite/rust.test/objects-owned-object-owned-method.rs deleted file mode 100644 index 0d675c1..0000000 --- a/gcc/testsuite/rust.test/objects-owned-object-owned-method.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test invoked `&self` methods on owned objects where the values -// closed over contain managed values. This implies that the ~ boxes -// will have headers that must be skipped over. - -trait FooTrait { - fn foo(~self) -> uint; -} - -struct BarStruct { - x: uint -} - -impl FooTrait for BarStruct { - fn foo(~self) -> uint { - self.x - } -} - -pub fn main() { - let foo = ~BarStruct{ x: 22 } as ~FooTrait; - assert_eq!(22, foo.foo()); -} diff --git a/gcc/testsuite/rust.test/once-move-out-on-heap.rs b/gcc/testsuite/rust.test/once-move-out-on-heap.rs deleted file mode 100644 index 858f8ec..0000000 --- a/gcc/testsuite/rust.test/once-move-out-on-heap.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing guarantees provided by once functions. - -// xfail-fast - -#[feature(once_fns)]; -extern mod extra; -use extra::arc; -use std::util; - -fn foo(blk: ~once fn()) { - blk(); -} - -fn main() { - let x = arc::Arc::new(true); - do foo { - assert!(*x.get()); - util::ignore(x); - } -} diff --git a/gcc/testsuite/rust.test/once-move-out-on-stack.rs b/gcc/testsuite/rust.test/once-move-out-on-stack.rs deleted file mode 100644 index 8e34027..0000000 --- a/gcc/testsuite/rust.test/once-move-out-on-stack.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing guarantees provided by once functions. - -// xfail-fast - -#[feature(once_fns)]; -extern mod extra; -use extra::arc; -use std::util; - -fn foo(blk: &once fn()) { - blk(); -} - -fn main() { - let x = arc::Arc::new(true); - do foo { - assert!(*x.get()); - util::ignore(x); - } -} diff --git a/gcc/testsuite/rust.test/one-tuple.rs b/gcc/testsuite/rust.test/one-tuple.rs deleted file mode 100644 index 8377a45..0000000 --- a/gcc/testsuite/rust.test/one-tuple.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Why one-tuples? Because macros. - -pub fn main() { - match ('c',) { - (x,) => { - assert_eq!(x, 'c'); - } - } - // test the 1-tuple type too - let x: (char,) = ('d',); - let (y,) = x; - assert_eq!(y, 'd'); -} diff --git a/gcc/testsuite/rust.test/opeq.rs b/gcc/testsuite/rust.test/opeq.rs deleted file mode 100644 index 5172af1..0000000 --- a/gcc/testsuite/rust.test/opeq.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let mut x: int = 1; - x *= 2; - info2!("{}", x); - assert_eq!(x, 2); - x += 3; - info2!("{}", x); - assert_eq!(x, 5); - x *= x; - info2!("{}", x); - assert_eq!(x, 25); - x /= 5; - info2!("{}", x); - assert_eq!(x, 5); -} diff --git a/gcc/testsuite/rust.test/operator-associativity.rs b/gcc/testsuite/rust.test/operator-associativity.rs deleted file mode 100644 index bee6d23..0000000 --- a/gcc/testsuite/rust.test/operator-associativity.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// Testcase for issue #130, operator associativity. -pub fn main() { assert!((3 * 5 / 2 == 7)); } diff --git a/gcc/testsuite/rust.test/operator-overloading.rs b/gcc/testsuite/rust.test/operator-overloading.rs deleted file mode 100644 index 05aa1e7..0000000 --- a/gcc/testsuite/rust.test/operator-overloading.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -use std::cmp; -use std::ops; - -struct Point { - x: int, - y: int -} - -impl ops::Add for Point { - fn add(&self, other: &Point) -> Point { - Point {x: self.x + (*other).x, y: self.y + (*other).y} - } -} - -impl ops::Sub for Point { - fn sub(&self, other: &Point) -> Point { - Point {x: self.x - (*other).x, y: self.y - (*other).y} - } -} - -impl ops::Neg for Point { - fn neg(&self) -> Point { - Point {x: -self.x, y: -self.y} - } -} - -impl ops::Not for Point { - fn not(&self) -> Point { - Point {x: !self.x, y: !self.y } - } -} - -impl ops::Index for Point { - fn index(&self, x: &bool) -> int { - if *x { self.x } else { self.y } - } -} - -impl cmp::Eq for Point { - fn eq(&self, other: &Point) -> bool { - (*self).x == (*other).x && (*self).y == (*other).y - } - fn ne(&self, other: &Point) -> bool { !(*self).eq(other) } -} - -pub fn main() { - let mut p = Point {x: 10, y: 20}; - p = p + Point {x: 101, y: 102}; - p = p - Point {x: 100, y: 100}; - assert_eq!(p + Point {x: 5, y: 5}, Point {x: 16, y: 27}); - assert_eq!(-p, Point {x: -11, y: -22}); - assert_eq!(p[true], 11); - assert_eq!(p[false], 22); - - let q = !p; - assert_eq!(q.x, !(p.x)); - assert_eq!(q.y, !(p.y)); - - // Issue #1733 - let result: ~fn(int) = |_|(); - result(p[true]); -} diff --git a/gcc/testsuite/rust.test/option-ext.rs b/gcc/testsuite/rust.test/option-ext.rs deleted file mode 100644 index 343c4d7..0000000 --- a/gcc/testsuite/rust.test/option-ext.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let thing = ~"{{ f }}"; - let f = thing.find_str("{{"); - - if f.is_none() { - println("None!"); - } -} diff --git a/gcc/testsuite/rust.test/option-unwrap.rs b/gcc/testsuite/rust.test/option-unwrap.rs deleted file mode 100644 index 7c8872f..0000000 --- a/gcc/testsuite/rust.test/option-unwrap.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct dtor { - x: @mut int, - -} - -#[unsafe_destructor] -impl Drop for dtor { - fn drop(&mut self) { - // abuse access to shared mutable state to write this code - *self.x -= 1; - } -} - -fn unwrap(o: Option) -> T { - match o { - Some(v) => v, - None => fail2!() - } -} - -pub fn main() { - let x = @mut 1; - - { - let b = Some(dtor { x:x }); - let _c = unwrap(b); - } - - assert_eq!(*x, 0); -} diff --git a/gcc/testsuite/rust.test/or-pattern.rs b/gcc/testsuite/rust.test/or-pattern.rs deleted file mode 100644 index a014257..0000000 --- a/gcc/testsuite/rust.test/or-pattern.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum blah { a(int, int, uint), b(int, int), c, } - -fn or_alt(q: blah) -> int { - match q { a(x, y, _) | b(x, y) => { return x + y; } c => { return 0; } } -} - -pub fn main() { - assert_eq!(or_alt(c), 0); - assert_eq!(or_alt(a(10, 100, 0u)), 110); - assert_eq!(or_alt(b(20, 200)), 220); -} diff --git a/gcc/testsuite/rust.test/output-slot-variants.rs b/gcc/testsuite/rust.test/output-slot-variants.rs deleted file mode 100644 index 6939a4a..0000000 --- a/gcc/testsuite/rust.test/output-slot-variants.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -struct A { a: int, b: int } -struct Abox { a: @int, b: @int } - -fn ret_int_i() -> int { return 10; } - -fn ret_ext_i() -> @int { return @10; } - -fn ret_int_rec() -> A { return A {a: 10, b: 10}; } - -fn ret_ext_rec() -> @A { return @A {a: 10, b: 10}; } - -fn ret_ext_mem() -> Abox { return Abox {a: @10, b: @10}; } - -fn ret_ext_ext_mem() -> @Abox { return @Abox{a: @10, b: @10}; } - -pub fn main() { - let mut int_i: int; - let mut ext_i: @int; - let mut int_rec: A; - let mut ext_rec: @A; - let mut ext_mem: Abox; - let mut ext_ext_mem: @Abox; - int_i = ret_int_i(); // initializing - - int_i = ret_int_i(); // non-initializing - - int_i = ret_int_i(); // non-initializing - - ext_i = ret_ext_i(); // initializing - - ext_i = ret_ext_i(); // non-initializing - - ext_i = ret_ext_i(); // non-initializing - - int_rec = ret_int_rec(); // initializing - - int_rec = ret_int_rec(); // non-initializing - - int_rec = ret_int_rec(); // non-initializing - - ext_rec = ret_ext_rec(); // initializing - - ext_rec = ret_ext_rec(); // non-initializing - - ext_rec = ret_ext_rec(); // non-initializing - - ext_mem = ret_ext_mem(); // initializing - - ext_mem = ret_ext_mem(); // non-initializing - - ext_mem = ret_ext_mem(); // non-initializing - - ext_ext_mem = ret_ext_ext_mem(); // initializing - - ext_ext_mem = ret_ext_ext_mem(); // non-initializing - - ext_ext_mem = ret_ext_ext_mem(); // non-initializing - -} diff --git a/gcc/testsuite/rust.test/over-constrained-vregs.rs b/gcc/testsuite/rust.test/over-constrained-vregs.rs deleted file mode 100644 index 0fc56ce..0000000 --- a/gcc/testsuite/rust.test/over-constrained-vregs.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// Regression test for issue #152. -pub fn main() { - let mut b: uint = 1u; - while b <= 32u { - 0u << b; - b <<= 1u; - info2!("{:?}", b); - } -} diff --git a/gcc/testsuite/rust.test/overload-index-operator.rs b/gcc/testsuite/rust.test/overload-index-operator.rs deleted file mode 100644 index 8de802e..0000000 --- a/gcc/testsuite/rust.test/overload-index-operator.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test overloading of the `[]` operator. In particular test that it -// takes its argument *by reference*. - -use std::ops::Index; - -struct AssociationList { - pairs: ~[AssociationPair] -} - -#[deriving(Clone)] -struct AssociationPair { - key: K, - value: V -} - -impl AssociationList { - fn push(&mut self, key: K, value: V) { - self.pairs.push(AssociationPair {key: key, value: value}); - } -} - -impl Index for AssociationList { - fn index(&self, index: &K) -> V { - for pair in self.pairs.iter() { - if pair.key == *index { - return pair.value.clone(); - } - } - fail2!("No value found for key: {:?}", index); - } -} - -pub fn main() { - let foo = ~"foo"; - let bar = ~"bar"; - - let mut list = AssociationList {pairs: ~[]}; - list.push(foo.clone(), 22); - list.push(bar.clone(), 44); - - assert!(list[foo] == 22) - assert!(list[bar] == 44) - - assert!(list[foo] == 22) - assert!(list[bar] == 44) -} diff --git a/gcc/testsuite/rust.test/owned-implies-static.rs b/gcc/testsuite/rust.test/owned-implies-static.rs deleted file mode 100644 index f327f6b..0000000 --- a/gcc/testsuite/rust.test/owned-implies-static.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(_x: T) {} - -pub fn main() { - f(~5); -} diff --git a/gcc/testsuite/rust.test/packed-struct-borrow-element.rs b/gcc/testsuite/rust.test/packed-struct-borrow-element.rs deleted file mode 100644 index 1434e1d..0000000 --- a/gcc/testsuite/rust.test/packed-struct-borrow-element.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[packed] -struct Foo { - bar: u8, - baz: uint -} - -pub fn main() { - let foo = Foo { bar: 1, baz: 2 }; - let brw = &foo.baz; - - assert_eq!(*brw, 2); -} diff --git a/gcc/testsuite/rust.test/packed-struct-generic-layout.rs b/gcc/testsuite/rust.test/packed-struct-generic-layout.rs deleted file mode 100644 index 91b4994..0000000 --- a/gcc/testsuite/rust.test/packed-struct-generic-layout.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; - -#[packed] -struct S { - a: T, - b: u8, - c: S -} - -pub fn main() { - unsafe { - let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 }; - let transd : [u8, .. 9] = cast::transmute(s); - // Don't worry about endianness, the numbers are palindromic. - assert_eq!(transd, - [0xff, 0xff, 0xff, 0xff, - 1, - 0xaa, 0xaa, 0xaa, 0xaa]); - - - let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16}; - let transd : [u8, .. 4] = cast::transmute(s); - // Again, no endianness problems. - assert_eq!(transd, - [1, 2, 0b10000001, 0b10000001]); - } -} diff --git a/gcc/testsuite/rust.test/packed-struct-generic-size.rs b/gcc/testsuite/rust.test/packed-struct-generic-size.rs deleted file mode 100644 index 1d3d8cf..0000000 --- a/gcc/testsuite/rust.test/packed-struct-generic-size.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -#[packed] -struct S { - a: T, - b: u8, - c: S -} - -pub fn main() { - assert_eq!(mem::size_of::>(), 3); - - assert_eq!(mem::size_of::>(), 11); - - assert_eq!(mem::size_of::>(), - 1 + mem::size_of::<~str>() + mem::size_of::<@mut [int]>()); -} diff --git a/gcc/testsuite/rust.test/packed-struct-layout.rs b/gcc/testsuite/rust.test/packed-struct-layout.rs deleted file mode 100644 index f361db4..0000000 --- a/gcc/testsuite/rust.test/packed-struct-layout.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; - -#[packed] -struct S4 { - a: u8, - b: [u8, .. 3], -} - -#[packed] -struct S5 { - a: u8, - b: u32 -} - -pub fn main() { - unsafe { - let s4 = S4 { a: 1, b: [2,3,4] }; - let transd : [u8, .. 4] = cast::transmute(s4); - assert_eq!(transd, [1, 2, 3, 4]); - - let s5 = S5 { a: 1, b: 0xff_00_00_ff }; - let transd : [u8, .. 5] = cast::transmute(s5); - // Don't worry about endianness, the u32 is palindromic. - assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); - } -} diff --git a/gcc/testsuite/rust.test/packed-struct-match.rs b/gcc/testsuite/rust.test/packed-struct-match.rs deleted file mode 100644 index 27ab2c8..0000000 --- a/gcc/testsuite/rust.test/packed-struct-match.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[packed] -struct Foo { - bar: u8, - baz: uint -} - -pub fn main() { - let foo = Foo { bar: 1, baz: 2 }; - match foo { - Foo {bar, baz} => { - assert_eq!(bar, 1); - assert_eq!(baz, 2); - } - } -} diff --git a/gcc/testsuite/rust.test/packed-struct-size-xc.rs b/gcc/testsuite/rust.test/packed-struct-size-xc.rs deleted file mode 100644 index 5b4426d..0000000 --- a/gcc/testsuite/rust.test/packed-struct-size-xc.rs +++ /dev/null @@ -1,10 +0,0 @@ -// xfail-fast -// aux-build:packed.rs - -extern mod packed; - -use std::mem; - -fn main() { - assert_eq!(mem::size_of::(), 5); -} diff --git a/gcc/testsuite/rust.test/packed-struct-size.rs b/gcc/testsuite/rust.test/packed-struct-size.rs deleted file mode 100644 index cc4cb99..0000000 --- a/gcc/testsuite/rust.test/packed-struct-size.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -#[packed] -struct S4 { - a: u8, - b: [u8, .. 3], -} - -#[packed] -struct S5 { - a: u8, - b: u32 -} - -#[packed] -struct S13_str { - a: i64, - b: f32, - c: u8, - d: ~str -} - -enum Foo { - Bar = 1, - Baz = 2 -} - -#[packed] -struct S3_Foo { - a: u8, - b: u16, - c: Foo -} - -#[packed] -struct S7_Option { - a: f32, - b: u8, - c: u16, - d: Option<@mut f64> -} - -// Placing packed structs in statics should work -static TEST_S4: S4 = S4 { a: 1, b: [2, 3, 4] }; -static TEST_S5: S5 = S5 { a: 3, b: 67 }; -static TEST_S3_Foo: S3_Foo = S3_Foo { a: 1, b: 2, c: Baz }; - - -pub fn main() { - assert_eq!(mem::size_of::(), 4); - assert_eq!(mem::size_of::(), 5); - assert_eq!(mem::size_of::(), 13 + mem::size_of::<~str>()); - assert_eq!(mem::size_of::(), 3 + mem::size_of::()); - assert_eq!(mem::size_of::(), 7 + mem::size_of::>()); -} diff --git a/gcc/testsuite/rust.test/packed-struct-vec.rs b/gcc/testsuite/rust.test/packed-struct-vec.rs deleted file mode 100644 index 6007cc2..0000000 --- a/gcc/testsuite/rust.test/packed-struct-vec.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-android: FIXME(#9116) Bus error - -use std::mem; - -#[packed] -#[deriving(Eq)] -struct Foo { - bar: u8, - baz: u64 -} - -pub fn main() { - let foos = [Foo { bar: 1, baz: 2 }, .. 10]; - - assert_eq!(mem::size_of::<[Foo, .. 10]>(), 90); - - for i in range(0u, 10) { - assert_eq!(foos[i], Foo { bar: 1, baz: 2}); - } - - for &foo in foos.iter() { - assert_eq!(foo, Foo { bar: 1, baz: 2 }); - } -} diff --git a/gcc/testsuite/rust.test/packed-tuple-struct-layout.rs b/gcc/testsuite/rust.test/packed-tuple-struct-layout.rs deleted file mode 100644 index b3261fa..0000000 --- a/gcc/testsuite/rust.test/packed-tuple-struct-layout.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; - -#[packed] -struct S4(u8,[u8, .. 3]); - -#[packed] -struct S5(u8,u32); - -pub fn main() { - unsafe { - let s4 = S4(1, [2,3,4]); - let transd : [u8, .. 4] = cast::transmute(s4); - assert_eq!(transd, [1, 2, 3, 4]); - - let s5 = S5(1, 0xff_00_00_ff); - let transd : [u8, .. 5] = cast::transmute(s5); - // Don't worry about endianness, the u32 is palindromic. - assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); - } -} diff --git a/gcc/testsuite/rust.test/packed-tuple-struct-size.rs b/gcc/testsuite/rust.test/packed-tuple-struct-size.rs deleted file mode 100644 index 76362ff..0000000 --- a/gcc/testsuite/rust.test/packed-tuple-struct-size.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -#[packed] -struct S4(u8,[u8, .. 3]); - -#[packed] -struct S5(u8, u32); - -#[packed] -struct S13_str(i64, f32, u8, ~str); - -enum Foo { - Bar = 1, - Baz = 2 -} - -#[packed] -struct S3_Foo(u8, u16, Foo); - -#[packed] -struct S7_Option(f32, u8, u16, Option<@mut f64>); - -pub fn main() { - assert_eq!(mem::size_of::(), 4); - - assert_eq!(mem::size_of::(), 5); - - assert_eq!(mem::size_of::(), - 13 + mem::size_of::<~str>()); - - assert_eq!(mem::size_of::(), - 3 + mem::size_of::()); - - assert_eq!(mem::size_of::(), - 7 + mem::size_of::>()); -} diff --git a/gcc/testsuite/rust.test/paren-free.rs b/gcc/testsuite/rust.test/paren-free.rs deleted file mode 100644 index 29789f3..0000000 --- a/gcc/testsuite/rust.test/paren-free.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = true; - if x { let mut i = 10; while i > 0 { i -= 1; } } - match x { true => { info2!("right"); } false => { info2!("wrong"); } } -} diff --git a/gcc/testsuite/rust.test/parse-fail.rs b/gcc/testsuite/rust.test/parse-fail.rs deleted file mode 100644 index 7d4a74f..0000000 --- a/gcc/testsuite/rust.test/parse-fail.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unreachable_code)]; - -// -*- rust -*- -fn dont_call_me() { fail2!(); info2!("{}", 1); } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/pass-by-copy.rs b/gcc/testsuite/rust.test/pass-by-copy.rs deleted file mode 100644 index a9cfd3a..0000000 --- a/gcc/testsuite/rust.test/pass-by-copy.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn magic(x: A) { info2!("{:?}", x); } -fn magic2(x: @int) { info2!("{:?}", x); } - -struct A { a: @int } - -pub fn main() { - let a = A {a: @10}; - let b = @10; - magic(a); magic(A {a: @20}); - magic2(b); magic2(@20); -} diff --git a/gcc/testsuite/rust.test/path.rs b/gcc/testsuite/rust.test/path.rs deleted file mode 100644 index 44953c4..0000000 --- a/gcc/testsuite/rust.test/path.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -mod foo { - pub fn bar(_offset: uint) { } -} - -pub fn main() { foo::bar(0u); } diff --git a/gcc/testsuite/rust.test/pattern-bound-var-in-for-each.rs b/gcc/testsuite/rust.test/pattern-bound-var-in-for-each.rs deleted file mode 100644 index fde1999..0000000 --- a/gcc/testsuite/rust.test/pattern-bound-var-in-for-each.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that trans_path checks whether a -// pattern-bound var is an upvar (when translating -// the for-each body) - -fn foo(src: uint) { - - match Some(src) { - Some(src_id) => { - for _i in range(0u, 10u) { - let yyy = src_id; - assert_eq!(yyy, 0u); - } - } - _ => { } - } -} - -pub fn main() { foo(0u); } diff --git a/gcc/testsuite/rust.test/pattern-in-closure.rs b/gcc/testsuite/rust.test/pattern-in-closure.rs deleted file mode 100644 index b6cb7f4..0000000 --- a/gcc/testsuite/rust.test/pattern-in-closure.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int, - y: int -} - -pub fn main() { - let f = |(x, _): (int, int)| println((x + 1).to_str()); - let g = |Foo { x: x, y: _y }: Foo| println((x + 1).to_str()); - f((2, 3)); - g(Foo { x: 1, y: 2 }); -} diff --git a/gcc/testsuite/rust.test/placement-new-arena.rs b/gcc/testsuite/rust.test/placement-new-arena.rs deleted file mode 100644 index 238ea74..0000000 --- a/gcc/testsuite/rust.test/placement-new-arena.rs +++ /dev/null @@ -1,22 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; -use extra::arena::Arena; - -pub fn main() { - let mut arena = Arena::new(); - let p = &mut arena; - let x = p.alloc(|| 4u); - println!("{}", *x); - assert_eq!(*x, 4u); -} diff --git a/gcc/testsuite/rust.test/pred-not-bool.rs b/gcc/testsuite/rust.test/pred-not-bool.rs deleted file mode 100644 index 15bf05f..0000000 --- a/gcc/testsuite/rust.test/pred-not-bool.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// this checks that a pred with a non-bool return -// type is rejected, even if the pred is never used - -fn bad(_a: int) -> int { return 37; } //~ ERROR Non-boolean return type - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/preempt.rs b/gcc/testsuite/rust.test/preempt.rs deleted file mode 100644 index f34cc26..0000000 --- a/gcc/testsuite/rust.test/preempt.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// This checks that preemption works. - -// note: halfway done porting to modern rust -extern mod extra; - -use std::comm; -use extra::comm; - -fn starve_main(alive: Port) { - info!("signalling main"); - alive.recv(); - info!("starving main"); - let mut i: int = 0; - loop { i += 1; } -} - -pub fn main() { - let (port, chan) = stream(); - - info!("main started"); - do spawn { - starve_main(port); - }; - let mut i: int = 0; - info!("main waiting for alive signal"); - chan.send(i); - info!("main got alive signal"); - while i < 50 { info!("main iterated"); i += 1; } - info!("main completed"); -} diff --git a/gcc/testsuite/rust.test/privacy1.rs b/gcc/testsuite/rust.test/privacy1.rs deleted file mode 100644 index 7a07c97..0000000 --- a/gcc/testsuite/rust.test/privacy1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub mod test2 { - // This used to generate an ICE (make sure that default functions are - // parented to their trait to find the first private thing as the trait). - - struct B; - trait A { fn foo(&self) {} } - impl A for B {} - - mod tests { - use super::A; - fn foo() { - let a = super::B; - a.foo(); - } - } -} - - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/private-class-field.rs b/gcc/testsuite/rust.test/private-class-field.rs deleted file mode 100644 index 868cbbf..0000000 --- a/gcc/testsuite/rust.test/private-class-field.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn meow_count(&mut self) -> uint { self.meows } -} - -fn cat(in_x : uint, in_y : int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan : cat = cat(52u, 99); - assert_eq!(nyan.meow_count(), 52u); -} diff --git a/gcc/testsuite/rust.test/private-method.rs b/gcc/testsuite/rust.test/private-method.rs deleted file mode 100644 index 8b2b5bf..0000000 --- a/gcc/testsuite/rust.test/private-method.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn play(&mut self) { - self.meows += 1u; - self.nap(); - } -} - -impl cat { - fn nap(&mut self) { for _ in range(1u, 10u) { } } -} - -fn cat(in_x : uint, in_y : int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan : cat = cat(52u, 99); - nyan.play(); -} diff --git a/gcc/testsuite/rust.test/pub-extern-privacy.rs b/gcc/testsuite/rust.test/pub-extern-privacy.rs deleted file mode 100644 index e4e260a..0000000 --- a/gcc/testsuite/rust.test/pub-extern-privacy.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::cast::transmute; - -mod a { - extern { - pub fn free(x: *u8); - } -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - a::free(transmute(0)); - } -} diff --git a/gcc/testsuite/rust.test/pub-use-xcrate.rs b/gcc/testsuite/rust.test/pub-use-xcrate.rs deleted file mode 100644 index ca1290d..0000000 --- a/gcc/testsuite/rust.test/pub-use-xcrate.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:pub_use_xcrate1.rs -// aux-build:pub_use_xcrate2.rs - -extern mod pub_use_xcrate2; - -use pub_use_xcrate2::Foo; - -pub fn main() { - let _foo: Foo = Foo { - name: 0 - }; -} diff --git a/gcc/testsuite/rust.test/pub_use_mods_xcrate_exe.rs b/gcc/testsuite/rust.test/pub_use_mods_xcrate_exe.rs deleted file mode 100644 index ada6cac..0000000 --- a/gcc/testsuite/rust.test/pub_use_mods_xcrate_exe.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:pub_use_mods_xcrate.rs - -#[allow(unused_imports)]; - -extern mod pub_use_mods_xcrate; -use pub_use_mods_xcrate::a::c; - -pub fn main(){} diff --git a/gcc/testsuite/rust.test/pure-sum.rs b/gcc/testsuite/rust.test/pure-sum.rs deleted file mode 100644 index 17eab78..0000000 --- a/gcc/testsuite/rust.test/pure-sum.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that functions can modify local state. - -fn sums_to(v: ~[int], sum: int) -> bool { - let mut i = 0u; - let mut sum0 = 0; - while i < v.len() { - sum0 += v[i]; - i += 1u; - } - return sum0 == sum; -} - -fn sums_to_using_uniq(v: ~[int], sum: int) -> bool { - let mut i = 0u; - let mut sum0 = ~0; - while i < v.len() { - *sum0 += v[i]; - i += 1u; - } - return *sum0 == sum; -} - -fn sums_to_using_rec(v: ~[int], sum: int) -> bool { - let mut i = 0u; - let mut sum0 = F {f: 0}; - while i < v.len() { - sum0.f += v[i]; - i += 1u; - } - return sum0.f == sum; -} - -struct F { f: T } - -fn sums_to_using_uniq_rec(v: ~[int], sum: int) -> bool { - let mut i = 0u; - let mut sum0 = F {f: ~0}; - while i < v.len() { - *sum0.f += v[i]; - i += 1u; - } - return *sum0.f == sum; -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/purity-infer.rs b/gcc/testsuite/rust.test/purity-infer.rs deleted file mode 100644 index 030df6b..0000000 --- a/gcc/testsuite/rust.test/purity-infer.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -fn something(f: &fn()) { f(); } -pub fn main() { - something(|| error2!("hi!") ); -} diff --git a/gcc/testsuite/rust.test/raw-str.rs b/gcc/testsuite/rust.test/raw-str.rs deleted file mode 100644 index bfe5326..0000000 Binary files a/gcc/testsuite/rust.test/raw-str.rs and /dev/null differ diff --git a/gcc/testsuite/rust.test/rcvr-borrowed-to-region.rs b/gcc/testsuite/rust.test/rcvr-borrowed-to-region.rs deleted file mode 100644 index 376a149..0000000 --- a/gcc/testsuite/rust.test/rcvr-borrowed-to-region.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait get { - fn get(self) -> int; -} - -// Note: impl on a slice; we're checking that the pointers below -// correctly get borrowed to `&`. (similar to impling for `int`, with -// `&self` instead of `self`.) -impl<'self> get for &'self int { - fn get(self) -> int { - return *self; - } -} - -pub fn main() { - let x = @mut 6; - let y = x.get(); - assert_eq!(y, 6); - - let x = @6; - let y = x.get(); - info2!("y={}", y); - assert_eq!(y, 6); - - let x = ~6; - let y = x.get(); - info2!("y={}", y); - assert_eq!(y, 6); - - let x = &6; - let y = x.get(); - info2!("y={}", y); - assert_eq!(y, 6); -} diff --git a/gcc/testsuite/rust.test/rcvr-borrowed-to-slice.rs b/gcc/testsuite/rust.test/rcvr-borrowed-to-slice.rs deleted file mode 100644 index 1f1b9d3..0000000 --- a/gcc/testsuite/rust.test/rcvr-borrowed-to-slice.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait sum { - fn sum_(self) -> int; -} - -// Note: impl on a slice -impl<'self> sum for &'self [int] { - fn sum_(self) -> int { - self.iter().fold(0, |a, &b| a + b) - } -} - -fn call_sum(x: &[int]) -> int { x.sum_() } - -pub fn main() { - let x = ~[1, 2, 3]; - let y = call_sum(x); - info2!("y=={}", y); - assert_eq!(y, 6); - - let x = ~[1, 2, 3]; - let y = x.sum_(); - info2!("y=={}", y); - assert_eq!(y, 6); - - let x = ~[1, 2, 3]; - let y = x.sum_(); - info2!("y=={}", y); - assert_eq!(y, 6); -} diff --git a/gcc/testsuite/rust.test/readalias.rs b/gcc/testsuite/rust.test/readalias.rs deleted file mode 100644 index 7447073..0000000 --- a/gcc/testsuite/rust.test/readalias.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -struct Point {x: int, y: int, z: int} - -fn f(p: Point) { assert!((p.z == 12)); } - -pub fn main() { let x: Point = Point {x: 10, y: 11, z: 12}; f(x); } diff --git a/gcc/testsuite/rust.test/rec-align-u32.rs b/gcc/testsuite/rust.test/rec-align-u32.rs deleted file mode 100644 index 43304b6..0000000 --- a/gcc/testsuite/rust.test/rec-align-u32.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -// Issue #2303 - -use std::mem; - -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; - } -} - -// This is the type with the questionable alignment -struct Inner { - c64: u32 -} - -// This is the type that contains the type with the -// questionable alignment, for testing -struct Outer { - c8: u8, - t: Inner -} - - -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "arm")] -mod m { - pub fn align() -> uint { 4u } - pub fn size() -> uint { 8u } -} - -#[cfg(target_arch = "x86_64")] -mod m { - pub fn align() -> uint { 4u } - pub fn size() -> uint { 8u } -} - -pub fn main() { - unsafe { - let x = Outer {c8: 22u8, t: Inner {c64: 44u32}}; - - // Send it through the shape code - let y = format!("{:?}", x); - - info2!("align inner = {:?}", rusti::min_align_of::()); - info2!("size outer = {:?}", mem::size_of::()); - info2!("y = {}", y); - - // per clang/gcc the alignment of `inner` is 4 on x86. - assert_eq!(rusti::min_align_of::(), m::align()); - - // per clang/gcc the size of `outer` should be 12 - // because `inner`s alignment was 4. - assert_eq!(mem::size_of::(), m::size()); - - assert_eq!(y, ~"Outer{c8: 22u8, t: Inner{c64: 44u32}}"); - } -} diff --git a/gcc/testsuite/rust.test/rec-align-u64.rs b/gcc/testsuite/rust.test/rec-align-u64.rs deleted file mode 100644 index 5adb8cf..0000000 --- a/gcc/testsuite/rust.test/rec-align-u64.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -// Issue #2303 - -use std::mem; - -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; - } -} - -// This is the type with the questionable alignment -struct Inner { - c64: u64 -} - -// This is the type that contains the type with the -// questionable alignment, for testing -struct Outer { - c8: u8, - t: Inner -} - - -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -mod m { - #[cfg(target_arch = "x86")] - pub mod m { - pub fn align() -> uint { 4u } - pub fn size() -> uint { 12u } - } - - #[cfg(target_arch = "x86_64")] - pub mod m { - pub fn align() -> uint { 8u } - pub fn size() -> uint { 16u } - } -} - -#[cfg(target_os = "win32")] -mod m { - #[cfg(target_arch = "x86")] - pub mod m { - pub fn align() -> uint { 8u } - pub fn size() -> uint { 16u } - } -} - -#[cfg(target_os = "android")] -mod m { - #[cfg(target_arch = "arm")] - pub mod m { - pub fn align() -> uint { 8u } - pub fn size() -> uint { 16u } - } -} - -pub fn main() { - unsafe { - let x = Outer {c8: 22u8, t: Inner {c64: 44u64}}; - - // Send it through the shape code - let y = format!("{:?}", x); - - info2!("align inner = {}", rusti::min_align_of::()); - info2!("size outer = {}", mem::size_of::()); - info2!("y = {}", y); - - // per clang/gcc the alignment of `Inner` is 4 on x86. - assert_eq!(rusti::min_align_of::(), m::m::align()); - - // per clang/gcc the size of `Outer` should be 12 - // because `Inner`s alignment was 4. - assert_eq!(mem::size_of::(), m::m::size()); - - assert_eq!(y, ~"Outer{c8: 22u8, t: Inner{c64: 44u64}}"); - } -} diff --git a/gcc/testsuite/rust.test/rec-auto.rs b/gcc/testsuite/rust.test/rec-auto.rs deleted file mode 100644 index 086d03a..0000000 --- a/gcc/testsuite/rust.test/rec-auto.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Issue #50. - -struct X { foo: ~str, bar: ~str } - -pub fn main() { - let x = X {foo: ~"hello", bar: ~"world"}; - info2!("{}", x.foo.clone()); - info2!("{}", x.bar.clone()); -} diff --git a/gcc/testsuite/rust.test/rec-extend.rs b/gcc/testsuite/rust.test/rec-extend.rs deleted file mode 100644 index 4e029be..0000000 --- a/gcc/testsuite/rust.test/rec-extend.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -struct Point {x: int, y: int} - -pub fn main() { - let origin: Point = Point {x: 0, y: 0}; - let right: Point = Point {x: origin.x + 10,.. origin}; - let up: Point = Point {y: origin.y + 10,.. origin}; - assert_eq!(origin.x, 0); - assert_eq!(origin.y, 0); - assert_eq!(right.x, 10); - assert_eq!(right.y, 0); - assert_eq!(up.x, 0); - assert_eq!(up.y, 10); -} diff --git a/gcc/testsuite/rust.test/rec-tup.rs b/gcc/testsuite/rust.test/rec-tup.rs deleted file mode 100644 index fb5c5f3..0000000 --- a/gcc/testsuite/rust.test/rec-tup.rs +++ /dev/null @@ -1,37 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Point {x: int, y: int} - -type rect = (Point, Point); - -fn fst(r: rect) -> Point { let (fst, _) = r; return fst; } -fn snd(r: rect) -> Point { let (_, snd) = r; return snd; } - -fn f(r: rect, x1: int, y1: int, x2: int, y2: int) { - assert_eq!(fst(r).x, x1); - assert_eq!(fst(r).y, y1); - assert_eq!(snd(r).x, x2); - assert_eq!(snd(r).y, y2); -} - -pub fn main() { - let r: rect = (Point {x: 10, y: 20}, Point {x: 11, y: 22}); - assert_eq!(fst(r).x, 10); - assert_eq!(fst(r).y, 20); - assert_eq!(snd(r).x, 11); - assert_eq!(snd(r).y, 22); - let r2 = r; - let x: int = fst(r2).x; - assert_eq!(x, 10); - f(r, 10, 20, 11, 22); - f(r2, 10, 20, 11, 22); -} diff --git a/gcc/testsuite/rust.test/rec.rs b/gcc/testsuite/rust.test/rec.rs deleted file mode 100644 index fa3fa01..0000000 --- a/gcc/testsuite/rust.test/rec.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -struct Rect {x: int, y: int, w: int, h: int} - -fn f(r: Rect, x: int, y: int, w: int, h: int) { - assert_eq!(r.x, x); - assert_eq!(r.y, y); - assert_eq!(r.w, w); - assert_eq!(r.h, h); -} - -pub fn main() { - let r: Rect = Rect {x: 10, y: 20, w: 100, h: 200}; - assert_eq!(r.x, 10); - assert_eq!(r.y, 20); - assert_eq!(r.w, 100); - assert_eq!(r.h, 200); - let r2: Rect = r; - let x: int = r2.x; - assert_eq!(x, 10); - f(r, 10, 20, 100, 200); - f(r2, 10, 20, 100, 200); -} diff --git a/gcc/testsuite/rust.test/record-pat.rs b/gcc/testsuite/rust.test/record-pat.rs deleted file mode 100644 index d1b15b9..0000000 --- a/gcc/testsuite/rust.test/record-pat.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum t1 { a(int), b(uint), } -struct T2 {x: t1, y: int} -enum t3 { c(T2, uint), } - -fn m(input: t3) -> int { - match input { - c(T2 {x: a(m), _}, _) => { return m; } - c(T2 {x: b(m), y: y}, z) => { return ((m + z) as int) + y; } - } -} - -pub fn main() { - assert_eq!(m(c(T2 {x: a(10), y: 5}, 4u)), 10); - assert_eq!(m(c(T2 {x: b(10u), y: 5}, 4u)), 19); -} diff --git a/gcc/testsuite/rust.test/recursion.rs b/gcc/testsuite/rust.test/recursion.rs deleted file mode 100644 index 5ecd09f..0000000 --- a/gcc/testsuite/rust.test/recursion.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -enum Nil {Nil} -struct Cons {head:int, tail:T} -trait Dot {fn dot(other:self) -> int;} -impl Dot for Nil { - fn dot(_:Nil) -> int {0} -} -impl Dot for Cons { - fn dot(other:Cons) -> int { - self.head * other.head + self.tail.dot(other.tail) - } -} -fn test (n:int, i:int, first:T, second:T) ->int { - match n { - 0 => {first.dot(second)} - // Error message should be here. It should be a type error - // to instantiate `test` at a type other than T. (See #4287) - _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} - } -} -pub fn main() { - let n = test(1, 0, Nil, Nil); - println!("{}", n); -} diff --git a/gcc/testsuite/rust.test/reexport-should-still-link.rs b/gcc/testsuite/rust.test/reexport-should-still-link.rs deleted file mode 100644 index ed5c394..0000000 --- a/gcc/testsuite/rust.test/reexport-should-still-link.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:reexport-should-still-link.rs -// xfail-fast windows doesn't like extern mod - -extern mod foo(name = "reexport-should-still-link"); - -fn main() { - foo::bar(); -} diff --git a/gcc/testsuite/rust.test/reexport-star.rs b/gcc/testsuite/rust.test/reexport-star.rs deleted file mode 100644 index df1df36..0000000 --- a/gcc/testsuite/rust.test/reexport-star.rs +++ /dev/null @@ -1,29 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -// FIXME #3654 - -mod a { - pub fn f() {} - pub fn g() {} -} - -mod b { - pub use a::*; -} - -pub fn main() { - b::f(); - b::g(); -} diff --git a/gcc/testsuite/rust.test/reexported-static-methods-cross-crate.rs b/gcc/testsuite/rust.test/reexported-static-methods-cross-crate.rs deleted file mode 100644 index e8e58d7..0000000 --- a/gcc/testsuite/rust.test/reexported-static-methods-cross-crate.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:reexported_static_methods.rs -extern mod reexported_static_methods; - -use reexported_static_methods::Foo; -use reexported_static_methods::Baz; -use reexported_static_methods::Boz; -use reexported_static_methods::Bort; - -pub fn main() { - assert_eq!(42, Foo::foo()); - assert_eq!(84, Baz::bar()); - assert!(Boz::boz(1)); - assert_eq!(~"bort()", Bort::bort()); -} diff --git a/gcc/testsuite/rust.test/reflect-visit-data.rs b/gcc/testsuite/rust.test/reflect-visit-data.rs deleted file mode 100644 index 5a2243b..0000000 --- a/gcc/testsuite/rust.test/reflect-visit-data.rs +++ /dev/null @@ -1,648 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -use std::libc::c_void; -use std::ptr; -use std::mem; -use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque}; -use std::unstable::raw::Vec; - -#[doc = "High-level interfaces to `std::unstable::intrinsics::visit_ty` reflection system."] - -/// Trait for visitor that wishes to reflect on data. -trait movable_ptr { - fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void); -} - -/// Helper function for alignment calculation. -#[inline(always)] -fn align(size: uint, align: uint) -> uint { - ((size + align) - 1u) & !(align - 1u) -} - -struct ptr_visit_adaptor(Inner); - -impl ptr_visit_adaptor { - - #[inline(always)] - pub fn bump(&mut self, sz: uint) { - do self.inner.move_ptr() |p| { - ((p as uint) + sz) as *c_void - }; - } - - #[inline(always)] - pub fn align(&mut self, a: uint) { - do self.inner.move_ptr() |p| { - align(p as uint, a) as *c_void - }; - } - - #[inline(always)] - pub fn align_to(&mut self) { - self.align(mem::min_align_of::()); - } - - #[inline(always)] - pub fn bump_past(&mut self) { - self.bump(mem::size_of::()); - } - -} - -impl TyVisitor for ptr_visit_adaptor { - - fn visit_bot(&mut self) -> bool { - self.align_to::<()>(); - if ! self.inner.visit_bot() { return false; } - self.bump_past::<()>(); - true - } - - fn visit_nil(&mut self) -> bool { - self.align_to::<()>(); - if ! self.inner.visit_nil() { return false; } - self.bump_past::<()>(); - true - } - - fn visit_bool(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_bool() { return false; } - self.bump_past::(); - true - } - - fn visit_int(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_int() { return false; } - self.bump_past::(); - true - } - - fn visit_i8(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_i8() { return false; } - self.bump_past::(); - true - } - - fn visit_i16(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_i16() { return false; } - self.bump_past::(); - true - } - - fn visit_i32(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_i32() { return false; } - self.bump_past::(); - true - } - - fn visit_i64(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_i64() { return false; } - self.bump_past::(); - true - } - - fn visit_uint(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_uint() { return false; } - self.bump_past::(); - true - } - - fn visit_u8(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_u8() { return false; } - self.bump_past::(); - true - } - - fn visit_u16(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_u16() { return false; } - self.bump_past::(); - true - } - - fn visit_u32(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_u32() { return false; } - self.bump_past::(); - true - } - - fn visit_u64(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_u64() { return false; } - self.bump_past::(); - true - } - - fn visit_f32(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_f32() { return false; } - self.bump_past::(); - true - } - - fn visit_f64(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_f64() { return false; } - self.bump_past::(); - true - } - - fn visit_char(&mut self) -> bool { - self.align_to::(); - if ! self.inner.visit_char() { return false; } - self.bump_past::(); - true - } - - fn visit_estr_box(&mut self) -> bool { - self.align_to::<@str>(); - if ! self.inner.visit_estr_box() { return false; } - self.bump_past::<@str>(); - true - } - - fn visit_estr_uniq(&mut self) -> bool { - self.align_to::<~str>(); - if ! self.inner.visit_estr_uniq() { return false; } - self.bump_past::<~str>(); - true - } - - fn visit_estr_slice(&mut self) -> bool { - self.align_to::<&'static str>(); - if ! self.inner.visit_estr_slice() { return false; } - self.bump_past::<&'static str>(); - true - } - - fn visit_estr_fixed(&mut self, n: uint, - sz: uint, - align: uint) -> bool { - self.align(align); - if ! self.inner.visit_estr_fixed(n, sz, align) { return false; } - self.bump(sz); - true - } - - fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<@u8>(); - if ! self.inner.visit_box(mtbl, inner) { return false; } - self.bump_past::<@u8>(); - true - } - - fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<~u8>(); - if ! self.inner.visit_uniq(mtbl, inner) { return false; } - self.bump_past::<~u8>(); - true - } - - fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<~u8>(); - if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; } - self.bump_past::<~u8>(); - true - } - - fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<*u8>(); - if ! self.inner.visit_ptr(mtbl, inner) { return false; } - self.bump_past::<*u8>(); - true - } - - fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<&'static u8>(); - if ! self.inner.visit_rptr(mtbl, inner) { return false; } - self.bump_past::<&'static u8>(); - true - } - - fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::>(); - // FIXME (#3732): Inner really has to move its own pointers on this one. - // or else possibly we could have some weird interface wherein we - // read-off a word from inner's pointers, but the read-word has to - // always be the same in all sub-pointers? Dubious. - if ! self.inner.visit_vec(mtbl, inner) { return false; } - true - } - - fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<~[u8]>(); - if ! self.inner.visit_vec(mtbl, inner) { return false; } - self.bump_past::<~[u8]>(); - true - } - - fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<@[u8]>(); - if ! self.inner.visit_evec_box(mtbl, inner) { return false; } - self.bump_past::<@[u8]>(); - true - } - - fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<~[u8]>(); - if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; } - self.bump_past::<~[u8]>(); - true - } - - fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<~[@u8]>(); - if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; } - self.bump_past::<~[@u8]>(); - true - } - - fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<&'static [u8]>(); - if ! self.inner.visit_evec_slice(mtbl, inner) { return false; } - self.bump_past::<&'static [u8]>(); - true - } - - fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, - mtbl: uint, inner: *TyDesc) -> bool { - self.align(align); - if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) { - return false; - } - self.bump(sz); - true - } - - fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { - self.align(align); - if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; } - true - } - - fn visit_rec_field(&mut self, i: uint, name: &str, - mtbl: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_rec_field(i, name, mtbl, inner) { return false; } - true - } - - fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { - if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; } - true - } - - fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint, - align: uint) -> bool { - self.align(align); - if ! self.inner.visit_enter_class(name, named_fields, n_fields, sz, align) { - return false; - } - true - } - - fn visit_class_field(&mut self, i: uint, name: &str, named: bool, - mtbl: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_class_field(i, name, named, mtbl, inner) { - return false; - } - true - } - - fn visit_leave_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint, - align: uint) -> bool { - if ! self.inner.visit_leave_class(name, named_fields, n_fields, sz, align) { - return false; - } - true - } - - fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { - self.align(align); - if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; } - true - } - - fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_tup_field(i, inner) { return false; } - true - } - - fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { - if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; } - true - } - - fn visit_enter_fn(&mut self, purity: uint, proto: uint, - n_inputs: uint, retstyle: uint) -> bool { - if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) { - return false - } - true - } - - fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_fn_input(i, mode, inner) { return false; } - true - } - - fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_fn_output(retstyle, inner) { return false; } - true - } - - fn visit_leave_fn(&mut self, purity: uint, proto: uint, - n_inputs: uint, retstyle: uint) -> bool { - if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) { - return false; - } - true - } - - fn visit_enter_enum(&mut self, n_variants: uint, - get_disr: extern unsafe fn(ptr: *Opaque) -> int, - sz: uint, align: uint) - -> bool { - self.align(align); - if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { return false; } - true - } - - fn visit_enter_enum_variant(&mut self, variant: uint, - disr_val: int, - n_fields: uint, - name: &str) -> bool { - if ! self.inner.visit_enter_enum_variant(variant, disr_val, - n_fields, name) { - return false; - } - true - } - - fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } - true - } - - fn visit_leave_enum_variant(&mut self, variant: uint, - disr_val: int, - n_fields: uint, - name: &str) -> bool { - if ! self.inner.visit_leave_enum_variant(variant, disr_val, - n_fields, name) { - return false; - } - true - } - - fn visit_leave_enum(&mut self, n_variants: uint, - get_disr: extern unsafe fn(ptr: *Opaque) -> int, - sz: uint, align: uint) - -> bool { - if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { return false; } - true - } - - fn visit_trait(&mut self, name: &str) -> bool { - self.align_to::<@TyVisitor>(); - if ! self.inner.visit_trait(name) { return false; } - self.bump_past::<@TyVisitor>(); - true - } - - fn visit_param(&mut self, i: uint) -> bool { - if ! self.inner.visit_param(i) { return false; } - true - } - - fn visit_self(&mut self) -> bool { - self.align_to::<&'static u8>(); - if ! self.inner.visit_self() { return false; } - self.align_to::<&'static u8>(); - true - } - - fn visit_type(&mut self) -> bool { - if ! self.inner.visit_type() { return false; } - true - } - - fn visit_opaque_box(&mut self) -> bool { - self.align_to::<@u8>(); - if ! self.inner.visit_opaque_box() { return false; } - self.bump_past::<@u8>(); - true - } - - fn visit_closure_ptr(&mut self, ck: uint) -> bool { - self.align_to::<(uint,uint)>(); - if ! self.inner.visit_closure_ptr(ck) { return false; } - self.bump_past::<(uint,uint)>(); - true - } -} - -struct my_visitor(@mut Stuff); - -struct Stuff { - ptr1: *c_void, - ptr2: *c_void, - vals: ~[~str] -} - -impl my_visitor { - pub fn get(&mut self, f: &fn(T)) { - unsafe { - f((*(self.ptr1 as *T)).clone()); - } - } - - pub fn visit_inner(&mut self, inner: *TyDesc) -> bool { - unsafe { - let u = my_visitor(**self); - let mut v = ptr_visit_adaptor::(Inner {inner: u}); - visit_tydesc(inner, &mut v as &mut TyVisitor); - true - } - } -} - -struct Inner { inner: V } - -impl movable_ptr for my_visitor { - fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void) { - self.ptr1 = adjustment(self.ptr1); - self.ptr2 = adjustment(self.ptr2); - } -} - -impl TyVisitor for my_visitor { - - fn visit_bot(&mut self) -> bool { true } - fn visit_nil(&mut self) -> bool { true } - fn visit_bool(&mut self) -> bool { - do self.get::() |b| { - self.vals.push(b.to_str()); - }; - true - } - fn visit_int(&mut self) -> bool { - do self.get::() |i| { - self.vals.push(i.to_str()); - }; - true - } - fn visit_i8(&mut self) -> bool { true } - fn visit_i16(&mut self) -> bool { true } - fn visit_i32(&mut self) -> bool { true } - fn visit_i64(&mut self) -> bool { true } - - fn visit_uint(&mut self) -> bool { true } - fn visit_u8(&mut self) -> bool { true } - fn visit_u16(&mut self) -> bool { true } - fn visit_u32(&mut self) -> bool { true } - fn visit_u64(&mut self) -> bool { true } - - fn visit_f32(&mut self) -> bool { true } - fn visit_f64(&mut self) -> bool { true } - - fn visit_char(&mut self) -> bool { true } - - fn visit_estr_box(&mut self) -> bool { true } - fn visit_estr_uniq(&mut self) -> bool { true } - fn visit_estr_slice(&mut self) -> bool { true } - fn visit_estr_fixed(&mut self, _n: uint, _sz: uint, - _align: uint) -> bool { true } - - fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - - fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint, - _mtbl: uint, _inner: *TyDesc) -> bool { true } - - fn visit_enter_rec(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_rec_field(&mut self, _i: uint, _name: &str, - _mtbl: uint, inner: *TyDesc) -> bool { - error2!("rec field!"); - self.visit_inner(inner) - } - fn visit_leave_rec(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_class(&mut self, _name: &str, _named_fields: bool, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_class_field(&mut self, _i: uint, _name: &str, _named: bool, - _mtbl: uint, inner: *TyDesc) -> bool { - self.visit_inner(inner) - } - fn visit_leave_class(&mut self, _name: &str, _named_fields: bool, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_tup(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(&mut self, _i: uint, inner: *TyDesc) -> bool { - error2!("tup field!"); - self.visit_inner(inner) - } - fn visit_leave_tup(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_enum(&mut self, _n_variants: uint, - _get_disr: extern unsafe fn(ptr: *Opaque) -> int, - _sz: uint, _align: uint) -> bool { - // FIXME (#3732): this needs to rewind between enum variants, or something. - true - } - fn visit_enter_enum_variant(&mut self, _variant: uint, - _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } - fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, inner: *TyDesc) -> bool { - self.visit_inner(inner) - } - fn visit_leave_enum_variant(&mut self, _variant: uint, - _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } - fn visit_leave_enum(&mut self, _n_variants: uint, - _get_disr: extern unsafe fn(ptr: *Opaque) -> int, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, - _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { - true - } - fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { - true - } - fn visit_leave_fn(&mut self, _purity: uint, _proto: uint, - _n_inputs: uint, _retstyle: uint) -> bool { true } - - - fn visit_trait(&mut self, _name: &str) -> bool { true } - fn visit_param(&mut self, _i: uint) -> bool { true } - fn visit_self(&mut self) -> bool { true } - fn visit_type(&mut self) -> bool { true } - fn visit_opaque_box(&mut self) -> bool { true } - fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } -} - -fn get_tydesc_for(_t: T) -> *TyDesc { - unsafe { - get_tydesc::() - } -} - -struct Triple { x: int, y: int, z: int } - -pub fn main() { - unsafe { - let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}, (12,)); - let p = ptr::to_unsafe_ptr(&r) as *c_void; - let u = my_visitor(@mut Stuff {ptr1: p, - ptr2: p, - vals: ~[]}); - let mut v = ptr_visit_adaptor(Inner {inner: u}); - let td = get_tydesc_for(r); - error2!("tydesc sz: {}, align: {}", - (*td).size, (*td).align); - visit_tydesc(td, &mut v as &mut TyVisitor); - - let r = u.vals.clone(); - for s in r.iter() { - println!("val: {}", *s); - } - error2!("{:?}", u.vals.clone()); - assert_eq!(u.vals.clone(), - ~[ ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12"]); - } -} diff --git a/gcc/testsuite/rust.test/reflect-visit-type.rs b/gcc/testsuite/rust.test/reflect-visit-type.rs deleted file mode 100644 index 0afc5dd..0000000 --- a/gcc/testsuite/rust.test/reflect-visit-type.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque}; - -struct MyVisitor { - types: @mut ~[~str], -} - -impl TyVisitor for MyVisitor { - fn visit_bot(&mut self) -> bool { - self.types.push(~"bot"); - error2!("visited bot type"); - true - } - fn visit_nil(&mut self) -> bool { - self.types.push(~"nil"); - error2!("visited nil type"); - true - } - fn visit_bool(&mut self) -> bool { - self.types.push(~"bool"); - error2!("visited bool type"); - true - } - fn visit_int(&mut self) -> bool { - self.types.push(~"int"); - error2!("visited int type"); - true - } - fn visit_i8(&mut self) -> bool { - self.types.push(~"i8"); - error2!("visited i8 type"); - true - } - fn visit_i16(&mut self) -> bool { - self.types.push(~"i16"); - error2!("visited i16 type"); - true - } - fn visit_i32(&mut self) -> bool { true } - fn visit_i64(&mut self) -> bool { true } - - fn visit_uint(&mut self) -> bool { true } - fn visit_u8(&mut self) -> bool { true } - fn visit_u16(&mut self) -> bool { true } - fn visit_u32(&mut self) -> bool { true } - fn visit_u64(&mut self) -> bool { true } - - fn visit_f32(&mut self) -> bool { true } - fn visit_f64(&mut self) -> bool { true } - - fn visit_char(&mut self) -> bool { true } - - fn visit_estr_box(&mut self) -> bool { true } - fn visit_estr_uniq(&mut self) -> bool { true } - fn visit_estr_slice(&mut self) -> bool { true } - fn visit_estr_fixed(&mut self, - _sz: uint, _sz: uint, - _align: uint) -> bool { true } - - fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - - fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { - self.types.push(~"["); - unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor); } - self.types.push(~"]"); - true - } - fn visit_evec_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { - self.types.push(~"["); - unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor) }; - self.types.push(~"]"); - true - } - fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint, - _mtbl: uint, _inner: *TyDesc) -> bool { true } - - fn visit_enter_rec(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_rec_field(&mut self, _i: uint, _name: &str, - _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_rec(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_class(&mut self, _name: &str, _named_fields: bool, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_class_field(&mut self, _i: uint, _name: &str, _named: bool, - _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_class(&mut self, _name: &str, _named_fields: bool, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_tup(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(&mut self, _i: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_tup(&mut self, _n_fields: uint, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_enum(&mut self, _n_variants: uint, - _get_disr: extern unsafe fn(ptr: *Opaque) -> int, - _sz: uint, _align: uint) -> bool { true } - fn visit_enter_enum_variant(&mut self, - _variant: uint, - _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } - fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_enum_variant(&mut self, - _variant: uint, - _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } - fn visit_leave_enum(&mut self, - _n_variants: uint, - _get_disr: extern unsafe fn(ptr: *Opaque) -> int, - _sz: uint, _align: uint) -> bool { true } - - fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, - _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } - fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_fn(&mut self, _purity: uint, _proto: uint, - _n_inputs: uint, _retstyle: uint) -> bool { true } - - - fn visit_trait(&mut self, _name: &str) -> bool { true } - fn visit_param(&mut self, _i: uint) -> bool { true } - fn visit_self(&mut self) -> bool { true } - fn visit_type(&mut self) -> bool { true } - fn visit_opaque_box(&mut self) -> bool { true } - fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } -} - -fn visit_ty(v: &mut MyVisitor) { - unsafe { visit_tydesc(get_tydesc::(), v as &mut TyVisitor) } -} - -pub fn main() { - let mut v = MyVisitor {types: @mut ~[]}; - - visit_ty::(&mut v); - visit_ty::(&mut v); - visit_ty::(&mut v); - visit_ty::(&mut v); - visit_ty::<~[int]>(&mut v); - - for s in v.types.iter() { - println!("type: {}", (*s).clone()); - } - assert_eq!((*v.types).clone(), ~[~"bool", ~"int", ~"i8", ~"i16", ~"[", ~"int", ~"]"]); -} diff --git a/gcc/testsuite/rust.test/region-dependent-addr-of.rs b/gcc/testsuite/rust.test/region-dependent-addr-of.rs deleted file mode 100644 index 1d44d8d..0000000 --- a/gcc/testsuite/rust.test/region-dependent-addr-of.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test lifetimes are linked properly when we create dependent region pointers. -// Issue #3148. - -struct A { - value: B -} - -struct B { - v1: int, - v2: [int, ..3], - v3: ~[int], - v4: C, - v5: ~C, - v6: Option -} - -struct C { - f: int -} - -fn get_v1<'v>(a: &'v A) -> &'v int { - // Region inferencer must deduce that &v < L2 < L1 - let foo = &a.value; // L1 - &foo.v1 // L2 -} - -fn get_v2<'v>(a: &'v A, i: uint) -> &'v int { - let foo = &a.value; - &foo.v2[i] -} - -fn get_v3<'v>(a: &'v A, i: uint) -> &'v int { - let foo = &a.value; - &foo.v3[i] -} - -fn get_v4<'v>(a: &'v A, _i: uint) -> &'v int { - let foo = &a.value; - &foo.v4.f -} - -fn get_v5<'v>(a: &'v A, _i: uint) -> &'v int { - let foo = &a.value; - &foo.v5.f -} - -fn get_v6_a<'v>(a: &'v A, _i: uint) -> &'v int { - match a.value.v6 { - Some(ref v) => &v.f, - None => fail2!() - } -} - -fn get_v6_b<'v>(a: &'v A, _i: uint) -> &'v int { - match *a { - A { value: B { v6: Some(ref v), _ } } => &v.f, - _ => fail2!() - } -} - -fn get_v6_c<'v>(a: &'v A, _i: uint) -> &'v int { - match a { - &A { value: B { v6: Some(ref v), _ } } => &v.f, - _ => fail2!() - } -} - -fn get_v5_ref<'v>(a: &'v A, _i: uint) -> &'v int { - match &a.value { - &B {v5: ~C {f: ref v}, _} => v - } -} - -pub fn main() { - let a = A {value: B {v1: 22, - v2: [23, 24, 25], - v3: ~[26, 27, 28], - v4: C { f: 29 }, - v5: ~C { f: 30 }, - v6: Some(C { f: 31 })}}; - - let p = get_v1(&a); - assert_eq!(*p, a.value.v1); - - let p = get_v2(&a, 1); - assert_eq!(*p, a.value.v2[1]); - - let p = get_v3(&a, 1); - assert_eq!(*p, a.value.v3[1]); - - let p = get_v4(&a, 1); - assert_eq!(*p, a.value.v4.f); - - let p = get_v5(&a, 1); - assert_eq!(*p, a.value.v5.f); - - let p = get_v6_a(&a, 1); - assert_eq!(*p, a.value.v6.unwrap().f); - - let p = get_v6_b(&a, 1); - assert_eq!(*p, a.value.v6.unwrap().f); - - let p = get_v6_c(&a, 1); - assert_eq!(*p, a.value.v6.unwrap().f); - - let p = get_v5_ref(&a, 1); - assert_eq!(*p, a.value.v5.f); -} diff --git a/gcc/testsuite/rust.test/region-dependent-autofn.rs b/gcc/testsuite/rust.test/region-dependent-autofn.rs deleted file mode 100644 index bce2159..0000000 --- a/gcc/testsuite/rust.test/region-dependent-autofn.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test lifetimes are linked properly when we autoslice a vector. -// Issue #3148. - -fn subslice<'r>(v: &'r fn()) -> &'r fn() { v } - -fn both<'r>(v: &'r fn()) -> &'r fn() { - subslice(subslice(v)) -} - -pub fn main() { - both(main); -} diff --git a/gcc/testsuite/rust.test/region-dependent-autoslice.rs b/gcc/testsuite/rust.test/region-dependent-autoslice.rs deleted file mode 100644 index dab8815..0000000 --- a/gcc/testsuite/rust.test/region-dependent-autoslice.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test lifetimes are linked properly when we autoslice a vector. -// Issue #3148. - -fn subslice1<'r>(v: &'r [uint]) -> &'r [uint] { v } - -fn both<'r>(v: &'r [uint]) -> &'r [uint] { - subslice1(subslice1(v)) -} - -pub fn main() { - let v = ~[1,2,3]; - both(v); -} diff --git a/gcc/testsuite/rust.test/region-return-interior-of-option.rs b/gcc/testsuite/rust.test/region-return-interior-of-option.rs deleted file mode 100644 index 9258b14..0000000 --- a/gcc/testsuite/rust.test/region-return-interior-of-option.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn get<'r, T>(opt: &'r Option) -> &'r T { - match *opt { - Some(ref v) => v, - None => fail2!("none") - } -} - -pub fn main() { - let mut x = Some(23); - - { - let y = get(&x); - assert_eq!(*y, 23); - } - - x = Some(24); - - { - let y = get(&x); - assert_eq!(*y, 24); - } -} diff --git a/gcc/testsuite/rust.test/regions-addr-of-interior-of-unique-box.rs b/gcc/testsuite/rust.test/regions-addr-of-interior-of-unique-box.rs deleted file mode 100644 index 7efe622..0000000 --- a/gcc/testsuite/rust.test/regions-addr-of-interior-of-unique-box.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Point { - x: int, - y: int -} - -struct Character { - pos: ~Point -} - -fn get_x<'r>(x: &'r Character) -> &'r int { - // interesting case because the scope of this - // borrow of the unique pointer is in fact - // larger than the fn itself - return &x.pos.x; -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-addr-of-ret.rs b/gcc/testsuite/rust.test/regions-addr-of-ret.rs deleted file mode 100644 index 08b1d24..0000000 --- a/gcc/testsuite/rust.test/regions-addr-of-ret.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f<'a>(x : &'a int) -> &'a int { - return &*x; -} - -pub fn main() { - let three = &3; - error2!("{}", *f(three)); -} diff --git a/gcc/testsuite/rust.test/regions-appearance-constraint.rs b/gcc/testsuite/rust.test/regions-appearance-constraint.rs deleted file mode 100644 index 2297277..0000000 --- a/gcc/testsuite/rust.test/regions-appearance-constraint.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* Tests conditional rooting of the box y */ - -fn testfn(cond: bool) { - let mut x = @3; - let mut y = @4; - - let mut a = &*x; - - let mut exp = 3; - if cond { - a = &*y; - - exp = 4; - } - - x = @5; - y = @6; - assert_eq!(*a, exp); - assert_eq!(x, @5); - assert_eq!(y, @6); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-borrow-at.rs b/gcc/testsuite/rust.test/regions-borrow-at.rs deleted file mode 100644 index a504296..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-at.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &uint) -> uint { - *x -} - -pub fn main() { - let p = @22u; - let r = foo(p); - info2!("r={}", r); - assert_eq!(r, 22u); -} diff --git a/gcc/testsuite/rust.test/regions-borrow-estr-uniq.rs b/gcc/testsuite/rust.test/regions-borrow-estr-uniq.rs deleted file mode 100644 index b7d9b9f..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-estr-uniq.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &str) -> u8 { - x[0] -} - -pub fn main() { - let p = ~"hello"; - let r = foo(p); - assert_eq!(r, 'h' as u8); - - let p = ~"hello"; - let r = foo(p); - assert_eq!(r, 'h' as u8); -} diff --git a/gcc/testsuite/rust.test/regions-borrow-evec-at.rs b/gcc/testsuite/rust.test/regions-borrow-evec-at.rs deleted file mode 100644 index 45e5b1a..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-evec-at.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &[uint]) -> uint { - x[0] -} - -pub fn main() { - let p = @[22u]; - let r = foo(p); - assert_eq!(r, 22u); -} diff --git a/gcc/testsuite/rust.test/regions-borrow-evec-fixed.rs b/gcc/testsuite/rust.test/regions-borrow-evec-fixed.rs deleted file mode 100644 index 9022ff9..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-evec-fixed.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &[int]) -> int { - x[0] -} - -pub fn main() { - let p = [1,2,3,4,5]; - assert_eq!(foo(p), 1); -} diff --git a/gcc/testsuite/rust.test/regions-borrow-evec-uniq.rs b/gcc/testsuite/rust.test/regions-borrow-evec-uniq.rs deleted file mode 100644 index 914c51e..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-evec-uniq.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &[int]) -> int { - x[0] -} - -pub fn main() { - let p = ~[1,2,3,4,5]; - let r = foo(p); - assert_eq!(r, 1); - - let p = ~[5,4,3,2,1]; - let r = foo(p); - assert_eq!(r, 5); -} diff --git a/gcc/testsuite/rust.test/regions-borrow-uniq.rs b/gcc/testsuite/rust.test/regions-borrow-uniq.rs deleted file mode 100644 index 10037d9..0000000 --- a/gcc/testsuite/rust.test/regions-borrow-uniq.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &uint) -> uint { - *x -} - -pub fn main() { - let p = ~3u; - let r = foo(p); - assert_eq!(r, 3u); -} diff --git a/gcc/testsuite/rust.test/regions-bot.rs b/gcc/testsuite/rust.test/regions-bot.rs deleted file mode 100644 index 5d8d5d6..0000000 --- a/gcc/testsuite/rust.test/regions-bot.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A very limited test of the "bottom" region - -fn produce_static() -> &'static T { fail2!(); } - -fn foo(_x: &T) -> &uint { produce_static() } - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-copy-closure.rs b/gcc/testsuite/rust.test/regions-copy-closure.rs deleted file mode 100644 index 0b96273..0000000 --- a/gcc/testsuite/rust.test/regions-copy-closure.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct closure_box<'self> { - cl: &'self fn(), -} - -fn box_it<'r>(x: &'r fn()) -> closure_box<'r> { - closure_box {cl: x} -} - -pub fn main() { - let mut i = 3; - let cl_box = box_it(|| i += 1); - assert_eq!(i, 3); - (cl_box.cl)(); - assert_eq!(i, 4); -} diff --git a/gcc/testsuite/rust.test/regions-creating-enums2.rs b/gcc/testsuite/rust.test/regions-creating-enums2.rs deleted file mode 100644 index a9a6aa0..0000000 --- a/gcc/testsuite/rust.test/regions-creating-enums2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum ast<'self> { - num(uint), - add(&'self ast<'self>, &'self ast<'self>) -} - -fn mk_add_ok<'r>(x: &'r ast<'r>, y: &'r ast<'r>) -> ast<'r> { - add(x, y) -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-creating-enums5.rs b/gcc/testsuite/rust.test/regions-creating-enums5.rs deleted file mode 100644 index 380e680..0000000 --- a/gcc/testsuite/rust.test/regions-creating-enums5.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum ast<'self> { - num(uint), - add(&'self ast<'self>, &'self ast<'self>) -} - -fn mk_add_ok<'a>(x: &'a ast<'a>, y: &'a ast<'a>, _z: &ast) -> ast<'a> { - add(x, y) -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-escape-into-other-fn.rs b/gcc/testsuite/rust.test/regions-escape-into-other-fn.rs deleted file mode 100644 index 986071e..0000000 --- a/gcc/testsuite/rust.test/regions-escape-into-other-fn.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo<'r>(x: &'r uint) -> &'r uint { x } -fn bar(x: &uint) -> uint { *x } - -pub fn main() { - let p = @3u; - assert_eq!(bar(foo(p)), 3); -} diff --git a/gcc/testsuite/rust.test/regions-expl-self.rs b/gcc/testsuite/rust.test/regions-expl-self.rs deleted file mode 100644 index 58c1388..0000000 --- a/gcc/testsuite/rust.test/regions-expl-self.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that you can insert an explicit lifetime in explicit self. - -struct Foo { - f: uint -} - -impl Foo { - pub fn foo<'a>(&'a self) {} -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/regions-fn-subtyping-2.rs b/gcc/testsuite/rust.test/regions-fn-subtyping-2.rs deleted file mode 100644 index ef8d9970..0000000 --- a/gcc/testsuite/rust.test/regions-fn-subtyping-2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #2263. - -// Here, `f` is a function that takes a pointer `x` and a function -// `g`, where `g` requires its argument `y` to be in the same region -// that `x` is in. -fn has_same_region(f: &fn<'a>(x: &'a int, g: &fn(y: &'a int))) { - // `f` should be the type that `wants_same_region` wants, but - // right now the compiler complains that it isn't. - wants_same_region(f); -} - -fn wants_same_region(_f: &fn<'b>(x: &'b int, g: &fn(y: &'b int))) { -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-fn-subtyping.rs b/gcc/testsuite/rust.test/regions-fn-subtyping.rs deleted file mode 100644 index 06c8aca..0000000 --- a/gcc/testsuite/rust.test/regions-fn-subtyping.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #2263. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -// Should pass region checking. -fn ok(f: &fn(x: &uint)) { - // Here, g is a function that can accept a uint pointer with - // lifetime r, and f is a function that can accept a uint pointer - // with any lifetime. The assignment g = f should be OK (i.e., - // f's type should be a subtype of g's type), because f can be - // used in any context that expects g's type. But this currently - // fails. - let mut g: &fn<'r>(y: &'r uint) = |x| { }; - g = f; -} - -// This version is the same as above, except that here, g's type is -// inferred. -fn ok_inferred(f: &fn(x: &uint)) { - let mut g: &fn<'r>(x: &'r uint) = |_| {}; - g = f; -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/regions-infer-borrow-scope-addr-of.rs b/gcc/testsuite/rust.test/regions-infer-borrow-scope-addr-of.rs deleted file mode 100644 index 6284130..0000000 --- a/gcc/testsuite/rust.test/regions-infer-borrow-scope-addr-of.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -pub fn main() { - let mut x = 4; - - for i in range(0u, 3) { - // ensure that the borrow in this alt - // does not inferfere with the swap - // below. note that it would it you - // naively borrowed &x for the lifetime - // of the variable x, as we once did - match i { - i => { - let y = &x; - assert!(i < *y); - } - } - let mut y = 4; - util::swap(&mut y, &mut x); - } -} diff --git a/gcc/testsuite/rust.test/regions-infer-borrow-scope-view.rs b/gcc/testsuite/rust.test/regions-infer-borrow-scope-view.rs deleted file mode 100644 index 8f7452f..0000000 --- a/gcc/testsuite/rust.test/regions-infer-borrow-scope-view.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn view<'r, T>(x: &'r [T]) -> &'r [T] {x} - -pub fn main() { - let v = ~[1, 2, 3]; - let x = view(v); - let y = view(x); - assert!((v[0] == x[0]) && (v[0] == y[0])); -} diff --git a/gcc/testsuite/rust.test/regions-infer-borrow-scope-within-loop-ok.rs b/gcc/testsuite/rust.test/regions-infer-borrow-scope-within-loop-ok.rs deleted file mode 100644 index db4a51b..0000000 --- a/gcc/testsuite/rust.test/regions-infer-borrow-scope-within-loop-ok.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn borrow<'r, T>(x: &'r T) -> &'r T {x} - -pub fn main() { - let x = @3; - loop { - let y = borrow(x); - assert_eq!(*x, *y); - break; - } -} diff --git a/gcc/testsuite/rust.test/regions-infer-borrow-scope.rs b/gcc/testsuite/rust.test/regions-infer-borrow-scope.rs deleted file mode 100644 index 6bd3fa5..0000000 --- a/gcc/testsuite/rust.test/regions-infer-borrow-scope.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Point {x: int, y: int} - -fn x_coord<'r>(p: &'r Point) -> &'r int { - return &p.x; -} - -pub fn main() { - let p = @Point {x: 3, y: 4}; - let xc = x_coord(p); - assert_eq!(*xc, 3); -} diff --git a/gcc/testsuite/rust.test/regions-infer-call-2.rs b/gcc/testsuite/rust.test/regions-infer-call-2.rs deleted file mode 100644 index 42be3b5..0000000 --- a/gcc/testsuite/rust.test/regions-infer-call-2.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn takes_two(x: &int, y: &int) -> int { *x + *y } - -fn with(f: &fn(x: &int) -> T) -> T { - f(&20) -} - -fn has_one<'a>(x: &'a int) -> int { - do with |y| { takes_two(x, y) } -} - -pub fn main() { - assert_eq!(has_one(&2), 22); -} diff --git a/gcc/testsuite/rust.test/regions-infer-call.rs b/gcc/testsuite/rust.test/regions-infer-call.rs deleted file mode 100644 index fdb7485..0000000 --- a/gcc/testsuite/rust.test/regions-infer-call.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn takes_two(x: &int, y: &int) -> int { *x + *y } - -fn has_two<'a,'b>(x: &'a int, y: &'b int) -> int { - takes_two(x, y) -} - -pub fn main() { - assert_eq!(has_two(&20, &2), 22); -} diff --git a/gcc/testsuite/rust.test/regions-infer-contravariance-due-to-ret.rs b/gcc/testsuite/rust.test/regions-infer-contravariance-due-to-ret.rs deleted file mode 100644 index f07105c..0000000 --- a/gcc/testsuite/rust.test/regions-infer-contravariance-due-to-ret.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct boxed_int<'self> { - f: &'self int, -} - -fn max<'r>(bi: &'r boxed_int, f: &'r int) -> int { - if *bi.f > *f {*bi.f} else {*f} -} - -fn with(bi: &boxed_int) -> int { - let i = 22; - max(bi, &i) -} - -pub fn main() { - let g = 21; - let foo = boxed_int { f: &g }; - assert_eq!(with(&foo), 22); -} diff --git a/gcc/testsuite/rust.test/regions-mock-trans.rs b/gcc/testsuite/rust.test/regions-mock-trans.rs deleted file mode 100644 index e66a34b..0000000 --- a/gcc/testsuite/rust.test/regions-mock-trans.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; -use std::libc; -use std::mem; - -struct arena(()); - -struct Bcx<'self> { - fcx: &'self Fcx<'self> -} - -struct Fcx<'self> { - arena: &'self arena, - ccx: &'self Ccx -} - -struct Ccx { - x: int -} - -#[fixed_stack_segment] #[inline(never)] -fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { - unsafe { - cast::transmute(libc::malloc(mem::size_of::>() - as libc::size_t)) - } -} - -fn h<'a>(bcx : &'a Bcx<'a>) -> &'a Bcx<'a> { - return alloc(bcx.fcx.arena); -} - -#[fixed_stack_segment] #[inline(never)] -fn g(fcx : &Fcx) { - let bcx = Bcx { fcx: fcx }; - let bcx2 = h(&bcx); - unsafe { - libc::free(cast::transmute(bcx2)); - } -} - -fn f(ccx : &Ccx) { - let a = arena(()); - let fcx = Fcx { arena: &a, ccx: ccx }; - return g(&fcx); -} - -pub fn main() { - let ccx = Ccx { x: 0 }; - f(&ccx); -} diff --git a/gcc/testsuite/rust.test/regions-nullary-variant.rs b/gcc/testsuite/rust.test/regions-nullary-variant.rs deleted file mode 100644 index e842ed5..0000000 --- a/gcc/testsuite/rust.test/regions-nullary-variant.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum roption<'self> { - a, b(&'self uint) -} - -fn mk<'r>(cond: bool, ptr: &'r uint) -> roption<'r> { - if cond {a} else {b(ptr)} -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/regions-params.rs b/gcc/testsuite/rust.test/regions-params.rs deleted file mode 100644 index ea32cf8..0000000 --- a/gcc/testsuite/rust.test/regions-params.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn region_identity<'r>(x: &'r uint) -> &'r uint { x } - -fn apply(t: T, f: &fn(T) -> T) -> T { f(t) } - -fn parameterized(x: &uint) -> uint { - let z = apply(x, ({|y| - region_identity(y) - })); - *z -} - -pub fn main() { - let x = 3u; - assert_eq!(parameterized(&x), 3u); -} diff --git a/gcc/testsuite/rust.test/regions-self-impls.rs b/gcc/testsuite/rust.test/regions-self-impls.rs deleted file mode 100644 index 61d0888..0000000 --- a/gcc/testsuite/rust.test/regions-self-impls.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Clam<'self> { - chowder: &'self int -} - -trait get_chowder<'self> { - fn get_chowder(&self) -> &'self int; -} - -impl<'self> get_chowder<'self> for Clam<'self> { - fn get_chowder(&self) -> &'self int { return self.chowder; } -} - -pub fn main() { - let clam = Clam { chowder: &3 }; - info2!("{:?}", *clam.get_chowder()); - clam.get_chowder(); -} diff --git a/gcc/testsuite/rust.test/regions-self-in-enums.rs b/gcc/testsuite/rust.test/regions-self-in-enums.rs deleted file mode 100644 index f0b7306..0000000 --- a/gcc/testsuite/rust.test/regions-self-in-enums.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum int_wrapper<'self> { - int_wrapper_ctor(&'self int) -} - -pub fn main() { - let x = 3; - let y = int_wrapper_ctor(&x); - let mut z : ∫ - match y { - int_wrapper_ctor(zz) => { z = zz; } - } - info2!("{:?}", *z); -} diff --git a/gcc/testsuite/rust.test/regions-simple.rs b/gcc/testsuite/rust.test/regions-simple.rs deleted file mode 100644 index e57c2e9..0000000 --- a/gcc/testsuite/rust.test/regions-simple.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut x: int = 3; - let y: &mut int = &mut x; - *y = 5; - info2!("{:?}", *y); -} diff --git a/gcc/testsuite/rust.test/regions-static-closure.rs b/gcc/testsuite/rust.test/regions-static-closure.rs deleted file mode 100644 index 3cb6fea..0000000 --- a/gcc/testsuite/rust.test/regions-static-closure.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct closure_box<'self> { - cl: &'self fn(), -} - -fn box_it<'r>(x: &'r fn()) -> closure_box<'r> { - closure_box {cl: x} -} - -fn call_static_closure(cl: closure_box<'static>) { - (cl.cl)(); -} - -pub fn main() { - let cl_box = box_it(|| info2!("Hello, world!")); - call_static_closure(cl_box); -} diff --git a/gcc/testsuite/rust.test/rename-directory.rs b/gcc/testsuite/rust.test/rename-directory.rs deleted file mode 100644 index 76a1d32..0000000 --- a/gcc/testsuite/rust.test/rename-directory.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test can't be a unit test in std, -// because it needs TempDir, which is in extra - -// xfail-fast -extern mod extra; - -use extra::tempfile::TempDir; -use std::os; -use std::libc; - -fn rename_directory() { - #[fixed_stack_segment]; - unsafe { - static U_RWX: i32 = (libc::S_IRUSR | libc::S_IWUSR | libc::S_IXUSR) as i32; - - let tmpdir = TempDir::new("rename_directory").expect("rename_directory failed"); - let tmpdir = tmpdir.path(); - let old_path = tmpdir.join_many(["foo", "bar", "baz"]); - assert!(os::mkdir_recursive(&old_path, U_RWX)); - let test_file = &old_path.join("temp.txt"); - - /* Write the temp input file */ - let ostream = do test_file.with_c_str |fromp| { - do "w+b".with_c_str |modebuf| { - libc::fopen(fromp, modebuf) - } - }; - assert!((ostream as uint != 0u)); - let s = ~"hello"; - do "hello".with_c_str |buf| { - let write_len = libc::fwrite(buf as *libc::c_void, - 1u as libc::size_t, - (s.len() + 1u) as libc::size_t, - ostream); - assert_eq!(write_len, (s.len() + 1) as libc::size_t) - } - assert_eq!(libc::fclose(ostream), (0u as libc::c_int)); - - let new_path = tmpdir.join_many(["quux", "blat"]); - assert!(os::mkdir_recursive(&new_path, U_RWX)); - assert!(os::rename_file(&old_path, &new_path.join("newdir"))); - assert!(os::path_is_dir(&new_path.join("newdir"))); - assert!(os::path_exists(&new_path.join_many(["newdir", "temp.txt"]))); - } -} - -fn main() { rename_directory() } diff --git a/gcc/testsuite/rust.test/repeat-expr-in-static.rs b/gcc/testsuite/rust.test/repeat-expr-in-static.rs deleted file mode 100644 index d060db2..0000000 --- a/gcc/testsuite/rust.test/repeat-expr-in-static.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static FOO: [int, ..4] = [32, ..4]; -static BAR: [int, ..4] = [32, 32, 32, 32]; - -pub fn main() { - assert_eq!(FOO, BAR); -} diff --git a/gcc/testsuite/rust.test/repeated-vector-syntax.rs b/gcc/testsuite/rust.test/repeated-vector-syntax.rs deleted file mode 100644 index 6291e22..0000000 --- a/gcc/testsuite/rust.test/repeated-vector-syntax.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone)] -struct Foo { - a: ~str, -} - -pub fn main() { - let x = [ @[true], ..512 ]; - let y = [ 0, ..1 ]; - - error2!("{:?}", x); - error2!("{:?}", y); -} diff --git a/gcc/testsuite/rust.test/resolve-issue-2428.rs b/gcc/testsuite/rust.test/resolve-issue-2428.rs deleted file mode 100644 index 57f6596..0000000 --- a/gcc/testsuite/rust.test/resolve-issue-2428.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static foo: int = 4 >> 1; -enum bs { thing = foo } -pub fn main() { assert!((thing as int == foo)); } diff --git a/gcc/testsuite/rust.test/resource-assign-is-not-copy.rs b/gcc/testsuite/rust.test/resource-assign-is-not-copy.rs deleted file mode 100644 index 2e30044..0000000 --- a/gcc/testsuite/rust.test/resource-assign-is-not-copy.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct r { - i: @mut int, -} - -#[unsafe_destructor] -impl Drop for r { - fn drop(&mut self) { - *(self.i) += 1; - } -} - -fn r(i: @mut int) -> r { - r { - i: i - } -} - -pub fn main() { - let i = @mut 0; - // Even though these look like copies, they are guaranteed not to be - { - let a = r(i); - let b = (a, 10); - let (c, _d) = b; - info2!("{:?}", c); - } - assert_eq!(*i, 1); -} diff --git a/gcc/testsuite/rust.test/resource-cycle.rs b/gcc/testsuite/rust.test/resource-cycle.rs deleted file mode 100644 index e738420..0000000 --- a/gcc/testsuite/rust.test/resource-cycle.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Don't leak the unique pointers - -use std::cast; - -struct r { - v: *int, -} - -impl Drop for r { - fn drop(&mut self) { - unsafe { - info2!("r's dtor: self = {:x}, self.v = {:x}, self.v's value = {:x}", - cast::transmute::<*mut r, uint>(self), - cast::transmute::<**int, uint>(&(self.v)), - cast::transmute::<*int, uint>(self.v)); - let _v2: ~int = cast::transmute(self.v); - } - } -} - -fn r(v: *int) -> r { - r { - v: v - } -} - -struct t(Node); - -struct Node { - next: Option<@mut t>, - r: r -} - -pub fn main() { - unsafe { - let i1 = ~0; - let i1p = cast::transmute_copy(&i1); - cast::forget(i1); - let i2 = ~0; - let i2p = cast::transmute_copy(&i2); - cast::forget(i2); - - let x1 = @mut t(Node{ - next: None, - r: { - let rs = r(i1p); - info2!("r = {:x}", cast::transmute::<*r, uint>(&rs)); - rs } - }); - - info2!("x1 = {:x}, x1.r = {:x}", - cast::transmute::<@mut t, uint>(x1), - cast::transmute::<*r, uint>(&x1.r)); - - let x2 = @mut t(Node{ - next: None, - r: { - let rs = r(i2p); - info2!("r2 = {:x}", cast::transmute::<*r, uint>(&rs)); - rs - } - }); - - info2!("x2 = {:x}, x2.r = {:x}", - cast::transmute::<@mut t, uint>(x2), - cast::transmute::<*r, uint>(&(x2.r))); - - x1.next = Some(x2); - x2.next = Some(x1); - } -} diff --git a/gcc/testsuite/rust.test/resource-cycle2.rs b/gcc/testsuite/rust.test/resource-cycle2.rs deleted file mode 100644 index 45ee6ce..0000000 --- a/gcc/testsuite/rust.test/resource-cycle2.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Don't leak the unique pointers - -use std::cast; - -struct U { - a: int, - b: int, - c: *int -} - -struct r { - v: U, -} - -impl Drop for r { - fn drop(&mut self) { - unsafe { - let _v2: ~int = cast::transmute(self.v.c); - } - } -} - -fn r(v: U) -> r { - r { - v: v - } -} - -struct t(Node); - -struct Node { - next: Option<@mut t>, - r: r -} - -pub fn main() { - unsafe { - let i1 = ~0xA; - let i1p = cast::transmute_copy(&i1); - cast::forget(i1); - let i2 = ~0xA; - let i2p = cast::transmute_copy(&i2); - cast::forget(i2); - - let u1 = U {a: 0xB, b: 0xC, c: i1p}; - let u2 = U {a: 0xB, b: 0xC, c: i2p}; - - let x1 = @mut t(Node { - next: None, - r: r(u1) - }); - let x2 = @mut t(Node { - next: None, - r: r(u2) - }); - x1.next = Some(x2); - x2.next = Some(x1); - } -} diff --git a/gcc/testsuite/rust.test/resource-cycle3.rs b/gcc/testsuite/rust.test/resource-cycle3.rs deleted file mode 100644 index 0435f0b..0000000 --- a/gcc/testsuite/rust.test/resource-cycle3.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// same as resource-cycle2, but be sure to give r multiple fields... - -// Don't leak the unique pointers - -use std::cast; - -struct U { - a: int, - b: int, - c: *int -} - -struct R { - v: U, - w: int, - x: *int, -} - -impl Drop for R { - fn drop(&mut self) { - unsafe { - let _v2: ~int = cast::transmute(self.v.c); - // let _v3: ~int = cast::transmute_copy(self.x); - } - } -} - -fn r(v: U, w: int, _x: *int) -> R { - unsafe { - R { - v: v, - w: w, - x: cast::transmute(0) - } - } -} - -struct t(Node); - -struct Node { - next: Option<@mut t>, - r: R -} - -pub fn main() { - unsafe { - let i1 = ~0xA; - let i1p = cast::transmute_copy(&i1); - cast::forget(i1); - let i2 = ~0xA; - let i2p = cast::transmute_copy(&i2); - cast::forget(i2); - - let u1 = U {a: 0xB, b: 0xC, c: i1p}; - let u2 = U {a: 0xB, b: 0xC, c: i2p}; - - let x1 = @mut t(Node{ - next: None, - r: r(u1, 42, i1p) - }); - let x2 = @mut t(Node{ - next: None, - r: r(u2, 42, i2p) - }); - x1.next = Some(x2); - x2.next = Some(x1); - } -} diff --git a/gcc/testsuite/rust.test/resource-destruct.rs b/gcc/testsuite/rust.test/resource-destruct.rs deleted file mode 100644 index 70adccb..0000000 --- a/gcc/testsuite/rust.test/resource-destruct.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct shrinky_pointer { - i: @@mut int, -} - -#[unsafe_destructor] -impl Drop for shrinky_pointer { - fn drop(&mut self) { - error2!("Hello!"); **(self.i) -= 1; - } -} - -impl shrinky_pointer { - pub fn look_at(&self) -> int { return **(self.i); } -} - -fn shrinky_pointer(i: @@mut int) -> shrinky_pointer { - shrinky_pointer { - i: i - } -} - -pub fn main() { - let my_total = @@mut 10; - { let pt = shrinky_pointer(my_total); assert!((pt.look_at() == 10)); } - error2!("my_total = {}", **my_total); - assert_eq!(**my_total, 9); -} diff --git a/gcc/testsuite/rust.test/resource-in-struct.rs b/gcc/testsuite/rust.test/resource-in-struct.rs deleted file mode 100644 index d59f79e..0000000 --- a/gcc/testsuite/rust.test/resource-in-struct.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Ensures that class dtors run if the object is inside an enum -// variant - -type closable = @mut bool; - -struct close_res { - i: closable, - -} - -#[unsafe_destructor] -impl Drop for close_res { - fn drop(&mut self) { - *(self.i) = false; - } -} - -fn close_res(i: closable) -> close_res { - close_res { - i: i - } -} - -enum option { none, some(T), } - -fn sink(_res: option) { } - -pub fn main() { - let c = @mut true; - sink(none); - sink(some(close_res(c))); - assert!((!*c)); -} diff --git a/gcc/testsuite/rust.test/ret-bang.rs b/gcc/testsuite/rust.test/ret-bang.rs deleted file mode 100644 index f56cf57..0000000 --- a/gcc/testsuite/rust.test/ret-bang.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn my_err(s: ~str) -> ! { error2!("{:?}", s); fail2!(); } - -fn okay(i: uint) -> int { - if i == 3u { my_err(~"I don't like three"); } else { return 42; } -} - -pub fn main() { okay(4u); } diff --git a/gcc/testsuite/rust.test/ret-none.rs b/gcc/testsuite/rust.test/ret-none.rs deleted file mode 100644 index b1974f7..0000000 --- a/gcc/testsuite/rust.test/ret-none.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum option { none, some(T), } - -fn f() -> option { return none; } - -pub fn main() { f::(); } diff --git a/gcc/testsuite/rust.test/return-nil.rs b/gcc/testsuite/rust.test/return-nil.rs deleted file mode 100644 index b5a8126..0000000 --- a/gcc/testsuite/rust.test/return-nil.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn f() { let x: () = (); return x; } - -pub fn main() { let _x = f(); } diff --git a/gcc/testsuite/rust.test/rt-run-twice.rs b/gcc/testsuite/rust.test/rt-run-twice.rs deleted file mode 100644 index 0bb02ed..0000000 --- a/gcc/testsuite/rust.test/rt-run-twice.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows uses a different test runner - -use std::rt; - -#[start] -fn start(argc: int, argv: **u8) -> int { - do rt::start(argc, argv) { - println("First invocation"); - }; - - do rt::start(argc, argv) { - println("Second invocation"); - }; - - 0 -} diff --git a/gcc/testsuite/rust.test/rt-start-main-thread.rs b/gcc/testsuite/rust.test/rt-start-main-thread.rs deleted file mode 100644 index 9a6dfb2..0000000 --- a/gcc/testsuite/rust.test/rt-start-main-thread.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -#[start] -fn start(argc: int, argv: **u8) -> int { - do std::rt::start_on_main_thread(argc, argv) { - info2!("running on main thread"); - do spawn { - info2!("running on another thread"); - } - } -} diff --git a/gcc/testsuite/rust.test/rtio-processes.rs b/gcc/testsuite/rust.test/rtio-processes.rs deleted file mode 100644 index 70d8b8f..0000000 --- a/gcc/testsuite/rust.test/rtio-processes.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: --test -// xfail-fast - -// In the current state of affairs, libuv registers a SIGCHLD handler when a -// process is spawned through it. This is not done with a SA_RESTART flag, -// meaning that all of our syscalls run the risk of returning EINTR. This error -// is not correctly handled in the majority of std::io, so these can't run with -// the main body of tests there. -// -// That being said, libuv correctly handles EINTR completely, so these tests -// themselves are safe against that. Currently the test runner may run into this -// problem, but it's less likely than a whole suite of tests... -// -// See #9341 - -use std::rt::io::process::{Process, ProcessConfig, CreatePipe, Ignored}; -use std::rt::io::{Reader, Writer}; -use std::rt::io::pipe::PipeStream; -use std::str; - -#[test] -#[cfg(unix, not(target_os="android"))] -fn smoke() { - let io = ~[]; - let args = ProcessConfig { - program: "/bin/sh", - args: [~"-c", ~"true"], - env: None, - cwd: None, - io: io, - }; - let p = Process::new(args); - assert!(p.is_some()); - let mut p = p.unwrap(); - assert_eq!(p.wait(), 0); -} - -#[test] -#[cfg(unix, not(target_os="android"))] -fn smoke_failure() { - let io = ~[]; - let args = ProcessConfig { - program: "if-this-is-a-binary-then-the-world-has-ended", - args: [], - env: None, - cwd: None, - io: io, - }; - let p = Process::new(args); - assert!(p.is_some()); - let mut p = p.unwrap(); - assert!(p.wait() != 0); -} - -#[test] -#[cfg(unix, not(target_os="android"))] -fn exit_reported_right() { - let io = ~[]; - let args = ProcessConfig { - program: "/bin/sh", - args: [~"-c", ~"exit 1"], - env: None, - cwd: None, - io: io, - }; - let p = Process::new(args); - assert!(p.is_some()); - let mut p = p.unwrap(); - assert_eq!(p.wait(), 1); -} - -fn read_all(input: &mut Reader) -> ~str { - let mut ret = ~""; - let mut buf = [0, ..1024]; - loop { - match input.read(buf) { - None => { break } - Some(n) => { ret = ret + str::from_utf8(buf.slice_to(n)); } - } - } - return ret; -} - -fn run_output(args: ProcessConfig) -> ~str { - let p = Process::new(args); - assert!(p.is_some()); - let mut p = p.unwrap(); - assert!(p.io[0].is_none()); - assert!(p.io[1].is_some()); - let ret = read_all(p.io[1].get_mut_ref() as &mut Reader); - assert_eq!(p.wait(), 0); - return ret; -} - -#[test] -#[cfg(unix, not(target_os="android"))] -fn stdout_works() { - let pipe = PipeStream::new().unwrap(); - let io = ~[Ignored, CreatePipe(pipe, false, true)]; - let args = ProcessConfig { - program: "/bin/sh", - args: [~"-c", ~"echo foobar"], - env: None, - cwd: None, - io: io, - }; - assert_eq!(run_output(args), ~"foobar\n"); -} - -#[test] -#[cfg(unix, not(target_os="android"))] -fn set_cwd_works() { - let pipe = PipeStream::new().unwrap(); - let io = ~[Ignored, CreatePipe(pipe, false, true)]; - let cwd = Some("/"); - let args = ProcessConfig { - program: "/bin/sh", - args: [~"-c", ~"pwd"], - env: None, - cwd: cwd, - io: io, - }; - assert_eq!(run_output(args), ~"/\n"); -} - -#[test] -#[cfg(unix, not(target_os="android"))] -fn stdin_works() { - let input = PipeStream::new().unwrap(); - let output = PipeStream::new().unwrap(); - let io = ~[CreatePipe(input, true, false), - CreatePipe(output, false, true)]; - let args = ProcessConfig { - program: "/bin/sh", - args: [~"-c", ~"read line; echo $line"], - env: None, - cwd: None, - io: io, - }; - let mut p = Process::new(args).expect("didn't create a proces?!"); - p.io[0].get_mut_ref().write("foobar".as_bytes()); - p.io[0] = None; // close stdin; - let out = read_all(p.io[1].get_mut_ref() as &mut Reader); - assert_eq!(p.wait(), 0); - assert_eq!(out, ~"foobar\n"); -} diff --git a/gcc/testsuite/rust.test/select-macro.rs b/gcc/testsuite/rust.test/select-macro.rs deleted file mode 100644 index d576875..0000000 --- a/gcc/testsuite/rust.test/select-macro.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test - this isn't really a test. - - { - -// select! -macro_rules! select_if ( - - { - $index:expr, - $count:expr - } => { - fail!() - }; - - { - $index:expr, - $count:expr, - $port:path => [ - $(type_this $message:path$(($(x $x: ident),+))dont_type_this* - -> $next:ident => { $e:expr }),+ - ] - $(, $ports:path => [ - $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this* - -> $nexts:ident => { $es:expr }),+ - ] )* - } => { - if $index == $count { - match pipes::try_recv($port) { - $(Some($message($($($x,)+)* next)) => { - let $next = next; - $e - })+ - _ => fail!() - } - } else { - select_if!( - $index, - $count + 1 - $(, $ports => [ - $(type_this $messages$(($(x $xs),+))dont_type_this* - -> $nexts => { $es }),+ - ])* - ) - } - }; -) - -macro_rules! select ( - { - $( $port:path => { - $($message:path$(($($x: ident),+))dont_type_this* - -> $next:ident $e:expr),+ - } )+ - } => { - let index = pipes::selecti([$(($port).header()),+]); - select_if!(index, 0 $(, $port => [ - $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+ - ])+) - } -) - -} diff --git a/gcc/testsuite/rust.test/self-shadowing-import.rs b/gcc/testsuite/rust.test/self-shadowing-import.rs deleted file mode 100644 index b1d3642..0000000 --- a/gcc/testsuite/rust.test/self-shadowing-import.rs +++ /dev/null @@ -1,26 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod a { - pub mod b { - pub mod a { - pub fn foo() -> int { return 1; } - } - } -} - -mod c { - use a::b::a; - pub fn bar() { assert!((a::foo() == 1)); } -} - -pub fn main() { c::bar(); } diff --git a/gcc/testsuite/rust.test/self-type-param.rs b/gcc/testsuite/rust.test/self-type-param.rs deleted file mode 100644 index d90ec51b..0000000 --- a/gcc/testsuite/rust.test/self-type-param.rs +++ /dev/null @@ -1,15 +0,0 @@ -trait MyTrait { - fn f(&self) -> Self; -} - -struct S { - x: int -} - -impl MyTrait for S { - fn f(&self) -> S { - S { x: 3 } - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/send-iloop.rs b/gcc/testsuite/rust.test/send-iloop.rs deleted file mode 100644 index d872680..0000000 --- a/gcc/testsuite/rust.test/send-iloop.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test linked failure -extern mod extra; - -use std::comm; -use std::task; - -fn die() { - fail!(); -} - -fn iloop() { - task::spawn(|| die() ); - let (p, c) = comm::stream::<()>(); - loop { - // Sending and receiving here because these actions deschedule, - // at which point our child can kill us. - c.send(()); - p.recv(); - // The above comment no longer makes sense but I'm - // reluctant to remove a linked failure test case. - task::deschedule(); - } -} - -pub fn main() { - for _ in range(0u, 16u) { - task::spawn_unlinked(|| iloop() ); - } -} diff --git a/gcc/testsuite/rust.test/send-resource.rs b/gcc/testsuite/rust.test/send-resource.rs deleted file mode 100644 index 81e2d0a..0000000 --- a/gcc/testsuite/rust.test/send-resource.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -struct test { - f: int, -} - -impl Drop for test { - fn drop(&mut self) {} -} - -fn test(f: int) -> test { - test { - f: f - } -} - -pub fn main() { - let (p, c) = stream(); - - do task::spawn() { - let (pp, cc) = stream(); - c.send(cc); - - let _r = pp.recv(); - } - - p.recv().send(test(42)); -} diff --git a/gcc/testsuite/rust.test/send-type-inference.rs b/gcc/testsuite/rust.test/send-type-inference.rs deleted file mode 100644 index 79b0591..0000000 --- a/gcc/testsuite/rust.test/send-type-inference.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// tests that ctrl's type gets inferred properly -struct Command { - key: K, - val: V -} - -fn cache_server(c: Chan>>) { - let (_ctrl_port, ctrl_chan) = stream(); - c.send(ctrl_chan); -} -pub fn main() { } diff --git a/gcc/testsuite/rust.test/send_str_hashmap.rs b/gcc/testsuite/rust.test/send_str_hashmap.rs deleted file mode 100644 index 1e3bd58..0000000 --- a/gcc/testsuite/rust.test/send_str_hashmap.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::clone::{Clone, DeepClone}; -use std::cmp::{TotalEq, Ord, TotalOrd, Equiv}; -use std::cmp::Equal; -use std::container::{Container, Map, MutableMap}; -use std::default::Default; -use std::send_str::{SendStr, SendStrOwned, SendStrStatic}; -use std::str::Str; -use std::to_str::ToStr; -use std::hashmap::HashMap; -use std::option::Some; - -pub fn main() { - let mut map: HashMap = HashMap::new(); - assert!(map.insert(SendStrStatic("foo"), 42)); - assert!(!map.insert(SendStrOwned(~"foo"), 42)); - assert!(!map.insert(SendStrStatic("foo"), 42)); - assert!(!map.insert(SendStrOwned(~"foo"), 42)); - - assert!(!map.insert(SendStrStatic("foo"), 43)); - assert!(!map.insert(SendStrOwned(~"foo"), 44)); - assert!(!map.insert(SendStrStatic("foo"), 45)); - assert!(!map.insert(SendStrOwned(~"foo"), 46)); - - let v = 46; - - assert_eq!(map.find(&SendStrOwned(~"foo")), Some(&v)); - assert_eq!(map.find(&SendStrStatic("foo")), Some(&v)); - - let (a, b, c, d) = (50, 51, 52, 53); - - assert!(map.insert(SendStrStatic("abc"), a)); - assert!(map.insert(SendStrOwned(~"bcd"), b)); - assert!(map.insert(SendStrStatic("cde"), c)); - assert!(map.insert(SendStrOwned(~"def"), d)); - - assert!(!map.insert(SendStrStatic("abc"), a)); - assert!(!map.insert(SendStrOwned(~"bcd"), b)); - assert!(!map.insert(SendStrStatic("cde"), c)); - assert!(!map.insert(SendStrOwned(~"def"), d)); - - assert!(!map.insert(SendStrOwned(~"abc"), a)); - assert!(!map.insert(SendStrStatic("bcd"), b)); - assert!(!map.insert(SendStrOwned(~"cde"), c)); - assert!(!map.insert(SendStrStatic("def"), d)); - - assert_eq!(map.find_equiv(&("abc")), Some(&a)); - assert_eq!(map.find_equiv(&("bcd")), Some(&b)); - assert_eq!(map.find_equiv(&("cde")), Some(&c)); - assert_eq!(map.find_equiv(&("def")), Some(&d)); - - assert_eq!(map.find_equiv(&(~"abc")), Some(&a)); - assert_eq!(map.find_equiv(&(~"bcd")), Some(&b)); - assert_eq!(map.find_equiv(&(~"cde")), Some(&c)); - assert_eq!(map.find_equiv(&(~"def")), Some(&d)); - - assert_eq!(map.find_equiv(&(@"abc")), Some(&a)); - assert_eq!(map.find_equiv(&(@"bcd")), Some(&b)); - assert_eq!(map.find_equiv(&(@"cde")), Some(&c)); - assert_eq!(map.find_equiv(&(@"def")), Some(&d)); - - assert_eq!(map.find_equiv(&SendStrStatic("abc")), Some(&a)); - assert_eq!(map.find_equiv(&SendStrStatic("bcd")), Some(&b)); - assert_eq!(map.find_equiv(&SendStrStatic("cde")), Some(&c)); - assert_eq!(map.find_equiv(&SendStrStatic("def")), Some(&d)); - - assert_eq!(map.find_equiv(&SendStrOwned(~"abc")), Some(&a)); - assert_eq!(map.find_equiv(&SendStrOwned(~"bcd")), Some(&b)); - assert_eq!(map.find_equiv(&SendStrOwned(~"cde")), Some(&c)); - assert_eq!(map.find_equiv(&SendStrOwned(~"def")), Some(&d)); -} diff --git a/gcc/testsuite/rust.test/send_str_treemap.rs b/gcc/testsuite/rust.test/send_str_treemap.rs deleted file mode 100644 index 23ad0ac..0000000 --- a/gcc/testsuite/rust.test/send_str_treemap.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::clone::{Clone, DeepClone}; -use std::cmp::{TotalEq, Ord, TotalOrd, Equiv}; -use std::cmp::Equal; -use std::container::{Container, Map, MutableMap}; -use std::default::Default; -use std::send_str::{SendStr, SendStrOwned, SendStrStatic}; -use std::str::Str; -use std::to_str::ToStr; -use self::extra::treemap::TreeMap; -use std::option::Some; - -pub fn main() { - let mut map: TreeMap = TreeMap::new(); - assert!(map.insert(SendStrStatic("foo"), 42)); - assert!(!map.insert(SendStrOwned(~"foo"), 42)); - assert!(!map.insert(SendStrStatic("foo"), 42)); - assert!(!map.insert(SendStrOwned(~"foo"), 42)); - - assert!(!map.insert(SendStrStatic("foo"), 43)); - assert!(!map.insert(SendStrOwned(~"foo"), 44)); - assert!(!map.insert(SendStrStatic("foo"), 45)); - assert!(!map.insert(SendStrOwned(~"foo"), 46)); - - let v = 46; - - assert_eq!(map.find(&SendStrOwned(~"foo")), Some(&v)); - assert_eq!(map.find(&SendStrStatic("foo")), Some(&v)); - - let (a, b, c, d) = (50, 51, 52, 53); - - assert!(map.insert(SendStrStatic("abc"), a)); - assert!(map.insert(SendStrOwned(~"bcd"), b)); - assert!(map.insert(SendStrStatic("cde"), c)); - assert!(map.insert(SendStrOwned(~"def"), d)); - - assert!(!map.insert(SendStrStatic("abc"), a)); - assert!(!map.insert(SendStrOwned(~"bcd"), b)); - assert!(!map.insert(SendStrStatic("cde"), c)); - assert!(!map.insert(SendStrOwned(~"def"), d)); - - assert!(!map.insert(SendStrOwned(~"abc"), a)); - assert!(!map.insert(SendStrStatic("bcd"), b)); - assert!(!map.insert(SendStrOwned(~"cde"), c)); - assert!(!map.insert(SendStrStatic("def"), d)); - - assert_eq!(map.find(&SendStrStatic("abc")), Some(&a)); - assert_eq!(map.find(&SendStrStatic("bcd")), Some(&b)); - assert_eq!(map.find(&SendStrStatic("cde")), Some(&c)); - assert_eq!(map.find(&SendStrStatic("def")), Some(&d)); - - assert_eq!(map.find(&SendStrOwned(~"abc")), Some(&a)); - assert_eq!(map.find(&SendStrOwned(~"bcd")), Some(&b)); - assert_eq!(map.find(&SendStrOwned(~"cde")), Some(&c)); - assert_eq!(map.find(&SendStrOwned(~"def")), Some(&d)); - - assert!(map.pop(&SendStrStatic("foo")).is_some()); - assert_eq!(map.move_iter().map(|(k, v)| k.to_str() + v.to_str()) - .to_owned_vec() - .concat(), - ~"abc50bcd51cde52def53"); -} diff --git a/gcc/testsuite/rust.test/sendable-class.rs b/gcc/testsuite/rust.test/sendable-class.rs deleted file mode 100644 index 6b26296..0000000 --- a/gcc/testsuite/rust.test/sendable-class.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that a class with only sendable fields can be sent - -use std::comm; - -struct foo { - i: int, - j: char, -} - -fn foo(i:int, j: char) -> foo { - foo { - i: i, - j: j - } -} - -pub fn main() { - let (_po, ch) = comm::stream(); - ch.send(foo(42, 'c')); -} diff --git a/gcc/testsuite/rust.test/sendfn-generic-fn.rs b/gcc/testsuite/rust.test/sendfn-generic-fn.rs deleted file mode 100644 index 7cc83e2..0000000 --- a/gcc/testsuite/rust.test/sendfn-generic-fn.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -use std::task; - -pub fn main() { test05(); } - -#[deriving(Clone)] -struct Pair { - a: A, - b: B, -} - -fn make_generic_record(a: A, b: B) -> Pair { - return Pair {a: a, b: b}; -} - -fn test05_start(f: &~fn(v: f64, v: ~str) -> Pair) { - let p = (*f)(22.22, ~"Hi"); - info2!("{:?}", p.clone()); - assert!(p.a == 22.22); - assert!(p.b == ~"Hi"); - - let q = (*f)(44.44, ~"Ho"); - info2!("{:?}", q.clone()); - assert!(q.a == 44.44); - assert!(q.b == ~"Ho"); -} - -fn spawn(f: extern fn(&~fn(A,B)->Pair)) { - let arg: ~fn(A, B) -> Pair = |a, b| make_generic_record(a, b); - task::spawn(|| f(&arg)); -} - -fn test05() { - spawn::(test05_start); -} diff --git a/gcc/testsuite/rust.test/sendfn-is-a-block.rs b/gcc/testsuite/rust.test/sendfn-is-a-block.rs deleted file mode 100644 index f7808f7..0000000 --- a/gcc/testsuite/rust.test/sendfn-is-a-block.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn test(f: &fn(uint) -> uint) -> uint { - return f(22u); -} - -pub fn main() { - let y = test(|x| 4u * x); - assert_eq!(y, 88u); -} diff --git a/gcc/testsuite/rust.test/sendfn-spawn-with-fn-arg.rs b/gcc/testsuite/rust.test/sendfn-spawn-with-fn-arg.rs deleted file mode 100644 index 6cc8b27..0000000 --- a/gcc/testsuite/rust.test/sendfn-spawn-with-fn-arg.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cell::Cell; -use std::task; - -pub fn main() { test05(); } - -fn test05_start(f: ~fn(int)) { - f(22); -} - -fn test05() { - let three = ~3; - let fn_to_send: ~fn(int) = |n| { - error2!("{}", *three + n); // will copy x into the closure - assert_eq!(*three, 3); - }; - let fn_to_send = Cell::new(fn_to_send); - task::spawn(|| { - test05_start(fn_to_send.take()); - }); -} diff --git a/gcc/testsuite/rust.test/seq-compare.rs b/gcc/testsuite/rust.test/seq-compare.rs deleted file mode 100644 index 86907bd..0000000 --- a/gcc/testsuite/rust.test/seq-compare.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - assert!((~"hello" < ~"hellr")); - assert!((~"hello " > ~"hello")); - assert!((~"hello" != ~"there")); - assert!((~[1, 2, 3, 4] > ~[1, 2, 3])); - assert!((~[1, 2, 3] < ~[1, 2, 3, 4])); - assert!((~[1, 2, 4, 4] > ~[1, 2, 3, 4])); - assert!((~[1, 2, 3, 4] < ~[1, 2, 4, 4])); - assert!((~[1, 2, 3] <= ~[1, 2, 3])); - assert!((~[1, 2, 3] <= ~[1, 2, 3, 3])); - assert!((~[1, 2, 3, 4] > ~[1, 2, 3])); - assert_eq!(~[1, 2, 3], ~[1, 2, 3]); - assert!((~[1, 2, 3] != ~[1, 1, 3])); -} diff --git a/gcc/testsuite/rust.test/shadow.rs b/gcc/testsuite/rust.test/shadow.rs deleted file mode 100644 index 345c2aa..0000000 --- a/gcc/testsuite/rust.test/shadow.rs +++ /dev/null @@ -1,31 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(c: ~[int]) { - let a: int = 5; - let mut b: ~[int] = ~[]; - - - match none:: { - some::(_) => { - for _i in c.iter() { - info2!("{:?}", a); - let a = 17; - b.push(a); - } - } - _ => { } - } -} - -enum t { none, some(T), } - -pub fn main() { let x = 10; let x = x + 20; assert!((x == 30)); foo(~[]); } diff --git a/gcc/testsuite/rust.test/shape_intrinsic_tag_then_rec.rs b/gcc/testsuite/rust.test/shape_intrinsic_tag_then_rec.rs deleted file mode 100644 index a989ac6..0000000 --- a/gcc/testsuite/rust.test/shape_intrinsic_tag_then_rec.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Exercises a bug in the shape code that was exposed -// on x86_64: when there is a enum embedded in an -// interior record which is then itself interior to -// something else, shape calculations were off. - -#[deriving(Clone)] -enum opt_span { - //hack (as opposed to option), to make `span` compile - os_none, - os_some(@Span), -} - -#[deriving(Clone)] -struct Span { - lo: uint, - hi: uint, - expanded_from: opt_span, -} - -#[deriving(Clone)] -struct Spanned { - data: T, - span: Span, -} - -type ty_ = uint; - -#[deriving(Clone)] -struct Path_ { - global: bool, - idents: ~[~str], - types: ~[@ty], -} - -type path = Spanned; -type ty = Spanned; - -#[deriving(Clone)] -struct X { - sp: Span, - path: path, -} - -pub fn main() { - let sp: Span = Span {lo: 57451u, hi: 57542u, expanded_from: os_none}; - let t: @ty = @Spanned { data: 3u, span: sp }; - let p_: Path_ = Path_ { global: true, idents: ~[~"hi"], types: ~[t] }; - let p: path = Spanned { data: p_, span: sp }; - let x = X { sp: sp, path: p }; - error2!("{:?}", x.path.clone()); - error2!("{:?}", x.clone()); -} diff --git a/gcc/testsuite/rust.test/shebang.rs b/gcc/testsuite/rust.test/shebang.rs deleted file mode 100644 index 94760ce..0000000 --- a/gcc/testsuite/rust.test/shebang.rs +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env rustx -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact - -pub fn main() { println("Hello World"); } diff --git a/gcc/testsuite/rust.test/shift.rs b/gcc/testsuite/rust.test/shift.rs deleted file mode 100644 index 945bb88..0000000 --- a/gcc/testsuite/rust.test/shift.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing shifts for various combinations of integers -// Issue #1570 - -pub fn main() { - test_misc(); - test_expr(); - test_const(); -} - -fn test_misc() { - assert_eq!(1 << 1i8 << 1u8 << 1i16 << 1u8 << 1u64, 32); -} - -fn test_expr() { - let v10 = 10 as uint; - let v4 = 4 as u8; - let v2 = 2 as u8; - assert_eq!(v10 >> v2, v2 as uint); - assert_eq!(v10 << v4, 160 as uint); - - let v10 = 10 as u8; - let v4 = 4 as uint; - let v2 = 2 as uint; - assert_eq!(v10 >> v2, v2 as u8); - assert_eq!(v10 << v4, 160 as u8); - - let v10 = 10 as int; - let v4 = 4 as i8; - let v2 = 2 as i8; - assert_eq!(v10 >> v2, v2 as int); - assert_eq!(v10 << v4, 160 as int); - - let v10 = 10 as i8; - let v4 = 4 as int; - let v2 = 2 as int; - assert_eq!(v10 >> v2, v2 as i8); - assert_eq!(v10 << v4, 160 as i8); - - let v10 = 10 as uint; - let v4 = 4 as int; - let v2 = 2 as int; - assert_eq!(v10 >> v2, v2 as uint); - assert_eq!(v10 << v4, 160 as uint); -} - -fn test_const() { - static r1_1: uint = 10u >> 2u8; - static r2_1: uint = 10u << 4u8; - assert_eq!(r1_1, 2 as uint); - assert_eq!(r2_1, 160 as uint); - - static r1_2: u8 = 10u8 >> 2u; - static r2_2: u8 = 10u8 << 4u; - assert_eq!(r1_2, 2 as u8); - assert_eq!(r2_2, 160 as u8); - - static r1_3: int = 10 >> 2i8; - static r2_3: int = 10 << 4i8; - assert_eq!(r1_3, 2 as int); - assert_eq!(r2_3, 160 as int); - - static r1_4: i8 = 10i8 >> 2; - static r2_4: i8 = 10i8 << 4; - assert_eq!(r1_4, 2 as i8); - assert_eq!(r2_4, 160 as i8); - - static r1_5: uint = 10u >> 2i8; - static r2_5: uint = 10u << 4i8; - assert_eq!(r1_5, 2 as uint); - assert_eq!(r2_5, 160 as uint); -} diff --git a/gcc/testsuite/rust.test/signed-shift-const-eval.rs b/gcc/testsuite/rust.test/signed-shift-const-eval.rs deleted file mode 100644 index 92c83c2..0000000 --- a/gcc/testsuite/rust.test/signed-shift-const-eval.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum test { thing = -5 >> 1u } -pub fn main() { - assert_eq!(thing as int, -3); -} diff --git a/gcc/testsuite/rust.test/simd-binop.rs b/gcc/testsuite/rust.test/simd-binop.rs deleted file mode 100644 index 74502b5..0000000 --- a/gcc/testsuite/rust.test/simd-binop.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable::simd::{i32x4, f32x4}; - -fn test_int(e: i32) -> i32 { - let v = i32x4(e, 0i32, 0i32, 0i32); - let i32x4(e2, _, _, _) = v * v + v - v; - e2 -} - -fn test_float(e: f32) -> f32 { - let v = f32x4(e, 0f32, 0f32, 0f32); - let f32x4(e2, _, _, _) = v * v + v - v; - e2 -} - -pub fn main() { - assert_eq!(test_int(3i32), 9i32); - assert_eq!(test_float(3f32), 9f32); -} diff --git a/gcc/testsuite/rust.test/simd-type.rs b/gcc/testsuite/rust.test/simd-type.rs deleted file mode 100644 index 643daad..0000000 --- a/gcc/testsuite/rust.test/simd-type.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[simd] -struct RGBA { - r: f32, - g: f32, - b: f32, - a: f32 -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/simple-generic-match.rs b/gcc/testsuite/rust.test/simple-generic-match.rs deleted file mode 100644 index 3f3b1c8..0000000 --- a/gcc/testsuite/rust.test/simple-generic-match.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum clam { a(T), } - -pub fn main() { let c = a(2); match c { a::(_) => { } } } diff --git a/gcc/testsuite/rust.test/simple-generic-tag.rs b/gcc/testsuite/rust.test/simple-generic-tag.rs deleted file mode 100644 index 8a36f9e..0000000 --- a/gcc/testsuite/rust.test/simple-generic-tag.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum clam { a(T), } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/simple-infer.rs b/gcc/testsuite/rust.test/simple-infer.rs deleted file mode 100644 index 0924655..0000000 --- a/gcc/testsuite/rust.test/simple-infer.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { let mut n; n = 1; info2!("{}", n); } diff --git a/gcc/testsuite/rust.test/simple-match-generic-tag.rs b/gcc/testsuite/rust.test/simple-match-generic-tag.rs deleted file mode 100644 index 1c080bb..0000000 --- a/gcc/testsuite/rust.test/simple-match-generic-tag.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum opt { none, } - -pub fn main() { - let x = none::; - match x { none:: => { info2!("hello world"); } } -} diff --git a/gcc/testsuite/rust.test/size-and-align.rs b/gcc/testsuite/rust.test/size-and-align.rs deleted file mode 100644 index d34da04..0000000 --- a/gcc/testsuite/rust.test/size-and-align.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -enum clam { a(T, int), b, } - -fn uhoh(v: ~[clam]) { - match v[1] { - a::(ref _t, ref u) => { - info2!("incorrect"); - info2!("{:?}", u); - fail2!(); - } - b:: => { info2!("correct"); } - } -} - -pub fn main() { - let v: ~[clam] = ~[b::, b::, a::(42, 17)]; - uhoh::(v); -} diff --git a/gcc/testsuite/rust.test/sized-borrowed-pointer.rs b/gcc/testsuite/rust.test/sized-borrowed-pointer.rs deleted file mode 100644 index 348b756..0000000 --- a/gcc/testsuite/rust.test/sized-borrowed-pointer.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Possibly-dynamic size of typaram should be cleared at pointer boundary. - -fn bar() { } -fn foo() { bar::<&T>() } -pub fn main() { } diff --git a/gcc/testsuite/rust.test/sized-owned-pointer.rs b/gcc/testsuite/rust.test/sized-owned-pointer.rs deleted file mode 100644 index 0c05fdd..0000000 --- a/gcc/testsuite/rust.test/sized-owned-pointer.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Possibly-dynamic size of typaram should be cleared at pointer boundary. - -fn bar() { } -fn foo() { bar::<~T>() } -pub fn main() { } diff --git a/gcc/testsuite/rust.test/smallest-hello-world.rs b/gcc/testsuite/rust.test/smallest-hello-world.rs deleted file mode 100644 index 1e5ea71..0000000 --- a/gcc/testsuite/rust.test/smallest-hello-world.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test - FIXME(#8538) some kind of problem linking induced by extern "C" fns that I do not understand -// xfail-fast - windows doesn't like this - -// Smallest hello world with no runtime - -#[no_std]; - -// This is an unfortunate thing to have to do on linux :( -#[cfg(target_os = "linux")] -#[doc(hidden)] -pub mod linkhack { - #[link_args="-lrustrt -lrt"] - extern {} -} - -extern { - fn puts(s: *u8); -} - -extern "rust-intrinsic" { - fn transmute(t: T) -> U; -} - -#[start] -fn main(_: int, _: **u8, _: *u8) -> int { - unsafe { - let (ptr, _): (*u8, uint) = transmute("Hello!"); - puts(ptr); - } - return 0; -} - diff --git a/gcc/testsuite/rust.test/spawn-fn.rs b/gcc/testsuite/rust.test/spawn-fn.rs deleted file mode 100644 index f95ddca..0000000 --- a/gcc/testsuite/rust.test/spawn-fn.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -fn x(s: ~str, n: int) { - info2!("{:?}", s); - info2!("{:?}", n); -} - -pub fn main() { - task::spawn(|| x(~"hello from first spawned fn", 65) ); - task::spawn(|| x(~"hello from second spawned fn", 66) ); - task::spawn(|| x(~"hello from third spawned fn", 67) ); - let mut i: int = 30; - while i > 0 { i = i - 1; info2!("parent sleeping"); task::deschedule(); } -} diff --git a/gcc/testsuite/rust.test/spawn-types.rs b/gcc/testsuite/rust.test/spawn-types.rs deleted file mode 100644 index 111e0df..0000000 --- a/gcc/testsuite/rust.test/spawn-types.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - Make sure we can spawn tasks that take different types of - parameters. This is based on a test case for #520 provided by Rob - Arnold. - */ - -use std::task; - -type ctx = Chan; - -fn iotask(_cx: &ctx, ip: ~str) { - assert_eq!(ip, ~"localhost"); -} - -pub fn main() { - let (_p, ch) = stream::(); - task::spawn(|| iotask(&ch, ~"localhost") ); -} diff --git a/gcc/testsuite/rust.test/spawn.rs b/gcc/testsuite/rust.test/spawn.rs deleted file mode 100644 index 9273752..0000000 --- a/gcc/testsuite/rust.test/spawn.rs +++ /dev/null @@ -1,20 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -pub fn main() { - task::spawn(|| child(10) ); -} - -fn child(i: int) { error2!("{}", i); assert!((i == 10)); } diff --git a/gcc/testsuite/rust.test/spawn2.rs b/gcc/testsuite/rust.test/spawn2.rs deleted file mode 100644 index 31967b3..0000000 --- a/gcc/testsuite/rust.test/spawn2.rs +++ /dev/null @@ -1,36 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { task::spawn(|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); } - -fn child(args: (int, int, int, int, int, int, int, int, int)) { - let (i1, i2, i3, i4, i5, i6, i7, i8, i9) = args; - error2!("{}", i1); - error2!("{}", i2); - error2!("{}", i3); - error2!("{}", i4); - error2!("{}", i5); - error2!("{}", i6); - error2!("{}", i7); - error2!("{}", i8); - error2!("{}", i9); - assert_eq!(i1, 10); - assert_eq!(i2, 20); - assert_eq!(i3, 30); - assert_eq!(i4, 40); - assert_eq!(i5, 50); - assert_eq!(i6, 60); - assert_eq!(i7, 70); - assert_eq!(i8, 80); - assert_eq!(i9, 90); -} diff --git a/gcc/testsuite/rust.test/stable-addr-of.rs b/gcc/testsuite/rust.test/stable-addr-of.rs deleted file mode 100644 index dc68777..0000000 --- a/gcc/testsuite/rust.test/stable-addr-of.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #2040 - -use std::ptr; - -pub fn main() { - let foo = 1; - assert_eq!(ptr::to_unsafe_ptr(&foo), ptr::to_unsafe_ptr(&foo)); -} diff --git a/gcc/testsuite/rust.test/stat.rs b/gcc/testsuite/rust.test/stat.rs deleted file mode 100644 index aa0661d..0000000 --- a/gcc/testsuite/rust.test/stat.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use extra::tempfile; -use std::io::WriterUtil; -use std::io; -use std::os; - -pub fn main() { - let dir = tempfile::TempDir::new_in(&Path::new("."), "").unwrap(); - let path = dir.path().join("file"); - - { - match io::file_writer(&path, [io::Create, io::Truncate]) { - Err(ref e) => fail2!("{}", e.clone()), - Ok(f) => { - for _ in range(0u, 1000) { - f.write_u8(0); - } - } - } - } - - assert!(path.exists()); - assert_eq!(path.get_size(), Some(1000)); -} diff --git a/gcc/testsuite/rust.test/static-assert.rs b/gcc/testsuite/rust.test/static-assert.rs deleted file mode 100644 index 93c8d67..0000000 --- a/gcc/testsuite/rust.test/static-assert.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[static_assert] -static b: bool = true; - -#[static_assert] -static c: bool = 1 == 1; - -#[static_assert] -static d: bool = 1 != 2; - -#[static_assert] -static f: bool = (4/2) == 2; - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/static-fn-inline-xc.rs b/gcc/testsuite/rust.test/static-fn-inline-xc.rs deleted file mode 100644 index e344166..0000000 --- a/gcc/testsuite/rust.test/static-fn-inline-xc.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:static_fn_inline_xc_aux.rs - -extern mod mycore(name ="static_fn_inline_xc_aux"); - -use mycore::num; - -pub fn main() { - let _1: f64 = num::Num2::from_int2(1i); -} diff --git a/gcc/testsuite/rust.test/static-fn-trait-xc.rs b/gcc/testsuite/rust.test/static-fn-trait-xc.rs deleted file mode 100644 index 4166587..0000000 --- a/gcc/testsuite/rust.test/static-fn-trait-xc.rs +++ /dev/null @@ -1,10 +0,0 @@ -// aux-build:static_fn_trait_xc_aux.rs -// xfail-fast - -extern mod mycore(name ="static_fn_trait_xc_aux"); - -use mycore::num; - -pub fn main() { - let _1: f64 = num::Num2::from_int2(1i); -} diff --git a/gcc/testsuite/rust.test/static-function-pointer-xc.rs b/gcc/testsuite/rust.test/static-function-pointer-xc.rs deleted file mode 100644 index 0ba47320..0000000 --- a/gcc/testsuite/rust.test/static-function-pointer-xc.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:static-function-pointer-aux.rs -extern mod aux(name = "static-function-pointer-aux"); - -fn f(x: int) -> int { x } - -fn main() { - assert_eq!(aux::F(42), -42); - unsafe { - assert_eq!(aux::MutF(42), -42); - aux::MutF = f; - assert_eq!(aux::MutF(42), 42); - aux::MutF = aux::f; - assert_eq!(aux::MutF(42), -42); - } -} diff --git a/gcc/testsuite/rust.test/static-function-pointer.rs b/gcc/testsuite/rust.test/static-function-pointer.rs deleted file mode 100644 index f8a8891..0000000 --- a/gcc/testsuite/rust.test/static-function-pointer.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(x: int) -> int { x } -fn g(x: int) -> int { 2 * x } - -static F: extern fn(int) -> int = f; -static mut G: extern fn(int) -> int = f; - -pub fn main() { - assert_eq!(F(42), 42); - unsafe { - assert_eq!(G(42), 42); - G = g; - assert_eq!(G(42), 84); - } -} diff --git a/gcc/testsuite/rust.test/static-impl.rs b/gcc/testsuite/rust.test/static-impl.rs deleted file mode 100644 index 651b334..0000000 --- a/gcc/testsuite/rust.test/static-impl.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -pub trait plus { - fn plus(&self) -> int; -} - -mod a { - use plus; - impl plus for uint { fn plus(&self) -> int { *self as int + 20 } } -} - -mod b { - use plus; - impl plus for ~str { fn plus(&self) -> int { 200 } } -} - -trait uint_utils { - fn str(&self) -> ~str; - fn multi(&self, f: &fn(uint)); -} - -impl uint_utils for uint { - fn str(&self) -> ~str { self.to_str() } - fn multi(&self, f: &fn(uint)) { - let mut c = 0u; - while c < *self { f(c); c += 1u; } - } -} - -trait vec_utils { - fn length_(&self, ) -> uint; - fn iter_(&self, f: &fn(&T)); - fn map_(&self, f: &fn(&T) -> U) -> ~[U]; -} - -impl vec_utils for ~[T] { - fn length_(&self) -> uint { self.len() } - fn iter_(&self, f: &fn(&T)) { for x in self.iter() { f(x); } } - fn map_(&self, f: &fn(&T) -> U) -> ~[U] { - let mut r = ~[]; - for elt in self.iter() { - r.push(f(elt)); - } - r - } -} - -pub fn main() { - assert_eq!(10u.plus(), 30); - assert_eq!((~"hi").plus(), 200); - - assert_eq!((~[1]).length_().str(), ~"1"); - assert_eq!((~[3, 4]).map_(|a| *a + 4 )[0], 7); - assert_eq!((~[3, 4]).map_::(|a| *a as uint + 4u )[0], 7u); - let mut x = 0u; - 10u.multi(|_n| x += 2u ); - assert_eq!(x, 20u); -} diff --git a/gcc/testsuite/rust.test/static-method-in-trait-with-tps-intracrate.rs b/gcc/testsuite/rust.test/static-method-in-trait-with-tps-intracrate.rs deleted file mode 100644 index d1fcc46..0000000 --- a/gcc/testsuite/rust.test/static-method-in-trait-with-tps-intracrate.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Deserializer { - fn read_int(&self) -> int; -} - -trait Deserializable { - fn deserialize(d: &D) -> Self; -} - -impl Deserializable for int { - fn deserialize(d: &D) -> int { - return d.read_int(); - } -} - -struct FromThinAir { dummy: () } - -impl Deserializer for FromThinAir { - fn read_int(&self) -> int { 22 } -} - -pub fn main() { - let d = FromThinAir { dummy: () }; - let i: int = Deserializable::deserialize(&d); - assert_eq!(i, 22); -} diff --git a/gcc/testsuite/rust.test/static-method-xcrate.rs b/gcc/testsuite/rust.test/static-method-xcrate.rs deleted file mode 100644 index 6697daa..0000000 --- a/gcc/testsuite/rust.test/static-method-xcrate.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:static-methods-crate.rs - -extern mod static_methods_crate; - -use static_methods_crate::read; - -pub fn main() { - let result: int = read(~"5"); - assert_eq!(result, 5); - assert_eq!(read::readMaybe(~"false"), Some(false)); - assert_eq!(read::readMaybe(~"foo"), None::); -} diff --git a/gcc/testsuite/rust.test/static-methods-in-traits.rs b/gcc/testsuite/rust.test/static-methods-in-traits.rs deleted file mode 100644 index 180cd11..0000000 --- a/gcc/testsuite/rust.test/static-methods-in-traits.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod a { - pub trait Foo { - fn foo() -> Self; - } - - impl Foo for int { - fn foo() -> int { - 3 - } - } - - impl Foo for uint { - fn foo() -> uint { - 5u - } - } -} - -pub fn main() { - let x: int = a::Foo::foo(); - let y: uint = a::Foo::foo(); - assert_eq!(x, 3); - assert_eq!(y, 5); -} diff --git a/gcc/testsuite/rust.test/static-methods-in-traits2.rs b/gcc/testsuite/rust.test/static-methods-in-traits2.rs deleted file mode 100644 index a73978c..0000000 --- a/gcc/testsuite/rust.test/static-methods-in-traits2.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub trait Number: NumConv { - fn from(n: T) -> Self; -} - -impl Number for f64 { - fn from(n: T) -> f64 { n.to_float() } -} - -pub trait NumConv { - fn to_float(&self) -> f64; -} - -impl NumConv for f64 { - fn to_float(&self) -> f64 { *self } -} - -pub fn main() { - let _: f64 = Number::from(0.0f64); -} diff --git a/gcc/testsuite/rust.test/static-mut-foreign.rs b/gcc/testsuite/rust.test/static-mut-foreign.rs deleted file mode 100644 index 0d042d0..0000000 --- a/gcc/testsuite/rust.test/static-mut-foreign.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Constants (static variables) can be used to match in patterns, but mutable -// statics cannot. This ensures that there's some form of error if this is -// attempted. - -use std::libc; - -#[nolink] -extern { - static mut rust_dbg_static_mut: libc::c_int; - pub fn rust_dbg_static_mut_check_four(); -} - -unsafe fn static_bound(_: &'static libc::c_int) {} - -fn static_bound_set(a: &'static mut libc::c_int) { - *a = 3; -} - -#[fixed_stack_segment] #[inline(never)] -unsafe fn run() { - assert!(rust_dbg_static_mut == 3); - rust_dbg_static_mut = 4; - assert!(rust_dbg_static_mut == 4); - rust_dbg_static_mut_check_four(); - rust_dbg_static_mut += 1; - assert!(rust_dbg_static_mut == 5); - rust_dbg_static_mut *= 3; - assert!(rust_dbg_static_mut == 15); - rust_dbg_static_mut = -3; - assert!(rust_dbg_static_mut == -3); - static_bound(&rust_dbg_static_mut); - static_bound_set(&mut rust_dbg_static_mut); -} - -pub fn main() { - unsafe { run() } -} diff --git a/gcc/testsuite/rust.test/static-mut-xc.rs b/gcc/testsuite/rust.test/static-mut-xc.rs deleted file mode 100644 index ab6bdc2..0000000 --- a/gcc/testsuite/rust.test/static-mut-xc.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Constants (static variables) can be used to match in patterns, but mutable -// statics cannot. This ensures that there's some form of error if this is -// attempted. - -// xfail-fast -// aux-build:static_mut_xc.rs - -extern mod static_mut_xc; - -unsafe fn static_bound(_: &'static int) {} - -fn static_bound_set(a: &'static mut int) { - *a = 3; -} - -unsafe fn run() { - assert!(static_mut_xc::a == 3); - static_mut_xc::a = 4; - assert!(static_mut_xc::a == 4); - static_mut_xc::a += 1; - assert!(static_mut_xc::a == 5); - static_mut_xc::a *= 3; - assert!(static_mut_xc::a == 15); - static_mut_xc::a = -3; - assert!(static_mut_xc::a == -3); - static_bound(&static_mut_xc::a); - static_bound_set(&mut static_mut_xc::a); -} - -pub fn main() { - unsafe { run() } -} - -pub mod inner { - pub static mut a: int = 4; -} diff --git a/gcc/testsuite/rust.test/static-vec-autoref.rs b/gcc/testsuite/rust.test/static-vec-autoref.rs deleted file mode 100644 index 8d6f085..0000000 --- a/gcc/testsuite/rust.test/static-vec-autoref.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct T(&'static [int]); - -static A: T = T(&'static [5, 4, 3]); -static B: T = T(&[5, 4, 3]); -static C: T = T([5, 4, 3]); - -pub fn main() { - assert_eq!(A[0], 5); - assert_eq!(B[1], 4); - assert_eq!(C[2], 3); -} diff --git a/gcc/testsuite/rust.test/str-append.rs b/gcc/testsuite/rust.test/str-append.rs deleted file mode 100644 index fe57c5dd..0000000 --- a/gcc/testsuite/rust.test/str-append.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- -extern mod extra; - -fn test1() { - let mut s: ~str = ~"hello"; - s.push_str("world"); - info2!("{}", s.clone()); - assert_eq!(s[9], 'd' as u8); -} - -fn test2() { - // This tests for issue #163 - - let ff: ~str = ~"abc"; - let a: ~str = ff + "ABC" + ff; - let b: ~str = ~"ABC" + ff + "ABC"; - info2!("{}", a.clone()); - info2!("{}", b.clone()); - assert_eq!(a, ~"abcABCabc"); - assert_eq!(b, ~"ABCabcABC"); -} - -pub fn main() { test1(); test2(); } diff --git a/gcc/testsuite/rust.test/str-concat.rs b/gcc/testsuite/rust.test/str-concat.rs deleted file mode 100644 index dc605c5..0000000 --- a/gcc/testsuite/rust.test/str-concat.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let a: ~str = ~"hello"; - let b: ~str = ~"world"; - let s: ~str = a + b; - info2!("{}", s.clone()); - assert_eq!(s[9], 'd' as u8); -} diff --git a/gcc/testsuite/rust.test/str-growth.rs b/gcc/testsuite/rust.test/str-growth.rs deleted file mode 100644 index 0cdf184..0000000 --- a/gcc/testsuite/rust.test/str-growth.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let mut s = ~"a"; - s.push_char('b'); - assert_eq!(s[0], 'a' as u8); - assert_eq!(s[1], 'b' as u8); - s.push_char('c'); - s.push_char('d'); - assert_eq!(s[0], 'a' as u8); - assert_eq!(s[1], 'b' as u8); - assert_eq!(s[2], 'c' as u8); - assert_eq!(s[3], 'd' as u8); -} diff --git a/gcc/testsuite/rust.test/str-idx.rs b/gcc/testsuite/rust.test/str-idx.rs deleted file mode 100644 index ca80f71..0000000 --- a/gcc/testsuite/rust.test/str-idx.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let s = ~"hello"; - let c: u8 = s[4]; - info2!("{:?}", c); - assert_eq!(c, 0x6f as u8); -} diff --git a/gcc/testsuite/rust.test/str-multiline.rs b/gcc/testsuite/rust.test/str-multiline.rs deleted file mode 100644 index 28c2cd7..0000000 --- a/gcc/testsuite/rust.test/str-multiline.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- -extern mod extra; - -pub fn main() { - let a: ~str = ~"this \ -is a test"; - let b: ~str = - ~"this \ - is \ - another \ - test"; - assert_eq!(a, ~"this is a test"); - assert_eq!(b, ~"this is another test"); -} diff --git a/gcc/testsuite/rust.test/string-self-append.rs b/gcc/testsuite/rust.test/string-self-append.rs deleted file mode 100644 index f230bb3..0000000 --- a/gcc/testsuite/rust.test/string-self-append.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -pub fn main() { - // Make sure we properly handle repeated self-appends. - let mut a: ~str = ~"A"; - let mut i = 20; - let mut expected_len = 1u; - while i > 0 { - error2!("{}", a.len()); - assert_eq!(a.len(), expected_len); - a = a + a; // FIXME(#3387)---can't write a += a - i -= 1; - expected_len *= 2u; - } -} diff --git a/gcc/testsuite/rust.test/struct-deref.rs b/gcc/testsuite/rust.test/struct-deref.rs deleted file mode 100644 index b1de988..0000000 --- a/gcc/testsuite/rust.test/struct-deref.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(int); - -pub fn main() { - let x: Foo = Foo(2); - assert_eq!(*x, 2); -} diff --git a/gcc/testsuite/rust.test/struct-destructuring-cross-crate.rs b/gcc/testsuite/rust.test/struct-destructuring-cross-crate.rs deleted file mode 100644 index 23c5087..0000000 --- a/gcc/testsuite/rust.test/struct-destructuring-cross-crate.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:struct_destructuring_cross_crate.rs - -extern mod struct_destructuring_cross_crate; - -pub fn main() { - let x = struct_destructuring_cross_crate::S { x: 1, y: 2 }; - let struct_destructuring_cross_crate::S { x: a, y: b } = x; - assert_eq!(a, 1); - assert_eq!(b, 2); -} diff --git a/gcc/testsuite/rust.test/struct-field-assignability.rs b/gcc/testsuite/rust.test/struct-field-assignability.rs deleted file mode 100644 index 335e13c..0000000 --- a/gcc/testsuite/rust.test/struct-field-assignability.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo<'self> { - x: &'self int -} - -pub fn main() { - let f = Foo { x: @3 }; - assert_eq!(*f.x, 3); -} diff --git a/gcc/testsuite/rust.test/struct-like-variant-construct.rs b/gcc/testsuite/rust.test/struct-like-variant-construct.rs deleted file mode 100644 index a7c9e3b..0000000 --- a/gcc/testsuite/rust.test/struct-like-variant-construct.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum Foo { - Bar { - a: int, - b: int - }, - Baz { - c: f64, - d: f64 - } -} - -pub fn main() { - let _x = Bar { a: 2, b: 3 }; -} diff --git a/gcc/testsuite/rust.test/struct-like-variant-match.rs b/gcc/testsuite/rust.test/struct-like-variant-match.rs deleted file mode 100644 index bb03f57..0000000 --- a/gcc/testsuite/rust.test/struct-like-variant-match.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum Foo { - Bar { - x: int, - y: int - }, - Baz { - x: f64, - y: f64 - } -} - -fn f(x: &Foo) { - match *x { - Baz { x: x, y: y } => { - assert_eq!(x, 1.0); - assert_eq!(y, 2.0); - } - Bar { y: y, x: x } => { - assert_eq!(x, 1); - assert_eq!(y, 2); - } - } -} - -pub fn main() { - let x = Bar { x: 1, y: 2 }; - f(&x); - let y = Baz { x: 1.0, y: 2.0 }; - f(&y); -} diff --git a/gcc/testsuite/rust.test/struct-literal-dtor.rs b/gcc/testsuite/rust.test/struct-literal-dtor.rs deleted file mode 100644 index a423879..0000000 --- a/gcc/testsuite/rust.test/struct-literal-dtor.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct foo { - x: ~str, -} - -impl Drop for foo { - fn drop(&mut self) { - error2!("{}", self.x); - } -} - -pub fn main() { - let _z = foo { x: ~"Hello" }; -} diff --git a/gcc/testsuite/rust.test/struct-new-as-field-name.rs b/gcc/testsuite/rust.test/struct-new-as-field-name.rs deleted file mode 100644 index fb93c56..0000000 --- a/gcc/testsuite/rust.test/struct-new-as-field-name.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo { - new: int, -} - -pub fn main() { - let foo = Foo{ new: 3 }; - assert_eq!(foo.new, 3); -} diff --git a/gcc/testsuite/rust.test/struct-order-of-eval-1.rs b/gcc/testsuite/rust.test/struct-order-of-eval-1.rs deleted file mode 100644 index 1b70894..0000000 --- a/gcc/testsuite/rust.test/struct-order-of-eval-1.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S { f0: ~str, f1: int } - -pub fn main() { - let s = ~"Hello, world!"; - let _s = S { f0: s.to_owned(), ..S { f0: s, f1: 23 } }; -} diff --git a/gcc/testsuite/rust.test/struct-order-of-eval-2.rs b/gcc/testsuite/rust.test/struct-order-of-eval-2.rs deleted file mode 100644 index a576e29..0000000 --- a/gcc/testsuite/rust.test/struct-order-of-eval-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S { f0: ~str, f1: ~str } - -pub fn main() { - let s = ~"Hello, world!"; - let _s = S { f1: s.to_owned(), f0: s }; -} diff --git a/gcc/testsuite/rust.test/struct-pattern-matching.rs b/gcc/testsuite/rust.test/struct-pattern-matching.rs deleted file mode 100644 index d2b038f..0000000 --- a/gcc/testsuite/rust.test/struct-pattern-matching.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int, - y: int, -} - -pub fn main() { - let a = Foo { x: 1, y: 2 }; - match a { - Foo { x: x, y: y } => println!("yes, {}, {}", x, y) - } -} diff --git a/gcc/testsuite/rust.test/struct-return.rs b/gcc/testsuite/rust.test/struct-return.rs deleted file mode 100644 index 7b5988b..0000000 --- a/gcc/testsuite/rust.test/struct-return.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast #9205 - -pub struct Quad { a: u64, b: u64, c: u64, d: u64 } -pub struct Floats { a: f64, b: u8, c: f64 } - -mod rustrt { - use super::{Floats, Quad}; - - #[nolink] - extern { - pub fn rust_dbg_abi_1(q: Quad) -> Quad; - pub fn rust_dbg_abi_2(f: Floats) -> Floats; - } -} - -#[fixed_stack_segment] #[inline(never)] -fn test1() { - unsafe { - let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa_u64, - b: 0xbbbb_bbbb_bbbb_bbbb_u64, - c: 0xcccc_cccc_cccc_cccc_u64, - d: 0xdddd_dddd_dddd_dddd_u64 }; - let qq = rustrt::rust_dbg_abi_1(q); - error2!("a: {:x}", qq.a as uint); - error2!("b: {:x}", qq.b as uint); - error2!("c: {:x}", qq.c as uint); - error2!("d: {:x}", qq.d as uint); - assert_eq!(qq.a, q.c + 1u64); - assert_eq!(qq.b, q.d - 1u64); - assert_eq!(qq.c, q.a + 1u64); - assert_eq!(qq.d, q.b - 1u64); - } -} - -#[cfg(target_arch = "x86_64")] -#[fixed_stack_segment] -#[inline(never)] -fn test2() { - unsafe { - let f = Floats { a: 1.234567890e-15_f64, - b: 0b_1010_1010_u8, - c: 1.0987654321e-15_f64 }; - let ff = rustrt::rust_dbg_abi_2(f); - error2!("a: {}", ff.a as f64); - error2!("b: {}", ff.b as uint); - error2!("c: {}", ff.c as f64); - assert_eq!(ff.a, f.c + 1.0f64); - assert_eq!(ff.b, 0xff_u8); - assert_eq!(ff.c, f.a - 1.0f64); - } -} - -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "arm")] -fn test2() { -} - -pub fn main() { - test1(); - test2(); -} diff --git a/gcc/testsuite/rust.test/struct-update-moves-and-copies.rs b/gcc/testsuite/rust.test/struct-update-moves-and-copies.rs deleted file mode 100644 index a0fb31e..0000000 --- a/gcc/testsuite/rust.test/struct-update-moves-and-copies.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue 4691: Ensure that functional-struct-updates operates -// correctly and moves rather than copy when appropriate. - -use NC = std::util::NonCopyable; - -struct ncint { nc: NC, v: int } -fn ncint(v: int) -> ncint { ncint { nc: NC, v: v } } - -struct NoFoo { copied: int, noncopy: ncint, } -impl NoFoo { - fn new(x:int,y:int) -> NoFoo { NoFoo { copied: x, noncopy: ncint(y) } } -} - -struct MoveFoo { copied: int, moved: ~int, } -impl MoveFoo { - fn new(x:int,y:int) -> MoveFoo { MoveFoo { copied: x, moved: ~y } } -} - -struct DropNoFoo { inner: NoFoo } -impl DropNoFoo { - fn new(x:int,y:int) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } } -} -impl Drop for DropNoFoo { fn drop(&mut self) { } } - -struct DropMoveFoo { inner: MoveFoo } -impl DropMoveFoo { - fn new(x:int,y:int) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } } -} -impl Drop for DropMoveFoo { fn drop(&mut self) { } } - - -fn test0() { - // just copy implicitly copyable fields from `f`, no moves - // (and thus it is okay that these are Drop; compare against - // compile-fail test: borrowck-struct-update-with-dtor.rs). - - // Case 1: NonCopyable - let f = DropNoFoo::new(1, 2); - let b = DropNoFoo { inner: NoFoo { noncopy: ncint(3), ..f.inner }}; - let c = DropNoFoo { inner: NoFoo { noncopy: ncint(4), ..f.inner }}; - assert_eq!(f.inner.copied, 1); - assert_eq!(f.inner.noncopy.v, 2); - - assert_eq!(b.inner.copied, 1); - assert_eq!(b.inner.noncopy.v, 3); - - assert_eq!(c.inner.copied, 1); - assert_eq!(c.inner.noncopy.v, 4); - - // Case 2: Owned - let f = DropMoveFoo::new(5, 6); - let b = DropMoveFoo { inner: MoveFoo { moved: ~7, ..f.inner }}; - let c = DropMoveFoo { inner: MoveFoo { moved: ~8, ..f.inner }}; - assert_eq!(f.inner.copied, 5); - assert_eq!(*f.inner.moved, 6); - - assert_eq!(b.inner.copied, 5); - assert_eq!(*b.inner.moved, 7); - - assert_eq!(c.inner.copied, 5); - assert_eq!(*c.inner.moved, 8); -} - -fn test1() { - // copying move-by-default fields from `f`, so it moves: - let f = MoveFoo::new(11, 12); - - let b = MoveFoo {moved: ~13, ..f}; - let c = MoveFoo {copied: 14, ..f}; - assert_eq!(b.copied, 11); - assert_eq!(*b.moved, 13); - assert_eq!(c.copied, 14); - assert_eq!(*c.moved, 12); -} - -fn test2() { - // move non-copyable field - let f = NoFoo::new(21, 22); - let b = NoFoo {noncopy: ncint(23), ..f}; - let c = NoFoo {copied: 24, ..f}; - assert_eq!(b.copied, 21); - assert_eq!(b.noncopy.v, 23); - assert_eq!(c.copied, 24); - assert_eq!(c.noncopy.v, 22); -} - -pub fn main() { - test0(); - test1(); - test2(); -} diff --git a/gcc/testsuite/rust.test/struct_variant_xc.rs b/gcc/testsuite/rust.test/struct_variant_xc.rs deleted file mode 100644 index 2dd7887..0000000 --- a/gcc/testsuite/rust.test/struct_variant_xc.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:struct_variant_xc_aux.rs -extern mod struct_variant_xc_aux; - -use struct_variant_xc_aux::Variant; - -fn main() { - let _ = Variant { arg: 1 }; -} diff --git a/gcc/testsuite/rust.test/structured-compare.rs b/gcc/testsuite/rust.test/structured-compare.rs deleted file mode 100644 index c67a72e..0000000 --- a/gcc/testsuite/rust.test/structured-compare.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum foo { large, small, } - -impl Eq for foo { - fn eq(&self, other: &foo) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &foo) -> bool { !(*self).eq(other) } -} - -pub fn main() { - let a = (1, 2, 3); - let b = (1, 2, 3); - assert_eq!(a, b); - assert!((a != (1, 2, 4))); - assert!((a < (1, 2, 4))); - assert!((a <= (1, 2, 4))); - assert!(((1, 2, 4) > a)); - assert!(((1, 2, 4) >= a)); - let x = large; - let y = small; - assert!((x != y)); - assert_eq!(x, large); - assert!((x != small)); -} diff --git a/gcc/testsuite/rust.test/super.rs b/gcc/testsuite/rust.test/super.rs deleted file mode 100644 index b5eb6e8..0000000 --- a/gcc/testsuite/rust.test/super.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod a { - pub fn f() {} - pub mod b { - fn g() { - super::f(); - } - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/supertrait-default-generics.rs b/gcc/testsuite/rust.test/supertrait-default-generics.rs deleted file mode 100644 index 2cfc221..0000000 --- a/gcc/testsuite/rust.test/supertrait-default-generics.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// There is some other borrowck bug, so we make the stuff not mut. - -trait Positioned { - fn SetX(&mut self, S); - fn X(&self) -> S; -} - -trait Movable>: Positioned { - fn translate(&mut self, dx: S) { - let x = self.X() + dx; - self.SetX(x); - } -} - -struct Point { x: S, y: S } - -impl Positioned for Point { - fn SetX(&mut self, x: S) { - self.x = x; - } - fn X(&self) -> S { - self.x.clone() - } -} - -impl> Movable for Point {} - -pub fn main() { - let mut p = Point{ x: 1, y: 2}; - p.translate(3); - assert_eq!(p.X(), 4); -} diff --git a/gcc/testsuite/rust.test/supported-cast.rs b/gcc/testsuite/rust.test/supported-cast.rs deleted file mode 100644 index 090e932..0000000 --- a/gcc/testsuite/rust.test/supported-cast.rs +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -pub fn main() { - let f = 1 as *libc::FILE; - info2!("{}", f as int); - info2!("{}", f as uint); - info2!("{}", f as i8); - info2!("{}", f as i16); - info2!("{}", f as i32); - info2!("{}", f as i64); - info2!("{}", f as u8); - info2!("{}", f as u16); - info2!("{}", f as u32); - info2!("{}", f as u64); - - info2!("{}", 1 as int); - info2!("{}", 1 as uint); - info2!("{}", 1 as *libc::FILE); - info2!("{}", 1 as i8); - info2!("{}", 1 as i16); - info2!("{}", 1 as i32); - info2!("{}", 1 as i64); - info2!("{}", 1 as u8); - info2!("{}", 1 as u16); - info2!("{}", 1 as u32); - info2!("{}", 1 as u64); - info2!("{}", 1 as f32); - info2!("{}", 1 as f64); - - info2!("{}", 1u as int); - info2!("{}", 1u as uint); - info2!("{}", 1u as *libc::FILE); - info2!("{}", 1u as i8); - info2!("{}", 1u as i16); - info2!("{}", 1u as i32); - info2!("{}", 1u as i64); - info2!("{}", 1u as u8); - info2!("{}", 1u as u16); - info2!("{}", 1u as u32); - info2!("{}", 1u as u64); - info2!("{}", 1u as f32); - info2!("{}", 1u as f64); - - info2!("{}", 1i8 as int); - info2!("{}", 1i8 as uint); - info2!("{}", 1i8 as *libc::FILE); - info2!("{}", 1i8 as i8); - info2!("{}", 1i8 as i16); - info2!("{}", 1i8 as i32); - info2!("{}", 1i8 as i64); - info2!("{}", 1i8 as u8); - info2!("{}", 1i8 as u16); - info2!("{}", 1i8 as u32); - info2!("{}", 1i8 as u64); - info2!("{}", 1i8 as f32); - info2!("{}", 1i8 as f64); - - info2!("{}", 1u8 as int); - info2!("{}", 1u8 as uint); - info2!("{}", 1u8 as *libc::FILE); - info2!("{}", 1u8 as i8); - info2!("{}", 1u8 as i16); - info2!("{}", 1u8 as i32); - info2!("{}", 1u8 as i64); - info2!("{}", 1u8 as u8); - info2!("{}", 1u8 as u16); - info2!("{}", 1u8 as u32); - info2!("{}", 1u8 as u64); - info2!("{}", 1u8 as f32); - info2!("{}", 1u8 as f64); - - info2!("{}", 1i16 as int); - info2!("{}", 1i16 as uint); - info2!("{}", 1i16 as *libc::FILE); - info2!("{}", 1i16 as i8); - info2!("{}", 1i16 as i16); - info2!("{}", 1i16 as i32); - info2!("{}", 1i16 as i64); - info2!("{}", 1i16 as u8); - info2!("{}", 1i16 as u16); - info2!("{}", 1i16 as u32); - info2!("{}", 1i16 as u64); - info2!("{}", 1i16 as f32); - info2!("{}", 1i16 as f64); - - info2!("{}", 1u16 as int); - info2!("{}", 1u16 as uint); - info2!("{}", 1u16 as *libc::FILE); - info2!("{}", 1u16 as i8); - info2!("{}", 1u16 as i16); - info2!("{}", 1u16 as i32); - info2!("{}", 1u16 as i64); - info2!("{}", 1u16 as u8); - info2!("{}", 1u16 as u16); - info2!("{}", 1u16 as u32); - info2!("{}", 1u16 as u64); - info2!("{}", 1u16 as f32); - info2!("{}", 1u16 as f64); - - info2!("{}", 1i32 as int); - info2!("{}", 1i32 as uint); - info2!("{}", 1i32 as *libc::FILE); - info2!("{}", 1i32 as i8); - info2!("{}", 1i32 as i16); - info2!("{}", 1i32 as i32); - info2!("{}", 1i32 as i64); - info2!("{}", 1i32 as u8); - info2!("{}", 1i32 as u16); - info2!("{}", 1i32 as u32); - info2!("{}", 1i32 as u64); - info2!("{}", 1i32 as f32); - info2!("{}", 1i32 as f64); - - info2!("{}", 1u32 as int); - info2!("{}", 1u32 as uint); - info2!("{}", 1u32 as *libc::FILE); - info2!("{}", 1u32 as i8); - info2!("{}", 1u32 as i16); - info2!("{}", 1u32 as i32); - info2!("{}", 1u32 as i64); - info2!("{}", 1u32 as u8); - info2!("{}", 1u32 as u16); - info2!("{}", 1u32 as u32); - info2!("{}", 1u32 as u64); - info2!("{}", 1u32 as f32); - info2!("{}", 1u32 as f64); - - info2!("{}", 1i64 as int); - info2!("{}", 1i64 as uint); - info2!("{}", 1i64 as *libc::FILE); - info2!("{}", 1i64 as i8); - info2!("{}", 1i64 as i16); - info2!("{}", 1i64 as i32); - info2!("{}", 1i64 as i64); - info2!("{}", 1i64 as u8); - info2!("{}", 1i64 as u16); - info2!("{}", 1i64 as u32); - info2!("{}", 1i64 as u64); - info2!("{}", 1i64 as f32); - info2!("{}", 1i64 as f64); - - info2!("{}", 1u64 as int); - info2!("{}", 1u64 as uint); - info2!("{}", 1u64 as *libc::FILE); - info2!("{}", 1u64 as i8); - info2!("{}", 1u64 as i16); - info2!("{}", 1u64 as i32); - info2!("{}", 1u64 as i64); - info2!("{}", 1u64 as u8); - info2!("{}", 1u64 as u16); - info2!("{}", 1u64 as u32); - info2!("{}", 1u64 as u64); - info2!("{}", 1u64 as f32); - info2!("{}", 1u64 as f64); - - info2!("{}", 1u64 as int); - info2!("{}", 1u64 as uint); - info2!("{}", 1u64 as *libc::FILE); - info2!("{}", 1u64 as i8); - info2!("{}", 1u64 as i16); - info2!("{}", 1u64 as i32); - info2!("{}", 1u64 as i64); - info2!("{}", 1u64 as u8); - info2!("{}", 1u64 as u16); - info2!("{}", 1u64 as u32); - info2!("{}", 1u64 as u64); - info2!("{}", 1u64 as f32); - info2!("{}", 1u64 as f64); - - info2!("{}", true as int); - info2!("{}", true as uint); - info2!("{}", true as *libc::FILE); - info2!("{}", true as i8); - info2!("{}", true as i16); - info2!("{}", true as i32); - info2!("{}", true as i64); - info2!("{}", true as u8); - info2!("{}", true as u16); - info2!("{}", true as u32); - info2!("{}", true as u64); - info2!("{}", true as f32); - info2!("{}", true as f64); - - info2!("{}", 1. as int); - info2!("{}", 1. as uint); - info2!("{}", 1. as i8); - info2!("{}", 1. as i16); - info2!("{}", 1. as i32); - info2!("{}", 1. as i64); - info2!("{}", 1. as u8); - info2!("{}", 1. as u16); - info2!("{}", 1. as u32); - info2!("{}", 1. as u64); - info2!("{}", 1. as f32); - info2!("{}", 1. as f64); - - info2!("{}", 1f32 as int); - info2!("{}", 1f32 as uint); - info2!("{}", 1f32 as i8); - info2!("{}", 1f32 as i16); - info2!("{}", 1f32 as i32); - info2!("{}", 1f32 as i64); - info2!("{}", 1f32 as u8); - info2!("{}", 1f32 as u16); - info2!("{}", 1f32 as u32); - info2!("{}", 1f32 as u64); - info2!("{}", 1f32 as f32); - info2!("{}", 1f32 as f64); - - info2!("{}", 1f64 as int); - info2!("{}", 1f64 as uint); - info2!("{}", 1f64 as i8); - info2!("{}", 1f64 as i16); - info2!("{}", 1f64 as i32); - info2!("{}", 1f64 as i64); - info2!("{}", 1f64 as u8); - info2!("{}", 1f64 as u16); - info2!("{}", 1f64 as u32); - info2!("{}", 1f64 as u64); - info2!("{}", 1f64 as f32); - info2!("{}", 1f64 as f64); -} diff --git a/gcc/testsuite/rust.test/swap-1.rs b/gcc/testsuite/rust.test/swap-1.rs deleted file mode 100644 index 1c0c05c..0000000 --- a/gcc/testsuite/rust.test/swap-1.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -pub fn main() { - let mut x = 3; let mut y = 7; - util::swap(&mut x, &mut y); - assert!((x == 7)); assert!((y == 3)); -} diff --git a/gcc/testsuite/rust.test/swap-2.rs b/gcc/testsuite/rust.test/swap-2.rs deleted file mode 100644 index 2ec2eb3..0000000 --- a/gcc/testsuite/rust.test/swap-2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -pub fn main() { - let mut a: ~[int] = ~[0, 1, 2, 3, 4, 5, 6]; - a.swap(2, 4); - assert_eq!(a[2], 4); - assert_eq!(a[4], 2); - let mut n = 42; - util::swap(&mut n, &mut a[0]); - assert_eq!(a[0], 42); - assert_eq!(n, 0); -} diff --git a/gcc/testsuite/rust.test/swap-overlapping.rs b/gcc/testsuite/rust.test/swap-overlapping.rs deleted file mode 100644 index 5349d05..0000000 --- a/gcc/testsuite/rust.test/swap-overlapping.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same - -use std::ptr; - -pub fn main() { - let mut test = TestDescAndFn { - desc: TestDesc { - name: DynTestName(~"test"), - should_fail: false - }, - testfn: DynTestFn(|| ()), - }; - do_swap(&mut test); -} - -fn do_swap(test: &mut TestDescAndFn) { - unsafe { - ptr::swap_ptr(test, test); - } -} - -pub enum TestName { - DynTestName(~str) -} - -pub enum TestFn { - DynTestFn(~fn()), - DynBenchFn(~fn(&mut int)) -} - -pub struct TestDesc { - name: TestName, - should_fail: bool -} - -pub struct TestDescAndFn { - desc: TestDesc, - testfn: TestFn, -} diff --git a/gcc/testsuite/rust.test/syntax-extension-bytes.rs b/gcc/testsuite/rust.test/syntax-extension-bytes.rs deleted file mode 100644 index 5b66d5f..0000000 --- a/gcc/testsuite/rust.test/syntax-extension-bytes.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static static_vec: &'static [u8] = bytes!("abc", 0xFF, '!'); - -pub fn main() { - let vec = bytes!("abc"); - assert_eq!(vec, &[97_u8, 98_u8, 99_u8]); - - let vec = bytes!("null", 0); - assert_eq!(vec, &[110_u8, 117_u8, 108_u8, 108_u8, 0_u8]); - - let vec = bytes!(' ', " ", 32, 32u8); - assert_eq!(vec, &[32_u8, 32_u8, 32_u8, 32_u8]); - - assert_eq!(static_vec, &[97_u8, 98_u8, 99_u8, 255_u8, 33_u8]); -} diff --git a/gcc/testsuite/rust.test/syntax-extension-cfg.rs b/gcc/testsuite/rust.test/syntax-extension-cfg.rs deleted file mode 100644 index 89ca7de..0000000 --- a/gcc/testsuite/rust.test/syntax-extension-cfg.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast compile-flags doesn't work with fast-check -// compile-flags: --cfg foo --cfg bar(baz) --cfg qux="foo" - -fn main() { - // check - if ! cfg!(foo) { fail2!() } - if cfg!(not(foo)) { fail2!() } - - if ! cfg!(bar(baz)) { fail2!() } - if cfg!(not(bar(baz))) { fail2!() } - - if ! cfg!(qux="foo") { fail2!() } - if cfg!(not(qux="foo")) { fail2!() } - - if ! cfg!(foo, bar(baz), qux="foo") { fail2!() } - if cfg!(not(foo, bar(baz), qux="foo")) { fail2!() } - - if cfg!(not_a_cfg) { fail2!() } - if cfg!(not_a_cfg, foo, bar(baz), qux="foo") { fail2!() } - - if ! cfg!(not(not_a_cfg)) { fail2!() } - if ! cfg!(not(not_a_cfg), foo, bar(baz), qux="foo") { fail2!() } - - if cfg!(trailing_comma, ) { fail2!() } -} diff --git a/gcc/testsuite/rust.test/syntax-extension-minor.rs b/gcc/testsuite/rust.test/syntax-extension-minor.rs deleted file mode 100644 index 60294e6..0000000 --- a/gcc/testsuite/rust.test/syntax-extension-minor.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// this now fails (correctly, I claim) because hygiene prevents -// the assembled identifier from being a reference to the binding. - -pub fn main() { - let asdf_fdsa = ~"<.<"; - assert_eq!(concat_idents!(asd, f_f, dsa), ~"<.<"); - - assert!(stringify!(use_mention_distinction) == - "use_mention_distinction"); -} diff --git a/gcc/testsuite/rust.test/syntax-extension-shell.rs b/gcc/testsuite/rust.test/syntax-extension-shell.rs deleted file mode 100644 index cc934b9..0000000 --- a/gcc/testsuite/rust.test/syntax-extension-shell.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -pub fn main() { - let s = shell!( uname -a ); - log(debug, s); -} diff --git a/gcc/testsuite/rust.test/syntax-extension-source-utils.rs b/gcc/testsuite/rust.test/syntax-extension-source-utils.rs deleted file mode 100644 index bf93dd0..0000000 --- a/gcc/testsuite/rust.test/syntax-extension-source-utils.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test is brittle! -// xfail-pretty - the pretty tests lose path information, breaking include! - -#[feature(macro_rules)]; - -pub mod m1 { - pub mod m2 { - pub fn where_am_i() -> ~str { (module_path!()).to_owned() } - } -} - -macro_rules! indirect_line( () => ( line!() ) ) - -pub fn main() { - assert_eq!(line!(), 25); - //assert!((col!() == 11)); - assert_eq!(indirect_line!(), 27); - assert!((file!().to_owned().ends_with("syntax-extension-source-utils.rs"))); - assert_eq!(stringify!((2*3) + 5).to_owned(), ~"( 2 * 3 ) + 5"); - assert!(include!("syntax-extension-source-utils-files/includeme.fragment").to_owned() - == ~"victory robot 6"); - - assert!( - include_str!("syntax-extension-source-utils-files/includeme.fragment").to_owned() - .starts_with("/* this is for ")); - assert!( - include_bin!("syntax-extension-source-utils-files/includeme.fragment") - [1] == (42 as u8)); // '*' - // The Windows tests are wrapped in an extra module for some reason - assert!((m1::m2::where_am_i().ends_with("m1::m2"))); -} diff --git a/gcc/testsuite/rust.test/tag-align-dyn-u64.rs b/gcc/testsuite/rust.test/tag-align-dyn-u64.rs deleted file mode 100644 index 946c293..0000000 --- a/gcc/testsuite/rust.test/tag-align-dyn-u64.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #7340 fails on 32-bit linux -use std::ptr; - -enum a_tag { - a_tag(A) -} - -struct t_rec { - c8: u8, - t: a_tag -} - -fn mk_rec() -> t_rec { - return t_rec { c8:0u8, t:a_tag(0u64) }; -} - -fn is_8_byte_aligned(u: &a_tag) -> bool { - let p = ptr::to_unsafe_ptr(u) as uint; - return (p & 7u) == 0u; -} - -pub fn main() { - let x = mk_rec(); - assert!(is_8_byte_aligned(&x.t)); -} diff --git a/gcc/testsuite/rust.test/tag-align-dyn-variants.rs b/gcc/testsuite/rust.test/tag-align-dyn-variants.rs deleted file mode 100644 index 748aa03..0000000 --- a/gcc/testsuite/rust.test/tag-align-dyn-variants.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #7340 fails on 32-bit linux -use std::ptr; - -enum a_tag { - varA(A), - varB(B) -} - -struct t_rec { - chA: u8, - tA: a_tag, - chB: u8, - tB: a_tag -} - -fn mk_rec(a: A, b: B) -> t_rec { - return t_rec{ chA:0u8, tA:varA(a), chB:1u8, tB:varB(b) }; -} - -fn is_aligned(amnt: uint, u: &A) -> bool { - let p = ptr::to_unsafe_ptr(u) as uint; - return (p & (amnt-1u)) == 0u; -} - -fn variant_data_is_aligned(amnt: uint, u: &a_tag) -> bool { - match u { - &varA(ref a) => is_aligned(amnt, a), - &varB(ref b) => is_aligned(amnt, b) - } -} - -pub fn main() { - let x = mk_rec(22u64, 23u64); - assert!(is_aligned(8u, &x.tA)); - assert!(variant_data_is_aligned(8u, &x.tA)); - assert!(is_aligned(8u, &x.tB)); - assert!(variant_data_is_aligned(8u, &x.tB)); - - let x = mk_rec(22u64, 23u32); - assert!(is_aligned(8u, &x.tA)); - assert!(variant_data_is_aligned(8u, &x.tA)); - assert!(is_aligned(8u, &x.tB)); - assert!(variant_data_is_aligned(4u, &x.tB)); - - let x = mk_rec(22u32, 23u64); - assert!(is_aligned(8u, &x.tA)); - assert!(variant_data_is_aligned(4u, &x.tA)); - assert!(is_aligned(8u, &x.tB)); - assert!(variant_data_is_aligned(8u, &x.tB)); - - let x = mk_rec(22u32, 23u32); - assert!(is_aligned(4u, &x.tA)); - assert!(variant_data_is_aligned(4u, &x.tA)); - assert!(is_aligned(4u, &x.tB)); - assert!(variant_data_is_aligned(4u, &x.tB)); - - let x = mk_rec(22f64, 23f64); - assert!(is_aligned(8u, &x.tA)); - assert!(variant_data_is_aligned(8u, &x.tA)); - assert!(is_aligned(8u, &x.tB)); - assert!(variant_data_is_aligned(8u, &x.tB)); -} diff --git a/gcc/testsuite/rust.test/tag-align-shape.rs b/gcc/testsuite/rust.test/tag-align-shape.rs deleted file mode 100644 index 6f5ca09..0000000 --- a/gcc/testsuite/rust.test/tag-align-shape.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -enum a_tag { - a_tag(u64) -} - -struct t_rec { - c8: u8, - t: a_tag -} - -pub fn main() { - let x = t_rec {c8: 22u8, t: a_tag(44u64)}; - let y = format!("{:?}", x); - info2!("y = {}", y); - assert_eq!(y, ~"t_rec{c8: 22u8, t: a_tag(44u64)}"); -} diff --git a/gcc/testsuite/rust.test/tag-align-u64.rs b/gcc/testsuite/rust.test/tag-align-u64.rs deleted file mode 100644 index df9e853..0000000 --- a/gcc/testsuite/rust.test/tag-align-u64.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #7340 fails on 32-bit linux -use std::ptr; - -enum a_tag { - a_tag(u64) -} - -struct t_rec { - c8: u8, - t: a_tag -} - -fn mk_rec() -> t_rec { - return t_rec { c8:0u8, t:a_tag(0u64) }; -} - -fn is_8_byte_aligned(u: &a_tag) -> bool { - let p = ptr::to_unsafe_ptr(u) as u64; - return (p & 7u64) == 0u64; -} - -pub fn main() { - let x = mk_rec(); - assert!(is_8_byte_aligned(&x.t)); -} diff --git a/gcc/testsuite/rust.test/tag-disr-val-shape.rs b/gcc/testsuite/rust.test/tag-disr-val-shape.rs deleted file mode 100644 index 3566eed..0000000 --- a/gcc/testsuite/rust.test/tag-disr-val-shape.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum color { - red = 0xff0000, - green = 0x00ff00, - blue = 0x0000ff, - black = 0x000000, - white = 0xFFFFFF, -} - -pub fn main() { - let act = format!("{:?}", red); - println(act); - assert_eq!(~"red", act); - assert_eq!(~"green", format!("{:?}", green)); - assert_eq!(~"white", format!("{:?}", white)); -} diff --git a/gcc/testsuite/rust.test/tag-exports.rs b/gcc/testsuite/rust.test/tag-exports.rs deleted file mode 100644 index b18bf66..0000000 --- a/gcc/testsuite/rust.test/tag-exports.rs +++ /dev/null @@ -1,29 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(globs)]; - -use alder::*; - -mod alder { - pub enum burnside { couch, davis } - pub enum everett { flanders, glisan, hoyt } - pub enum irving { johnson, kearney, lovejoy } - pub enum marshall { northrup, overton } -} - -pub fn main() { - let _pettygrove: burnside = couch; - let _quimby: everett = flanders; - let _raleigh: irving = johnson; - let _savier: marshall; -} diff --git a/gcc/testsuite/rust.test/tag-in-block.rs b/gcc/testsuite/rust.test/tag-in-block.rs deleted file mode 100644 index 99eacb5..0000000 --- a/gcc/testsuite/rust.test/tag-in-block.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn foo() { - fn zed(_z: bar) { } - enum bar { nil, } - fn baz() { zed(nil); } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/tag-variant-disr-type-mismatch.rs b/gcc/testsuite/rust.test/tag-variant-disr-type-mismatch.rs deleted file mode 100644 index 3d63acd..0000000 --- a/gcc/testsuite/rust.test/tag-variant-disr-type-mismatch.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum color { - red = 1u, - blue = 2, -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/tag-variant-disr-val.rs b/gcc/testsuite/rust.test/tag-variant-disr-val.rs deleted file mode 100644 index 8eed265..0000000 --- a/gcc/testsuite/rust.test/tag-variant-disr-val.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum color { - red = 0xff0000, - green = 0x00ff00, - blue = 0x0000ff, - black = 0x000000, - white = 0xFFFFFF, - imaginary = -1, - purple = 1 << 1, - orange = 8 >> 1 -} - -impl Eq for color { - fn eq(&self, other: &color) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &color) -> bool { !(*self).eq(other) } -} - -pub fn main() { - test_color(red, 0xff0000, ~"red"); - test_color(green, 0x00ff00, ~"green"); - test_color(blue, 0x0000ff, ~"blue"); - test_color(black, 0x000000, ~"black"); - test_color(white, 0xFFFFFF, ~"white"); - test_color(imaginary, -1, ~"imaginary"); - test_color(purple, 2, ~"purple"); - test_color(orange, 4, ~"orange"); -} - -fn test_color(color: color, val: int, name: ~str) { - //assert!(unsafe::transmute(color) == val); - assert_eq!(color as int, val); - assert_eq!(color as f64, val as f64); - assert!(get_color_alt(color) == name); - assert!(get_color_if(color) == name); -} - -fn get_color_alt(color: color) -> ~str { - match color { - red => {~"red"} - green => {~"green"} - blue => {~"blue"} - black => {~"black"} - white => {~"white"} - imaginary => {~"imaginary"} - purple => {~"purple"} - orange => {~"orange"} - } -} - -fn get_color_if(color: color) -> ~str { - if color == red {~"red"} - else if color == green {~"green"} - else if color == blue {~"blue"} - else if color == black {~"black"} - else if color == white {~"white"} - else if color == imaginary {~"imaginary"} - else if color == purple {~"purple"} - else if color == orange {~"orange"} - else {~"unknown"} -} diff --git a/gcc/testsuite/rust.test/tag.rs b/gcc/testsuite/rust.test/tag.rs deleted file mode 100644 index ff251a7..0000000 --- a/gcc/testsuite/rust.test/tag.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// -*- rust -*- - -enum colour { red(int, int), green, } - -impl Eq for colour { - fn eq(&self, other: &colour) -> bool { - match *self { - red(a0, b0) => { - match (*other) { - red(a1, b1) => a0 == a1 && b0 == b1, - green => false, - } - } - green => { - match (*other) { - red(*) => false, - green => true - } - } - } - } - fn ne(&self, other: &colour) -> bool { !(*self).eq(other) } -} - -fn f() { let x = red(1, 2); let y = green; assert!((x != y)); } - -pub fn main() { f(); } diff --git a/gcc/testsuite/rust.test/tail-call-arg-leak.rs b/gcc/testsuite/rust.test/tail-call-arg-leak.rs deleted file mode 100644 index 6649649..0000000 --- a/gcc/testsuite/rust.test/tail-call-arg-leak.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// use of tail calls causes arg slot leaks, issue #160. -fn inner(dummy: ~str, b: bool) { if b { return inner(dummy, false); } } - -pub fn main() { inner(~"hi", true); } diff --git a/gcc/testsuite/rust.test/tail-cps.rs b/gcc/testsuite/rust.test/tail-cps.rs deleted file mode 100644 index 9991f05..0000000 --- a/gcc/testsuite/rust.test/tail-cps.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn checktrue(rs: bool) -> bool { assert!((rs)); return true; } - -pub fn main() { let k = checktrue; evenk(42, k); oddk(45, k); } - -fn evenk(n: int, k: extern fn(bool) -> bool) -> bool { - info2!("evenk"); - info2!("{:?}", n); - if n == 0 { return k(true); } else { return oddk(n - 1, k); } -} - -fn oddk(n: int, k: extern fn(bool) -> bool) -> bool { - info2!("oddk"); - info2!("{:?}", n); - if n == 0 { return k(false); } else { return evenk(n - 1, k); } -} diff --git a/gcc/testsuite/rust.test/tail-direct.rs b/gcc/testsuite/rust.test/tail-direct.rs deleted file mode 100644 index 847e848..0000000 --- a/gcc/testsuite/rust.test/tail-direct.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { assert!((even(42))); assert!((odd(45))); } - -fn even(n: int) -> bool { if n == 0 { return true; } else { return odd(n - 1); } } - -fn odd(n: int) -> bool { if n == 0 { return false; } else { return even(n - 1); } } diff --git a/gcc/testsuite/rust.test/task-comm-0.rs b/gcc/testsuite/rust.test/task-comm-0.rs deleted file mode 100644 index 69d6609..0000000 --- a/gcc/testsuite/rust.test/task-comm-0.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm::Chan; -use std::comm; -use std::task; - -pub fn main() { test05(); } - -fn test05_start(ch : &Chan) { - ch.send(10); - error2!("sent 10"); - ch.send(20); - error2!("sent 20"); - ch.send(30); - error2!("sent 30"); -} - -fn test05() { - let (po, ch) = comm::stream(); - task::spawn(|| test05_start(&ch) ); - let mut value: int = po.recv(); - error2!("{}", value); - value = po.recv(); - error2!("{}", value); - value = po.recv(); - error2!("{}", value); - assert_eq!(value, 30); -} diff --git a/gcc/testsuite/rust.test/task-comm-1.rs b/gcc/testsuite/rust.test/task-comm-1.rs deleted file mode 100644 index f169566..0000000 --- a/gcc/testsuite/rust.test/task-comm-1.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { test00(); } - -fn start() { info2!("Started / Finished task."); } - -fn test00() { - task::try(|| start() ); - info2!("Completing."); -} diff --git a/gcc/testsuite/rust.test/task-comm-10.rs b/gcc/testsuite/rust.test/task-comm-10.rs deleted file mode 100644 index 023bb14..0000000 --- a/gcc/testsuite/rust.test/task-comm-10.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm; -use std::task; - -fn start(c: &comm::Chan>) { - let (p, ch) = comm::stream(); - c.send(ch); - - let mut a; - let mut b; - a = p.recv(); - assert!(a == ~"A"); - error2!("{:?}", a); - b = p.recv(); - assert!(b == ~"B"); - error2!("{:?}", b); -} - -pub fn main() { - let (p, ch) = comm::stream(); - let _child = task::spawn(|| start(&ch) ); - - let c = p.recv(); - c.send(~"A"); - c.send(~"B"); - task::deschedule(); -} diff --git a/gcc/testsuite/rust.test/task-comm-11.rs b/gcc/testsuite/rust.test/task-comm-11.rs deleted file mode 100644 index 5d1a68e..0000000 --- a/gcc/testsuite/rust.test/task-comm-11.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm; -use std::task; - -fn start(c: &comm::Chan>) { - let (_p, ch) = comm::stream(); - c.send(ch); -} - -pub fn main() { - let (p, ch) = comm::stream(); - let _child = task::spawn(|| start(&ch) ); - let _c = p.recv(); -} diff --git a/gcc/testsuite/rust.test/task-comm-12.rs b/gcc/testsuite/rust.test/task-comm-12.rs deleted file mode 100644 index 9d5f893..0000000 --- a/gcc/testsuite/rust.test/task-comm-12.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -pub fn main() { test00(); } - -fn start(_task_number: int) { info2!("Started / Finished task."); } - -fn test00() { - let i: int = 0; - let mut builder = task::task(); - let result = builder.future_result(); - do builder.spawn { - start(i) - } - - // Sleep long enough for the task to finish. - let mut i = 0; - while i < 10000 { - task::deschedule(); - i += 1; - } - - // Try joining tasks that have already finished. - result.recv(); - - info2!("Joined task."); -} diff --git a/gcc/testsuite/rust.test/task-comm-13.rs b/gcc/testsuite/rust.test/task-comm-13.rs deleted file mode 100644 index 2bbed14..0000000 --- a/gcc/testsuite/rust.test/task-comm-13.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm; -use std::task; - -fn start(c: &comm::Chan, start: int, number_of_messages: int) { - let mut i: int = 0; - while i < number_of_messages { c.send(start + i); i += 1; } -} - -pub fn main() { - info2!("Check that we don't deadlock."); - let (_p, ch) = comm::stream(); - task::try(|| start(&ch, 0, 10) ); - info2!("Joined task"); -} diff --git a/gcc/testsuite/rust.test/task-comm-14.rs b/gcc/testsuite/rust.test/task-comm-14.rs deleted file mode 100644 index cacaea5..0000000 --- a/gcc/testsuite/rust.test/task-comm-14.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -use std::comm; -use std::task; - -pub fn main() { - let (po, ch) = comm::stream(); - let ch = comm::SharedChan::new(ch); - - // Spawn 10 tasks each sending us back one int. - let mut i = 10; - while (i > 0) { - info2!("{}", i); - let ch = ch.clone(); - task::spawn({let i = i; || child(i, &ch)}); - i = i - 1; - } - - // Spawned tasks are likely killed before they get a chance to send - // anything back, so we deadlock here. - - i = 10; - while (i > 0) { - info2!("{}", i); - po.recv(); - i = i - 1; - } - - info2!("main thread exiting"); -} - -fn child(x: int, ch: &comm::SharedChan) { - info2!("{}", x); - ch.send(x); -} diff --git a/gcc/testsuite/rust.test/task-comm-15.rs b/gcc/testsuite/rust.test/task-comm-15.rs deleted file mode 100644 index 394b7e4..0000000 --- a/gcc/testsuite/rust.test/task-comm-15.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm; -use std::task; - -fn start(c: &comm::Chan, i0: int) { - let mut i = i0; - while i > 0 { - c.send(0); - i = i - 1; - } -} - -pub fn main() { - // Spawn a task that sends us back messages. The parent task - // is likely to terminate before the child completes, so from - // the child's point of view the receiver may die. We should - // drop messages on the floor in this case, and not crash! - let (p, ch) = comm::stream(); - task::spawn(|| start(&ch, 10)); - p.recv(); -} diff --git a/gcc/testsuite/rust.test/task-comm-16.rs b/gcc/testsuite/rust.test/task-comm-16.rs deleted file mode 100644 index d5a4b1a..0000000 --- a/gcc/testsuite/rust.test/task-comm-16.rs +++ /dev/null @@ -1,116 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::comm; -use std::cmp; - -// Tests of ports and channels on various types -fn test_rec() { - struct R {val0: int, val1: u8, val2: char} - - let (po, ch) = comm::stream(); - let r0: R = R {val0: 0, val1: 1u8, val2: '2'}; - ch.send(r0); - let mut r1: R; - r1 = po.recv(); - assert_eq!(r1.val0, 0); - assert_eq!(r1.val1, 1u8); - assert_eq!(r1.val2, '2'); -} - -fn test_vec() { - let (po, ch) = comm::stream(); - let v0: ~[int] = ~[0, 1, 2]; - ch.send(v0); - let v1 = po.recv(); - assert_eq!(v1[0], 0); - assert_eq!(v1[1], 1); - assert_eq!(v1[2], 2); -} - -fn test_str() { - let (po, ch) = comm::stream(); - let s0 = ~"test"; - ch.send(s0); - let s1 = po.recv(); - assert_eq!(s1[0], 't' as u8); - assert_eq!(s1[1], 'e' as u8); - assert_eq!(s1[2], 's' as u8); - assert_eq!(s1[3], 't' as u8); -} - -enum t { - tag1, - tag2(int), - tag3(int, u8, char) -} - -impl cmp::Eq for t { - fn eq(&self, other: &t) -> bool { - match *self { - tag1 => { - match (*other) { - tag1 => true, - _ => false - } - } - tag2(e0a) => { - match (*other) { - tag2(e0b) => e0a == e0b, - _ => false - } - } - tag3(e0a, e1a, e2a) => { - match (*other) { - tag3(e0b, e1b, e2b) => - e0a == e0b && e1a == e1b && e2a == e2b, - _ => false - } - } - } - } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } -} - -fn test_tag() { - let (po, ch) = comm::stream(); - ch.send(tag1); - ch.send(tag2(10)); - ch.send(tag3(10, 11u8, 'A')); - let mut t1: t; - t1 = po.recv(); - assert_eq!(t1, tag1); - t1 = po.recv(); - assert_eq!(t1, tag2(10)); - t1 = po.recv(); - assert_eq!(t1, tag3(10, 11u8, 'A')); -} - -fn test_chan() { - let (po, ch) = comm::stream(); - let (po0, ch0) = comm::stream(); - ch.send(ch0); - let ch1 = po.recv(); - // Does the transmitted channel still work? - - ch1.send(10); - let mut i: int; - i = po0.recv(); - assert_eq!(i, 10); -} - -pub fn main() { - test_rec(); - test_vec(); - test_str(); - test_tag(); - test_chan(); -} diff --git a/gcc/testsuite/rust.test/task-comm-17.rs b/gcc/testsuite/rust.test/task-comm-17.rs deleted file mode 100644 index 47e0a71..0000000 --- a/gcc/testsuite/rust.test/task-comm-17.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #922 - -// This test is specifically about spawning temporary closures. - -extern mod extra; - -use std::task; - -fn f() { -} - -pub fn main() { - task::spawn(|| f() ); -} diff --git a/gcc/testsuite/rust.test/task-comm-3.rs b/gcc/testsuite/rust.test/task-comm-3.rs deleted file mode 100644 index b4a1a38..0000000 --- a/gcc/testsuite/rust.test/task-comm-3.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm::SharedChan; -use std::comm; -use std::task; - -pub fn main() { info2!("===== WITHOUT THREADS ====="); test00(); } - -fn test00_start(ch: &SharedChan, message: int, count: int) { - info2!("Starting test00_start"); - let mut i: int = 0; - while i < count { - info2!("Sending Message"); - ch.send(message + 0); - i = i + 1; - } - info2!("Ending test00_start"); -} - -fn test00() { - let number_of_tasks: int = 16; - let number_of_messages: int = 4; - - info2!("Creating tasks"); - - let (po, ch) = comm::stream(); - let ch = comm::SharedChan::new(ch); - - let mut i: int = 0; - - // Create and spawn tasks... - let mut results = ~[]; - while i < number_of_tasks { - let ch = ch.clone(); - let mut builder = task::task(); - results.push(builder.future_result()); - builder.spawn({ - let i = i; - || test00_start(&ch, i, number_of_messages) - }); - i = i + 1; - } - - // Read from spawned tasks... - let mut sum = 0; - for _r in results.iter() { - i = 0; - while i < number_of_messages { - let value = po.recv(); - sum += value; - i = i + 1; - } - } - - // Join spawned tasks... - for r in results.iter() { r.recv(); } - - info2!("Completed: Final number is: "); - error2!("{:?}", sum); - // assert (sum == (((number_of_tasks * (number_of_tasks - 1)) / 2) * - // number_of_messages)); - assert_eq!(sum, 480); -} diff --git a/gcc/testsuite/rust.test/task-comm-4.rs b/gcc/testsuite/rust.test/task-comm-4.rs deleted file mode 100644 index 80d981b..0000000 --- a/gcc/testsuite/rust.test/task-comm-4.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -use std::comm; - -pub fn main() { test00(); } - -fn test00() { - let mut r: int = 0; - let mut sum: int = 0; - let (p, c) = comm::stream(); - c.send(1); - c.send(2); - c.send(3); - c.send(4); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - c.send(5); - c.send(6); - c.send(7); - c.send(8); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - r = p.recv(); - sum += r; - info2!("{}", r); - assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); -} diff --git a/gcc/testsuite/rust.test/task-comm-5.rs b/gcc/testsuite/rust.test/task-comm-5.rs deleted file mode 100644 index 40cc7ef..0000000 --- a/gcc/testsuite/rust.test/task-comm-5.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::comm; - -pub fn main() { test00(); } - -fn test00() { - let _r: int = 0; - let mut sum: int = 0; - let (p, c) = comm::stream(); - let number_of_messages: int = 1000; - let mut i: int = 0; - while i < number_of_messages { c.send(i + 0); i += 1; } - i = 0; - while i < number_of_messages { sum += p.recv(); i += 1; } - assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); -} diff --git a/gcc/testsuite/rust.test/task-comm-6.rs b/gcc/testsuite/rust.test/task-comm-6.rs deleted file mode 100644 index b398ab4..0000000 --- a/gcc/testsuite/rust.test/task-comm-6.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -use std::comm::SharedChan; -use std::comm; - -pub fn main() { test00(); } - -fn test00() { - let mut r: int = 0; - let mut sum: int = 0; - let (p, ch) = comm::stream(); - let ch = SharedChan::new(ch); - let c0 = ch.clone(); - let c1 = ch.clone(); - let c2 = ch.clone(); - let c3 = ch.clone(); - let number_of_messages: int = 1000; - let mut i: int = 0; - while i < number_of_messages { - c0.send(i + 0); - c1.send(i + 0); - c2.send(i + 0); - c3.send(i + 0); - i += 1; - } - i = 0; - while i < number_of_messages { - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - i += 1; - } - assert_eq!(sum, 1998000); - // assert (sum == 4 * ((number_of_messages * - // (number_of_messages - 1)) / 2)); - -} diff --git a/gcc/testsuite/rust.test/task-comm-7.rs b/gcc/testsuite/rust.test/task-comm-7.rs deleted file mode 100644 index c7c16af..0000000 --- a/gcc/testsuite/rust.test/task-comm-7.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -#[allow(dead_assignment)]; - -extern mod extra; - -use std::comm; -use std::task; - -pub fn main() { test00(); } - -fn test00_start(c: &comm::SharedChan, start: int, number_of_messages: int) { - let mut i: int = 0; - while i < number_of_messages { c.send(start + i); i += 1; } -} - -fn test00() { - let mut r: int = 0; - let mut sum: int = 0; - let (p, ch) = comm::stream(); - let ch = comm::SharedChan::new(ch); - let number_of_messages: int = 10; - - let c = ch.clone(); - do task::spawn || { - test00_start(&c, number_of_messages * 0, number_of_messages); - } - let c = ch.clone(); - do task::spawn || { - test00_start(&c, number_of_messages * 1, number_of_messages); - } - let c = ch.clone(); - do task::spawn || { - test00_start(&c, number_of_messages * 2, number_of_messages); - } - let c = ch.clone(); - do task::spawn || { - test00_start(&c, number_of_messages * 3, number_of_messages); - } - - let mut i: int = 0; - while i < number_of_messages { - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - r = p.recv(); - sum += r; - i += 1; - } - - assert_eq!(sum, number_of_messages * 4 * (number_of_messages * 4 - 1) / 2); -} diff --git a/gcc/testsuite/rust.test/task-comm-9.rs b/gcc/testsuite/rust.test/task-comm-9.rs deleted file mode 100644 index 20d2220..0000000 --- a/gcc/testsuite/rust.test/task-comm-9.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm; -use std::task; - -pub fn main() { test00(); } - -fn test00_start(c: &comm::Chan, number_of_messages: int) { - let mut i: int = 0; - while i < number_of_messages { c.send(i + 0); i += 1; } -} - -fn test00() { - let r: int = 0; - let mut sum: int = 0; - let (p, ch) = comm::stream(); - let number_of_messages: int = 10; - - let mut builder = task::task(); - let result = builder.future_result(); - do builder.spawn { - test00_start(&ch, number_of_messages); - } - - let mut i: int = 0; - while i < number_of_messages { - sum += p.recv(); - info2!("{:?}", r); - i += 1; - } - - result.recv(); - - assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); -} diff --git a/gcc/testsuite/rust.test/task-comm-chan-nil.rs b/gcc/testsuite/rust.test/task-comm-chan-nil.rs deleted file mode 100644 index 8010089..0000000 --- a/gcc/testsuite/rust.test/task-comm-chan-nil.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -extern mod extra; - -use std::comm; - -// rustboot can't transmit nils across channels because they don't have -// any size, but rustc currently can because they do have size. Whether -// or not this is desirable I don't know, but here's a regression test. -pub fn main() { - let (po, ch) = comm::stream(); - ch.send(()); - let n: () = po.recv(); - assert_eq!(n, ()); -} diff --git a/gcc/testsuite/rust.test/task-killjoin-rsrc.rs b/gcc/testsuite/rust.test/task-killjoin-rsrc.rs deleted file mode 100644 index 10116e5..0000000 --- a/gcc/testsuite/rust.test/task-killjoin-rsrc.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test linked failure - -// A port of task-killjoin to use a class with a dtor to manage -// the join. - -use std::cell::Cell; -use std::comm::*; -use std::ptr; -use std::task; - -struct notify { - ch: Chan, v: @mut bool, -} - -#[unsafe_destructor] -impl Drop for notify { - fn drop(&mut self) { - unsafe { - error!("notify: task=%? v=%x unwinding=%b b=%b", - 0, - ptr::to_unsafe_ptr(&(*(self.v))) as uint, - task::failing(), - *(self.v)); - let b = *(self.v); - self.ch.send(b); - } - } -} - -fn notify(ch: Chan, v: @mut bool) -> notify { - notify { - ch: ch, - v: v - } -} - -fn joinable(f: ~fn()) -> Port { - fn wrapper(c: Chan, f: &fn()) { - let b = @mut false; - error!("wrapper: task=%? allocated v=%x", - 0, - ptr::to_unsafe_ptr(&(*b)) as uint); - let _r = notify(c, b); - f(); - *b = true; - } - let (p, c) = stream(); - let c = Cell::new(c); - do task::spawn_unlinked { - let ccc = c.take(); - wrapper(ccc, f) - } - p -} - -fn join(port: Port) -> bool { - port.recv() -} - -fn supervised() { - // Deschedule to make sure the supervisor joins before we - // fail. This is currently not needed because the supervisor - // runs first, but I can imagine that changing. - error!("supervised task=%?", 0); - task::deschedule(); - fail!(); -} - -fn supervisor() { - error!("supervisor task=%?", 0); - let t = joinable(supervised); - join(t); -} - -pub fn main() { - join(joinable(supervisor)); -} diff --git a/gcc/testsuite/rust.test/task-killjoin.rs b/gcc/testsuite/rust.test/task-killjoin.rs deleted file mode 100644 index cba1371..0000000 --- a/gcc/testsuite/rust.test/task-killjoin.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test linked failure - -// Create a task that is supervised by another task, join the supervised task -// from the supervising task, then fail the supervised task. The supervised -// task will kill the supervising task, waking it up. The supervising task no -// longer needs to be wakened when the supervised task exits. - -use std::task; - -fn supervised() { - // Deschedule to make sure the supervisor joins before we fail. This is - // currently not needed because the supervisor runs first, but I can - // imagine that changing. - task::deschedule(); - fail!(); -} - -fn supervisor() { - // Unsupervise this task so the process doesn't return a failure status as - // a result of the main task being killed. - let f = supervised; - task::try(supervised); -} - -pub fn main() { - task::spawn_unlinked(supervisor) -} diff --git a/gcc/testsuite/rust.test/task-life-0.rs b/gcc/testsuite/rust.test/task-life-0.rs deleted file mode 100644 index b58fe2a..0000000 --- a/gcc/testsuite/rust.test/task-life-0.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -pub fn main() { - task::spawn(|| child(~"Hello") ); -} - -fn child(_s: ~str) { - -} diff --git a/gcc/testsuite/rust.test/task-spawn-move-and-copy.rs b/gcc/testsuite/rust.test/task-spawn-move-and-copy.rs deleted file mode 100644 index 9269705..0000000 --- a/gcc/testsuite/rust.test/task-spawn-move-and-copy.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; -use std::task; - -pub fn main() { - let (p, ch) = stream::(); - - let x = ~1; - let x_in_parent = ptr::to_unsafe_ptr(&(*x)) as uint; - - task::spawn(|| { - let x_in_child = ptr::to_unsafe_ptr(&(*x)) as uint; - ch.send(x_in_child); - }); - - let x_in_child = p.recv(); - assert_eq!(x_in_parent, x_in_child); -} diff --git a/gcc/testsuite/rust.test/tempfile.rs b/gcc/testsuite/rust.test/tempfile.rs deleted file mode 100644 index 5d12f4e8..0000000 --- a/gcc/testsuite/rust.test/tempfile.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like 'extern mod extra' - -// These tests are here to exercise the functionality of the `tempfile` module. -// One might expect these tests to be located in that module, but sadly they -// cannot. The tests need to invoke `os::change_dir` which cannot be done in the -// normal test infrastructure. If the tests change the current working -// directory, then *all* tests which require relative paths suddenly break b/c -// they're in a different location than before. Hence, these tests are all run -// serially here. - -extern mod extra; - -use extra::tempfile::TempDir; -use std::os; -use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; -use std::task; -use std::cell::Cell; - -fn test_tempdir() { - let path = { - let p = TempDir::new_in(&Path::new("."), "foobar").unwrap(); - let p = p.path(); - assert!(p.as_vec().ends_with(bytes!("foobar"))); - p.clone() - }; - assert!(!os::path_exists(&path)); -} - -fn test_rm_tempdir() { - let (rd, wr) = stream(); - let f: ~fn() = || { - let tmp = TempDir::new("test_rm_tempdir").unwrap(); - wr.send(tmp.path().clone()); - fail2!("fail to unwind past `tmp`"); - }; - task::try(f); - let path = rd.recv(); - assert!(!os::path_exists(&path)); - - let tmp = TempDir::new("test_rm_tempdir").unwrap(); - let path = tmp.path().clone(); - let cell = Cell::new(tmp); - let f: ~fn() = || { - let _tmp = cell.take(); - fail2!("fail to unwind past `tmp`"); - }; - task::try(f); - assert!(!os::path_exists(&path)); - - let path; - { - let f: ~fn() -> TempDir = || { - TempDir::new("test_rm_tempdir").unwrap() - }; - let tmp = task::try(f).expect("test_rm_tmdir"); - path = tmp.path().clone(); - assert!(os::path_exists(&path)); - } - assert!(!os::path_exists(&path)); - - let path; - { - let tmp = TempDir::new("test_rm_tempdir").unwrap(); - path = tmp.unwrap(); - } - assert!(os::path_exists(&path)); - os::remove_dir_recursive(&path); - assert!(!os::path_exists(&path)); -} - -// Ideally these would be in std::os but then core would need -// to depend on std -fn recursive_mkdir_rel() { - let path = Path::new("frob"); - let cwd = os::getcwd(); - debug2!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.display(), - cwd.display(), os::path_exists(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); -} - -fn recursive_mkdir_dot() { - let dot = Path::new("."); - assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - let dotdot = Path::new(".."); - assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); -} - -fn recursive_mkdir_rel_2() { - let path = Path::new("./frob/baz"); - let cwd = os::getcwd(); - debug2!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.display(), - cwd.display(), os::path_exists(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); - assert!(os::path_is_dir(&path.dir_path())); - let path2 = Path::new("quux/blat"); - debug2!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(), - cwd.display()); - assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path2)); - assert!(os::path_is_dir(&path2.dir_path())); -} - -// Ideally this would be in core, but needs TempFile -pub fn test_rmdir_recursive_ok() { - let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32; - - let tmpdir = TempDir::new("test").expect("test_rmdir_recursive_ok: \ - couldn't create temp dir"); - let tmpdir = tmpdir.path(); - let root = tmpdir.join("foo"); - - debug2!("making {}", root.display()); - assert!(os::make_dir(&root, rwx)); - assert!(os::make_dir(&root.join("foo"), rwx)); - assert!(os::make_dir(&root.join("foo").join("bar"), rwx)); - assert!(os::make_dir(&root.join("foo").join("bar").join("blat"), rwx)); - assert!(os::remove_dir_recursive(&root)); - assert!(!os::path_exists(&root)); - assert!(!os::path_exists(&root.join("bar"))); - assert!(!os::path_exists(&root.join("bar").join("blat"))); -} - -fn in_tmpdir(f: &fn()) { - let tmpdir = TempDir::new("test").expect("can't make tmpdir"); - assert!(os::change_dir(tmpdir.path())); - - f(); -} - -fn main() { - in_tmpdir(test_tempdir); - in_tmpdir(test_rm_tempdir); - in_tmpdir(recursive_mkdir_rel); - in_tmpdir(recursive_mkdir_dot); - in_tmpdir(recursive_mkdir_rel_2); - in_tmpdir(test_rmdir_recursive_ok); -} diff --git a/gcc/testsuite/rust.test/terminate-in-initializer.rs b/gcc/testsuite/rust.test/terminate-in-initializer.rs deleted file mode 100644 index 37cbc2b..0000000 --- a/gcc/testsuite/rust.test/terminate-in-initializer.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #787 -// Don't try to clean up uninitialized locals - -extern mod extra; - -use std::task; - -fn test_break() { loop { let _x: @int = break; } } - -fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: @int = continue; } } - -fn test_ret() { let _x: @int = return; } - -fn test_fail() { - fn f() { let _x: @int = fail2!(); } - task::try(|| f() ); -} - -fn test_fail_indirect() { - fn f() -> ! { fail2!(); } - fn g() { let _x: @int = f(); } - task::try(|| g() ); -} - -pub fn main() { - test_break(); - test_cont(); - test_ret(); - test_fail(); - test_fail_indirect(); -} diff --git a/gcc/testsuite/rust.test/test-ignore-cfg.rs b/gcc/testsuite/rust.test/test-ignore-cfg.rs deleted file mode 100644 index 6e6670e..0000000 --- a/gcc/testsuite/rust.test/test-ignore-cfg.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: --test --cfg ignorecfg -// xfail-fast - -extern mod extra; - -#[test] -#[ignore(cfg(ignorecfg))] -fn shouldignore() { -} - -#[test] -#[ignore(cfg(noignorecfg))] -fn shouldnotignore() { -} - -#[test] -fn checktests() { - // Pull the tests out of the secreturn test module - let tests = __test::TESTS; - - assert!( - tests.iter().any(|t| t.desc.name.to_str() == ~"shouldignore" && t.desc.ignore)); - - assert!( - tests.iter().any(|t| t.desc.name.to_str() == ~"shouldnotignore" && !t.desc.ignore)); -} diff --git a/gcc/testsuite/rust.test/test-runner-hides-main.rs b/gcc/testsuite/rust.test/test-runner-hides-main.rs deleted file mode 100644 index a399d22..0000000 --- a/gcc/testsuite/rust.test/test-runner-hides-main.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:--test -// xfail-fast - -extern mod extra; - -// Building as a test runner means that a synthetic main will be run, -// not ours -pub fn main() { fail2!(); } diff --git a/gcc/testsuite/rust.test/threads.rs b/gcc/testsuite/rust.test/threads.rs deleted file mode 100644 index 81fcfd7..0000000 --- a/gcc/testsuite/rust.test/threads.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -pub fn main() { - let mut i = 10; - while i > 0 { task::spawn({let i = i; || child(i)}); i = i - 1; } - info2!("main thread exiting"); -} - -fn child(x: int) { info2!("{}", x); } diff --git a/gcc/testsuite/rust.test/trait-bounds-basic.rs b/gcc/testsuite/rust.test/trait-bounds-basic.rs deleted file mode 100644 index 9fef70a..0000000 --- a/gcc/testsuite/rust.test/trait-bounds-basic.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { -} - -fn a(_x: ~Foo:) { -} - -fn b(_x: ~Foo:Send) { -} - -fn c(x: ~Foo:Freeze+Send) { - a(x); -} - -fn d(x: ~Foo:Send) { - b(x); -} - -fn e(x: ~Foo) { // sugar for ~Foo:Owned - b(x); -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/trait-bounds-in-arc.rs b/gcc/testsuite/rust.test/trait-bounds-in-arc.rs deleted file mode 100644 index a4510ef..0000000 --- a/gcc/testsuite/rust.test/trait-bounds-in-arc.rs +++ /dev/null @@ -1,105 +0,0 @@ -// xfail-pretty - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that a heterogeneous list of existential types can be put inside an Arc -// and shared between tasks as long as all types fulfill Freeze+Send. - -// xfail-fast - -extern mod extra; -use extra::arc; -use std::comm; -use std::task; -use std::cell; - -trait Pet { - fn name(&self, blk: &fn(&str)); - fn num_legs(&self) -> uint; - fn of_good_pedigree(&self) -> bool; -} - -struct Catte { - num_whiskers: uint, - name: ~str, -} - -struct Dogge { - bark_decibels: uint, - tricks_known: uint, - name: ~str, -} - -struct Goldfyshe { - swim_speed: uint, - name: ~str, -} - -impl Pet for Catte { - fn name(&self, blk: &fn(&str)) { blk(self.name) } - fn num_legs(&self) -> uint { 4 } - fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 } -} -impl Pet for Dogge { - fn name(&self, blk: &fn(&str)) { blk(self.name) } - fn num_legs(&self) -> uint { 4 } - fn of_good_pedigree(&self) -> bool { - self.bark_decibels < 70 || self.tricks_known > 20 - } -} -impl Pet for Goldfyshe { - fn name(&self, blk: &fn(&str)) { blk(self.name) } - fn num_legs(&self) -> uint { 0 } - fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 } -} - -fn main() { - let catte = Catte { num_whiskers: 7, name: ~"alonzo_church" }; - let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" }; - let dogge2 = Dogge { bark_decibels: 55, tricks_known: 11, name: ~"albert_einstein" }; - let fishe = Goldfyshe { swim_speed: 998, name: ~"alec_guinness" }; - let arc = arc::Arc::new(~[~catte as ~Pet:Freeze+Send, - ~dogge1 as ~Pet:Freeze+Send, - ~fishe as ~Pet:Freeze+Send, - ~dogge2 as ~Pet:Freeze+Send]); - let (p1,c1) = comm::stream(); - let arc1 = cell::Cell::new(arc.clone()); - do task::spawn { check_legs(arc1.take()); c1.send(()); } - let (p2,c2) = comm::stream(); - let arc2 = cell::Cell::new(arc.clone()); - do task::spawn { check_names(arc2.take()); c2.send(()); } - let (p3,c3) = comm::stream(); - let arc3 = cell::Cell::new(arc.clone()); - do task::spawn { check_pedigree(arc3.take()); c3.send(()); } - p1.recv(); - p2.recv(); - p3.recv(); -} - -fn check_legs(arc: arc::Arc<~[~Pet:Freeze+Send]>) { - let mut legs = 0; - for pet in arc.get().iter() { - legs += pet.num_legs(); - } - assert!(legs == 12); -} -fn check_names(arc: arc::Arc<~[~Pet:Freeze+Send]>) { - for pet in arc.get().iter() { - do pet.name |name| { - assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8); - } - } -} -fn check_pedigree(arc: arc::Arc<~[~Pet:Freeze+Send]>) { - for pet in arc.get().iter() { - assert!(pet.of_good_pedigree()); - } -} diff --git a/gcc/testsuite/rust.test/trait-bounds-recursion.rs b/gcc/testsuite/rust.test/trait-bounds-recursion.rs deleted file mode 100644 index 49f8999..0000000 --- a/gcc/testsuite/rust.test/trait-bounds-recursion.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait I { fn i(&self) -> Self; } - -trait A { - fn id(x:T) -> T { x.i() } -} - -trait J { fn j(&self) -> Self; } - -trait B> { - fn id(x:T) -> T { x.j() } -} - -trait C { - fn id>(x:T) -> T { x.j() } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/trait-bounds.rs b/gcc/testsuite/rust.test/trait-bounds.rs deleted file mode 100644 index 7ec6ffb..0000000 --- a/gcc/testsuite/rust.test/trait-bounds.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait connection { - fn read(&self) -> int; -} - -trait connection_factory { - fn create(&self) -> C; -} - -type my_connection = (); -type my_connection_factory = (); - -impl connection for () { - fn read(&self) -> int { 43 } -} - -impl connection_factory for my_connection_factory { - fn create(&self) -> my_connection { () } -} - -pub fn main() { - let factory = (); - let connection = factory.create(); - let result = connection.read(); - assert_eq!(result, 43); -} diff --git a/gcc/testsuite/rust.test/trait-cast.rs b/gcc/testsuite/rust.test/trait-cast.rs deleted file mode 100644 index 0d62466..0000000 --- a/gcc/testsuite/rust.test/trait-cast.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test cyclic detector when using trait instances. - -struct Tree(@mut TreeR); -struct TreeR { - left: Option, - right: Option, - val: ~to_str -} - -trait to_str { - fn to_str_(&self) -> ~str; -} - -impl to_str for Option { - fn to_str_(&self) -> ~str { - match *self { - None => { ~"none" } - Some(ref t) => { ~"some(" + t.to_str_() + ~")" } - } - } -} - -impl to_str for int { - fn to_str_(&self) -> ~str { self.to_str() } -} - -impl to_str for Tree { - fn to_str_(&self) -> ~str { - let (l, r) = (self.left, self.right); - let val = &self.val; - format!("[{}, {}, {}]", val.to_str_(), l.to_str_(), r.to_str_()) - } -} - -fn foo(x: T) -> ~str { x.to_str_() } - -pub fn main() { - let t1 = Tree(@mut TreeR{left: None, - right: None, - val: ~1 as ~to_str }); - let t2 = Tree(@mut TreeR{left: Some(t1), - right: Some(t1), - val: ~2 as ~to_str }); - let expected = ~"[2, some([1, none, none]), some([1, none, none])]"; - assert!(t2.to_str_() == expected); - assert!(foo(t2) == expected); - t1.left = Some(t2); // create cycle -} diff --git a/gcc/testsuite/rust.test/trait-composition-trivial.rs b/gcc/testsuite/rust.test/trait-composition-trivial.rs deleted file mode 100644 index de130bf..0000000 --- a/gcc/testsuite/rust.test/trait-composition-trivial.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn foo(&self); -} - -trait Bar : Foo { - fn bar(&self); -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/trait-default-method-bound-subst.rs b/gcc/testsuite/rust.test/trait-default-method-bound-subst.rs deleted file mode 100644 index ff0c23b..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-bound-subst.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait A { - fn g(&self, x: T, y: U) -> (T, U) { (x, y) } -} - -impl A for int { } -impl A for uint { } - -fn f>(i: V, j: T, k: U) -> (T, U) { - i.g(j, k) -} - -pub fn main () { - assert_eq!(f(0, 1, 2), (1, 2)); - assert_eq!(f(0u, 1, 2), (1, 2)); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-bound-subst2.rs b/gcc/testsuite/rust.test/trait-default-method-bound-subst2.rs deleted file mode 100644 index 1ea3879..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-bound-subst2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait A { - fn g(&self, x: T) -> T { x } -} - -impl A for int { } - -fn f>(i: V, j: T) -> T { - i.g(j) -} - -pub fn main () { - assert_eq!(f(0, 2), 2); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-bound-subst3.rs b/gcc/testsuite/rust.test/trait-default-method-bound-subst3.rs deleted file mode 100644 index aff20ff..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-bound-subst3.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait A { - fn g(&self, x: T, y: T) -> (T, T) { (x, y) } -} - -impl A for int { } - -fn f(i: V, j: T, k: T) -> (T, T) { - i.g(j, k) -} - -pub fn main () { - assert_eq!(f(0, 1, 2), (1, 2)); - assert_eq!(f(0, 1u8, 2u8), (1u8, 2u8)); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-bound-subst4.rs b/gcc/testsuite/rust.test/trait-default-method-bound-subst4.rs deleted file mode 100644 index fdc42e5..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-bound-subst4.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait A { - fn g(&self, x: uint) -> uint { x } -} - -impl A for int { } - -fn f>(i: V, j: uint) -> uint { - i.g(j) -} - -pub fn main () { - assert_eq!(f::(0, 2u), 2u); - assert_eq!(f::(0, 2u), 2u); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-bound.rs b/gcc/testsuite/rust.test/trait-default-method-bound.rs deleted file mode 100644 index 8a2f1b1..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-bound.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait A { - fn g(&self) -> int { 10 } -} - -impl A for int { } - -fn f(i: T) { - assert_eq!(i.g(), 10); -} - -pub fn main () { - f(0); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-xc-2.rs b/gcc/testsuite/rust.test/trait-default-method-xc-2.rs deleted file mode 100644 index 1dad5d2..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-xc-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// xfail-fast -// aux-build:trait_default_method_xc_aux.rs -// aux-build:trait_default_method_xc_aux_2.rs - - -extern mod aux(name = "trait_default_method_xc_aux"); -extern mod aux2(name = "trait_default_method_xc_aux_2"); -use aux::A; -use aux2::{a_struct, welp}; - - -fn main () { - - let a = a_struct { x: 0 }; - let b = a_struct { x: 1 }; - - assert_eq!(0i.g(), 10); - assert_eq!(a.g(), 10); - assert_eq!(a.h(), 11); - assert_eq!(b.g(), 10); - assert_eq!(b.h(), 11); - assert_eq!(A::lurr(&a, &b), 21); - - welp(&0); -} diff --git a/gcc/testsuite/rust.test/trait-default-method-xc.rs b/gcc/testsuite/rust.test/trait-default-method-xc.rs deleted file mode 100644 index 1013a12..0000000 --- a/gcc/testsuite/rust.test/trait-default-method-xc.rs +++ /dev/null @@ -1,81 +0,0 @@ -// xfail-fast -// aux-build:trait_default_method_xc_aux.rs - - -extern mod aux(name = "trait_default_method_xc_aux"); -use aux::{A, TestEquality, Something}; -use aux::B; - -fn f(i: T) { - assert_eq!(i.g(), 10); -} - -fn welp(i: int, _x: &T) -> int { - i.g() -} - -mod stuff { - pub struct thing { x: int } -} - -impl A for stuff::thing { - fn f(&self) -> int { 10 } -} - -fn g>(i: V, j: T, k: U) -> (T, U) { - i.thing(j, k) -} - -fn eq(lhs: &T, rhs: &T) -> bool { - lhs.test_eq(rhs) -} -fn neq(lhs: &T, rhs: &T) -> bool { - lhs.test_neq(rhs) -} - - -impl TestEquality for stuff::thing { - fn test_eq(&self, rhs: &stuff::thing) -> bool { - //self.x.test_eq(&rhs.x) - eq(&self.x, &rhs.x) - } -} - - -fn main () { - // Some tests of random things - f(0); - - assert_eq!(A::lurr(&0, &1), 21); - - let a = stuff::thing { x: 0 }; - let b = stuff::thing { x: 1 }; - let c = Something { x: 1 }; - - assert_eq!(0i.g(), 10); - assert_eq!(a.g(), 10); - assert_eq!(a.h(), 11); - assert_eq!(c.h(), 11); - - assert_eq!(0i.thing(3.14, 1), (3.14, 1)); - assert_eq!(B::staticthing(&0i, 3.14, 1), (3.14, 1)); - assert_eq!(B::::staticthing::(&0i, 3.14, 1), (3.14, 1)); - - assert_eq!(g(0i, 3.14, 1), (3.14, 1)); - assert_eq!(g(false, 3.14, 1), (3.14, 1)); - - let obj = @0i as @A; - assert_eq!(obj.h(), 11); - - - // Trying out a real one - assert!(12.test_neq(&10)); - assert!(!10.test_neq(&10)); - assert!(a.test_neq(&b)); - assert!(!a.test_neq(&a)); - - assert!(neq(&12, &10)); - assert!(!neq(&10, &10)); - assert!(neq(&a, &b)); - assert!(!neq(&a, &a)); -} diff --git a/gcc/testsuite/rust.test/trait-generic.rs b/gcc/testsuite/rust.test/trait-generic.rs deleted file mode 100644 index f448bcb..0000000 --- a/gcc/testsuite/rust.test/trait-generic.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -trait to_str { - fn to_string(&self) -> ~str; -} -impl to_str for int { - fn to_string(&self) -> ~str { self.to_str() } -} -impl to_str for ~str { - fn to_string(&self) -> ~str { self.clone() } -} -impl to_str for () { - fn to_string(&self) -> ~str { ~"()" } -} - -trait map { - fn map(&self, f: &fn(&T) -> U) -> ~[U]; -} -impl map for ~[T] { - fn map(&self, f: &fn(&T) -> U) -> ~[U] { - let mut r = ~[]; - // FIXME: #7355 generates bad code with VecIterator - for i in range(0u, self.len()) { - r.push(f(&self[i])); - } - r - } -} - -fn foo>(x: T) -> ~[~str] { - x.map(|_e| ~"hi" ) -} -fn bar>(x: T) -> ~[~str] { - x.map(|_e| _e.to_string() ) -} - -pub fn main() { - assert_eq!(foo(~[1]), ~[~"hi"]); - assert_eq!(bar::(~[4, 5]), ~[~"4", ~"5"]); - assert_eq!(bar::<~str, ~[~str]>(~[~"x", ~"y"]), ~[~"x", ~"y"]); - assert_eq!(bar::<(), ~[()]>(~[()]), ~[~"()"]); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-auto-xc-2.rs b/gcc/testsuite/rust.test/trait-inheritance-auto-xc-2.rs deleted file mode 100644 index 3f8d536..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-auto-xc-2.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:trait_inheritance_auto_xc_2_aux.rs - -extern mod aux(name = "trait_inheritance_auto_xc_2_aux"); - -// aux defines impls of Foo, Bar and Baz for A -use aux::{Foo, Bar, Baz, A}; - -// We want to extend all Foo, Bar, Bazes to Quuxes -pub trait Quux: Foo + Bar + Baz { } -impl Quux for T { } - -fn f(a: &T) { - assert_eq!(a.f(), 10); - assert_eq!(a.g(), 20); - assert_eq!(a.h(), 30); -} - -pub fn main() { - let a = &A { x: 3 }; - f(a); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-auto-xc.rs b/gcc/testsuite/rust.test/trait-inheritance-auto-xc.rs deleted file mode 100644 index 2e8883f..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-auto-xc.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:trait_inheritance_auto_xc_aux.rs - -extern mod aux(name = "trait_inheritance_auto_xc_aux"); - -use aux::{Foo, Bar, Baz, Quux}; - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } - -fn f(a: &T) { - assert_eq!(a.f(), 10); - assert_eq!(a.g(), 20); - assert_eq!(a.h(), 30); -} - -pub fn main() { - let a = &A { x: 3 }; - f(a); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-auto.rs b/gcc/testsuite/rust.test/trait-inheritance-auto.rs deleted file mode 100644 index c5a7720..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-auto.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing that this impl turns A into a Quux, because -// A is already a Foo Bar Baz -impl Quux for T { } - -trait Foo { fn f(&self) -> int; } -trait Bar { fn g(&self) -> int; } -trait Baz { fn h(&self) -> int; } - -trait Quux: Foo + Bar + Baz { } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } - -fn f(a: &T) { - assert_eq!(a.f(), 10); - assert_eq!(a.g(), 20); - assert_eq!(a.h(), 30); -} - -pub fn main() { - let a = &A { x: 3 }; - f(a); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited.rs b/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited.rs deleted file mode 100644 index 4625890..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } - -// Call a function on Foo, given a T: Bar -fn gg(a: &T) -> int { - a.f() -} - -pub fn main() { - let a = &A { x: 3 }; - assert_eq!(gg(a), 10); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited2.rs b/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited2.rs deleted file mode 100644 index 7b79ad4..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-call-bound-inherited2.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } -trait Baz : Bar { fn h(&self) -> int; } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } - -// Call a function on Foo, given a T: Baz, -// which is inherited via Bar -fn gg(a: &T) -> int { - a.f() -} - -pub fn main() { - let a = &A { x: 3 }; - assert_eq!(gg(a), 10); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-cast-without-call-to-supertrait.rs b/gcc/testsuite/rust.test/trait-inheritance-cast-without-call-to-supertrait.rs deleted file mode 100644 index 68a31ba..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-cast-without-call-to-supertrait.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing that we can cast to a subtrait and call subtrait -// methods. Not testing supertrait methods - -trait Foo { - fn f(&self) -> int; -} - -trait Bar : Foo { - fn g(&self) -> int; -} - -struct A { - x: int -} - -impl Foo for A { - fn f(&self) -> int { 10 } -} - -impl Bar for A { - fn g(&self) -> int { 20 } -} - -pub fn main() { - let a = &A { x: 3 }; - let afoo = a as &Foo; - let abar = a as &Bar; - assert_eq!(afoo.f(), 10); - assert_eq!(abar.g(), 20); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-cast.rs b/gcc/testsuite/rust.test/trait-inheritance-cast.rs deleted file mode 100644 index 1f69ba2..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-cast.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// Testing that supertrait methods can be called on subtrait object types -// It's not clear yet that we want this - -trait Foo { - fn f() -> int; -} - -trait Bar : Foo { - fn g() -> int; -} - -struct A { - x: int -} - -impl Foo for A { - fn f() -> int { 10 } -} - -impl Bar for A { - fn g() -> int { 20 } -} - -pub fn main() { - let a = &A { x: 3 }; - let afoo = a as &Foo; - let abar = a as &Bar; - assert_eq!(afoo.f(), 10); - assert_eq!(abar.g(), 20); - assert_eq!(abar.f(), 10); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call-xc.rs b/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call-xc.rs deleted file mode 100644 index eddec87..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call-xc.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:trait_inheritance_cross_trait_call_xc_aux.rs - -extern mod aux(name = "trait_inheritance_cross_trait_call_xc_aux"); - -use aux::Foo; - -trait Bar : Foo { - fn g(&self) -> int; -} - -impl Bar for aux::A { - fn g(&self) -> int { self.f() } -} - -pub fn main() { - let a = &aux::A { x: 3 }; - assert_eq!(a.g(), 10); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call.rs b/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call.rs deleted file mode 100644 index 7b047b5..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-cross-trait-call.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } - -impl Bar for A { - // Testing that this impl can call the impl of Foo - fn g(&self) -> int { self.f() } -} - -pub fn main() { - let a = &A { x: 3 }; - assert_eq!(a.g(), 10); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-diamond.rs b/gcc/testsuite/rust.test/trait-inheritance-diamond.rs deleted file mode 100644 index 253c10a..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-diamond.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// B and C both require A, so D does as well, twice, but that's just fine - -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } -trait D: B + C { fn d(&self) -> int; } - -struct S { bogus: () } - -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } -impl D for S { fn d(&self) -> int { 40 } } - -fn f(x: &T) { - assert_eq!(x.a(), 10); - assert_eq!(x.b(), 20); - assert_eq!(x.c(), 30); - assert_eq!(x.d(), 40); -} - -pub fn main() { - let value = &S { bogus: () }; - f(value); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-multiple-inheritors.rs b/gcc/testsuite/rust.test/trait-inheritance-multiple-inheritors.rs deleted file mode 100644 index 6cd3d62..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-multiple-inheritors.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } - -struct S { bogus: () } - -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } - -// Both B and C inherit from A -fn f(x: &T) { - assert_eq!(x.a(), 10); - assert_eq!(x.b(), 20); - assert_eq!(x.c(), 30); -} - -pub fn main() { - f(&S { bogus: () }) -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-multiple-params.rs b/gcc/testsuite/rust.test/trait-inheritance-multiple-params.rs deleted file mode 100644 index b5524c6..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-multiple-params.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } - -struct S { bogus: () } - -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } - -// Multiple type params, multiple levels of inheritance -fn f(x: &X, y: &Y, z: &Z) { - assert_eq!(x.a(), 10); - assert_eq!(y.a(), 10); - assert_eq!(y.b(), 20); - assert_eq!(z.a(), 10); - assert_eq!(z.c(), 30); -} - -pub fn main() { - let s = &S { bogus: () }; - f(s, s, s); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num.rs b/gcc/testsuite/rust.test/trait-inheritance-num.rs deleted file mode 100644 index 8d3c258..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num.rs +++ /dev/null @@ -1,25 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::cmp::{Eq, Ord}; -use std::num::NumCast; - -pub trait NumExt: Num + NumCast + Eq + Ord {} - -pub trait FloatExt: NumExt + ApproxEq {} - -fn greater_than_one(n: &T) -> bool { *n > NumCast::from(1).unwrap() } -fn greater_than_one_float(n: &T) -> bool { *n > NumCast::from(1).unwrap() } - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num0.rs b/gcc/testsuite/rust.test/trait-inheritance-num0.rs deleted file mode 100644 index 46efac8..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num0.rs +++ /dev/null @@ -1,28 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Extending Num and using inherited static methods - -use std::num::NumCast; - -trait Num { - fn from_int(i: int) -> Self; - fn gt(&self, other: &Self) -> bool; -} - -pub trait NumExt: Num + NumCast { } - -fn greater_than_one(n: &T) -> bool { - n.gt(&NumCast::from(1).unwrap()) -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num1.rs b/gcc/testsuite/rust.test/trait-inheritance-num1.rs deleted file mode 100644 index 28abae1..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num1.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Ord; -use std::num::NumCast; - -pub trait NumExt: Num + NumCast + Ord { } - -fn greater_than_one(n: &T) -> bool { - *n > NumCast::from(1).unwrap() -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num2.rs b/gcc/testsuite/rust.test/trait-inheritance-num2.rs deleted file mode 100644 index 994941b..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num2.rs +++ /dev/null @@ -1,102 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A more complex example of numeric extensions - -extern mod extra; - -use std::cmp::{Eq, Ord}; - -pub trait TypeExt {} - - -impl TypeExt for u8 {} -impl TypeExt for u16 {} -impl TypeExt for u32 {} -impl TypeExt for u64 {} -impl TypeExt for uint {} - -impl TypeExt for i8 {} -impl TypeExt for i16 {} -impl TypeExt for i32 {} -impl TypeExt for i64 {} -impl TypeExt for int {} - -impl TypeExt for f32 {} -impl TypeExt for f64 {} - - -pub trait NumExt: TypeExt + Eq + Ord + Num + NumCast {} - -impl NumExt for u8 {} -impl NumExt for u16 {} -impl NumExt for u32 {} -impl NumExt for u64 {} -impl NumExt for uint {} - -impl NumExt for i8 {} -impl NumExt for i16 {} -impl NumExt for i32 {} -impl NumExt for i64 {} -impl NumExt for int {} - -impl NumExt for f32 {} -impl NumExt for f64 {} - - -pub trait UnSignedExt: NumExt {} - -impl UnSignedExt for u8 {} -impl UnSignedExt for u16 {} -impl UnSignedExt for u32 {} -impl UnSignedExt for u64 {} -impl UnSignedExt for uint {} - - -pub trait SignedExt: NumExt {} - -impl SignedExt for i8 {} -impl SignedExt for i16 {} -impl SignedExt for i32 {} -impl SignedExt for i64 {} -impl SignedExt for int {} - -impl SignedExt for f32 {} -impl SignedExt for f64 {} - - -pub trait IntegerExt: NumExt {} - -impl IntegerExt for u8 {} -impl IntegerExt for u16 {} -impl IntegerExt for u32 {} -impl IntegerExt for u64 {} -impl IntegerExt for uint {} - -impl IntegerExt for i8 {} -impl IntegerExt for i16 {} -impl IntegerExt for i32 {} -impl IntegerExt for i64 {} -impl IntegerExt for int {} - - -pub trait FloatExt: NumExt + ApproxEq {} - -impl FloatExt for f32 {} -impl FloatExt for f64 {} - - -fn test_float_ext(n: T) { println!("{}", n < n) } - -pub fn main() { - test_float_ext(1f32); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num3.rs b/gcc/testsuite/rust.test/trait-inheritance-num3.rs deleted file mode 100644 index 7909f01..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num3.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::{Eq, Ord}; -use std::num::NumCast; - -pub trait NumExt: Eq + Ord + Num + NumCast {} - -impl NumExt for f32 {} - -fn num_eq_one(n: T) { - println!("{}", n == NumCast::from(1).unwrap()) -} - -pub fn main() { - num_eq_one(1f32); // you need to actually use the function to trigger the ICE -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-num5.rs b/gcc/testsuite/rust.test/trait-inheritance-num5.rs deleted file mode 100644 index 0310dde..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-num5.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Eq; -use std::num::NumCast; - -pub trait NumExt: Eq + Num + NumCast {} - -impl NumExt for f32 {} -impl NumExt for int {} - -fn num_eq_one() -> T { - NumCast::from(1).unwrap() -} - -pub fn main() { - num_eq_one::(); // you need to actually use the function to trigger the ICE -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-overloading-simple.rs b/gcc/testsuite/rust.test/trait-inheritance-overloading-simple.rs deleted file mode 100644 index 3a0f2dd..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-overloading-simple.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Eq; - -trait MyNum : Eq { } - -struct MyInt { val: int } - -impl Eq for MyInt { - fn eq(&self, other: &MyInt) -> bool { self.val == other.val } - fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } -} - -impl MyNum for MyInt {} - -fn f(x: T, y: T) -> bool { - return x == y; -} - -fn mi(v: int) -> MyInt { MyInt { val: v } } - -pub fn main() { - let (x, y, z) = (mi(3), mi(5), mi(3)); - assert!(x != y); - assert_eq!(x, z); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-overloading-xc-exe.rs b/gcc/testsuite/rust.test/trait-inheritance-overloading-xc-exe.rs deleted file mode 100644 index 84d54d9..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-overloading-xc-exe.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:trait_inheritance_overloading_xc.rs - -extern mod trait_inheritance_overloading_xc; -use trait_inheritance_overloading_xc::{MyNum, MyInt}; - -fn f(x: T, y: T) -> (T, T, T) { - return (x + y, x - y, x * y); -} - -fn mi(v: int) -> MyInt { MyInt { val: v } } - -pub fn main() { - let (x, y) = (mi(3), mi(5)); - let (a, b, c) = f(x, y); - assert_eq!(a, mi(8)); - assert_eq!(b, mi(-2)); - assert_eq!(c, mi(15)); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-overloading.rs b/gcc/testsuite/rust.test/trait-inheritance-overloading.rs deleted file mode 100644 index fb19bfa..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-overloading.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Eq; - -trait MyNum : Add + Sub + Mul + Eq { } - -struct MyInt { val: int } - -impl Add for MyInt { - fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } -} - -impl Sub for MyInt { - fn sub(&self, other: &MyInt) -> MyInt { mi(self.val - other.val) } -} - -impl Mul for MyInt { - fn mul(&self, other: &MyInt) -> MyInt { mi(self.val * other.val) } -} - -impl Eq for MyInt { - fn eq(&self, other: &MyInt) -> bool { self.val == other.val } - fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } -} - -impl MyNum for MyInt {} - -fn f(x: T, y: T) -> (T, T, T) { - return (x + y, x - y, x * y); -} - -fn mi(v: int) -> MyInt { MyInt { val: v } } - -pub fn main() { - let (x, y) = (mi(3), mi(5)); - let (a, b, c) = f(x, y); - assert_eq!(a, mi(8)); - assert_eq!(b, mi(-2)); - assert_eq!(c, mi(15)); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-self-in-supertype.rs b/gcc/testsuite/rust.test/trait-inheritance-self-in-supertype.rs deleted file mode 100644 index fac29e6..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-self-in-supertype.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Test for issue #4183: use of Self in supertraits. - -use std::num; - -pub static FUZZY_EPSILON: f64 = 0.1; - -pub trait FuzzyEq { - fn fuzzy_eq(&self, other: &Self) -> bool; - fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool; -} - -trait Float: FuzzyEq { - fn two_pi() -> Self; -} - -impl FuzzyEq for f32 { - fn fuzzy_eq(&self, other: &f32) -> bool { - self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32)) - } - - fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool { - num::abs(*self - *other) < *epsilon - } -} - -impl Float for f32 { - fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 } -} - -impl FuzzyEq for f64 { - fn fuzzy_eq(&self, other: &f64) -> bool { - self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64)) - } - - fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool { - num::abs(*self - *other) < *epsilon - } -} - -impl Float for f64 { - fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 } -} - -fn compare(f1: F) -> bool { - let f2 = Float::two_pi(); - f1.fuzzy_eq(&f2) -} - -pub fn main() { - assert!(compare::(6.28318530717958647692528676655900576)); - assert!(compare::(6.29)); - assert!(compare::(6.3)); - assert!(compare::(6.19)); - assert!(!compare::(7.28318530717958647692528676655900576)); - assert!(!compare::(6.18)); - - assert!(compare::(6.28318530717958647692528676655900576)); - assert!(compare::(6.29)); - assert!(compare::(6.3)); - assert!(compare::(6.19)); - assert!(!compare::(7.28318530717958647692528676655900576)); - assert!(!compare::(6.18)); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-self.rs b/gcc/testsuite/rust.test/trait-inheritance-self.rs deleted file mode 100644 index 75b71c6..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-self.rs +++ /dev/null @@ -1,28 +0,0 @@ -trait Foo { - fn f(&self, x: &T); -} - -trait Bar : Foo { - fn g(&self); -} - -struct S { - x: int -} - -impl Foo for S { - fn f(&self, x: &S) { - println(x.x.to_str()); - } -} - -impl Bar for S { - fn g(&self) { - self.f(self); - } -} - -pub fn main() { - let s = S { x: 1 }; - s.g(); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-simple.rs b/gcc/testsuite/rust.test/trait-inheritance-simple.rs deleted file mode 100644 index 113efa6..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-simple.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } - -fn ff(a: &T) -> int { - a.f() -} - -fn gg(a: &T) -> int { - a.g() -} - -pub fn main() { - let a = &A { x: 3 }; - assert_eq!(ff(a), 10); - assert_eq!(gg(a), 20); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-static.rs b/gcc/testsuite/rust.test/trait-inheritance-static.rs deleted file mode 100644 index 08543b2..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-static.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait MyNum { - fn from_int(int) -> Self; -} - -pub trait NumExt: MyNum { } - -struct S { v: int } - -impl MyNum for S { - fn from_int(i: int) -> S { - S { - v: i - } - } -} - -impl NumExt for S { } - -fn greater_than_one() -> T { MyNum::from_int(1) } - -pub fn main() { - let v: S = greater_than_one(); - assert_eq!(v.v, 1); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-static2.rs b/gcc/testsuite/rust.test/trait-inheritance-static2.rs deleted file mode 100644 index 9513117..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-static2.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait MyEq { } - -trait MyNum { - fn from_int(int) -> Self; -} - -pub trait NumExt: MyEq + MyNum { } - -struct S { v: int } - -impl MyEq for S { } - -impl MyNum for S { - fn from_int(i: int) -> S { - S { - v: i - } - } -} - -impl NumExt for S { } - -fn greater_than_one() -> T { MyNum::from_int(1) } - -pub fn main() { - let v: S = greater_than_one(); - assert_eq!(v.v, 1); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-subst.rs b/gcc/testsuite/rust.test/trait-inheritance-subst.rs deleted file mode 100644 index cd57e6a..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-subst.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait Add { - fn add(&self, rhs: &RHS) -> Result; -} - -trait MyNum : Add { } - -struct MyInt { val: int } - -impl Add for MyInt { - fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } -} - -impl MyNum for MyInt {} - -fn f(x: T, y: T) -> T { - return x.add(&y); -} - -fn mi(v: int) -> MyInt { MyInt { val: v } } - -pub fn main() { - let (x, y) = (mi(3), mi(5)); - let z = f(x, y); - assert!(z.val == 8) -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-subst2.rs b/gcc/testsuite/rust.test/trait-inheritance-subst2.rs deleted file mode 100644 index ebddfaf..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-subst2.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Panda { - fn chomp(&self, bamboo: &T) -> T; -} - -trait Add: Panda { - fn add(&self, rhs: &RHS) -> Result; -} - -trait MyNum : Add { } - -struct MyInt { val: int } - -impl Panda for MyInt { - fn chomp(&self, bamboo: &MyInt) -> MyInt { - mi(self.val + bamboo.val) - } -} - -impl Add for MyInt { - fn add(&self, other: &MyInt) -> MyInt { self.chomp(other) } -} - -impl MyNum for MyInt {} - -fn f(x: T, y: T) -> T { - return x.add(&y).chomp(&y); -} - -fn mi(v: int) -> MyInt { MyInt { val: v } } - -pub fn main() { - let (x, y) = (mi(3), mi(5)); - let z = f(x, y); - assert_eq!(z.val, 13); -} diff --git a/gcc/testsuite/rust.test/trait-inheritance-visibility.rs b/gcc/testsuite/rust.test/trait-inheritance-visibility.rs deleted file mode 100644 index 3cdedd8..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance-visibility.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod traits { - pub trait Foo { fn f(&self) -> int; } - - impl Foo for int { fn f(&self) -> int { 10 } } -} - -trait Quux: traits::Foo { } -impl Quux for T { } - -// Foo is not in scope but because Quux is we can still access -// Foo's methods on a Quux bound typaram -fn f(x: &T) { - assert_eq!(x.f(), 10); -} - -pub fn main() { - f(&0) -} diff --git a/gcc/testsuite/rust.test/trait-inheritance2.rs b/gcc/testsuite/rust.test/trait-inheritance2.rs deleted file mode 100644 index 7fa895d..0000000 --- a/gcc/testsuite/rust.test/trait-inheritance2.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { fn f(&self) -> int; } -trait Bar { fn g(&self) -> int; } -trait Baz { fn h(&self) -> int; } - -trait Quux: Foo + Bar + Baz { } - -struct A { x: int } - -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } -impl Quux for A {} - -fn f(a: &T) { - assert_eq!(a.f(), 10); - assert_eq!(a.g(), 20); - assert_eq!(a.h(), 30); -} - -pub fn main() { - let a = &A { x: 3 }; - f(a); -} diff --git a/gcc/testsuite/rust.test/trait-object-generics.rs b/gcc/testsuite/rust.test/trait-object-generics.rs deleted file mode 100644 index 3629316..0000000 --- a/gcc/testsuite/rust.test/trait-object-generics.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// test for #8664 - -pub trait Trait2 { - fn doit(&self); -} - -pub struct Impl { - /* - * With A2 we get the ICE: - * task failed at 'index out of bounds: the len is 1 but the index is 1', /home/tortue/rust_compiler_newest/src/librustc/middle/subst.rs:58 - */ - t: ~Trait2 -} - -impl Impl { - pub fn step(&self) { - self.t.doit() - } -} - -// test for #8601 - -enum Type { Constant } - -trait Trait { - fn method(&self,Type<(K,V)>) -> int; -} - -impl Trait for () { - fn method(&self, _x: Type<(u8,V)>) -> int { 0 } -} - -pub fn main () { - let a = @() as @Trait; - assert_eq!(a.method(Constant), 0); -} diff --git a/gcc/testsuite/rust.test/trait-region-pointer-simple.rs b/gcc/testsuite/rust.test/trait-region-pointer-simple.rs deleted file mode 100644 index 0b54ccb..0000000 --- a/gcc/testsuite/rust.test/trait-region-pointer-simple.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn f(&self) -> int; -} - -struct A { - x: int -} - -impl Foo for A { - fn f(&self) -> int { - println(~"Today's number is " + self.x.to_str()); - return self.x; - } -} - -pub fn main() { - let a = A { x: 3 }; - let b = (&a) as &Foo; - assert_eq!(b.f(), 3); -} diff --git a/gcc/testsuite/rust.test/trait-static-method-overwriting.rs b/gcc/testsuite/rust.test/trait-static-method-overwriting.rs deleted file mode 100644 index 5ac26e6..0000000 --- a/gcc/testsuite/rust.test/trait-static-method-overwriting.rs +++ /dev/null @@ -1,46 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod base { - use std::io; - - pub trait HasNew { - fn new() -> Self; - } - - pub struct Foo { - dummy: (), - } - - impl ::base::HasNew for Foo { - fn new() -> Foo { - println("Foo"); - Foo { dummy: () } - } - } - - pub struct Bar { - dummy: (), - } - - impl ::base::HasNew for Bar { - fn new() -> Bar { - io::println("Bar"); - Bar { dummy: () } - } - } -} - -pub fn main() { - let _f: base::Foo = base::HasNew::::new(); - let _b: base::Bar = base::HasNew::::new(); -} diff --git a/gcc/testsuite/rust.test/trait-to-str.rs b/gcc/testsuite/rust.test/trait-to-str.rs deleted file mode 100644 index baeb977..0000000 --- a/gcc/testsuite/rust.test/trait-to-str.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -trait to_str { - fn to_string(&self) -> ~str; -} - -impl to_str for int { - fn to_string(&self) -> ~str { self.to_str() } -} - -impl to_str for ~[T] { - fn to_string(&self) -> ~str { - format!("[{}]", self.iter().map(|e| e.to_string()).to_owned_vec().connect(", ")) - } -} - -pub fn main() { - assert!(1.to_string() == ~"1"); - assert!((~[2, 3, 4]).to_string() == ~"[2, 3, 4]"); - - fn indirect(x: T) -> ~str { - x.to_string() + "!" - } - assert!(indirect(~[10, 20]) == ~"[10, 20]!"); - - fn indirect2(x: T) -> ~str { - indirect(x) - } - assert!(indirect2(~[1]) == ~"[1]!"); -} diff --git a/gcc/testsuite/rust.test/trait-typedef-cc.rs b/gcc/testsuite/rust.test/trait-typedef-cc.rs deleted file mode 100644 index 294b8a57..0000000 --- a/gcc/testsuite/rust.test/trait-typedef-cc.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test FIXME: #3907 -// aux-build:trait_typedef_cc.rs -extern mod trait_typedef_cc; - -type Foo = trait_typedef_cc::Foo; - -struct S { - name: int -} - -impl Foo for S { - fn bar() { } -} - -pub fn main() { - let s = S { - name: 0 - }; - s.bar(); -} diff --git a/gcc/testsuite/rust.test/trait-with-bounds-default.rs b/gcc/testsuite/rust.test/trait-with-bounds-default.rs deleted file mode 100644 index ba2f32a0..0000000 --- a/gcc/testsuite/rust.test/trait-with-bounds-default.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait Clone2 { - /// Returns a copy of the value. The contents of owned pointers - /// are copied to maintain uniqueness, while the contents of - /// managed pointers are not copied. - fn clone(&self) -> Self; -} - -trait Getter { - fn do_get(&self) -> T; - - fn do_get2(&self) -> (T, T) { - let x = self.do_get(); - (x.clone(), x.clone()) - } - -} - -impl Getter for int { - fn do_get(&self) -> int { *self } -} - -impl Getter for Option { - fn do_get(&self) -> T { self.get_ref().clone() } -} - - -pub fn main() { - assert_eq!(3.do_get2(), (3, 3)); - assert_eq!(Some(~"hi").do_get2(), (~"hi", ~"hi")); -} diff --git a/gcc/testsuite/rust.test/traits-default-method-macro.rs b/gcc/testsuite/rust.test/traits-default-method-macro.rs deleted file mode 100644 index 340d0bc..0000000 --- a/gcc/testsuite/rust.test/traits-default-method-macro.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait Foo { - fn bar(&self) -> ~str { - format!("test") - } -} - -enum Baz { - Quux -} - -impl Foo for Baz { -} - -pub fn main() { - let q = Quux; - assert_eq!(q.bar(), ~"test"); -} diff --git a/gcc/testsuite/rust.test/traits-default-method-mut.rs b/gcc/testsuite/rust.test/traits-default-method-mut.rs deleted file mode 100644 index 4b217ba..0000000 --- a/gcc/testsuite/rust.test/traits-default-method-mut.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -trait Foo { - fn foo(&self, mut v: int) { v = 1; } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/traits-default-method-self.rs b/gcc/testsuite/rust.test/traits-default-method-self.rs deleted file mode 100644 index 1027008..0000000 --- a/gcc/testsuite/rust.test/traits-default-method-self.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait Cat { - fn meow(&self) -> bool; - fn scratch(&self) -> bool { self.purr() } - fn purr(&self) -> bool { true } -} - -impl Cat for int { - fn meow(&self) -> bool { - self.scratch() - } -} - -pub fn main() { - assert!(5.meow()); -} diff --git a/gcc/testsuite/rust.test/traits-default-method-trivial.rs b/gcc/testsuite/rust.test/traits-default-method-trivial.rs deleted file mode 100644 index c6a7ab5..0000000 --- a/gcc/testsuite/rust.test/traits-default-method-trivial.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait Cat { - fn meow(&self) -> bool; - fn scratch(&self) -> bool; - fn purr(&self) -> bool { true } -} - -impl Cat for int { - fn meow(&self) -> bool { - self.scratch() - } - fn scratch(&self) -> bool { - self.purr() - } -} - -pub fn main() { - assert!(5.meow()); -} diff --git a/gcc/testsuite/rust.test/transmute-non-immediate-to-immediate.rs b/gcc/testsuite/rust.test/transmute-non-immediate-to-immediate.rs deleted file mode 100644 index 9cdcd87..0000000 --- a/gcc/testsuite/rust.test/transmute-non-immediate-to-immediate.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #7988 -// Transmuting non-immediate type to immediate type - -pub fn main() { - unsafe { - ::std::cast::transmute::<[int,..1],int>([1]) - }; -} diff --git a/gcc/testsuite/rust.test/trivial-message.rs b/gcc/testsuite/rust.test/trivial-message.rs deleted file mode 100644 index 62b4154..0000000 --- a/gcc/testsuite/rust.test/trivial-message.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* - This is about the simplest program that can successfully send a - message. - */ - -use std::comm; - -pub fn main() { - let (po, ch) = comm::stream(); - ch.send(42); - let r = po.recv(); - error2!("{:?}", r); -} diff --git a/gcc/testsuite/rust.test/tup.rs b/gcc/testsuite/rust.test/tup.rs deleted file mode 100644 index 795ed1d..0000000 --- a/gcc/testsuite/rust.test/tup.rs +++ /dev/null @@ -1,28 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -type point = (int, int); - -fn f(p: point, x: int, y: int) { - let (a, b) = p; - assert_eq!(a, x); - assert_eq!(b, y); -} - -pub fn main() { - let p: point = (10, 20); - let (a, b) = p; - assert_eq!(a, 10); - assert_eq!(b, 20); - let p2: point = p; - f(p, 10, 20); - f(p2, 10, 20); -} diff --git a/gcc/testsuite/rust.test/tuple-struct-construct.rs b/gcc/testsuite/rust.test/tuple-struct-construct.rs deleted file mode 100644 index 3c15bc0..0000000 --- a/gcc/testsuite/rust.test/tuple-struct-construct.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(int, int); - -pub fn main() { - let x = Foo(1, 2); - println!("{:?}", x); -} diff --git a/gcc/testsuite/rust.test/tuple-struct-constructor-pointer.rs b/gcc/testsuite/rust.test/tuple-struct-constructor-pointer.rs deleted file mode 100644 index e51e6ff..0000000 --- a/gcc/testsuite/rust.test/tuple-struct-constructor-pointer.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Foo(int); -#[deriving(Eq)] -struct Bar(int, int); - -pub fn main() { - let f: extern fn(int) -> Foo = Foo; - let g: extern fn(int, int) -> Bar = Bar; - assert_eq!(f(42), Foo(42)); - assert_eq!(g(4, 7), Bar(4, 7)); -} diff --git a/gcc/testsuite/rust.test/tuple-struct-destructuring.rs b/gcc/testsuite/rust.test/tuple-struct-destructuring.rs deleted file mode 100644 index ec7675a..0000000 --- a/gcc/testsuite/rust.test/tuple-struct-destructuring.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(int, int); - -pub fn main() { - let x = Foo(1, 2); - let Foo(y, z) = x; - println!("{} {}", y, z); - assert_eq!(y, 1); - assert_eq!(z, 2); -} diff --git a/gcc/testsuite/rust.test/tuple-struct-matching.rs b/gcc/testsuite/rust.test/tuple-struct-matching.rs deleted file mode 100644 index f50b040..0000000 --- a/gcc/testsuite/rust.test/tuple-struct-matching.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(int, int); - -pub fn main() { - let x = Foo(1, 2); - match x { - Foo(a, b) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - println!("{} {}", a, b); - } - } -} diff --git a/gcc/testsuite/rust.test/tuple-struct-trivial.rs b/gcc/testsuite/rust.test/tuple-struct-trivial.rs deleted file mode 100644 index c22c812..0000000 --- a/gcc/testsuite/rust.test/tuple-struct-trivial.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo(int, int, int); - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/tydesc-name.rs b/gcc/testsuite/rust.test/tydesc-name.rs deleted file mode 100644 index 44a6a57..0000000 --- a/gcc/testsuite/rust.test/tydesc-name.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -use std::unstable::intrinsics::get_tydesc; - -struct Foo { - x: T -} - -fn main() { - unsafe { - assert_eq!((*get_tydesc::()).name, "int"); - assert_eq!((*get_tydesc::<~[int]>()).name, "~[int]"); - assert_eq!((*get_tydesc::>()).name, "Foo"); - } -} diff --git a/gcc/testsuite/rust.test/type-in-nested-module.rs b/gcc/testsuite/rust.test/type-in-nested-module.rs deleted file mode 100644 index f0b7ee0..0000000 --- a/gcc/testsuite/rust.test/type-in-nested-module.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -mod a { - pub mod b { - pub type t = int; - - pub fn foo() { let _x: t = 10; } - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/type-namespace.rs b/gcc/testsuite/rust.test/type-namespace.rs deleted file mode 100644 index e9b0324..0000000 --- a/gcc/testsuite/rust.test/type-namespace.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct A { a: int } - -fn a(a: A) -> int { return a.a; } - -pub fn main() { let x: A = A {a: 1}; assert!((a(x) == 1)); } diff --git a/gcc/testsuite/rust.test/type-param-constraints.rs b/gcc/testsuite/rust.test/type-param-constraints.rs deleted file mode 100644 index a1cb006..0000000 --- a/gcc/testsuite/rust.test/type-param-constraints.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn p_foo(_pinned: T) { } -fn s_foo(_shared: T) { } -fn u_foo(_unique: T) { } - -struct r { - i: int, -} - -impl Drop for r { - fn drop(&mut self) {} -} - -fn r(i:int) -> r { - r { - i: i - } -} - -pub fn main() { - p_foo(r(10)); - p_foo(@r(10)); - - p_foo(~r(10)); - p_foo(@10); - p_foo(~10); - p_foo(10); - - s_foo(@r(10)); - s_foo(@10); - s_foo(~10); - s_foo(10); - - u_foo(~10); - u_foo(10); -} diff --git a/gcc/testsuite/rust.test/type-param.rs b/gcc/testsuite/rust.test/type-param.rs deleted file mode 100644 index 209dade..0000000 --- a/gcc/testsuite/rust.test/type-param.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -type lteq = extern fn(T) -> bool; - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/type-params-in-for-each.rs b/gcc/testsuite/rust.test/type-params-in-for-each.rs deleted file mode 100644 index a5a9075..0000000 --- a/gcc/testsuite/rust.test/type-params-in-for-each.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S { - a: T, - b: uint, -} - -fn range_(lo: uint, hi: uint, it: &fn(uint)) { - let mut lo_ = lo; - while lo_ < hi { it(lo_); lo_ += 1u; } -} - -fn create_index(_index: ~[S], _hash_fn: extern fn(T) -> uint) { - do range_(0u, 256u) |_i| { - let _bucket: ~[T] = ~[]; - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/type-ptr.rs b/gcc/testsuite/rust.test/type-ptr.rs deleted file mode 100644 index a00b6b8..0000000 --- a/gcc/testsuite/rust.test/type-ptr.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(a: *int) -> *int { return a; } - -fn g(a: *int) -> *int { let b = f(a); return b; } - -pub fn main() { return; } diff --git a/gcc/testsuite/rust.test/type-sizes.rs b/gcc/testsuite/rust.test/type-sizes.rs deleted file mode 100644 index 2cdff23..0000000 --- a/gcc/testsuite/rust.test/type-sizes.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod std; -use std::mem::size_of; - -struct t {a: u8, b: i8} -struct u {a: u8, b: i8, c: u8} -struct v {a: u8, b: i8, c: v2, d: u32} -struct v2 {u: char, v: u8} -struct w {a: int, b: ()} -struct x {a: int, b: (), c: ()} -struct y {x: int} - -pub fn main() { - assert_eq!(size_of::(), 1 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 1 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 2 as uint); - assert_eq!(size_of::(), 3 as uint); - // Alignment causes padding before the char and the u32. - - assert!(size_of::() == - 16 as uint); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); -} diff --git a/gcc/testsuite/rust.test/type-use-i1-versus-i8.rs b/gcc/testsuite/rust.test/type-use-i1-versus-i8.rs deleted file mode 100644 index 88b4fff..0000000 --- a/gcc/testsuite/rust.test/type-use-i1-versus-i8.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable; - -pub fn main() { - unsafe { - let mut x: bool = false; - // this line breaks it - unstable::intrinsics::move_val_init(&mut x, false); - } -} diff --git a/gcc/testsuite/rust.test/typeck-macro-interaction-issue-8852.rs b/gcc/testsuite/rust.test/typeck-macro-interaction-issue-8852.rs deleted file mode 100644 index b4f2811..0000000 --- a/gcc/testsuite/rust.test/typeck-macro-interaction-issue-8852.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[feature(macro_rules)]; - -enum T { - A(int), - B(f64) -} - -macro_rules! test( - ($e:expr) => ( - fn foo(a:T, b:T) -> T { - match (a, b) { - (A(x), A(y)) => A($e), - (B(x), B(y)) => B($e), - _ => fail2!() - } - } - ) -) - -test!(x + y) - -pub fn main() { - foo(A(1), A(2)); -} diff --git a/gcc/testsuite/rust.test/typeclasses-eq-example-static.rs b/gcc/testsuite/rust.test/typeclasses-eq-example-static.rs deleted file mode 100644 index 0d37c0f..0000000 --- a/gcc/testsuite/rust.test/typeclasses-eq-example-static.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Example from lkuper's intern talk, August 2012 -- now with static -// methods! - -trait Equal { - fn isEq(a: Self, b: Self) -> bool; -} - -enum Color { cyan, magenta, yellow, black } - -impl Equal for Color { - fn isEq(a: Color, b: Color) -> bool { - match (a, b) { - (cyan, cyan) => { true } - (magenta, magenta) => { true } - (yellow, yellow) => { true } - (black, black) => { true } - _ => { false } - } - } -} - -enum ColorTree { - leaf(Color), - branch(@ColorTree, @ColorTree) -} - -impl Equal for ColorTree { - fn isEq(a: ColorTree, b: ColorTree) -> bool { - match (a, b) { - (leaf(x), leaf(y)) => { Equal::isEq(x, y) } - (branch(l1, r1), branch(l2, r2)) => { - Equal::isEq(*l1, *l2) && Equal::isEq(*r1, *r2) - } - _ => { false } - } - } -} - -pub fn main() { - assert!(Equal::isEq(cyan, cyan)); - assert!(Equal::isEq(magenta, magenta)); - assert!(!Equal::isEq(cyan, yellow)); - assert!(!Equal::isEq(magenta, cyan)); - - assert!(Equal::isEq(leaf(cyan), leaf(cyan))); - assert!(!Equal::isEq(leaf(cyan), leaf(yellow))); - - assert!(Equal::isEq(branch(@leaf(magenta), @leaf(cyan)), - branch(@leaf(magenta), @leaf(cyan)))); - - assert!(!Equal::isEq(branch(@leaf(magenta), @leaf(cyan)), - branch(@leaf(magenta), @leaf(magenta)))); - - error2!("Assertions all succeeded!"); -} diff --git a/gcc/testsuite/rust.test/typeclasses-eq-example.rs b/gcc/testsuite/rust.test/typeclasses-eq-example.rs deleted file mode 100644 index 11973df..0000000 --- a/gcc/testsuite/rust.test/typeclasses-eq-example.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Example from lkuper's intern talk, August 2012. - -trait Equal { - fn isEq(&self, a: Self) -> bool; -} - -enum Color { cyan, magenta, yellow, black } - -impl Equal for Color { - fn isEq(&self, a: Color) -> bool { - match (*self, a) { - (cyan, cyan) => { true } - (magenta, magenta) => { true } - (yellow, yellow) => { true } - (black, black) => { true } - _ => { false } - } - } -} - -enum ColorTree { - leaf(Color), - branch(@ColorTree, @ColorTree) -} - -impl Equal for ColorTree { - fn isEq(&self, a: ColorTree) -> bool { - match (*self, a) { - (leaf(x), leaf(y)) => { x.isEq(y) } - (branch(l1, r1), branch(l2, r2)) => { - (*l1).isEq(*l2) && (*r1).isEq(*r2) - } - _ => { false } - } - } -} - -pub fn main() { - assert!(cyan.isEq(cyan)); - assert!(magenta.isEq(magenta)); - assert!(!cyan.isEq(yellow)); - assert!(!magenta.isEq(cyan)); - - assert!(leaf(cyan).isEq(leaf(cyan))); - assert!(!leaf(cyan).isEq(leaf(yellow))); - - assert!(branch(@leaf(magenta), @leaf(cyan)) - .isEq(branch(@leaf(magenta), @leaf(cyan)))); - - assert!(!branch(@leaf(magenta), @leaf(cyan)) - .isEq(branch(@leaf(magenta), @leaf(magenta)))); - - error2!("Assertions all succeeded!"); -} diff --git a/gcc/testsuite/rust.test/typestate-cfg-nesting.rs b/gcc/testsuite/rust.test/typestate-cfg-nesting.rs deleted file mode 100644 index 6a2757c..0000000 --- a/gcc/testsuite/rust.test/typestate-cfg-nesting.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -fn f() { - let x = 10; let mut y = 11; - if true { match x { _ => { y = x; } } } else { } -} - -pub fn main() { - let x = 10; - let mut y = 11; - if true { while false { y = x; } } else { } -} diff --git a/gcc/testsuite/rust.test/typestate-multi-decl.rs b/gcc/testsuite/rust.test/typestate-multi-decl.rs deleted file mode 100644 index 42910c4..0000000 --- a/gcc/testsuite/rust.test/typestate-multi-decl.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let (x, y) = (10, 20); - let z = x + y; - assert!((z == 30)); -} diff --git a/gcc/testsuite/rust.test/u32-decr.rs b/gcc/testsuite/rust.test/u32-decr.rs deleted file mode 100644 index f40d06f..0000000 --- a/gcc/testsuite/rust.test/u32-decr.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let mut word: u32 = 200000u32; - word = word - 1u32; - assert_eq!(word, 199999u32); -} diff --git a/gcc/testsuite/rust.test/u8-incr-decr.rs b/gcc/testsuite/rust.test/u8-incr-decr.rs deleted file mode 100644 index 1854359..0000000 --- a/gcc/testsuite/rust.test/u8-incr-decr.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// These constants were chosen because they aren't used anywhere -// in the rest of the generated code so they're easily grep-able. -pub fn main() { - let mut x: u8 = 19u8; // 0x13 - - let mut y: u8 = 35u8; // 0x23 - - x = x + 7u8; // 0x7 - - y = y - 9u8; // 0x9 - - assert_eq!(x, y); -} diff --git a/gcc/testsuite/rust.test/u8-incr.rs b/gcc/testsuite/rust.test/u8-incr.rs deleted file mode 100644 index 1a40136..0000000 --- a/gcc/testsuite/rust.test/u8-incr.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let mut x: u8 = 12u8; - let y: u8 = 12u8; - x = x + 1u8; - x = x - 1u8; - assert_eq!(x, y); - // x = 14u8; - // x = x + 1u8; - -} diff --git a/gcc/testsuite/rust.test/uint.rs b/gcc/testsuite/rust.test/uint.rs deleted file mode 100644 index 9b645ef..0000000 --- a/gcc/testsuite/rust.test/uint.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { let _x: uint = 10 as uint; } diff --git a/gcc/testsuite/rust.test/unary-minus-suffix-inference.rs b/gcc/testsuite/rust.test/unary-minus-suffix-inference.rs deleted file mode 100644 index e1ed28b..0000000 --- a/gcc/testsuite/rust.test/unary-minus-suffix-inference.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let a = 1; - let a_neg: i8 = -a; - error2!("{}", a_neg); - - let b = 1; - let b_neg: i16 = -b; - error2!("{}", b_neg); - - let c = 1; - let c_neg: i32 = -c; - error2!("{}", c_neg); - - let d = 1; - let d_neg: i64 = -d; - error2!("{}", d_neg); - - let e = 1; - let e_neg: int = -e; - error2!("{}", e_neg); - - // intentional overflows - - let f = 1; - let f_neg: u8 = -f; - error2!("{}", f_neg); - - let g = 1; - let g_neg: u16 = -g; - error2!("{}", g_neg); - - let h = 1; - let h_neg: u32 = -h; - error2!("{}", h_neg); - - let i = 1; - let i_neg: u64 = -i; - error2!("{}", i_neg); - - let j = 1; - let j_neg: uint = -j; - error2!("{}", j_neg); -} diff --git a/gcc/testsuite/rust.test/unfold-cross-crate.rs b/gcc/testsuite/rust.test/unfold-cross-crate.rs deleted file mode 100644 index 5f63968..0000000 --- a/gcc/testsuite/rust.test/unfold-cross-crate.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::iter::Unfold; - -// Unfold had a bug with 'self that mean it didn't work -// cross-crate - -pub fn main() { - fn count(st: &mut uint) -> Option { - if *st < 10 { - let ret = Some(*st); - *st += 1; - ret - } else { - None - } - } - - let mut it = Unfold::new(0, count); - let mut i = 0; - for counted in it { - assert_eq!(counted, i); - i += 1; - } - assert_eq!(i, 10); -} diff --git a/gcc/testsuite/rust.test/unify-return-ty.rs b/gcc/testsuite/rust.test/unify-return-ty.rs deleted file mode 100644 index 8bdce60..0000000 --- a/gcc/testsuite/rust.test/unify-return-ty.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that the tail expr in null() has its type -// unified with the type *T, and so the type variable -// in that type gets resolved. -extern mod extra; - -use std::cast; - -fn null() -> *T { - unsafe { - cast::transmute(0) - } -} - -pub fn main() { null::(); } diff --git a/gcc/testsuite/rust.test/uniq-cc-generic.rs b/gcc/testsuite/rust.test/uniq-cc-generic.rs deleted file mode 100644 index 5d11513..0000000 --- a/gcc/testsuite/rust.test/uniq-cc-generic.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; - -enum maybe_pointy { - none, - p(@mut Pointy), -} - -struct Pointy { - a : maybe_pointy, - d : ~fn() -> uint, -} - -fn make_uniq_closure(a: A) -> ~fn() -> uint { - let result: ~fn() -> uint = || ptr::to_unsafe_ptr(&a) as uint; - result -} - -fn empty_pointy() -> @mut Pointy { - return @mut Pointy { - a : none, - d : make_uniq_closure(~"hi") - } -} - -pub fn main() { - let v = empty_pointy(); - v.a = p(v); -} diff --git a/gcc/testsuite/rust.test/uniq-cc.rs b/gcc/testsuite/rust.test/uniq-cc.rs deleted file mode 100644 index b54daa4..0000000 --- a/gcc/testsuite/rust.test/uniq-cc.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum maybe_pointy { - none, - p(@mut Pointy), -} - -struct Pointy { - a : maybe_pointy, - c : ~int, - d : ~fn()->(), -} - -fn empty_pointy() -> @mut Pointy { - return @mut Pointy { - a : none, - c : ~22, - d : || {}, - } -} - -pub fn main() { - let v = empty_pointy(); - v.a = p(v); -} diff --git a/gcc/testsuite/rust.test/unique-assign-copy.rs b/gcc/testsuite/rust.test/unique-assign-copy.rs deleted file mode 100644 index e59fe46..0000000 --- a/gcc/testsuite/rust.test/unique-assign-copy.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i = ~1; - // Should be a copy - let mut j; - j = i.clone(); - *i = 2; - *j = 3; - assert_eq!(*i, 2); - assert_eq!(*j, 3); -} diff --git a/gcc/testsuite/rust.test/unique-assign-drop.rs b/gcc/testsuite/rust.test/unique-assign-drop.rs deleted file mode 100644 index 9144ecc..0000000 --- a/gcc/testsuite/rust.test/unique-assign-drop.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let i = ~1; - let mut j = ~2; - // Should drop the previous value of j - j = i; - assert_eq!(*j, 1); -} diff --git a/gcc/testsuite/rust.test/unique-assign-generic.rs b/gcc/testsuite/rust.test/unique-assign-generic.rs deleted file mode 100644 index eb2638f2..0000000 --- a/gcc/testsuite/rust.test/unique-assign-generic.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(t: T) -> T { - let t1 = t; - t1 -} - -pub fn main() { - let t = f(~100); - assert_eq!(t, ~100); - let t = f(~@~[100]); - assert_eq!(t, ~@~[100]); -} diff --git a/gcc/testsuite/rust.test/unique-assign.rs b/gcc/testsuite/rust.test/unique-assign.rs deleted file mode 100644 index 43df53c..0000000 --- a/gcc/testsuite/rust.test/unique-assign.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i; - i = ~1; - assert_eq!(*i, 1); -} diff --git a/gcc/testsuite/rust.test/unique-autoderef-field.rs b/gcc/testsuite/rust.test/unique-autoderef-field.rs deleted file mode 100644 index 6836ba4..0000000 --- a/gcc/testsuite/rust.test/unique-autoderef-field.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct J { j: int } - -pub fn main() { - let i = ~J { - j: 100 - }; - assert_eq!(i.j, 100); -} diff --git a/gcc/testsuite/rust.test/unique-autoderef-index.rs b/gcc/testsuite/rust.test/unique-autoderef-index.rs deleted file mode 100644 index 46f9ca7..0000000 --- a/gcc/testsuite/rust.test/unique-autoderef-index.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~~[100]; - assert_eq!(i[0], 100); -} diff --git a/gcc/testsuite/rust.test/unique-cmp.rs b/gcc/testsuite/rust.test/unique-cmp.rs deleted file mode 100644 index b50d315..0000000 --- a/gcc/testsuite/rust.test/unique-cmp.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - assert!(i == ~100); - assert!(i < ~101); - assert!(i <= ~100); - assert!(i > ~99); - assert!(i >= ~99); -} diff --git a/gcc/testsuite/rust.test/unique-containing-tag.rs b/gcc/testsuite/rust.test/unique-containing-tag.rs deleted file mode 100644 index 1ebd584..0000000 --- a/gcc/testsuite/rust.test/unique-containing-tag.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - enum t { t1(int), t2(int), } - - let _x = ~t1(10); - - /*alt *x { - t1(a) { - assert_eq!(a, 10); - } - _ { fail!(); } - }*/ - - /*alt x { - ~t1(a) { - assert_eq!(a, 10); - } - _ { fail!(); } - }*/ -} diff --git a/gcc/testsuite/rust.test/unique-copy-box.rs b/gcc/testsuite/rust.test/unique-copy-box.rs deleted file mode 100644 index 6f4c859..0000000 --- a/gcc/testsuite/rust.test/unique-copy-box.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_variable)]; - -use std::managed; - -pub fn main() { - let i = ~@1; - let j = ~@2; - let rc1 = managed::refcount(*i); - let j = i.clone(); - let rc2 = managed::refcount(*i); - error2!("rc1: {} rc2: {}", rc1, rc2); - assert_eq!(rc1 + 1u, rc2); -} diff --git a/gcc/testsuite/rust.test/unique-create.rs b/gcc/testsuite/rust.test/unique-create.rs deleted file mode 100644 index 9570c17..0000000 --- a/gcc/testsuite/rust.test/unique-create.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - ~100; -} - -fn vec() { - ~[0]; -} diff --git a/gcc/testsuite/rust.test/unique-decl-init-copy.rs b/gcc/testsuite/rust.test/unique-decl-init-copy.rs deleted file mode 100644 index 13594d8..0000000 --- a/gcc/testsuite/rust.test/unique-decl-init-copy.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i = ~1; - // Should be a copy - let mut j = i.clone(); - *i = 2; - *j = 3; - assert_eq!(*i, 2); - assert_eq!(*j, 3); -} diff --git a/gcc/testsuite/rust.test/unique-decl-init.rs b/gcc/testsuite/rust.test/unique-decl-init.rs deleted file mode 100644 index c507d19..0000000 --- a/gcc/testsuite/rust.test/unique-decl-init.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~1; - let j = i; - assert_eq!(*j, 1); -} diff --git a/gcc/testsuite/rust.test/unique-decl-move-temp.rs b/gcc/testsuite/rust.test/unique-decl-move-temp.rs deleted file mode 100644 index 6cf781d..0000000 --- a/gcc/testsuite/rust.test/unique-decl-move-temp.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - assert_eq!(*i, 100); -} diff --git a/gcc/testsuite/rust.test/unique-decl-move.rs b/gcc/testsuite/rust.test/unique-decl-move.rs deleted file mode 100644 index 335275f..0000000 --- a/gcc/testsuite/rust.test/unique-decl-move.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - let j = i; - assert_eq!(*j, 100); -} diff --git a/gcc/testsuite/rust.test/unique-decl.rs b/gcc/testsuite/rust.test/unique-decl.rs deleted file mode 100644 index 14a6519..0000000 --- a/gcc/testsuite/rust.test/unique-decl.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _: ~int; -} - -fn f(_i: ~int) -> ~int { - fail2!(); -} diff --git a/gcc/testsuite/rust.test/unique-deref.rs b/gcc/testsuite/rust.test/unique-deref.rs deleted file mode 100644 index 6cf781d..0000000 --- a/gcc/testsuite/rust.test/unique-deref.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - assert_eq!(*i, 100); -} diff --git a/gcc/testsuite/rust.test/unique-destructure.rs b/gcc/testsuite/rust.test/unique-destructure.rs deleted file mode 100644 index 6c35cb4..0000000 --- a/gcc/testsuite/rust.test/unique-destructure.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { a: int, b: int } - -pub fn main() { - let ~Foo{a, b} = ~Foo{a: 100, b: 200}; - assert_eq!(a + b, 300); -} diff --git a/gcc/testsuite/rust.test/unique-drop-complex.rs b/gcc/testsuite/rust.test/unique-drop-complex.rs deleted file mode 100644 index 2090352..0000000 --- a/gcc/testsuite/rust.test/unique-drop-complex.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x = ~~[0,0,0,0,0]; -} diff --git a/gcc/testsuite/rust.test/unique-fn-arg-move.rs b/gcc/testsuite/rust.test/unique-fn-arg-move.rs deleted file mode 100644 index 503bbae..0000000 --- a/gcc/testsuite/rust.test/unique-fn-arg-move.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(i: ~int) { - assert_eq!(*i, 100); -} - -pub fn main() { - let i = ~100; - f(i); -} diff --git a/gcc/testsuite/rust.test/unique-fn-arg-mut.rs b/gcc/testsuite/rust.test/unique-fn-arg-mut.rs deleted file mode 100644 index c2d78c3..0000000 --- a/gcc/testsuite/rust.test/unique-fn-arg-mut.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(i: &mut ~int) { - *i = ~200; -} - -pub fn main() { - let mut i = ~100; - f(&mut i); - assert_eq!(*i, 200); -} diff --git a/gcc/testsuite/rust.test/unique-fn-arg.rs b/gcc/testsuite/rust.test/unique-fn-arg.rs deleted file mode 100644 index 230131b..0000000 --- a/gcc/testsuite/rust.test/unique-fn-arg.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(i: ~int) { - assert_eq!(*i, 100); -} - -pub fn main() { - f(~100); - let i = ~100; - f(i); -} diff --git a/gcc/testsuite/rust.test/unique-fn-ret.rs b/gcc/testsuite/rust.test/unique-fn-ret.rs deleted file mode 100644 index dd39e13..0000000 --- a/gcc/testsuite/rust.test/unique-fn-ret.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() -> ~int { - ~100 -} - -pub fn main() { - assert_eq!(f(), ~100); -} diff --git a/gcc/testsuite/rust.test/unique-generic-assign.rs b/gcc/testsuite/rust.test/unique-generic-assign.rs deleted file mode 100644 index 3805cbe..0000000 --- a/gcc/testsuite/rust.test/unique-generic-assign.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #976 - -fn f(x: ~T) { - let _x2 = x; -} -pub fn main() { } diff --git a/gcc/testsuite/rust.test/unique-in-tag.rs b/gcc/testsuite/rust.test/unique-in-tag.rs deleted file mode 100644 index d0fa48a..0000000 --- a/gcc/testsuite/rust.test/unique-in-tag.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test1() { - enum bar { u(~int), w(int), } - - let x = u(~10); - assert!(match x { - u(a) => { - error2!("{:?}", a); - *a - } - _ => { 66 } - } == 10); -} - -pub fn main() { - test1(); -} diff --git a/gcc/testsuite/rust.test/unique-in-vec-copy.rs b/gcc/testsuite/rust.test/unique-in-vec-copy.rs deleted file mode 100644 index 3a27d78..0000000 --- a/gcc/testsuite/rust.test/unique-in-vec-copy.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut a = ~[~10]; - let b = a.clone(); - - assert_eq!(*a[0], 10); - assert_eq!(*b[0], 10); - - // This should only modify the value in a, not b - *a[0] = 20; - - assert_eq!(*a[0], 20); - assert_eq!(*b[0], 10); -} diff --git a/gcc/testsuite/rust.test/unique-in-vec.rs b/gcc/testsuite/rust.test/unique-in-vec.rs deleted file mode 100644 index 51fceae..0000000 --- a/gcc/testsuite/rust.test/unique-in-vec.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - assert!((~[~100])[0] == ~100); -} diff --git a/gcc/testsuite/rust.test/unique-init.rs b/gcc/testsuite/rust.test/unique-init.rs deleted file mode 100644 index 6a87dd3..0000000 --- a/gcc/testsuite/rust.test/unique-init.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _i = ~100; -} diff --git a/gcc/testsuite/rust.test/unique-kinds.rs b/gcc/testsuite/rust.test/unique-kinds.rs deleted file mode 100644 index 11425a9..0000000 --- a/gcc/testsuite/rust.test/unique-kinds.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Eq; - -fn sendable() { - - fn f(i: T, j: T) { - assert_eq!(i, j); - } - - fn g(i: T, j: T) { - assert!(i != j); - } - - let i = ~100; - let j = ~100; - f(i, j); - let i = ~100; - let j = ~101; - g(i, j); -} - -fn copyable() { - - fn f(i: T, j: T) { - assert_eq!(i, j); - } - - fn g(i: T, j: T) { - assert!(i != j); - } - - let i = ~100; - let j = ~100; - f(i, j); - let i = ~100; - let j = ~101; - g(i, j); -} - -fn noncopyable() { - - fn f(i: T, j: T) { - assert_eq!(i, j); - } - - fn g(i: T, j: T) { - assert!(i != j); - } - - let i = ~100; - let j = ~100; - f(i, j); - let i = ~100; - let j = ~101; - g(i, j); -} - -pub fn main() { - sendable(); - copyable(); - noncopyable(); -} diff --git a/gcc/testsuite/rust.test/unique-log.rs b/gcc/testsuite/rust.test/unique-log.rs deleted file mode 100644 index 2434219..0000000 --- a/gcc/testsuite/rust.test/unique-log.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - error2!("{:?}", i); -} diff --git a/gcc/testsuite/rust.test/unique-match-discrim.rs b/gcc/testsuite/rust.test/unique-match-discrim.rs deleted file mode 100644 index 1f0b13d..0000000 --- a/gcc/testsuite/rust.test/unique-match-discrim.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #961 - -fn altsimple() { - match ~true { - _ => { } - } -} -pub fn main() { } diff --git a/gcc/testsuite/rust.test/unique-move-drop.rs b/gcc/testsuite/rust.test/unique-move-drop.rs deleted file mode 100644 index cbef004..0000000 --- a/gcc/testsuite/rust.test/unique-move-drop.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_variable)]; - -pub fn main() { - let i = ~100; - let j = ~200; - let j = i; - assert_eq!(*j, 100); -} diff --git a/gcc/testsuite/rust.test/unique-move-temp.rs b/gcc/testsuite/rust.test/unique-move-temp.rs deleted file mode 100644 index 7c7ca13..0000000 --- a/gcc/testsuite/rust.test/unique-move-temp.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i; - i = ~100; - assert_eq!(*i, 100); -} diff --git a/gcc/testsuite/rust.test/unique-move.rs b/gcc/testsuite/rust.test/unique-move.rs deleted file mode 100644 index dbdfc5c..0000000 --- a/gcc/testsuite/rust.test/unique-move.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i = ~100; - let mut j; - j = i; - assert_eq!(*j, 100); -} diff --git a/gcc/testsuite/rust.test/unique-mutable.rs b/gcc/testsuite/rust.test/unique-mutable.rs deleted file mode 100644 index 4f353c5..0000000 --- a/gcc/testsuite/rust.test/unique-mutable.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i = ~0; - *i = 1; - assert_eq!(*i, 1); -} diff --git a/gcc/testsuite/rust.test/unique-object-move.rs b/gcc/testsuite/rust.test/unique-object-move.rs deleted file mode 100644 index f6a4674..0000000 --- a/gcc/testsuite/rust.test/unique-object-move.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #5192 - -pub trait EventLoop { } - -pub struct UvEventLoop { - uvio: int -} - -impl EventLoop for UvEventLoop { } - -pub fn main() { - let loop_: ~EventLoop = ~UvEventLoop { uvio: 0 } as ~EventLoop; - let _loop2_ = loop_; -} diff --git a/gcc/testsuite/rust.test/unique-pat-2.rs b/gcc/testsuite/rust.test/unique-pat-2.rs deleted file mode 100644 index 49a873e..0000000 --- a/gcc/testsuite/rust.test/unique-pat-2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -struct Foo {a: int, b: uint} - -enum bar { u(~Foo), w(int), } - -pub fn main() { - assert!(match u(~Foo{a: 10, b: 40u}) { - u(~Foo{a: a, b: b}) => { a + (b as int) } - _ => { 66 } - } == 50); -} diff --git a/gcc/testsuite/rust.test/unique-pat-3.rs b/gcc/testsuite/rust.test/unique-pat-3.rs deleted file mode 100644 index 7a97909..0000000 --- a/gcc/testsuite/rust.test/unique-pat-3.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -enum bar { u(~int), w(int), } - -pub fn main() { - assert!(match u(~10) { - u(a) => { - error2!("{:?}", a); - *a - } - _ => { 66 } - } == 10); -} diff --git a/gcc/testsuite/rust.test/unique-pat.rs b/gcc/testsuite/rust.test/unique-pat.rs deleted file mode 100644 index d33db85..0000000 --- a/gcc/testsuite/rust.test/unique-pat.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn simple() { - match ~true { - ~true => { } - _ => { fail2!(); } - } -} - -pub fn main() { - simple(); -} diff --git a/gcc/testsuite/rust.test/unique-pinned-nocopy-2.rs b/gcc/testsuite/rust.test/unique-pinned-nocopy-2.rs deleted file mode 100644 index 6ba3866..0000000 --- a/gcc/testsuite/rust.test/unique-pinned-nocopy-2.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct r { - i: @mut int, -} - -#[unsafe_destructor] -impl Drop for r { - fn drop(&mut self) { - *(self.i) = *(self.i) + 1; - } -} - -fn r(i: @mut int) -> r { - r { - i: i - } -} - -pub fn main() { - let i = @mut 0; - { - let _j = ~r(i); - } - assert_eq!(*i, 1); -} diff --git a/gcc/testsuite/rust.test/unique-rec.rs b/gcc/testsuite/rust.test/unique-rec.rs deleted file mode 100644 index f740dd2..0000000 --- a/gcc/testsuite/rust.test/unique-rec.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct X { x: int } - -pub fn main() { - let x = ~X {x: 1}; - let bar = x; - assert_eq!(bar.x, 1); -} diff --git a/gcc/testsuite/rust.test/unique-send-2.rs b/gcc/testsuite/rust.test/unique-send-2.rs deleted file mode 100644 index e697af8..0000000 --- a/gcc/testsuite/rust.test/unique-send-2.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::comm::{SharedChan, stream}; -use std::task; - -fn child(c: &SharedChan<~uint>, i: uint) { - c.send(~i); -} - -pub fn main() { - let (p, ch) = stream(); - let ch = SharedChan::new(ch); - let n = 100u; - let mut expected = 0u; - for i in range(0u, n) { - let ch = ch.clone(); - task::spawn(|| child(&ch, i) ); - expected += i; - } - - let mut actual = 0u; - for _ in range(0u, n) { - let j = p.recv(); - actual += *j; - } - - assert_eq!(expected, actual); -} diff --git a/gcc/testsuite/rust.test/unique-send.rs b/gcc/testsuite/rust.test/unique-send.rs deleted file mode 100644 index a7d2f6a..0000000 --- a/gcc/testsuite/rust.test/unique-send.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let (p, c) = stream(); - c.send(~100); - let v = p.recv(); - assert_eq!(v, ~100); -} diff --git a/gcc/testsuite/rust.test/unique-swap.rs b/gcc/testsuite/rust.test/unique-swap.rs deleted file mode 100644 index a372e4a..0000000 --- a/gcc/testsuite/rust.test/unique-swap.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -pub fn main() { - let mut i = ~100; - let mut j = ~200; - util::swap(&mut i, &mut j); - assert_eq!(i, ~200); - assert_eq!(j, ~100); -} diff --git a/gcc/testsuite/rust.test/unit-like-struct-drop-run.rs b/gcc/testsuite/rust.test/unit-like-struct-drop-run.rs deleted file mode 100644 index 2d7234c..0000000 --- a/gcc/testsuite/rust.test/unit-like-struct-drop-run.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure the destructor is run for unit-like structs. - -use std::task; - -struct Foo; - -impl Drop for Foo { - fn drop(&mut self) { - fail2!("This failure should happen."); - } -} - -pub fn main() { - let x = do task::try { - let _b = Foo; - }; - assert_eq!(x, Err(())); -} diff --git a/gcc/testsuite/rust.test/unit-like-struct.rs b/gcc/testsuite/rust.test/unit-like-struct.rs deleted file mode 100644 index 82aeb08..0000000 --- a/gcc/testsuite/rust.test/unit-like-struct.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo; - -pub fn main() { - let x: Foo = Foo; - match x { - Foo => { println("hi"); } - } -} diff --git a/gcc/testsuite/rust.test/unit.rs b/gcc/testsuite/rust.test/unit.rs deleted file mode 100644 index a74bfc3..0000000 --- a/gcc/testsuite/rust.test/unit.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_variable)]; -#[allow(dead_assignment)]; - -// -*- rust -*- -fn f(u: ()) { return u; } - -pub fn main() { - let u1: () = (); - let mut u2: () = f(u1); - u2 = (); - return (); -} diff --git a/gcc/testsuite/rust.test/unnamed_argument_mode.rs b/gcc/testsuite/rust.test/unnamed_argument_mode.rs deleted file mode 100644 index c526585..0000000 --- a/gcc/testsuite/rust.test/unnamed_argument_mode.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn good(_a: &int) { -} - -// unnamed argument &int is now parse x: &int - -fn called(_f: &fn(&int)) { -} - -pub fn main() { - called(good); -} diff --git a/gcc/testsuite/rust.test/unreachable-code-1.rs b/gcc/testsuite/rust.test/unreachable-code-1.rs deleted file mode 100644 index e094f87..0000000 --- a/gcc/testsuite/rust.test/unreachable-code-1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unreachable_code)]; -#[allow(unused_variable)]; - -fn id(x: bool) -> bool { x } - -fn call_id() { - let c = fail2!(); - id(c); //~ WARNING unreachable statement -} - -fn call_id_3() { id(return) && id(return); } - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/unreachable-code.rs b/gcc/testsuite/rust.test/unreachable-code.rs deleted file mode 100644 index 55a359e..0000000 --- a/gcc/testsuite/rust.test/unreachable-code.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(path_statement)]; -#[allow(unreachable_code)]; -#[allow(unused_variable)]; - -fn id(x: bool) -> bool { x } - -fn call_id() { - let c = fail2!(); - id(c); -} - -fn call_id_2() { id(true) && id(return); } - -fn call_id_3() { id(return) && id(return); } - -fn ret_ret() -> int { return (return 2) + 3; } - -fn ret_guard() { - match 2 { - x if (return) => { x; } - _ => {} - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-blk.rs b/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-blk.rs deleted file mode 100644 index 8b1c003..0000000 --- a/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-blk.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// -// See also: compile-fail/unsafe-fn-called-from-safe.rs - -unsafe fn f() { return; } - -fn g() { - unsafe { - f(); - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-fn.rs b/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-fn.rs deleted file mode 100644 index 1564045..0000000 --- a/gcc/testsuite/rust.test/unsafe-fn-called-from-unsafe-fn.rs +++ /dev/null @@ -1,23 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// -// See also: compile-fail/unsafe-fn-called-from-safe.rs - -unsafe fn f() { return; } - -unsafe fn g() { - f(); -} - -pub fn main() { - return; -} diff --git a/gcc/testsuite/rust.test/unsafe-pointer-assignability.rs b/gcc/testsuite/rust.test/unsafe-pointer-assignability.rs deleted file mode 100644 index 3385c6f..0000000 --- a/gcc/testsuite/rust.test/unsafe-pointer-assignability.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(x: *int) { - unsafe { - assert_eq!(*x, 3); - } -} - -pub fn main() { - f(&3); -} diff --git a/gcc/testsuite/rust.test/unused-move-capture.rs b/gcc/testsuite/rust.test/unused-move-capture.rs deleted file mode 100644 index 662121a..0000000 --- a/gcc/testsuite/rust.test/unused-move-capture.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x = ~1; - let lam_move: &fn() = || {}; - lam_move(); -} diff --git a/gcc/testsuite/rust.test/unused-move.rs b/gcc/testsuite/rust.test/unused-move.rs deleted file mode 100644 index 375e866..0000000 --- a/gcc/testsuite/rust.test/unused-move.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #3878 -// Issue Name: Unused move causes a crash -// Abstract: zero-fill to block after drop - -#[allow(path_statement)]; - -pub fn main() -{ - let y = ~1; - y; -} diff --git a/gcc/testsuite/rust.test/unwind-box.rs b/gcc/testsuite/rust.test/unwind-box.rs deleted file mode 100644 index de65d9b..0000000 --- a/gcc/testsuite/rust.test/unwind-box.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -fn f() { - let _a = @0; - fail2!(); -} - -pub fn main() { - task::spawn_unlinked(f); -} diff --git a/gcc/testsuite/rust.test/unwind-resource.rs b/gcc/testsuite/rust.test/unwind-resource.rs deleted file mode 100644 index 6ab40c1..0000000 --- a/gcc/testsuite/rust.test/unwind-resource.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -extern mod extra; - -use std::comm::{stream, SharedChan}; -use std::task; - -struct complainer { - c: SharedChan, -} - -impl Drop for complainer { - fn drop(&mut self) { - error2!("About to send!"); - self.c.send(true); - error2!("Sent!"); - } -} - -fn complainer(c: SharedChan) -> complainer { - error2!("Hello!"); - complainer { - c: c - } -} - -fn f(c: SharedChan) { - let _c = complainer(c); - fail2!(); -} - -pub fn main() { - let (p, c) = stream(); - let c = SharedChan::new(c); - task::spawn_unlinked(|| f(c.clone()) ); - error2!("hiiiiiiiii"); - assert!(p.recv()); -} diff --git a/gcc/testsuite/rust.test/unwind-resource2.rs b/gcc/testsuite/rust.test/unwind-resource2.rs deleted file mode 100644 index 751b943..0000000 --- a/gcc/testsuite/rust.test/unwind-resource2.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -struct complainer { - c: @int, -} - -#[unsafe_destructor] -impl Drop for complainer { - fn drop(&mut self) {} -} - -fn complainer(c: @int) -> complainer { - complainer { - c: c - } -} - -fn f() { - let _c = complainer(@0); - fail2!(); -} - -pub fn main() { - task::spawn_unlinked(f); -} diff --git a/gcc/testsuite/rust.test/unwind-unique.rs b/gcc/testsuite/rust.test/unwind-unique.rs deleted file mode 100644 index 07610fe..0000000 --- a/gcc/testsuite/rust.test/unwind-unique.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::task; - -fn f() { - let _a = ~0; - fail2!(); -} - -pub fn main() { - task::spawn_unlinked(f); -} diff --git a/gcc/testsuite/rust.test/use-crate-name-alias.rs b/gcc/testsuite/rust.test/use-crate-name-alias.rs deleted file mode 100644 index 4954de3..0000000 --- a/gcc/testsuite/rust.test/use-crate-name-alias.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #1706 -extern mod stdlib(name="extra"); - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/use-import-export.rs b/gcc/testsuite/rust.test/use-import-export.rs deleted file mode 100644 index ec8033f..0000000 --- a/gcc/testsuite/rust.test/use-import-export.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -mod foo { - pub fn x() -> int { return 1; } -} - -mod bar { - pub fn y() -> int { return 1; } -} - -pub fn main() { foo::x(); bar::y(); } diff --git a/gcc/testsuite/rust.test/use-trait-before-def.rs b/gcc/testsuite/rust.test/use-trait-before-def.rs deleted file mode 100644 index 0b59ced..0000000 --- a/gcc/testsuite/rust.test/use-trait-before-def.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #1761 - -impl foo for int { fn foo(&self) -> int { 10 } } -trait foo { fn foo(&self) -> int; } -pub fn main() {} diff --git a/gcc/testsuite/rust.test/use-uninit-match.rs b/gcc/testsuite/rust.test/use-uninit-match.rs deleted file mode 100644 index 18698a4..0000000 --- a/gcc/testsuite/rust.test/use-uninit-match.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn foo(o: myoption) -> int { - let mut x: int = 5; - match o { - none:: => { } - some::(_t) => { x += 1; } - } - return x; -} - -enum myoption { none, some(T), } - -pub fn main() { info2!("{}", 5); } diff --git a/gcc/testsuite/rust.test/use-uninit-match2.rs b/gcc/testsuite/rust.test/use-uninit-match2.rs deleted file mode 100644 index 844b052..0000000 --- a/gcc/testsuite/rust.test/use-uninit-match2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn foo(o: myoption) -> int { - let mut x: int; - match o { - none:: => { fail2!(); } - some::(_t) => { x = 5; } - } - return x; -} - -enum myoption { none, some(T), } - -pub fn main() { info2!("{}", 5); } diff --git a/gcc/testsuite/rust.test/use.rs b/gcc/testsuite/rust.test/use.rs deleted file mode 100644 index 8ae8daf..0000000 --- a/gcc/testsuite/rust.test/use.rs +++ /dev/null @@ -1,28 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_imports)]; - -#[no_std]; -extern mod std; -extern mod zed(name = "std"); -extern mod bar(name = "std", vers = "0.9-pre"); - - -use std::str; -use x = zed::str; -mod baz { - pub use bar::str; - pub use x = std::str; -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/utf8.rs b/gcc/testsuite/rust.test/utf8.rs deleted file mode 100644 index 5222b0e..0000000 --- a/gcc/testsuite/rust.test/utf8.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let yen: char = '¥'; // 0xa5 - let c_cedilla: char = 'ç'; // 0xe7 - let thorn: char = 'þ'; // 0xfe - let y_diaeresis: char = 'ÿ'; // 0xff - let pi: char = 'Π'; // 0x3a0 - - assert_eq!(yen as int, 0xa5); - assert_eq!(c_cedilla as int, 0xe7); - assert_eq!(thorn as int, 0xfe); - assert_eq!(y_diaeresis as int, 0xff); - assert_eq!(pi as int, 0x3a0); - - assert_eq!(pi as int, '\u03a0' as int); - assert_eq!('\x0a' as int, '\n' as int); - - let bhutan: ~str = ~"འབྲུག་ཡུལ།"; - let japan: ~str = ~"日本"; - let uzbekistan: ~str = ~"Ўзбекистон"; - let austria: ~str = ~"Österreich"; - - let bhutan_e: ~str = - ~"\u0f60\u0f56\u0fb2\u0f74\u0f42\u0f0b\u0f61\u0f74\u0f63\u0f0d"; - let japan_e: ~str = ~"\u65e5\u672c"; - let uzbekistan_e: ~str = - ~"\u040e\u0437\u0431\u0435\u043a\u0438\u0441\u0442\u043e\u043d"; - let austria_e: ~str = ~"\u00d6sterreich"; - - let oo: char = 'Ö'; - assert_eq!(oo as int, 0xd6); - - fn check_str_eq(a: ~str, b: ~str) { - let mut i: int = 0; - for ab in a.byte_iter() { - info2!("{}", i); - info2!("{}", ab); - let bb: u8 = b[i]; - info2!("{}", bb); - assert_eq!(ab, bb); - i += 1; - } - } - - check_str_eq(bhutan, bhutan_e); - check_str_eq(japan, japan_e); - check_str_eq(uzbekistan, uzbekistan_e); - check_str_eq(austria, austria_e); -} diff --git a/gcc/testsuite/rust.test/utf8_chars.rs b/gcc/testsuite/rust.test/utf8_chars.rs deleted file mode 100644 index db258d4..0000000 --- a/gcc/testsuite/rust.test/utf8_chars.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::str; - -pub fn main() { - // Chars of 1, 2, 3, and 4 bytes - let chs: ~[char] = ~['e', 'é', '€', '\U00010000']; - let s: ~str = str::from_chars(chs); - let schs: ~[char] = s.iter().collect(); - - assert!(s.len() == 10u); - assert!(s.char_len() == 4u); - assert!(schs.len() == 4u); - assert!(str::from_chars(schs) == s); - assert!(s.char_at(0u) == 'e'); - assert!(s.char_at(1u) == 'é'); - - assert!((str::is_utf8(s.as_bytes()))); - // invalid prefix - assert!((!str::is_utf8([0x80_u8]))); - // invalid 2 byte prefix - assert!((!str::is_utf8([0xc0_u8]))); - assert!((!str::is_utf8([0xc0_u8, 0x10_u8]))); - // invalid 3 byte prefix - assert!((!str::is_utf8([0xe0_u8]))); - assert!((!str::is_utf8([0xe0_u8, 0x10_u8]))); - assert!((!str::is_utf8([0xe0_u8, 0xff_u8, 0x10_u8]))); - // invalid 4 byte prefix - assert!((!str::is_utf8([0xf0_u8]))); - assert!((!str::is_utf8([0xf0_u8, 0x10_u8]))); - assert!((!str::is_utf8([0xf0_u8, 0xff_u8, 0x10_u8]))); - assert!((!str::is_utf8([0xf0_u8, 0xff_u8, 0xff_u8, 0x10_u8]))); - - let mut stack = ~"a×c€"; - assert_eq!(stack.pop_char(), '€'); - assert_eq!(stack.pop_char(), 'c'); - stack.push_char('u'); - assert!(stack == ~"a×u"); - assert_eq!(stack.shift_char(), 'a'); - assert_eq!(stack.shift_char(), '×'); - stack.unshift_char('ß'); - assert!(stack == ~"ßu"); -} diff --git a/gcc/testsuite/rust.test/utf8_idents.rs b/gcc/testsuite/rust.test/utf8_idents.rs deleted file mode 100644 index 3bc29ea..0000000 --- a/gcc/testsuite/rust.test/utf8_idents.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::num; - -pub fn main() { - let ε = 0.00001; - let Π = 3.14; - let लंच = Π * Π + 1.54; - assert!(num::abs((लंच - 1.54) - (Π * Π)) < ε); - assert_eq!(საჭმელად_გემრიელი_სადილი(), 0); -} - -fn საჭმელად_გემრიელი_სადილი() -> int { - - // Lunch in several languages. - - let ランチ = 10; - let 午餐 = 10; - - let ארוחת_צהריי = 10; - let غداء = 10; - let լանչ = 10; - let обед = 10; - let абед = 10; - let μεσημεριανό = 10; - let hádegismatur = 10; - let ручек = 10; - - let ăn_trưa = 10; - let อาหารกลางวัน = 10; - - // Lunchy arithmetic, mm. - - assert_eq!(hádegismatur * ручек * обед, 1000); - assert_eq!(10, ארוחת_צהריי); - assert_eq!(ランチ + 午餐 + μεσημεριανό, 30); - assert_eq!(ăn_trưa + อาหารกลางวัน, 20); - return (абед + լանչ) >> غداء; -} diff --git a/gcc/testsuite/rust.test/variant-attributes.rs b/gcc/testsuite/rust.test/variant-attributes.rs deleted file mode 100644 index 54a1dd0..0000000 --- a/gcc/testsuite/rust.test/variant-attributes.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact - Make sure we actually print the attributes - -enum crew_of_enterprise_d { - - #[captain] - jean_luc_picard, - - #[oldcommander] - william_t_riker, - - #[chief_medical_officer] - beverly_crusher, - - #[ships_councellor] - deanna_troi, - - #[lieutenant_oldcommander] - data, - - #[chief_of_security] - worf, - - #[chief_engineer] - geordi_la_forge, -} - -fn boldly_go(_crew_member: crew_of_enterprise_d, _where: ~str) { } - -pub fn main() { boldly_go(worf, ~"where no one has gone before"); } diff --git a/gcc/testsuite/rust.test/variant-structs-trivial.rs b/gcc/testsuite/rust.test/variant-structs-trivial.rs deleted file mode 100644 index 66bdec4..0000000 --- a/gcc/testsuite/rust.test/variant-structs-trivial.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum Foo { - Bar { x: int }, - Baz { y: int } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/vec-concat.rs b/gcc/testsuite/rust.test/vec-concat.rs deleted file mode 100644 index 0a8a9b1..0000000 --- a/gcc/testsuite/rust.test/vec-concat.rs +++ /dev/null @@ -1,20 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let a: ~[int] = ~[1, 2, 3, 4, 5]; - let b: ~[int] = ~[6, 7, 8, 9, 0]; - let v: ~[int] = a + b; - info2!("{}", v[9]); - assert_eq!(v[0], 1); - assert_eq!(v[7], 8); - assert_eq!(v[9], 0); -} diff --git a/gcc/testsuite/rust.test/vec-drop.rs b/gcc/testsuite/rust.test/vec-drop.rs deleted file mode 100644 index d387d78..0000000 --- a/gcc/testsuite/rust.test/vec-drop.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -struct Pair { x: int, y: int } - -pub fn main() { - // This just tests whether the vec leaks its members. - - let _pvec: ~[@Pair] = - ~[@Pair{x: 1, y: 2}, @Pair{x: 3, y: 4}, @Pair{x: 5, y: 6}]; -} diff --git a/gcc/testsuite/rust.test/vec-fixed-length.rs b/gcc/testsuite/rust.test/vec-fixed-length.rs deleted file mode 100644 index 8e22be1..0000000 --- a/gcc/testsuite/rust.test/vec-fixed-length.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x: [int, ..4] = [1, 2, 3, 4]; - println!("{}", x[0]); -} diff --git a/gcc/testsuite/rust.test/vec-growth.rs b/gcc/testsuite/rust.test/vec-growth.rs deleted file mode 100644 index c9a4c57..0000000 --- a/gcc/testsuite/rust.test/vec-growth.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let mut v = ~[1]; - v.push(2); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); - assert_eq!(v[3], 4); - assert_eq!(v[4], 5); -} diff --git a/gcc/testsuite/rust.test/vec-ivec-deadlock.rs b/gcc/testsuite/rust.test/vec-ivec-deadlock.rs deleted file mode 100644 index ccc7768..0000000 --- a/gcc/testsuite/rust.test/vec-ivec-deadlock.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let a = ~[1, 2, 3, 4, 5]; - let mut b = ~[a.clone(), a.clone()]; - b = b + b; // FIXME(#3387)---can't write b += b -} diff --git a/gcc/testsuite/rust.test/vec-late-init.rs b/gcc/testsuite/rust.test/vec-late-init.rs deleted file mode 100644 index e11bd25..0000000 --- a/gcc/testsuite/rust.test/vec-late-init.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let mut later: ~[int]; - if true { later = ~[1]; } else { later = ~[2]; } - info2!("{}", later[0]); -} diff --git a/gcc/testsuite/rust.test/vec-matching-autoslice.rs b/gcc/testsuite/rust.test/vec-matching-autoslice.rs deleted file mode 100644 index 8965ee6..0000000 --- a/gcc/testsuite/rust.test/vec-matching-autoslice.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub fn main() { - let x = @[1, 2, 3]; - match x { - [2, .._] => fail2!(), - [1, ..tail] => { - assert_eq!(tail, [2, 3]); - } - [_] => fail2!(), - [] => fail2!() - } - - let y = (~[(1, true), (2, false)], 0.5); - match y { - ([_, _, _], 0.5) => fail2!(), - ([(1, a), (b, false), ..tail], _) => { - assert_eq!(a, true); - assert_eq!(b, 2); - assert!(tail.is_empty()); - } - ([.._tail], _) => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/vec-matching-fixed.rs b/gcc/testsuite/rust.test/vec-matching-fixed.rs deleted file mode 100644 index 3b45182..0000000 --- a/gcc/testsuite/rust.test/vec-matching-fixed.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn a() { - let x = [1, 2, 3]; - match x { - [1, 2, 4] => unreachable!(), - [0, 2, 3, .._] => unreachable!(), - [0, .._, 3] => unreachable!(), - [0, .._] => unreachable!(), - [1, 2, 3] => (), - [_, _, _] => unreachable!(), - } - match x { - [.._] => (), - } - match x { - [_, _, _, .._] => (), - } - match x { - [a, b, c] => { - assert_eq!(1, a); - assert_eq!(2, b); - assert_eq!(3, c); - } - } -} - -pub fn main() { - a(); -} diff --git a/gcc/testsuite/rust.test/vec-matching-fold.rs b/gcc/testsuite/rust.test/vec-matching-fold.rs deleted file mode 100644 index 22f1ccb..0000000 --- a/gcc/testsuite/rust.test/vec-matching-fold.rs +++ /dev/null @@ -1,31 +0,0 @@ -fn foldl(values: &[T], - initial: U, - function: &fn(partial: U, element: &T) -> U) - -> U { - match values { - [ref head, ..tail] => - foldl(tail, function(initial, head), function), - [] => initial.clone() - } -} - -fn foldr(values: &[T], - initial: U, - function: &fn(element: &T, partial: U) -> U) - -> U { - match values { - [..head, ref tail] => - foldr(head, function(tail, initial), function), - [] => initial.clone() - } -} - -pub fn main() { - let x = [1, 2, 3, 4, 5]; - - let product = foldl(x, 1, |a, b| a * *b); - assert_eq!(product, 120); - - let sum = foldr(x, 0, |a, b| *a + b); - assert_eq!(sum, 15); -} diff --git a/gcc/testsuite/rust.test/vec-matching-legal-tail-element-borrow.rs b/gcc/testsuite/rust.test/vec-matching-legal-tail-element-borrow.rs deleted file mode 100644 index d90abe3..0000000 --- a/gcc/testsuite/rust.test/vec-matching-legal-tail-element-borrow.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub fn main() { - let x = &[1, 2, 3, 4, 5]; - if !x.is_empty() { - let el = match x { - [1, ..ref tail] => &tail[0], - _ => unreachable!() - }; - println!("{}", *el); - } -} diff --git a/gcc/testsuite/rust.test/vec-matching.rs b/gcc/testsuite/rust.test/vec-matching.rs deleted file mode 100644 index dec29c8..0000000 --- a/gcc/testsuite/rust.test/vec-matching.rs +++ /dev/null @@ -1,75 +0,0 @@ -fn a() { - let x = ~[1]; - match x { - [_, _, _, _, _, .._] => fail2!(), - [.._, _, _, _, _] => fail2!(), - [_, .._, _, _] => fail2!(), - [_, _] => fail2!(), - [a] => { - assert_eq!(a, 1); - } - [] => fail2!() - } -} - -fn b() { - let x = ~[1, 2, 3]; - match x { - [a, b, ..c] => { - assert_eq!(a, 1); - assert_eq!(b, 2); - assert_eq!(c, &[3]); - } - _ => fail2!() - } - match x { - [..a, b, c] => { - assert_eq!(a, &[1]); - assert_eq!(b, 2); - assert_eq!(c, 3); - } - _ => fail2!() - } - match x { - [a, ..b, c] => { - assert_eq!(a, 1); - assert_eq!(b, &[2]); - assert_eq!(c, 3); - } - _ => fail2!() - } - match x { - [a, b, c] => { - assert_eq!(a, 1); - assert_eq!(b, 2); - assert_eq!(c, 3); - } - _ => fail2!() - } -} - -fn c() { - let x = [1]; - match x { - [2, .. _] => fail2!(), - [.. _] => () - } -} - -fn d() { - let x = [1, 2, 3]; - let branch = match x { - [1, 1, .. _] => 0, - [1, 2, 3, .. _] => 1, - [1, 2, .. _] => 2, - _ => 3 - }; - assert_eq!(branch, 1); -} - -pub fn main() { - a(); - b(); - c(); - d(); -} diff --git a/gcc/testsuite/rust.test/vec-push.rs b/gcc/testsuite/rust.test/vec-push.rs deleted file mode 100644 index 50e76db..0000000 --- a/gcc/testsuite/rust.test/vec-push.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { let mut v = ~[1, 2, 3]; v.push(1); } diff --git a/gcc/testsuite/rust.test/vec-self-append.rs b/gcc/testsuite/rust.test/vec-self-append.rs deleted file mode 100644 index 4d52865..0000000 --- a/gcc/testsuite/rust.test/vec-self-append.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -fn test_heap_to_heap() { - // a spills onto the heap - let mut a = ~[0, 1, 2, 3, 4]; - a = a + a; // FIXME(#3387)---can't write a += a - assert_eq!(a.len(), 10u); - assert_eq!(a[0], 0); - assert_eq!(a[1], 1); - assert_eq!(a[2], 2); - assert_eq!(a[3], 3); - assert_eq!(a[4], 4); - assert_eq!(a[5], 0); - assert_eq!(a[6], 1); - assert_eq!(a[7], 2); - assert_eq!(a[8], 3); - assert_eq!(a[9], 4); -} - -fn test_stack_to_heap() { - // a is entirely on the stack - let mut a = ~[0, 1, 2]; - // a spills to the heap - a = a + a; // FIXME(#3387)---can't write a += a - assert_eq!(a.len(), 6u); - assert_eq!(a[0], 0); - assert_eq!(a[1], 1); - assert_eq!(a[2], 2); - assert_eq!(a[3], 0); - assert_eq!(a[4], 1); - assert_eq!(a[5], 2); -} - -fn test_loop() { - // Make sure we properly handle repeated self-appends. - let mut a: ~[int] = ~[0]; - let mut i = 20; - let mut expected_len = 1u; - while i > 0 { - error2!("{}", a.len()); - assert_eq!(a.len(), expected_len); - a = a + a; // FIXME(#3387)---can't write a += a - i -= 1; - expected_len *= 2u; - } -} - -pub fn main() { test_heap_to_heap(); test_stack_to_heap(); test_loop(); } diff --git a/gcc/testsuite/rust.test/vec-slice-drop.rs b/gcc/testsuite/rust.test/vec-slice-drop.rs deleted file mode 100644 index 2a4bd2a..0000000 --- a/gcc/testsuite/rust.test/vec-slice-drop.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure that destructors get run on slice literals -struct foo { - x: @mut int, -} - -#[unsafe_destructor] -impl Drop for foo { - fn drop(&mut self) { - *self.x += 1; - } -} - -fn foo(x: @mut int) -> foo { - foo { - x: x - } -} - -pub fn main() { - let x = @mut 0; - { - let l = &[foo(x)]; - assert_eq!(*l[0].x, 0); - } - assert_eq!(*x, 1); -} diff --git a/gcc/testsuite/rust.test/vec-slice.rs b/gcc/testsuite/rust.test/vec-slice.rs deleted file mode 100644 index e3012b0..0000000 --- a/gcc/testsuite/rust.test/vec-slice.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let v = ~[1,2,3,4,5]; - let v2 = v.slice(1, 3); - assert_eq!(v2[0], 2); - assert_eq!(v2[1], 3); -} diff --git a/gcc/testsuite/rust.test/vec-tail-matching.rs b/gcc/testsuite/rust.test/vec-tail-matching.rs deleted file mode 100644 index dc2b3d2..0000000 --- a/gcc/testsuite/rust.test/vec-tail-matching.rs +++ /dev/null @@ -1,35 +0,0 @@ -struct Foo { - string: ~str -} - -pub fn main() { - let x = ~[ - Foo { string: ~"foo" }, - Foo { string: ~"bar" }, - Foo { string: ~"baz" } - ]; - match x { - [ref first, ..tail] => { - assert!(first.string == ~"foo"); - assert_eq!(tail.len(), 2); - assert!(tail[0].string == ~"bar"); - assert!(tail[1].string == ~"baz"); - - match tail { - [Foo { _ }, _, Foo { _ }, .. _tail] => { - unreachable!(); - } - [Foo { string: ref a }, Foo { string: ref b }] => { - assert_eq!("bar", a.slice(0, a.len())); - assert_eq!("baz", b.slice(0, b.len())); - } - _ => { - unreachable!(); - } - } - } - _ => { - unreachable!(); - } - } -} diff --git a/gcc/testsuite/rust.test/vec-to_str.rs b/gcc/testsuite/rust.test/vec-to_str.rs deleted file mode 100644 index a24ef38..0000000 --- a/gcc/testsuite/rust.test/vec-to_str.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - assert_eq!((~[0, 1]).to_str(), ~"[0, 1]"); - assert_eq!((&[1, 2]).to_str(), ~"[1, 2]"); - assert_eq!((@[2, 3]).to_str(), ~"[2, 3]"); - - let foo = ~[3, 4]; - let bar = &[4, 5]; - let baz = @[5, 6]; - - assert_eq!(foo.to_str(), ~"[3, 4]"); - assert_eq!(bar.to_str(), ~"[4, 5]"); - assert_eq!(baz.to_str(), ~"[5, 6]"); - -} diff --git a/gcc/testsuite/rust.test/vec-trailing-comma.rs b/gcc/testsuite/rust.test/vec-trailing-comma.rs deleted file mode 100644 index 426416f..0000000 --- a/gcc/testsuite/rust.test/vec-trailing-comma.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #2482. - -pub fn main() { - let v1: ~[int] = ~[10, 20, 30,]; - let v2: ~[int] = ~[10, 20, 30]; - assert_eq!(v1[2], v2[2]); - let v3: ~[int] = ~[10,]; - let v4: ~[int] = ~[10]; - assert_eq!(v3[0], v4[0]); -} diff --git a/gcc/testsuite/rust.test/vec.rs b/gcc/testsuite/rust.test/vec.rs deleted file mode 100644 index 34fcca9..0000000 --- a/gcc/testsuite/rust.test/vec.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let v: ~[int] = ~[10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - let mut x: int = 0; - assert_eq!(v[x], 10); - assert_eq!(v[x + 1], 20); - x = x + 1; - assert_eq!(v[x], 20); - assert_eq!(v[x - 1], 10); -} diff --git a/gcc/testsuite/rust.test/vector-no-ann-2.rs b/gcc/testsuite/rust.test/vector-no-ann-2.rs deleted file mode 100644 index 60124a7..0000000 --- a/gcc/testsuite/rust.test/vector-no-ann-2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { let _quux: @~[uint] = @~[]; } diff --git a/gcc/testsuite/rust.test/warn-ctypes-inhibit.rs b/gcc/testsuite/rust.test/warn-ctypes-inhibit.rs deleted file mode 100644 index f2cc2d7..0000000 --- a/gcc/testsuite/rust.test/warn-ctypes-inhibit.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-D ctypes - -#[allow(ctypes)]; - -mod libc { - #[nolink] - extern { - pub fn malloc(size: int) -> *u8; - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/weird-exprs.rs b/gcc/testsuite/rust.test/weird-exprs.rs deleted file mode 100644 index 9de4e29..0000000 --- a/gcc/testsuite/rust.test/weird-exprs.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -// Just a grab bag of stuff that you wouldn't want to actually write. - -fn strange() -> bool { let _x: bool = return true; } - -fn funny() { - fn f(_x: ()) { } - f(return); -} - -fn what() { - fn the(x: @mut bool) { return while !*x { *x = true; }; } - let i = @mut false; - let dont = {||the(i)}; - dont(); - assert!((*i)); -} - -fn zombiejesus() { - loop { - while (return) { - if (return) { - match (return) { - 1 => { - if (return) { - return - } else { - return - } - } - _ => { return } - }; - } else if (return) { - return; - } - } - if (return) { break; } - } -} - -fn notsure() { - let mut _x; - let mut _y = (_x = 0) == (_x = 0); - let mut _z = (_x = 0) < (_x = 0); - let _a = (_x += 0) == (_x = 0); - let _b = util::swap(&mut _y, &mut _z) == util::swap(&mut _y, &mut _z); -} - -fn canttouchthis() -> uint { - fn p() -> bool { true } - let _a = (assert!((true)) == (assert!(p()))); - let _c = (assert!((p())) == ()); - let _b: bool = (info2!("{}", 0) == (return 0u)); -} - -fn angrydome() { - loop { if break { } } - let mut i = 0; - loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => fail2!("wat") } } - break; } -} - -fn evil_lincoln() { let _evil = info2!("lincoln"); } - -pub fn main() { - strange(); - funny(); - what(); - zombiejesus(); - notsure(); - canttouchthis(); - angrydome(); - evil_lincoln(); -} diff --git a/gcc/testsuite/rust.test/while-cont.rs b/gcc/testsuite/rust.test/while-cont.rs deleted file mode 100644 index 44c3225..0000000 --- a/gcc/testsuite/rust.test/while-cont.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #825: Should recheck the loop condition after continuing -pub fn main() { - let mut i = 1; - while i > 0 { - assert!((i > 0)); - info2!("{}", i); - i -= 1; - continue; - } -} diff --git a/gcc/testsuite/rust.test/while-flow-graph.rs b/gcc/testsuite/rust.test/while-flow-graph.rs deleted file mode 100644 index 36d902d..0000000 --- a/gcc/testsuite/rust.test/while-flow-graph.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { let x: int = 10; while x == 10 && x == 11 { let _y = 0xf00; } } diff --git a/gcc/testsuite/rust.test/while-loop-constraints-2.rs b/gcc/testsuite/rust.test/while-loop-constraints-2.rs deleted file mode 100644 index a07d122..0000000 --- a/gcc/testsuite/rust.test/while-loop-constraints-2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -pub fn main() { - let mut y: int = 42; - let mut z: int = 42; - let mut x: int; - while z < 50 { - z += 1; - while false { x = y; y = z; } - info2!("{}", y); - } - assert!((y == 42 && z == 50)); -} diff --git a/gcc/testsuite/rust.test/while-prelude-drop.rs b/gcc/testsuite/rust.test/while-prelude-drop.rs deleted file mode 100644 index 503e37f..0000000 --- a/gcc/testsuite/rust.test/while-prelude-drop.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -#[deriving(Eq)] -enum t { a, b(~str), } - -fn make(i: int) -> t { - if i > 10 { return a; } - let mut s = ~"hello"; - // Ensure s is non-const. - - s.push_str("there"); - return b(s); -} - -pub fn main() { - let mut i = 0; - - - // The auto slot for the result of make(i) should not leak. - while make(i) != a { i += 1; } -} diff --git a/gcc/testsuite/rust.test/while-with-break.rs b/gcc/testsuite/rust.test/while-with-break.rs deleted file mode 100644 index 05eea29..0000000 --- a/gcc/testsuite/rust.test/while-with-break.rs +++ /dev/null @@ -1,19 +0,0 @@ - - - -// -*- rust -*- -pub fn main() { - let mut i: int = 90; - while i < 100 { - info2!("{}", i); - i = i + 1; - if i == 95 { - let _v: ~[int] = - ~[1, 2, 3, 4, 5]; // we check that it is freed by break - - info2!("breaking"); - break; - } - } - assert_eq!(i, 95); -} diff --git a/gcc/testsuite/rust.test/while.rs b/gcc/testsuite/rust.test/while.rs deleted file mode 100644 index 4295c89..0000000 --- a/gcc/testsuite/rust.test/while.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let mut x: int = 10; - let mut y: int = 0; - while y < x { info2!("{}", y); info2!("hello"); y = y + 1; } - while x > 0 { - info2!("goodbye"); - x = x - 1; - info2!("{}", x); - } -} diff --git a/gcc/testsuite/rust.test/writealias.rs b/gcc/testsuite/rust.test/writealias.rs deleted file mode 100644 index 06c2ca7..0000000 --- a/gcc/testsuite/rust.test/writealias.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use std::unstable; - -struct Point {x: int, y: int, z: int} - -fn f(p: &mut Point) { p.z = 13; } - -pub fn main() { - unsafe { - let x = Some(unstable::sync::Exclusive::new(true)); - match x { - Some(ref z) if z.with(|b| *b) => { - do z.with |b| { assert!(*b); } - }, - _ => fail2!() - } - } -} diff --git a/gcc/testsuite/rust.test/x86stdcall.rs b/gcc/testsuite/rust.test/x86stdcall.rs deleted file mode 100644 index f584237..0000000 --- a/gcc/testsuite/rust.test/x86stdcall.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// GetLastError doesn't seem to work with stack switching -// xfail-test - -#[cfg(target_os = "win32")] -extern "stdcall" mod kernel32 { - fn SetLastError(err: uint); - fn GetLastError() -> uint; -} - - -#[cfg(target_os = "win32")] -pub fn main() { - unsafe { - let expected = 1234u; - kernel32::SetLastError(expected); - let actual = kernel32::GetLastError(); - log(error, actual); - assert_eq!(expected, actual); - } -} - -#[cfg(target_os = "macos")] -#[cfg(target_os = "linux")] -#[cfg(target_os = "freebsd")] -pub fn main() { } diff --git a/gcc/testsuite/rust.test/x86stdcall2.rs b/gcc/testsuite/rust.test/x86stdcall2.rs deleted file mode 100644 index b16218a..0000000 --- a/gcc/testsuite/rust.test/x86stdcall2.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub type HANDLE = u32; -pub type DWORD = u32; -pub type SIZE_T = u32; -pub type LPVOID = uint; -pub type BOOL = u8; - -#[cfg(target_os = "win32")] -mod kernel32 { - use super::{HANDLE, DWORD, SIZE_T, LPVOID, BOOL}; - - extern "stdcall" { - pub fn GetProcessHeap() -> HANDLE; - pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) - -> LPVOID; - pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; - } -} - - -#[cfg(target_os = "win32")] -#[fixed_stack_segment] -pub fn main() { - let heap = unsafe { kernel32::GetProcessHeap() }; - let mem = unsafe { kernel32::HeapAlloc(heap, 0u32, 100u32) }; - assert!(mem != 0u); - let res = unsafe { kernel32::HeapFree(heap, 0u32, mem) }; - assert!(res != 0u8); -} - -#[cfg(target_os = "macos")] -#[cfg(target_os = "linux")] -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "android")] -pub fn main() { } diff --git a/gcc/testsuite/rust.test/xc_conditions_client.rs b/gcc/testsuite/rust.test/xc_conditions_client.rs deleted file mode 100644 index 730ed18..0000000 --- a/gcc/testsuite/rust.test/xc_conditions_client.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:xc_conditions.rs - -extern mod xc_conditions; -use xc_conditions::oops; -use xc_conditions::trouble; - -// Tests of cross-crate conditions; the condition is -// defined in lib, and we test various combinations -// of `trap` and `raise` in the client or the lib where -// the condition was defined. Also in test #4 we use -// more complex features (generics, traits) in -// combination with the condition. -// -// trap raise -// ------------ -// xc_conditions : client lib -// xc_conditions_2: client client -// xc_conditions_3: lib client -// xc_conditions_4: client client (with traits) -// -// the trap=lib, raise=lib case isn't tested since -// there's no cross-crate-ness to test in that case. - -pub fn main() { - do oops::cond.trap(|_i| 12345).inside { - let x = trouble(); - assert_eq!(x,12345); - } -} diff --git a/gcc/testsuite/rust.test/xc_conditions_client_2.rs b/gcc/testsuite/rust.test/xc_conditions_client_2.rs deleted file mode 100644 index 9666c03..0000000 --- a/gcc/testsuite/rust.test/xc_conditions_client_2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:xc_conditions_2.rs - -extern mod xc_conditions_2; -use xcc = xc_conditions_2; - -pub fn main() { - do xcc::oops::cond.trap(|_| 1).inside { - xcc::oops::cond.raise(1); - } -} diff --git a/gcc/testsuite/rust.test/xc_conditions_client_3.rs b/gcc/testsuite/rust.test/xc_conditions_client_3.rs deleted file mode 100644 index 7d16572..0000000 --- a/gcc/testsuite/rust.test/xc_conditions_client_3.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:xc_conditions_3.rs - -extern mod xc_conditions_3; -use xcc = xc_conditions_3; - -pub fn main() { - assert_eq!(xcc::guard(a, 1), 40); -} - -pub fn a() -> int { - assert_eq!(xcc::oops::cond.raise(7), 7); - xcc::guard(b, 2) -} - -pub fn b() -> int { - assert_eq!(xcc::oops::cond.raise(8), 16); - xcc::guard(c, 3) -} - -pub fn c() -> int { - assert_eq!(xcc::oops::cond.raise(9), 27); - xcc::guard(d, 4) -} - -pub fn d() -> int { - xcc::oops::cond.raise(10) -} diff --git a/gcc/testsuite/rust.test/xc_conditions_client_4.rs b/gcc/testsuite/rust.test/xc_conditions_client_4.rs deleted file mode 100644 index 69ddb37..0000000 --- a/gcc/testsuite/rust.test/xc_conditions_client_4.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:xc_conditions_4.rs - -extern mod xc_conditions_4; -use xcc = xc_conditions_4; - -struct SThunk { - x: int -} - -impl xcc::Thunk for SThunk { - fn call(self) -> xcc::Color { - xcc::oops::cond.raise((self.x, 1.23, ~"oh no")) - } -} - -pub fn main() { - do xcc::oops::cond.trap(|_| xcc::Red).inside { - let t = SThunk { x : 10 }; - assert_eq!(xcc::callback(t), xcc::Red) - } -} diff --git a/gcc/testsuite/rust.test/xcrate-address-insignificant.rs b/gcc/testsuite/rust.test/xcrate-address-insignificant.rs deleted file mode 100644 index 33f958f..0000000 --- a/gcc/testsuite/rust.test/xcrate-address-insignificant.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like aux-build -// aux-build:xcrate_address_insignificant.rs - -extern mod foo(name = "xcrate_address_insignificant"); - -fn main() { - assert_eq!(foo::foo::(), foo::bar()); -} diff --git a/gcc/testsuite/rust.test/xcrate-static-addresses.rs b/gcc/testsuite/rust.test/xcrate-static-addresses.rs deleted file mode 100644 index 7eb4adf..0000000 --- a/gcc/testsuite/rust.test/xcrate-static-addresses.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:xcrate_static_addresses.rs - -extern mod xcrate_static_addresses; - -use other = xcrate_static_addresses; - -pub fn main() { - other::verify_same(&other::global); - other::verify_same2(other::global2); - - // Previously this fail'd because there were two addresses that were being - // used when declaring constants. - do other::test::cond.trap(|_| { - }).inside { - other::raise(); - } -} diff --git a/gcc/testsuite/rust.test/xcrate-unit-struct.rs b/gcc/testsuite/rust.test/xcrate-unit-struct.rs deleted file mode 100644 index 79740c7..0000000 --- a/gcc/testsuite/rust.test/xcrate-unit-struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:xcrate_unit_struct.rs -// xfail-fast -extern mod xcrate_unit_struct; - -static s1: xcrate_unit_struct::Struct = xcrate_unit_struct::Struct; -static s2: xcrate_unit_struct::Unit = xcrate_unit_struct::Unit; -static s3: xcrate_unit_struct::Unit = - xcrate_unit_struct::Argument(xcrate_unit_struct::Struct); -static s4: xcrate_unit_struct::Unit = xcrate_unit_struct::Argument(s1); - -fn f1(_: xcrate_unit_struct::Struct) {} -fn f2(_: xcrate_unit_struct::Unit) {} - -fn main() { - f1(xcrate_unit_struct::Struct); - f2(xcrate_unit_struct::Unit); - f2(xcrate_unit_struct::Argument(xcrate_unit_struct::Struct)); - - f1(s1); - f2(s2); - f2(s3); - f2(s4); -} diff --git a/gcc/testsuite/rust.test/yield.rs b/gcc/testsuite/rust.test/yield.rs deleted file mode 100644 index 6f6f59d..0000000 --- a/gcc/testsuite/rust.test/yield.rs +++ /dev/null @@ -1,28 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { - let mut builder = task::task(); - let result = builder.future_result(); - builder.spawn(child); - error2!("1"); - task::deschedule(); - error2!("2"); - task::deschedule(); - error2!("3"); - result.recv(); -} - -fn child() { - error2!("4"); task::deschedule(); error2!("5"); task::deschedule(); error2!("6"); -} diff --git a/gcc/testsuite/rust.test/yield1.rs b/gcc/testsuite/rust.test/yield1.rs deleted file mode 100644 index 6b189e5..0000000 --- a/gcc/testsuite/rust.test/yield1.rs +++ /dev/null @@ -1,23 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { - let mut builder = task::task(); - let result = builder.future_result(); - builder.spawn(child); - error2!("1"); - task::deschedule(); - result.recv(); -} - -fn child() { error2!("2"); } diff --git a/gcc/testsuite/rust.test/yield2.rs b/gcc/testsuite/rust.test/yield2.rs deleted file mode 100644 index 6dc9653..0000000 --- a/gcc/testsuite/rust.test/yield2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { - let mut i: int = 0; - while i < 100 { i = i + 1; error2!("{}", i); task::deschedule(); } -} -- cgit v1.1

(&self, sp: Span, predicate: P) -> Span - where P: for <'r> FnMut(&'r char) -> bool - { - if let Ok(snippet) = self.span_to_snippet(sp) { - let offset = snippet.chars() - .take_while(predicate) - .map(|c| c.len_utf8()) - .sum::(); - - sp.with_hi(BytePos(sp.lo().0 + (offset as u32))) - } else { - sp - } - } - - pub fn def_span(&self, sp: Span) -> Span { - self.span_until_char(sp, '{') - } - - /// Returns a new span representing just the start-point of this span - pub fn start_point(&self, sp: Span) -> Span { - let pos = sp.lo().0; - let width = self.find_width_of_character_at_span(sp, false); - let corrected_start_position = pos.checked_add(width).unwrap_or(pos); - let end_point = BytePos(cmp::max(corrected_start_position, sp.lo().0)); - sp.with_hi(end_point) - } - - /// Returns a new span representing just the end-point of this span - pub fn end_point(&self, sp: Span) -> Span { - let pos = sp.hi().0; - - let width = self.find_width_of_character_at_span(sp, false); - let corrected_end_position = pos.checked_sub(width).unwrap_or(pos); - - let end_point = BytePos(cmp::max(corrected_end_position, sp.lo().0)); - sp.with_lo(end_point) - } - - /// Returns a new span representing the next character after the end-point of this span - pub fn next_point(&self, sp: Span) -> Span { - let start_of_next_point = sp.hi().0; - - let width = self.find_width_of_character_at_span(sp, true); - // If the width is 1, then the next span should point to the same `lo` and `hi`. However, - // in the case of a multibyte character, where the width != 1, the next span should - // span multiple bytes to include the whole character. - let end_of_next_point = start_of_next_point.checked_add( - width - 1).unwrap_or(start_of_next_point); - - let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point)); - Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt()) - } - - /// Finds the width of a character, either before or after the provided span. - fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 { - // Disregard malformed spans and assume a one-byte wide character. - if sp.lo() >= sp.hi() { - debug!("find_width_of_character_at_span: early return malformed span"); - return 1; - } - - let local_begin = self.lookup_byte_offset(sp.lo()); - let local_end = self.lookup_byte_offset(sp.hi()); - debug!("find_width_of_character_at_span: local_begin=`{:?}`, local_end=`{:?}`", - local_begin, local_end); - - if local_begin.sf.start_pos != local_end.sf.start_pos { - debug!("find_width_of_character_at_span: begin and end are in different files"); - return 1; - } - - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - debug!("find_width_of_character_at_span: start_index=`{:?}`, end_index=`{:?}`", - start_index, end_index); - - // Disregard indexes that are at the start or end of their spans, they can't fit bigger - // characters. - if (!forwards && end_index == usize::min_value()) || - (forwards && start_index == usize::max_value()) { - debug!("find_width_of_character_at_span: start or end of span, cannot be multibyte"); - return 1; - } - - let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize(); - debug!("find_width_of_character_at_span: source_len=`{:?}`", source_len); - // Ensure indexes are also not malformed. - if start_index > end_index || end_index > source_len { - debug!("find_width_of_character_at_span: source indexes are malformed"); - return 1; - } - - let src = local_begin.sf.external_src.borrow(); - - // We need to extend the snippet to the end of the src rather than to end_index so when - // searching forwards for boundaries we've got somewhere to search. - let snippet = if let Some(ref src) = local_begin.sf.src { - let len = src.len(); - (&src[start_index..len]) - } else if let Some(src) = src.get_source() { - let len = src.len(); - (&src[start_index..len]) - } else { - return 1; - }; - debug!("find_width_of_character_at_span: snippet=`{:?}`", snippet); - - let mut target = if forwards { end_index + 1 } else { end_index - 1 }; - debug!("find_width_of_character_at_span: initial target=`{:?}`", target); - - while !snippet.is_char_boundary(target - start_index) && target < source_len { - target = if forwards { - target + 1 - } else { - match target.checked_sub(1) { - Some(target) => target, - None => { - break; - } - } - }; - debug!("find_width_of_character_at_span: target=`{:?}`", target); - } - debug!("find_width_of_character_at_span: final target=`{:?}`", target); - - if forwards { - (target - end_index) as u32 - } else { - (end_index - target) as u32 - } - } - - pub fn get_source_file(&self, filename: &FileName) -> Option> { - for sf in self.files.borrow().source_files.iter() { - if *filename == sf.name { - return Some(sf.clone()); - } - } - None - } - - /// For a global BytePos compute the local offset within the containing SourceFile - pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos { - let idx = self.lookup_source_file_idx(bpos); - let sf = (*self.files.borrow().source_files)[idx].clone(); - let offset = bpos - sf.start_pos; - SourceFileAndBytePos {sf, pos: offset} - } - - /// Converts an absolute BytePos to a CharPos relative to the source_file. - pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { - let idx = self.lookup_source_file_idx(bpos); - let map = &(*self.files.borrow().source_files)[idx]; - - // The number of extra bytes due to multibyte chars in the SourceFile - let mut total_extra_bytes = 0; - - for mbc in map.multibyte_chars.iter() { - debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos); - if mbc.pos < bpos { - // every character is at least one byte, so we only - // count the actual extra bytes. - total_extra_bytes += mbc.bytes as u32 - 1; - // We should never see a byte position in the middle of a - // character - assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32); - } else { - break; - } - } - - assert!(map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32()); - CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize) - } - - // Return the index of the source_file (in self.files) which contains pos. - pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { - let files = self.files.borrow(); - let files = &files.source_files; - let count = files.len(); - - // Binary search for the source_file. - let mut a = 0; - let mut b = count; - while b - a > 1 { - let m = (a + b) / 2; - if files[m].start_pos > pos { - b = m; - } else { - a = m; - } - } - - assert!(a < count, "position {} does not resolve to a source location", pos.to_usize()); - - return a; - } - - pub fn count_lines(&self) -> usize { - self.files().iter().fold(0, |a, f| a + f.count_lines()) - } - - - pub fn generate_fn_name_span(&self, span: Span) -> Option { - let prev_span = self.span_extend_to_prev_str(span, "fn", true); - self.span_to_snippet(prev_span).map(|snippet| { - let len = snippet.find(|c: char| !c.is_alphanumeric() && c != '_') - .expect("no label after fn"); - prev_span.with_hi(BytePos(prev_span.lo().0 + len as u32)) - }).ok() - } - - /// Take the span of a type parameter in a function signature and try to generate a span for the - /// function name (with generics) and a new snippet for this span with the pointed type - /// parameter as a new local type parameter. - /// - /// For instance: - /// ```rust,ignore (pseudo-Rust) - /// // Given span - /// fn my_function(param: T) - /// // ^ Original span - /// - /// // Result - /// fn my_function(param: T) - /// // ^^^^^^^^^^^ Generated span with snippet `my_function` - /// ``` - /// - /// Attention: The method used is very fragile since it essentially duplicates the work of the - /// parser. If you need to use this function or something similar, please consider updating the - /// source_map functions and this function to something more robust. - pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> { - // Try to extend the span to the previous "fn" keyword to retrieve the function - // signature - let sugg_span = self.span_extend_to_prev_str(span, "fn", false); - if sugg_span != span { - if let Ok(snippet) = self.span_to_snippet(sugg_span) { - // Consume the function name - let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_') - .expect("no label after fn"); - - // Consume the generics part of the function signature - let mut bracket_counter = 0; - let mut last_char = None; - for c in snippet[offset..].chars() { - match c { - '<' => bracket_counter += 1, - '>' => bracket_counter -= 1, - '(' => if bracket_counter == 0 { break; } - _ => {} - } - offset += c.len_utf8(); - last_char = Some(c); - } - - // Adjust the suggestion span to encompass the function name with its generics - let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32)); - - // Prepare the new suggested snippet to append the type parameter that triggered - // the error in the generics of the function signature - let mut new_snippet = if last_char == Some('>') { - format!("{}, ", &snippet[..(offset - '>'.len_utf8())]) - } else { - format!("{}<", &snippet[..offset]) - }; - new_snippet.push_str( - &self.span_to_snippet(span).unwrap_or_else(|_| "T".to_string())); - new_snippet.push('>'); - - return Some((sugg_span, new_snippet)); - } - } - - None - } -} - -impl SourceMapper for SourceMap { - fn lookup_char_pos(&self, pos: BytePos) -> Loc { - self.lookup_char_pos(pos) - } - fn span_to_lines(&self, sp: Span) -> FileLinesResult { - self.span_to_lines(sp) - } - fn span_to_string(&self, sp: Span) -> String { - self.span_to_string(sp) - } - fn span_to_filename(&self, sp: Span) -> FileName { - self.span_to_filename(sp) - } - fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option { - self.merge_spans(sp_lhs, sp_rhs) - } - fn call_span_if_macro(&self, sp: Span) -> Span { - if self.span_to_filename(sp.clone()).is_macros() { - let v = sp.macro_backtrace(); - if let Some(use_site) = v.last() { - return use_site.call_site; - } - } - sp - } - fn ensure_source_file_source_present(&self, source_file: Lrc) -> bool { - source_file.add_external_src( - || match source_file.name { - FileName::Real(ref name) => self.file_loader.read_file(name).ok(), - _ => None, - } - ) - } - fn doctest_offset_line(&self, file: &FileName, line: usize) -> usize { - self.doctest_offset_line(file, line) - } -} - -#[derive(Clone)] -pub struct FilePathMapping { - mapping: Vec<(PathBuf, PathBuf)>, -} - -impl FilePathMapping { - pub fn empty() -> FilePathMapping { - FilePathMapping { - mapping: vec![] - } - } - - pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping { - FilePathMapping { - mapping, - } - } - - /// Applies any path prefix substitution as defined by the mapping. - /// The return value is the remapped path and a boolean indicating whether - /// the path was affected by the mapping. - pub fn map_prefix(&self, path: PathBuf) -> (PathBuf, bool) { - // NOTE: We are iterating over the mapping entries from last to first - // because entries specified later on the command line should - // take precedence. - for &(ref from, ref to) in self.mapping.iter().rev() { - if let Ok(rest) = path.strip_prefix(from) { - return (to.join(rest), true); - } - } - - (path, false) - } -} - -// _____________________________________________________________________________ -// Tests -// - -#[cfg(test)] -mod tests { - use super::*; - use rustc_data_structures::sync::Lrc; - - fn init_source_map() -> SourceMap { - let sm = SourceMap::new(FilePathMapping::empty()); - sm.new_source_file(PathBuf::from("blork.rs").into(), - "first line.\nsecond line".to_string()); - sm.new_source_file(PathBuf::from("empty.rs").into(), - String::new()); - sm.new_source_file(PathBuf::from("blork2.rs").into(), - "first line.\nsecond line".to_string()); - sm - } - - #[test] - fn t3() { - // Test lookup_byte_offset - let sm = init_source_map(); - - let srcfbp1 = sm.lookup_byte_offset(BytePos(23)); - assert_eq!(srcfbp1.sf.name, PathBuf::from("blork.rs").into()); - assert_eq!(srcfbp1.pos, BytePos(23)); - - let srcfbp1 = sm.lookup_byte_offset(BytePos(24)); - assert_eq!(srcfbp1.sf.name, PathBuf::from("empty.rs").into()); - assert_eq!(srcfbp1.pos, BytePos(0)); - - let srcfbp2 = sm.lookup_byte_offset(BytePos(25)); - assert_eq!(srcfbp2.sf.name, PathBuf::from("blork2.rs").into()); - assert_eq!(srcfbp2.pos, BytePos(0)); - } - - #[test] - fn t4() { - // Test bytepos_to_file_charpos - let sm = init_source_map(); - - let cp1 = sm.bytepos_to_file_charpos(BytePos(22)); - assert_eq!(cp1, CharPos(22)); - - let cp2 = sm.bytepos_to_file_charpos(BytePos(25)); - assert_eq!(cp2, CharPos(0)); - } - - #[test] - fn t5() { - // Test zero-length source_files. - let sm = init_source_map(); - - let loc1 = sm.lookup_char_pos(BytePos(22)); - assert_eq!(loc1.file.name, PathBuf::from("blork.rs").into()); - assert_eq!(loc1.line, 2); - assert_eq!(loc1.col, CharPos(10)); - - let loc2 = sm.lookup_char_pos(BytePos(25)); - assert_eq!(loc2.file.name, PathBuf::from("blork2.rs").into()); - assert_eq!(loc2.line, 1); - assert_eq!(loc2.col, CharPos(0)); - } - - fn init_source_map_mbc() -> SourceMap { - let sm = SourceMap::new(FilePathMapping::empty()); - // € is a three byte utf8 char. - sm.new_source_file(PathBuf::from("blork.rs").into(), - "fir€st €€€€ line.\nsecond line".to_string()); - sm.new_source_file(PathBuf::from("blork2.rs").into(), - "first line€€.\n€ second line".to_string()); - sm - } - - #[test] - fn t6() { - // Test bytepos_to_file_charpos in the presence of multi-byte chars - let sm = init_source_map_mbc(); - - let cp1 = sm.bytepos_to_file_charpos(BytePos(3)); - assert_eq!(cp1, CharPos(3)); - - let cp2 = sm.bytepos_to_file_charpos(BytePos(6)); - assert_eq!(cp2, CharPos(4)); - - let cp3 = sm.bytepos_to_file_charpos(BytePos(56)); - assert_eq!(cp3, CharPos(12)); - - let cp4 = sm.bytepos_to_file_charpos(BytePos(61)); - assert_eq!(cp4, CharPos(15)); - } - - #[test] - fn t7() { - // Test span_to_lines for a span ending at the end of source_file - let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); - let file_lines = sm.span_to_lines(span).unwrap(); - - assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into()); - assert_eq!(file_lines.lines.len(), 1); - assert_eq!(file_lines.lines[0].line_index, 1); - } - - /// Given a string like " ~~~~~~~~~~~~ ", produces a span - /// converting that range. The idea is that the string has the same - /// length as the input, and we uncover the byte positions. Note - /// that this can span lines and so on. - fn span_from_selection(input: &str, selection: &str) -> Span { - assert_eq!(input.len(), selection.len()); - let left_index = selection.find('~').unwrap() as u32; - let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index); - Span::new(BytePos(left_index), BytePos(right_index + 1), NO_EXPANSION) - } - - /// Tests span_to_snippet and span_to_lines for a span converting 3 - /// lines in the middle of a file. - #[test] - fn span_to_snippet_and_lines_spanning_multiple_lines() { - let sm = SourceMap::new(FilePathMapping::empty()); - let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n"; - let selection = " \n ~~\n~~~\n~~~~~ \n \n"; - sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string()); - let span = span_from_selection(inputtext, selection); - - // check that we are extracting the text we thought we were extracting - assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD"); - - // check that span_to_lines gives us the complete result with the lines/cols we expected - let lines = sm.span_to_lines(span).unwrap(); - let expected = vec![ - LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) }, - LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) }, - LineInfo { line_index: 3, start_col: CharPos(0), end_col: CharPos(5) } - ]; - assert_eq!(lines.lines, expected); - } - - #[test] - fn t8() { - // Test span_to_snippet for a span ending at the end of source_file - let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); - let snippet = sm.span_to_snippet(span); - - assert_eq!(snippet, Ok("second line".to_string())); - } - - #[test] - fn t9() { - // Test span_to_str for a span ending at the end of source_file - let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); - let sstr = sm.span_to_string(span); - - assert_eq!(sstr, "blork.rs:2:1: 2:12"); - } - - /// Tests failing to merge two spans on different lines - #[test] - fn span_merging_fail() { - let sm = SourceMap::new(FilePathMapping::empty()); - let inputtext = "bbbb BB\ncc CCC\n"; - let selection1 = " ~~\n \n"; - let selection2 = " \n ~~~\n"; - sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_owned()); - let span1 = span_from_selection(inputtext, selection1); - let span2 = span_from_selection(inputtext, selection2); - - assert!(sm.merge_spans(span1, span2).is_none()); - } - - /// Returns the span corresponding to the `n`th occurrence of - /// `substring` in `source_text`. - trait SourceMapExtension { - fn span_substr(&self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize) - -> Span; - } - - impl SourceMapExtension for SourceMap { - fn span_substr(&self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize) - -> Span - { - println!("span_substr(file={:?}/{:?}, substring={:?}, n={})", - file.name, file.start_pos, substring, n); - let mut i = 0; - let mut hi = 0; - loop { - let offset = source_text[hi..].find(substring).unwrap_or_else(|| { - panic!("source_text `{}` does not have {} occurrences of `{}`, only {}", - source_text, n, substring, i); - }); - let lo = hi + offset; - hi = lo + substring.len(); - if i == n { - let span = Span::new( - BytePos(lo as u32 + file.start_pos.0), - BytePos(hi as u32 + file.start_pos.0), - NO_EXPANSION, - ); - assert_eq!(&self.span_to_snippet(span).unwrap()[..], - substring); - return span; - } - i += 1; - } - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/std_inject.rs b/gcc/rust/rustc_parser/libsyntax/std_inject.rs deleted file mode 100644 index 6630bf9..0000000 --- a/gcc/rust/rustc_parser/libsyntax/std_inject.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::ast; -use crate::attr; -use crate::edition::Edition; -use crate::ext::hygiene::{Mark, SyntaxContext}; -use crate::symbol::{Ident, Symbol, kw, sym}; -use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, respan}; -use crate::ptr::P; -use crate::tokenstream::TokenStream; - -use std::cell::Cell; -use std::iter; -use syntax_pos::{DUMMY_SP, Span}; - -/// Craft a span that will be ignored by the stability lint's -/// call to source_map's `is_internal` check. -/// The expanded code uses the unstable `#[prelude_import]` attribute. -fn ignored_span(sp: Span, edition: Edition) -> Span { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo::with_unstable( - MacroAttribute(Symbol::intern("std_inject")), sp, edition, &[sym::prelude_import] - )); - sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) -} - -pub fn injected_crate_name() -> Option<&'static str> { - INJECTED_CRATE_NAME.with(|name| name.get()) -} - -thread_local! { - // A `Symbol` might make more sense here, but it doesn't work, probably for - // reasons relating to the use of thread-local storage for the Symbol - // interner. - static INJECTED_CRATE_NAME: Cell> = Cell::new(None); -} - -pub fn maybe_inject_crates_ref( - mut krate: ast::Crate, - alt_std_name: Option<&str>, - edition: Edition, -) -> ast::Crate { - let rust_2018 = edition >= Edition::Edition2018; - - // the first name in this list is the crate name of the crate with the prelude - let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) { - return krate; - } else if attr::contains_name(&krate.attrs, sym::no_std) { - if attr::contains_name(&krate.attrs, sym::compiler_builtins) { - &["core"] - } else { - &["core", "compiler_builtins"] - } - } else { - &["std"] - }; - - // .rev() to preserve ordering above in combination with insert(0, ...) - let alt_std_name = alt_std_name.map(Symbol::intern); - for orig_name_str in names.iter().rev() { - // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, - // so they don't accidentally interfere with the new import paths. - let orig_name_sym = Symbol::intern(orig_name_str); - let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym); - let (rename, orig_name) = if rust_2018 { - (orig_name_ident.gensym(), Some(orig_name_sym)) - } else { - (orig_name_ident, None) - }; - krate.module.items.insert(0, P(ast::Item { - attrs: vec![attr::mk_attr_outer( - DUMMY_SP, - attr::mk_attr_id(), - attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use)) - )], - vis: dummy_spanned(ast::VisibilityKind::Inherited), - node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), - ident: rename, - id: ast::DUMMY_NODE_ID, - span: DUMMY_SP, - tokens: None, - })); - } - - // the crates have been injected, the assumption is that the first one is the one with - // the prelude. - let name = names[0]; - - INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name))); - - let span = ignored_span(DUMMY_SP, edition); - krate.module.items.insert(0, P(ast::Item { - attrs: vec![ast::Attribute { - style: ast::AttrStyle::Outer, - path: ast::Path::from_ident(ast::Ident::new(sym::prelude_import, span)), - tokens: TokenStream::empty(), - id: attr::mk_attr_id(), - is_sugared_doc: false, - span, - }], - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - node: ast::ItemKind::Use(P(ast::UseTree { - prefix: ast::Path { - segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot)) - .chain( - [name, "prelude", "v1"].iter().cloned() - .map(ast::Ident::from_str) - ).map(ast::PathSegment::from_ident).collect(), - span, - }, - kind: ast::UseTreeKind::Glob, - span, - })), - id: ast::DUMMY_NODE_ID, - ident: ast::Ident::invalid(), - span, - tokens: None, - })); - - krate -} diff --git a/gcc/rust/rustc_parser/libsyntax/test.rs b/gcc/rust/rustc_parser/libsyntax/test.rs deleted file mode 100644 index c717f14..0000000 --- a/gcc/rust/rustc_parser/libsyntax/test.rs +++ /dev/null @@ -1,437 +0,0 @@ -// Code that generates a test runner to run all the tests in a crate - -#![allow(dead_code)] -#![allow(unused_imports)] - -use HasTestSignature::*; - -use std::iter; -use std::slice; -use std::mem; -use std::vec; - -use log::debug; -use smallvec::{smallvec, SmallVec}; -use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos}; - -use crate::attr::{self, HasAttrs}; -use crate::source_map::{self, SourceMap, ExpnInfo, MacroAttribute, dummy_spanned, respan}; -use crate::config; -use crate::entry::{self, EntryPointType}; -use crate::ext::base::{ExtCtxt, Resolver}; -use crate::ext::build::AstBuilder; -use crate::ext::expand::ExpansionConfig; -use crate::ext::hygiene::{self, Mark, SyntaxContext}; -use crate::mut_visit::{*, ExpectOne}; -use crate::feature_gate::Features; -use crate::util::map_in_place::MapInPlace; -use crate::parse::{token, ParseSess}; -use crate::ast::{self, Ident}; -use crate::ptr::P; -use crate::symbol::{self, Symbol, kw, sym}; -use crate::ThinVec; - -struct Test { - span: Span, - path: Vec, -} - -struct TestCtxt<'a> { - span_diagnostic: &'a errors::Handler, - path: Vec, - ext_cx: ExtCtxt<'a>, - test_cases: Vec, - reexport_test_harness_main: Option, - is_libtest: bool, - ctxt: SyntaxContext, - features: &'a Features, - test_runner: Option, - - // top-level re-export submodule, filled out after folding is finished - toplevel_reexport: Option, -} - -// Traverse the crate, collecting all the test functions, eliding any -// existing main functions, and synthesizing a main test harness -pub fn modify_for_testing(sess: &ParseSess, - resolver: &mut dyn Resolver, - should_test: bool, - krate: &mut ast::Crate, - span_diagnostic: &errors::Handler, - features: &Features) { - // Check for #[reexport_test_harness_main = "some_name"] which - // creates a `use __test::main as some_name;`. This needs to be - // unconditional, so that the attribute is still marked as used in - // non-test builds. - let reexport_test_harness_main = - attr::first_attr_value_str_by_name(&krate.attrs, sym::reexport_test_harness_main); - - // Do this here so that the test_runner crate attribute gets marked as used - // even in non-test builds - let test_runner = get_test_runner(span_diagnostic, &krate); - - if should_test { - generate_test_harness(sess, resolver, reexport_test_harness_main, - krate, span_diagnostic, features, test_runner) - } -} - -struct TestHarnessGenerator<'a> { - cx: TestCtxt<'a>, - tests: Vec, - - // submodule name, gensym'd identifier for re-exports - tested_submods: Vec<(Ident, Ident)>, -} - -impl<'a> MutVisitor for TestHarnessGenerator<'a> { - fn visit_crate(&mut self, c: &mut ast::Crate) { - noop_visit_crate(c, self); - - // Create a main function to run our tests - let test_main = { - let unresolved = mk_main(&mut self.cx); - self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap() - }; - - c.module.items.push(test_main); - } - - fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - let ident = i.ident; - if ident.name != kw::Invalid { - self.cx.path.push(ident); - } - debug!("current path: {}", path_name_i(&self.cx.path)); - - let mut item = i.into_inner(); - if is_test_case(&item) { - debug!("this is a test item"); - - let test = Test { - span: item.span, - path: self.cx.path.clone(), - }; - self.cx.test_cases.push(test); - self.tests.push(item.ident); - } - - // We don't want to recurse into anything other than mods, since - // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(mut module) = item.node { - let tests = mem::take(&mut self.tests); - let tested_submods = mem::take(&mut self.tested_submods); - noop_visit_mod(&mut module, self); - let tests = mem::replace(&mut self.tests, tests); - let tested_submods = mem::replace(&mut self.tested_submods, tested_submods); - - if !tests.is_empty() || !tested_submods.is_empty() { - let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods); - module.items.push(it); - - if !self.cx.path.is_empty() { - self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym)); - } else { - debug!("pushing nothing, sym: {:?}", sym); - self.cx.toplevel_reexport = Some(sym); - } - } - item.node = ast::ItemKind::Mod(module); - } - if ident.name != kw::Invalid { - self.cx.path.pop(); - } - smallvec![P(item)] - } - - fn visit_mac(&mut self, _mac: &mut ast::Mac) { - // Do nothing. - } -} - -/// A folder used to remove any entry points (like fn main) because the harness -/// generator will provide its own -struct EntryPointCleaner { - // Current depth in the ast - depth: usize, -} - -impl MutVisitor for EntryPointCleaner { - fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - self.depth += 1; - let item = noop_flat_map_item(i, self).expect_one("noop did something"); - self.depth -= 1; - - // Remove any #[main] or #[start] from the AST so it doesn't - // clash with the one we're going to add, but mark it as - // #[allow(dead_code)] to avoid printing warnings. - let item = match entry::entry_point_type(&item, self.depth) { - EntryPointType::MainNamed | - EntryPointType::MainAttr | - EntryPointType::Start => - item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| { - let allow_ident = Ident::with_empty_ctxt(sym::allow); - let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code")); - let allow_dead_code_item = attr::mk_list_item(DUMMY_SP, allow_ident, - vec![dc_nested]); - let allow_dead_code = attr::mk_attr_outer(DUMMY_SP, - attr::mk_attr_id(), - allow_dead_code_item); - - ast::Item { - id, - ident, - attrs: attrs.into_iter() - .filter(|attr| { - !attr.check_name(sym::main) && !attr.check_name(sym::start) - }) - .chain(iter::once(allow_dead_code)) - .collect(), - node, - vis, - span, - tokens, - } - }), - EntryPointType::None | - EntryPointType::OtherMain => item, - }; - - smallvec![item] - } - - fn visit_mac(&mut self, _mac: &mut ast::Mac) { - // Do nothing. - } -} - -/// Creates an item (specifically a module) that "pub use"s the tests passed in. -/// Each tested submodule will contain a similar reexport module that we will export -/// under the name of the original module. That is, `submod::__test_reexports` is -/// reexported like so `pub use submod::__test_reexports as submod`. -fn mk_reexport_mod(cx: &mut TestCtxt<'_>, - parent: ast::NodeId, - tests: Vec, - tested_submods: Vec<(Ident, Ident)>) - -> (P, Ident) { - let super_ = Ident::with_empty_ctxt(kw::Super); - - let items = tests.into_iter().map(|r| { - cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - cx.ext_cx.path(DUMMY_SP, vec![super_, r])) - }).chain(tested_submods.into_iter().map(|(r, sym)| { - let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); - cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), - Some(r), path) - })).collect(); - - let reexport_mod = ast::Mod { - inline: true, - inner: DUMMY_SP, - items, - }; - - let name = Ident::from_str("__test_reexports").gensym(); - let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; - cx.ext_cx.current_expansion.mark = cx.ext_cx.resolver.get_module_scope(parent); - let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { - ident: name, - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mod(reexport_mod), - vis: dummy_spanned(ast::VisibilityKind::Public), - span: DUMMY_SP, - tokens: None, - })).pop().unwrap(); - - (it, name) -} - -/// Crawl over the crate, inserting test reexports and the test main function -fn generate_test_harness(sess: &ParseSess, - resolver: &mut dyn Resolver, - reexport_test_harness_main: Option, - krate: &mut ast::Crate, - sd: &errors::Handler, - features: &Features, - test_runner: Option) { - // Remove the entry points - let mut cleaner = EntryPointCleaner { depth: 0 }; - cleaner.visit_crate(krate); - - let mark = Mark::fresh(Mark::root()); - - let mut econfig = ExpansionConfig::default("test".to_string()); - econfig.features = Some(features); - - let cx = TestCtxt { - span_diagnostic: sd, - ext_cx: ExtCtxt::new(sess, econfig, resolver), - path: Vec::new(), - test_cases: Vec::new(), - reexport_test_harness_main, - // N.B., doesn't consider the value of `--crate-name` passed on the command line. - is_libtest: attr::find_crate_name(&krate.attrs) - .map(|s| s == sym::test).unwrap_or(false), - toplevel_reexport: None, - ctxt: SyntaxContext::empty().apply_mark(mark), - features, - test_runner - }; - - mark.set_expn_info(ExpnInfo::with_unstable( - MacroAttribute(sym::test_case), DUMMY_SP, sess.edition, - &[sym::main, sym::test, sym::rustc_attrs], - )); - - TestHarnessGenerator { - cx, - tests: Vec::new(), - tested_submods: Vec::new(), - }.visit_crate(krate); -} - -/// Craft a span that will be ignored by the stability lint's -/// call to source_map's `is_internal` check. -/// The expanded code calls some unstable functions in the test crate. -fn ignored_span(cx: &TestCtxt<'_>, sp: Span) -> Span { - sp.with_ctxt(cx.ctxt) -} - -enum HasTestSignature { - Yes, - No(BadTestSignature), -} - -#[derive(PartialEq)] -enum BadTestSignature { - NotEvenAFunction, - WrongTypeSignature, - NoArgumentsAllowed, - ShouldPanicOnlyWithNoArgs, -} - -/// Creates a function item for use as the main function of a test build. -/// This function will call the `test_runner` as specified by the crate attribute -fn mk_main(cx: &mut TestCtxt<'_>) -> P { - // Writing this out by hand with 'ignored_span': - // pub fn main() { - // #![main] - // test::test_main_static(&[..tests]); - // } - let sp = ignored_span(cx, DUMMY_SP); - let ecx = &cx.ext_cx; - let test_id = Ident::with_empty_ctxt(sym::test); - - // test::test_main_static(...) - let mut test_runner = cx.test_runner.clone().unwrap_or( - ecx.path(sp, vec![ - test_id, ecx.ident_of("test_main_static") - ])); - - test_runner.span = sp; - - let test_main_path_expr = ecx.expr_path(test_runner); - let call_test_main = ecx.expr_call(sp, test_main_path_expr, - vec![mk_tests_slice(cx)]); - let call_test_main = ecx.stmt_expr(call_test_main); - - // #![main] - let main_meta = ecx.meta_word(sp, sym::main); - let main_attr = ecx.attribute(sp, main_meta); - - // extern crate test as test_gensym - let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, - test_id, - vec![], - ast::ItemKind::ExternCrate(None) - )); - - // pub fn main() { ... } - let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); - - // If no test runner is provided we need to import the test crate - let main_body = if cx.test_runner.is_none() { - ecx.block(sp, vec![test_extern_stmt, call_test_main]) - } else { - ecx.block(sp, vec![call_test_main]) - }; - - let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)), - ast::FnHeader::default(), - ast::Generics::default(), - main_body); - - // Honor the reexport_test_harness_main attribute - let main_id = match cx.reexport_test_harness_main { - Some(sym) => Ident::new(sym, sp), - None => Ident::from_str_and_span("main", sp).gensym(), - }; - - P(ast::Item { - ident: main_id, - attrs: vec![main_attr], - id: ast::DUMMY_NODE_ID, - node: main, - vis: dummy_spanned(ast::VisibilityKind::Public), - span: sp, - tokens: None, - }) - -} - -fn path_name_i(idents: &[Ident]) -> String { - let mut path_name = "".to_string(); - let mut idents_iter = idents.iter().peekable(); - while let Some(ident) = idents_iter.next() { - path_name.push_str(&ident.as_str()); - if idents_iter.peek().is_some() { - path_name.push_str("::") - } - } - path_name -} - -/// Creates a slice containing every test like so: -/// &[path::to::test1, path::to::test2] -fn mk_tests_slice(cx: &TestCtxt<'_>) -> P { - debug!("building test vector from {} tests", cx.test_cases.len()); - let ref ecx = cx.ext_cx; - - ecx.expr_vec_slice(DUMMY_SP, - cx.test_cases.iter().map(|test| { - ecx.expr_addr_of(test.span, - ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path)))) - }).collect()) -} - -/// Creates a path from the top-level __test module to the test via __test_reexports -fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec{ - let mut visible_path = vec![]; - match cx.toplevel_reexport { - Some(id) => visible_path.push(id), - None => { - cx.span_diagnostic.bug("expected to find top-level re-export name, but found None"); - } - } - visible_path.extend_from_slice(path); - visible_path -} - -fn is_test_case(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, sym::rustc_test_marker) -} - -fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option { - let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; - test_attr.meta_item_list().map(|meta_list| { - if meta_list.len() != 1 { - sd.span_fatal(test_attr.span, - "#![test_runner(..)] accepts exactly 1 argument").raise() - } - match meta_list[0].meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item.path.clone(), - _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise() - } - }) -} diff --git a/gcc/rust/rustc_parser/libsyntax/test_snippet.rs b/gcc/rust/rustc_parser/libsyntax/test_snippet.rs deleted file mode 100644 index 107cbe7..0000000 --- a/gcc/rust/rustc_parser/libsyntax/test_snippet.rs +++ /dev/null @@ -1,1164 +0,0 @@ -use crate::source_map::{SourceMap, FilePathMapping}; -use crate::with_default_globals; - -use errors::Handler; -use errors::emitter::EmitterWriter; - -use std::io; -use std::io::prelude::*; -use rustc_data_structures::sync::Lrc; -use std::str; -use std::sync::{Arc, Mutex}; -use std::path::Path; -use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan}; - -/// Identify a position in the text by the Nth occurrence of a string. -struct Position { - string: &'static str, - count: usize, -} - -struct SpanLabel { - start: Position, - end: Position, - label: &'static str, -} - -struct Shared { - data: Arc>, -} - -impl Write for Shared { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.data.lock().unwrap().write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.data.lock().unwrap().flush() - } -} - -fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) { - with_default_globals(|| { - let output = Arc::new(Mutex::new(Vec::new())); - - let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); - source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned()); - - let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end); - let mut msp = MultiSpan::from_span(primary_span); - for span_label in span_labels { - let span = make_span(&file_text, &span_label.start, &span_label.end); - msp.push_span_label(span, span_label.label.to_string()); - println!("span: {:?} label: {:?}", span, span_label.label); - println!("text: {:?}", source_map.span_to_snippet(span)); - } - - let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), - Some(source_map.clone()), - false, - false, - false); - let handler = Handler::with_emitter(true, None, Box::new(emitter)); - handler.span_err(msp, "foo"); - - assert!(expected_output.chars().next() == Some('\n'), - "expected output should begin with newline"); - let expected_output = &expected_output[1..]; - - let bytes = output.lock().unwrap(); - let actual_output = str::from_utf8(&bytes).unwrap(); - println!("expected output:\n------\n{}------", expected_output); - println!("actual output:\n------\n{}------", actual_output); - - assert!(expected_output == actual_output) - }) -} - -fn make_span(file_text: &str, start: &Position, end: &Position) -> Span { - let start = make_pos(file_text, start); - let end = make_pos(file_text, end) + end.string.len(); // just after matching thing ends - assert!(start <= end); - Span::new(BytePos(start as u32), BytePos(end as u32), NO_EXPANSION) -} - -fn make_pos(file_text: &str, pos: &Position) -> usize { - let mut remainder = file_text; - let mut offset = 0; - for _ in 0..pos.count { - if let Some(n) = remainder.find(&pos.string) { - offset += n; - remainder = &remainder[n + 1..]; - } else { - panic!("failed to find {} instances of {:?} in {:?}", - pos.count, - pos.string, - file_text); - } - } - offset -} - -#[test] -fn ends_on_col0() { - test_harness(r#" -fn foo() { -} -"#, - vec![ - SpanLabel { - start: Position { - string: "{", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "test", - }, - ], - r#" -error: foo - --> test.rs:2:10 - | -2 | fn foo() { - | __________^ -3 | | } - | |_^ test - -"#); -} - -#[test] -fn ends_on_col2() { - test_harness(r#" -fn foo() { - - - } -"#, - vec![ - SpanLabel { - start: Position { - string: "{", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "test", - }, - ], - r#" -error: foo - --> test.rs:2:10 - | -2 | fn foo() { - | __________^ -3 | | -4 | | -5 | | } - | |___^ test - -"#); -} -#[test] -fn non_nested() { - test_harness(r#" -fn foo() { - X0 Y0 - X1 Y1 - X2 Y2 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "Y2", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | X0 Y0 - | ____^__- - | | ___| - | || -4 | || X1 Y1 -5 | || X2 Y2 - | ||____^__- `Y` is a good letter too - | |____| - | `X` is a good letter - -"#); -} - -#[test] -fn nested() { - test_harness(r#" -fn foo() { - X0 Y0 - Y1 X1 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X1", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "Y1", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], -r#" -error: foo - --> test.rs:3:3 - | -3 | X0 Y0 - | ____^__- - | | ___| - | || -4 | || Y1 X1 - | ||____-__^ `X` is a good letter - | |_____| - | `Y` is a good letter too - -"#); -} - -#[test] -fn different_overlap() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Z1", - count: 1, - }, - end: Position { - string: "X3", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:6 - | -3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |_________- -5 | || X2 Y2 Z2 - | ||____^ `X` is a good letter -6 | | X3 Y3 Z3 - | |_____- `Y` is a good letter too - -"#); -} - -#[test] -fn triple_overlap() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "Y2", - count: 1, - }, - label: "`Y` is a good letter too", - }, - SpanLabel { - start: Position { - string: "Z0", - count: 1, - }, - end: Position { - string: "Z2", - count: 1, - }, - label: "`Z` label", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | X0 Y0 Z0 - | _____^__-__- - | | ____|__| - | || ___| - | ||| -4 | ||| X1 Y1 Z1 -5 | ||| X2 Y2 Z2 - | |||____^__-__- `Z` label - | ||____|__| - | |____| `Y` is a good letter too - | `X` is a good letter - -"#); -} - -#[test] -fn triple_exact_overlap() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`Y` is a good letter too", - }, - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X2", - count: 1, - }, - label: "`Z` label", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | / X0 Y0 Z0 -4 | | X1 Y1 Z1 -5 | | X2 Y2 Z2 - | | ^ - | | | - | | `X` is a good letter - | |____`Y` is a good letter too - | `Z` label - -"#); -} - -#[test] -fn minimum_depth() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "X1", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Y1", - count: 1, - }, - end: Position { - string: "Z2", - count: 1, - }, - label: "`Y` is a good letter too", - }, - SpanLabel { - start: Position { - string: "X2", - count: 1, - }, - end: Position { - string: "Y3", - count: 1, - }, - label: "`Z`", - }, - ], - r#" -error: foo - --> test.rs:3:6 - | -3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^_- - | ||____| - | | `X` is a good letter -5 | | X2 Y2 Z2 - | |____-______- `Y` is a good letter too - | ____| - | | -6 | | X3 Y3 Z3 - | |________- `Z` - -"#); -} - -#[test] -fn non_overlaping() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "X0", - count: 1, - }, - end: Position { - string: "X1", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Y2", - count: 1, - }, - end: Position { - string: "Z3", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | / X0 Y0 Z0 -4 | | X1 Y1 Z1 - | |____^ `X` is a good letter -5 | X2 Y2 Z2 - | ______- -6 | | X3 Y3 Z3 - | |__________- `Y` is a good letter too - -"#); -} - -#[test] -fn overlaping_start_and_end() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 - X2 Y2 Z2 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "X1", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Z1", - count: 1, - }, - end: Position { - string: "Z3", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:6 - | -3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^____- - | ||____| - | | `X` is a good letter -5 | | X2 Y2 Z2 -6 | | X3 Y3 Z3 - | |___________- `Y` is a good letter too - -"#); -} - -#[test] -fn multiple_labels_primary_without_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "`a` is a good letter", - }, - SpanLabel { - start: Position { - string: "c", - count: 1, - }, - end: Position { - string: "c", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:7 - | -3 | a { b { c } d } - | ----^^^^-^^-- `a` is a good letter - -"#); -} - -#[test] -fn multiple_labels_secondary_without_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "`a` is a good letter", - }, - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^-------^^ `a` is a good letter - -"#); -} - -#[test] -fn multiple_labels_primary_without_message_2() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "`b` is a good letter", - }, - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "c", - count: 1, - }, - end: Position { - string: "c", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:7 - | -3 | a { b { c } d } - | ----^^^^-^^-- - | | - | `b` is a good letter - -"#); -} - -#[test] -fn multiple_labels_secondary_without_message_2() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "`b` is a good letter", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^-------^^ - | | - | `b` is a good letter - -"#); -} - -#[test] -fn multiple_labels_secondary_without_message_3() { - test_harness(r#" -fn foo() { - a bc d -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "b", - count: 1, - }, - label: "`a` is a good letter", - }, - SpanLabel { - start: Position { - string: "c", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a bc d - | ^^^^---- - | | - | `a` is a good letter - -"#); -} - -#[test] -fn multiple_labels_without_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^-------^^ - -"#); -} - -#[test] -fn multiple_labels_without_message_2() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - SpanLabel { - start: Position { - string: "c", - count: 1, - }, - end: Position { - string: "c", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:7 - | -3 | a { b { c } d } - | ----^^^^-^^-- - -"#); -} - -#[test] -fn multiple_labels_with_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "`a` is a good letter", - }, - SpanLabel { - start: Position { - string: "b", - count: 1, - }, - end: Position { - string: "}", - count: 1, - }, - label: "`b` is a good letter", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^-------^^ - | | | - | | `b` is a good letter - | `a` is a good letter - -"#); -} - -#[test] -fn single_label_with_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "`a` is a good letter", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^^^^^^^^^^ `a` is a good letter - -"#); -} - -#[test] -fn single_label_without_message() { - test_harness(r#" -fn foo() { - a { b { c } d } -} -"#, - vec![ - SpanLabel { - start: Position { - string: "a", - count: 1, - }, - end: Position { - string: "d", - count: 1, - }, - label: "", - }, - ], - r#" -error: foo - --> test.rs:3:3 - | -3 | a { b { c } d } - | ^^^^^^^^^^^^^ - -"#); -} - -#[test] -fn long_snippet() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 - X1 Y1 Z1 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 - X2 Y2 Z2 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "X1", - count: 1, - }, - label: "`X` is a good letter", - }, - SpanLabel { - start: Position { - string: "Z1", - count: 1, - }, - end: Position { - string: "Z3", - count: 1, - }, - label: "`Y` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:6 - | -3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^____- - | ||____| - | | `X` is a good letter -5 | | 1 -6 | | 2 -7 | | 3 -... | -15 | | X2 Y2 Z2 -16 | | X3 Y3 Z3 - | |___________- `Y` is a good letter too - -"#); -} - -#[test] -fn long_snippet_multiple_spans() { - test_harness(r#" -fn foo() { - X0 Y0 Z0 -1 -2 -3 - X1 Y1 Z1 -4 -5 -6 - X2 Y2 Z2 -7 -8 -9 -10 - X3 Y3 Z3 -} -"#, - vec![ - SpanLabel { - start: Position { - string: "Y0", - count: 1, - }, - end: Position { - string: "Y3", - count: 1, - }, - label: "`Y` is a good letter", - }, - SpanLabel { - start: Position { - string: "Z1", - count: 1, - }, - end: Position { - string: "Z2", - count: 1, - }, - label: "`Z` is a good letter too", - }, - ], - r#" -error: foo - --> test.rs:3:6 - | -3 | X0 Y0 Z0 - | ______^ -4 | | 1 -5 | | 2 -6 | | 3 -7 | | X1 Y1 Z1 - | |_________- -8 | || 4 -9 | || 5 -10 | || 6 -11 | || X2 Y2 Z2 - | ||__________- `Z` is a good letter too -... | -15 | | 10 -16 | | X3 Y3 Z3 - | |_______^ `Y` is a good letter - -"#); -} diff --git a/gcc/rust/rustc_parser/libsyntax/tokenstream.rs b/gcc/rust/rustc_parser/libsyntax/tokenstream.rs deleted file mode 100644 index b32049b..0000000 --- a/gcc/rust/rustc_parser/libsyntax/tokenstream.rs +++ /dev/null @@ -1,665 +0,0 @@ -//! # Token Streams -//! -//! `TokenStream`s represent syntactic objects before they are converted into ASTs. -//! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s, -//! which are themselves a single `Token` or a `Delimited` subsequence of tokens. -//! -//! ## Ownership -//! -//! `TokenStreams` are persistent data structures constructed as ropes with reference -//! counted-children. In general, this means that calling an operation on a `TokenStream` -//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to -//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts, -//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking -//! ownership of the original. - -use crate::ext::base; -use crate::ext::tt::{macro_parser, quoted}; -use crate::parse::Directory; -use crate::parse::token::{self, DelimToken, Token, TokenKind}; -use crate::print::pprust; - -use syntax_pos::{BytePos, Mark, Span, DUMMY_SP}; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; -use rustc_data_structures::sync::Lrc; -use serialize::{Decoder, Decodable, Encoder, Encodable}; -use smallvec::{SmallVec, smallvec}; - -use std::borrow::Cow; -use std::{fmt, iter, mem}; - -/// When the main rust parser encounters a syntax-extension invocation, it -/// parses the arguments to the invocation as a token-tree. This is a very -/// loose structure, such that all sorts of different AST-fragments can -/// be passed to syntax extensions using a uniform type. -/// -/// If the syntax extension is an MBE macro, it will attempt to match its -/// LHS token tree against the provided token tree, and if it finds a -/// match, will transcribe the RHS token tree, splicing in any captured -/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds. -/// -/// The RHS of an MBE macro is the only place `SubstNt`s are substituted. -/// Nothing special happens to misnamed or misplaced `SubstNt`s. -#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] -pub enum TokenTree { - /// A single token - Token(Token), - /// A delimited sequence of token trees - Delimited(DelimSpan, DelimToken, TokenStream), -} - -// Ensure all fields of `TokenTree` is `Send` and `Sync`. -#[cfg(parallel_compiler)] -fn _dummy() -where - Token: Send + Sync, - DelimSpan: Send + Sync, - DelimToken: Send + Sync, - TokenStream: Send + Sync, -{} - -impl TokenTree { - /// Use this token tree as a matcher to parse given tts. - pub fn parse(cx: &base::ExtCtxt<'_>, mtch: &[quoted::TokenTree], tts: TokenStream) - -> macro_parser::NamedParseResult { - // `None` is because we're not interpolating - let directory = Directory { - path: Cow::from(cx.current_expansion.module.directory.as_path()), - ownership: cx.current_expansion.directory_ownership, - }; - macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true) - } - - /// Checks if this TokenTree is equal to the other, regardless of span information. - pub fn eq_unspanned(&self, other: &TokenTree) -> bool { - match (self, other) { - (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind, - (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => { - delim == delim2 && tts.eq_unspanned(&tts2) - } - _ => false, - } - } - - // See comments in `Nonterminal::to_tokenstream` for why we care about - // *probably* equal here rather than actual equality - // - // This is otherwise the same as `eq_unspanned`, only recursing with a - // different method. - pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool { - match (self, other) { - (TokenTree::Token(token), TokenTree::Token(token2)) => { - token.probably_equal_for_proc_macro(token2) - } - (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => { - delim == delim2 && tts.probably_equal_for_proc_macro(&tts2) - } - _ => false, - } - } - - /// Retrieves the TokenTree's span. - pub fn span(&self) -> Span { - match self { - TokenTree::Token(token) => token.span, - TokenTree::Delimited(sp, ..) => sp.entire(), - } - } - - /// Modify the `TokenTree`'s span in-place. - pub fn set_span(&mut self, span: Span) { - match self { - TokenTree::Token(token) => token.span = span, - TokenTree::Delimited(dspan, ..) => *dspan = DelimSpan::from_single(span), - } - } - - pub fn joint(self) -> TokenStream { - TokenStream::new(vec![(self, Joint)]) - } - - pub fn token(kind: TokenKind, span: Span) -> TokenTree { - TokenTree::Token(Token::new(kind, span)) - } - - /// Returns the opening delimiter as a token tree. - pub fn open_tt(span: Span, delim: DelimToken) -> TokenTree { - let open_span = if span.is_dummy() { - span - } else { - span.with_hi(span.lo() + BytePos(delim.len() as u32)) - }; - TokenTree::token(token::OpenDelim(delim), open_span) - } - - /// Returns the closing delimiter as a token tree. - pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree { - let close_span = if span.is_dummy() { - span - } else { - span.with_lo(span.hi() - BytePos(delim.len() as u32)) - }; - TokenTree::token(token::CloseDelim(delim), close_span) - } -} - -/// # Token Streams -/// -/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s. -/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s -/// instead of a representation of the abstract syntax tree. -/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. -/// -/// The use of `Option` is an optimization that avoids the need for an -/// allocation when the stream is empty. However, it is not guaranteed that an -/// empty stream is represented with `None`; it may be represented as a `Some` -/// around an empty `Vec`. -#[derive(Clone, Debug)] -pub struct TokenStream(pub Option>>); - -pub type TreeAndJoint = (TokenTree, IsJoint); - -// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] -static_assert_size!(TokenStream, 8); - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum IsJoint { - Joint, - NonJoint -} - -use IsJoint::*; - -impl TokenStream { - /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` - /// separating the two arguments with a comma for diagnostic suggestions. - pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> { - // Used to suggest if a user writes `foo!(a b);` - if let Some(ref stream) = self.0 { - let mut suggestion = None; - let mut iter = stream.iter().enumerate().peekable(); - while let Some((pos, ts)) = iter.next() { - if let Some((_, next)) = iter.peek() { - let sp = match (&ts, &next) { - (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue, - ((TokenTree::Token(token_left), NonJoint), - (TokenTree::Token(token_right), _)) - if ((token_left.is_ident() && !token_left.is_reserved_ident()) - || token_left.is_lit()) && - ((token_right.is_ident() && !token_right.is_reserved_ident()) - || token_right.is_lit()) => token_left.span, - ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(), - _ => continue, - }; - let sp = sp.shrink_to_hi(); - let comma = (TokenTree::token(token::Comma, sp), NonJoint); - suggestion = Some((pos, comma, sp)); - } - } - if let Some((pos, comma, sp)) = suggestion { - let mut new_stream = vec![]; - let parts = stream.split_at(pos + 1); - new_stream.extend_from_slice(parts.0); - new_stream.push(comma); - new_stream.extend_from_slice(parts.1); - return Some((TokenStream::new(new_stream), sp)); - } - } - None - } -} - -impl From for TokenStream { - fn from(tree: TokenTree) -> TokenStream { - TokenStream::new(vec![(tree, NonJoint)]) - } -} - -impl From for TreeAndJoint { - fn from(tree: TokenTree) -> TreeAndJoint { - (tree, NonJoint) - } -} - -impl> iter::FromIterator for TokenStream { - fn from_iter>(iter: I) -> Self { - TokenStream::from_streams(iter.into_iter().map(Into::into).collect::>()) - } -} - -impl Eq for TokenStream {} - -impl PartialEq for TokenStream { - fn eq(&self, other: &TokenStream) -> bool { - self.trees().eq(other.trees()) - } -} - -impl TokenStream { - pub fn len(&self) -> usize { - if let Some(ref slice) = self.0 { - slice.len() - } else { - 0 - } - } - - pub fn empty() -> TokenStream { - TokenStream(None) - } - - pub fn is_empty(&self) -> bool { - match self.0 { - None => true, - Some(ref stream) => stream.is_empty(), - } - } - - pub(crate) fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { - match streams.len() { - 0 => TokenStream::empty(), - 1 => streams.pop().unwrap(), - _ => { - // rust-lang/rust#57735: pre-allocate vector to avoid - // quadratic blow-up due to on-the-fly reallocations. - let tree_count = streams.iter() - .map(|ts| match &ts.0 { None => 0, Some(s) => s.len() }) - .sum(); - let mut vec = Vec::with_capacity(tree_count); - - for stream in streams { - match stream.0 { - None => {}, - Some(stream2) => vec.extend(stream2.iter().cloned()), - } - } - TokenStream::new(vec) - } - } - } - - pub fn new(streams: Vec) -> TokenStream { - match streams.len() { - 0 => TokenStream(None), - _ => TokenStream(Some(Lrc::new(streams))), - } - } - - pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec) { - if let Some(stream) = self.0 { - vec.extend(stream.iter().cloned()); - } - } - - pub fn trees(&self) -> Cursor { - self.clone().into_trees() - } - - pub fn into_trees(self) -> Cursor { - Cursor::new(self) - } - - /// Compares two TokenStreams, checking equality without regarding span information. - pub fn eq_unspanned(&self, other: &TokenStream) -> bool { - let mut t1 = self.trees(); - let mut t2 = other.trees(); - for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { - if !t1.eq_unspanned(&t2) { - return false; - } - } - t1.next().is_none() && t2.next().is_none() - } - - // See comments in `Nonterminal::to_tokenstream` for why we care about - // *probably* equal here rather than actual equality - // - // This is otherwise the same as `eq_unspanned`, only recursing with a - // different method. - pub fn probably_equal_for_proc_macro(&self, other: &TokenStream) -> bool { - // When checking for `probably_eq`, we ignore certain tokens that aren't - // preserved in the AST. Because they are not preserved, the pretty - // printer arbitrarily adds or removes them when printing as token - // streams, making a comparison between a token stream generated from an - // AST and a token stream which was parsed into an AST more reliable. - fn semantic_tree(tree: &TokenTree) -> bool { - if let TokenTree::Token(token) = tree { - if let - // The pretty printer tends to add trailing commas to - // everything, and in particular, after struct fields. - | token::Comma - // The pretty printer emits `NoDelim` as whitespace. - | token::OpenDelim(DelimToken::NoDelim) - | token::CloseDelim(DelimToken::NoDelim) - // The pretty printer collapses many semicolons into one. - | token::Semi - // The pretty printer collapses whitespace arbitrarily and can - // introduce whitespace from `NoDelim`. - | token::Whitespace - // The pretty printer can turn `$crate` into `::crate_name` - | token::ModSep = token.kind { - return false; - } - } - true - } - - let mut t1 = self.trees().filter(semantic_tree); - let mut t2 = other.trees().filter(semantic_tree); - for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { - if !t1.probably_equal_for_proc_macro(&t2) { - return false; - } - } - t1.next().is_none() && t2.next().is_none() - } - - pub fn map_enumerated TokenTree>(self, mut f: F) -> TokenStream { - TokenStream(self.0.map(|stream| { - Lrc::new( - stream - .iter() - .enumerate() - .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint)) - .collect()) - })) - } - - pub fn map TokenTree>(self, mut f: F) -> TokenStream { - TokenStream(self.0.map(|stream| { - Lrc::new( - stream - .iter() - .map(|(tree, is_joint)| (f(tree.clone()), *is_joint)) - .collect()) - })) - } - - fn first_tree_and_joint(&self) -> Option { - self.0.as_ref().map(|stream| { - stream.first().unwrap().clone() - }) - } - - fn last_tree_if_joint(&self) -> Option { - match self.0 { - None => None, - Some(ref stream) => { - if let (tree, Joint) = stream.last().unwrap() { - Some(tree.clone()) - } else { - None - } - } - } - } -} - -// 99.5%+ of the time we have 1 or 2 elements in this vector. -#[derive(Clone)] -pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>); - -impl TokenStreamBuilder { - pub fn new() -> TokenStreamBuilder { - TokenStreamBuilder(SmallVec::new()) - } - - pub fn push>(&mut self, stream: T) { - let stream = stream.into(); - let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); - if let Some(TokenTree::Token(last_token)) = last_tree_if_joint { - if let Some((TokenTree::Token(token), is_joint)) = stream.first_tree_and_joint() { - if let Some(glued_tok) = last_token.glue(token) { - let last_stream = self.0.pop().unwrap(); - self.push_all_but_last_tree(&last_stream); - let glued_tt = TokenTree::Token(glued_tok); - let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]); - self.0.push(glued_tokenstream); - self.push_all_but_first_tree(&stream); - return - } - } - } - self.0.push(stream); - } - - pub fn build(self) -> TokenStream { - TokenStream::from_streams(self.0) - } - - fn push_all_but_last_tree(&mut self, stream: &TokenStream) { - if let Some(ref streams) = stream.0 { - let len = streams.len(); - match len { - 1 => {} - _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))), - } - } - } - - fn push_all_but_first_tree(&mut self, stream: &TokenStream) { - if let Some(ref streams) = stream.0 { - let len = streams.len(); - match len { - 1 => {} - _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))), - } - } - } -} - -#[derive(Clone)] -pub struct Cursor { - pub stream: TokenStream, - index: usize, -} - -impl Iterator for Cursor { - type Item = TokenTree; - - fn next(&mut self) -> Option { - self.next_with_joint().map(|(tree, _)| tree) - } -} - -impl Cursor { - fn new(stream: TokenStream) -> Self { - Cursor { stream, index: 0 } - } - - pub fn next_with_joint(&mut self) -> Option { - match self.stream.0 { - None => None, - Some(ref stream) => { - if self.index < stream.len() { - self.index += 1; - Some(stream[self.index - 1].clone()) - } else { - None - } - } - } - } - - pub fn append(&mut self, new_stream: TokenStream) { - if new_stream.is_empty() { - return; - } - let index = self.index; - let stream = mem::replace(&mut self.stream, TokenStream(None)); - *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees(); - self.index = index; - } - - pub fn look_ahead(&self, n: usize) -> Option { - match self.stream.0 { - None => None, - Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()), - } - } -} - -impl fmt::Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&pprust::tokens_to_string(self.clone())) - } -} - -impl Encodable for TokenStream { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { - self.trees().collect::>().encode(encoder) - } -} - -impl Decodable for TokenStream { - fn decode(decoder: &mut D) -> Result { - Vec::::decode(decoder).map(|vec| vec.into_iter().collect()) - } -} - -#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] -pub struct DelimSpan { - pub open: Span, - pub close: Span, -} - -impl DelimSpan { - pub fn from_single(sp: Span) -> Self { - DelimSpan { - open: sp, - close: sp, - } - } - - pub fn from_pair(open: Span, close: Span) -> Self { - DelimSpan { open, close } - } - - pub fn dummy() -> Self { - Self::from_single(DUMMY_SP) - } - - pub fn entire(self) -> Span { - self.open.with_hi(self.close.hi()) - } - - pub fn apply_mark(self, mark: Mark) -> Self { - DelimSpan { - open: self.open.apply_mark(mark), - close: self.close.apply_mark(mark), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ast::Name; - use crate::with_default_globals; - use crate::util::parser_testing::string_to_stream; - use syntax_pos::{Span, BytePos, NO_EXPANSION}; - - fn string_to_ts(string: &str) -> TokenStream { - string_to_stream(string.to_owned()) - } - - fn sp(a: u32, b: u32) -> Span { - Span::new(BytePos(a), BytePos(b), NO_EXPANSION) - } - - #[test] - fn test_concat() { - with_default_globals(|| { - let test_res = string_to_ts("foo::bar::baz"); - let test_fst = string_to_ts("foo::bar"); - let test_snd = string_to_ts("::baz"); - let eq_res = TokenStream::from_streams(smallvec![test_fst, test_snd]); - assert_eq!(test_res.trees().count(), 5); - assert_eq!(eq_res.trees().count(), 5); - assert_eq!(test_res.eq_unspanned(&eq_res), true); - }) - } - - #[test] - fn test_to_from_bijection() { - with_default_globals(|| { - let test_start = string_to_ts("foo::bar(baz)"); - let test_end = test_start.trees().collect(); - assert_eq!(test_start, test_end) - }) - } - - #[test] - fn test_eq_0() { - with_default_globals(|| { - let test_res = string_to_ts("foo"); - let test_eqs = string_to_ts("foo"); - assert_eq!(test_res, test_eqs) - }) - } - - #[test] - fn test_eq_1() { - with_default_globals(|| { - let test_res = string_to_ts("::bar::baz"); - let test_eqs = string_to_ts("::bar::baz"); - assert_eq!(test_res, test_eqs) - }) - } - - #[test] - fn test_eq_3() { - with_default_globals(|| { - let test_res = string_to_ts(""); - let test_eqs = string_to_ts(""); - assert_eq!(test_res, test_eqs) - }) - } - - #[test] - fn test_diseq_0() { - with_default_globals(|| { - let test_res = string_to_ts("::bar::baz"); - let test_eqs = string_to_ts("bar::baz"); - assert_eq!(test_res == test_eqs, false) - }) - } - - #[test] - fn test_diseq_1() { - with_default_globals(|| { - let test_res = string_to_ts("(bar,baz)"); - let test_eqs = string_to_ts("bar,baz"); - assert_eq!(test_res == test_eqs, false) - }) - } - - #[test] - fn test_is_empty() { - with_default_globals(|| { - let test0: TokenStream = Vec::::new().into_iter().collect(); - let test1: TokenStream = - TokenTree::token(token::Ident(Name::intern("a"), false), sp(0, 1)).into(); - let test2 = string_to_ts("foo(bar::baz)"); - - assert_eq!(test0.is_empty(), true); - assert_eq!(test1.is_empty(), false); - assert_eq!(test2.is_empty(), false); - }) - } - - #[test] - fn test_dotdotdot() { - with_default_globals(|| { - let mut builder = TokenStreamBuilder::new(); - builder.push(TokenTree::token(token::Dot, sp(0, 1)).joint()); - builder.push(TokenTree::token(token::Dot, sp(1, 2)).joint()); - builder.push(TokenTree::token(token::Dot, sp(2, 3))); - let stream = builder.build(); - assert!(stream.eq_unspanned(&string_to_ts("..."))); - assert_eq!(stream.trees().count(), 1); - }) - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/util/lev_distance.rs b/gcc/rust/rustc_parser/libsyntax/util/lev_distance.rs deleted file mode 100644 index 885b5a4..0000000 --- a/gcc/rust/rustc_parser/libsyntax/util/lev_distance.rs +++ /dev/null @@ -1,136 +0,0 @@ -use std::cmp; -use crate::symbol::Symbol; - -/// Finds the Levenshtein distance between two strings -pub fn lev_distance(a: &str, b: &str) -> usize { - // cases which don't require further computation - if a.is_empty() { - return b.chars().count(); - } else if b.is_empty() { - return a.chars().count(); - } - - let mut dcol: Vec<_> = (0..=b.len()).collect(); - let mut t_last = 0; - - for (i, sc) in a.chars().enumerate() { - let mut current = i; - dcol[0] = current + 1; - - for (j, tc) in b.chars().enumerate() { - let next = dcol[j + 1]; - if sc == tc { - dcol[j + 1] = current; - } else { - dcol[j + 1] = cmp::min(current, next); - dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1; - } - current = next; - t_last = j; - } - } - dcol[t_last + 1] -} - -/// Finds the best match for a given word in the given iterator -/// -/// As a loose rule to avoid the obviously incorrect suggestions, it takes -/// an optional limit for the maximum allowable edit distance, which defaults -/// to one-third of the given word. -/// -/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with -/// a lower(upper)case letters mismatch. -pub fn find_best_match_for_name<'a, T>(iter_names: T, - lookup: &str, - dist: Option) -> Option - where T: Iterator { - let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d); - - let (case_insensitive_match, levenstein_match) = iter_names - .filter_map(|&name| { - let dist = lev_distance(lookup, &name.as_str()); - if dist <= max_dist { - Some((name, dist)) - } else { - None - } - }) - // Here we are collecting the next structure: - // (case_insensitive_match, (levenstein_match, levenstein_distance)) - .fold((None, None), |result, (candidate, dist)| { - ( - if candidate.as_str().to_uppercase() == lookup.to_uppercase() { - Some(candidate) - } else { - result.0 - }, - match result.1 { - None => Some((candidate, dist)), - Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }) - } - ) - }); - - if let Some(candidate) = case_insensitive_match { - Some(candidate) // exact case insensitive match has a higher priority - } else { - if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None } - } -} - -#[test] -fn test_lev_distance() { - use std::char::{from_u32, MAX}; - // Test bytelength agnosticity - for c in (0..MAX as u32) - .filter_map(|i| from_u32(i)) - .map(|i| i.to_string()) { - assert_eq!(lev_distance(&c[..], &c[..]), 0); - } - - let a = "\nMäry häd ä little lämb\n\nLittle lämb\n"; - let b = "\nMary häd ä little lämb\n\nLittle lämb\n"; - let c = "Mary häd ä little lämb\n\nLittle lämb\n"; - assert_eq!(lev_distance(a, b), 1); - assert_eq!(lev_distance(b, a), 1); - assert_eq!(lev_distance(a, c), 2); - assert_eq!(lev_distance(c, a), 2); - assert_eq!(lev_distance(b, c), 1); - assert_eq!(lev_distance(c, b), 1); -} - -#[test] -fn test_find_best_match_for_name() { - use crate::with_default_globals; - with_default_globals(|| { - let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")]; - assert_eq!( - find_best_match_for_name(input.iter(), "aaaa", None), - Some(Symbol::intern("aaab")) - ); - - assert_eq!( - find_best_match_for_name(input.iter(), "1111111111", None), - None - ); - - let input = vec![Symbol::intern("aAAA")]; - assert_eq!( - find_best_match_for_name(input.iter(), "AAAA", None), - Some(Symbol::intern("aAAA")) - ); - - let input = vec![Symbol::intern("AAAA")]; - // Returns None because `lev_distance > max_dist / 3` - assert_eq!( - find_best_match_for_name(input.iter(), "aaaa", None), - None - ); - - let input = vec![Symbol::intern("AAAA")]; - assert_eq!( - find_best_match_for_name(input.iter(), "aaaa", Some(4)), - Some(Symbol::intern("AAAA")) - ); - }) -} diff --git a/gcc/rust/rustc_parser/libsyntax/util/map_in_place.rs b/gcc/rust/rustc_parser/libsyntax/util/map_in_place.rs deleted file mode 100644 index 5724b54..0000000 --- a/gcc/rust/rustc_parser/libsyntax/util/map_in_place.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::ptr; -use smallvec::{Array, SmallVec}; - -pub trait MapInPlace: Sized { - fn map_in_place(&mut self, mut f: F) where F: FnMut(T) -> T { - self.flat_map_in_place(|e| Some(f(e))) - } - - fn flat_map_in_place(&mut self, f: F) - where F: FnMut(T) -> I, - I: IntoIterator; -} - -impl MapInPlace for Vec { - fn flat_map_in_place(&mut self, mut f: F) - where F: FnMut(T) -> I, - I: IntoIterator - { - let mut read_i = 0; - let mut write_i = 0; - unsafe { - let mut old_len = self.len(); - self.set_len(0); // make sure we just leak elements in case of panic - - while read_i < old_len { - // move the read_i'th item out of the vector and map it - // to an iterator - let e = ptr::read(self.get_unchecked(read_i)); - let iter = f(e).into_iter(); - read_i += 1; - - for e in iter { - if write_i < read_i { - ptr::write(self.get_unchecked_mut(write_i), e); - write_i += 1; - } else { - // If this is reached we ran out of space - // in the middle of the vector. - // However, the vector is in a valid state here, - // so we just do a somewhat inefficient insert. - self.set_len(old_len); - self.insert(write_i, e); - - old_len = self.len(); - self.set_len(0); - - read_i += 1; - write_i += 1; - } - } - } - - // write_i tracks the number of actually written new items. - self.set_len(write_i); - } - } -} - -impl> MapInPlace for SmallVec { - fn flat_map_in_place(&mut self, mut f: F) - where F: FnMut(T) -> I, - I: IntoIterator - { - let mut read_i = 0; - let mut write_i = 0; - unsafe { - let mut old_len = self.len(); - self.set_len(0); // make sure we just leak elements in case of panic - - while read_i < old_len { - // move the read_i'th item out of the vector and map it - // to an iterator - let e = ptr::read(self.get_unchecked(read_i)); - let iter = f(e).into_iter(); - read_i += 1; - - for e in iter { - if write_i < read_i { - ptr::write(self.get_unchecked_mut(write_i), e); - write_i += 1; - } else { - // If this is reached we ran out of space - // in the middle of the vector. - // However, the vector is in a valid state here, - // so we just do a somewhat inefficient insert. - self.set_len(old_len); - self.insert(write_i, e); - - old_len = self.len(); - self.set_len(0); - - read_i += 1; - write_i += 1; - } - } - } - - // write_i tracks the number of actually written new items. - self.set_len(write_i); - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/util/node_count.rs b/gcc/rust/rustc_parser/libsyntax/util/node_count.rs deleted file mode 100644 index f17eb3b..0000000 --- a/gcc/rust/rustc_parser/libsyntax/util/node_count.rs +++ /dev/null @@ -1,141 +0,0 @@ -// Simply gives a rought count of the number of nodes in an AST. - -use crate::visit::*; -use crate::ast::*; -use syntax_pos::Span; - -pub struct NodeCounter { - pub count: usize, -} - -impl NodeCounter { - pub fn new() -> NodeCounter { - NodeCounter { - count: 0, - } - } -} - -impl<'ast> Visitor<'ast> for NodeCounter { - fn visit_ident(&mut self, ident: Ident) { - self.count += 1; - walk_ident(self, ident); - } - fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) { - self.count += 1; - walk_mod(self, m) - } - fn visit_foreign_item(&mut self, i: &ForeignItem) { - self.count += 1; - walk_foreign_item(self, i) - } - fn visit_item(&mut self, i: &Item) { - self.count += 1; - walk_item(self, i) - } - fn visit_local(&mut self, l: &Local) { - self.count += 1; - walk_local(self, l) - } - fn visit_block(&mut self, b: &Block) { - self.count += 1; - walk_block(self, b) - } - fn visit_stmt(&mut self, s: &Stmt) { - self.count += 1; - walk_stmt(self, s) - } - fn visit_arm(&mut self, a: &Arm) { - self.count += 1; - walk_arm(self, a) - } - fn visit_pat(&mut self, p: &Pat) { - self.count += 1; - walk_pat(self, p) - } - fn visit_expr(&mut self, ex: &Expr) { - self.count += 1; - walk_expr(self, ex) - } - fn visit_ty(&mut self, t: &Ty) { - self.count += 1; - walk_ty(self, t) - } - fn visit_generic_param(&mut self, param: &GenericParam) { - self.count += 1; - walk_generic_param(self, param) - } - fn visit_generics(&mut self, g: &Generics) { - self.count += 1; - walk_generics(self, g) - } - fn visit_fn(&mut self, fk: FnKind<'_>, fd: &FnDecl, s: Span, _: NodeId) { - self.count += 1; - walk_fn(self, fk, fd, s) - } - fn visit_trait_item(&mut self, ti: &TraitItem) { - self.count += 1; - walk_trait_item(self, ti) - } - fn visit_impl_item(&mut self, ii: &ImplItem) { - self.count += 1; - walk_impl_item(self, ii) - } - fn visit_trait_ref(&mut self, t: &TraitRef) { - self.count += 1; - walk_trait_ref(self, t) - } - fn visit_param_bound(&mut self, bounds: &GenericBound) { - self.count += 1; - walk_param_bound(self, bounds) - } - fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) { - self.count += 1; - walk_poly_trait_ref(self, t, m) - } - fn visit_variant_data(&mut self, s: &VariantData, _: Ident, - _: &Generics, _: NodeId, _: Span) { - self.count += 1; - walk_struct_def(self, s) - } - fn visit_struct_field(&mut self, s: &StructField) { - self.count += 1; - walk_struct_field(self, s) - } - fn visit_enum_def(&mut self, enum_definition: &EnumDef, - generics: &Generics, item_id: NodeId, _: Span) { - self.count += 1; - walk_enum_def(self, enum_definition, generics, item_id) - } - fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) { - self.count += 1; - walk_variant(self, v, g, item_id) - } - fn visit_lifetime(&mut self, lifetime: &Lifetime) { - self.count += 1; - walk_lifetime(self, lifetime) - } - fn visit_mac(&mut self, _mac: &Mac) { - self.count += 1; - walk_mac(self, _mac) - } - fn visit_path(&mut self, path: &Path, _id: NodeId) { - self.count += 1; - walk_path(self, path) - } - fn visit_use_tree(&mut self, use_tree: &UseTree, id: NodeId, _nested: bool) { - self.count += 1; - walk_use_tree(self, use_tree, id) - } - fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) { - self.count += 1; - walk_generic_args(self, path_span, generic_args) - } - fn visit_assoc_ty_constraint(&mut self, constraint: &AssocTyConstraint) { - self.count += 1; - walk_assoc_ty_constraint(self, constraint) - } - fn visit_attribute(&mut self, _attr: &Attribute) { - self.count += 1; - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/util/parser.rs b/gcc/rust/rustc_parser/libsyntax/util/parser.rs deleted file mode 100644 index 1e52186..0000000 --- a/gcc/rust/rustc_parser/libsyntax/util/parser.rs +++ /dev/null @@ -1,402 +0,0 @@ -use crate::parse::token::{self, Token, BinOpToken}; -use crate::symbol::kw; -use crate::ast::{self, BinOpKind}; - -/// Associative operator with precedence. -/// -/// This is the enum which specifies operator precedence and fixity to the parser. -#[derive(PartialEq, Debug)] -pub enum AssocOp { - /// `+` - Add, - /// `-` - Subtract, - /// `*` - Multiply, - /// `/` - Divide, - /// `%` - Modulus, - /// `&&` - LAnd, - /// `||` - LOr, - /// `^` - BitXor, - /// `&` - BitAnd, - /// `|` - BitOr, - /// `<<` - ShiftLeft, - /// `>>` - ShiftRight, - /// `==` - Equal, - /// `<` - Less, - /// `<=` - LessEqual, - /// `!=` - NotEqual, - /// `>` - Greater, - /// `>=` - GreaterEqual, - /// `=` - Assign, - /// `?=` where ? is one of the BinOpToken - AssignOp(BinOpToken), - /// `as` - As, - /// `..` range - DotDot, - /// `..=` range - DotDotEq, - /// `:` - Colon, -} - -#[derive(PartialEq, Debug)] -pub enum Fixity { - /// The operator is left-associative - Left, - /// The operator is right-associative - Right, - /// The operator is not associative - None -} - -impl AssocOp { - /// Creates a new AssocOP from a token - pub fn from_token(t: &Token) -> Option { - use AssocOp::*; - match t.kind { - token::BinOpEq(k) => Some(AssignOp(k)), - token::Eq => Some(Assign), - token::BinOp(BinOpToken::Star) => Some(Multiply), - token::BinOp(BinOpToken::Slash) => Some(Divide), - token::BinOp(BinOpToken::Percent) => Some(Modulus), - token::BinOp(BinOpToken::Plus) => Some(Add), - token::BinOp(BinOpToken::Minus) => Some(Subtract), - token::BinOp(BinOpToken::Shl) => Some(ShiftLeft), - token::BinOp(BinOpToken::Shr) => Some(ShiftRight), - token::BinOp(BinOpToken::And) => Some(BitAnd), - token::BinOp(BinOpToken::Caret) => Some(BitXor), - token::BinOp(BinOpToken::Or) => Some(BitOr), - token::Lt => Some(Less), - token::Le => Some(LessEqual), - token::Ge => Some(GreaterEqual), - token::Gt => Some(Greater), - token::EqEq => Some(Equal), - token::Ne => Some(NotEqual), - token::AndAnd => Some(LAnd), - token::OrOr => Some(LOr), - token::DotDot => Some(DotDot), - token::DotDotEq => Some(DotDotEq), - // DotDotDot is no longer supported, but we need some way to display the error - token::DotDotDot => Some(DotDotEq), - token::Colon => Some(Colon), - _ if t.is_keyword(kw::As) => Some(As), - _ => None - } - } - - /// Creates a new AssocOp from ast::BinOpKind. - pub fn from_ast_binop(op: BinOpKind) -> Self { - use AssocOp::*; - match op { - BinOpKind::Lt => Less, - BinOpKind::Gt => Greater, - BinOpKind::Le => LessEqual, - BinOpKind::Ge => GreaterEqual, - BinOpKind::Eq => Equal, - BinOpKind::Ne => NotEqual, - BinOpKind::Mul => Multiply, - BinOpKind::Div => Divide, - BinOpKind::Rem => Modulus, - BinOpKind::Add => Add, - BinOpKind::Sub => Subtract, - BinOpKind::Shl => ShiftLeft, - BinOpKind::Shr => ShiftRight, - BinOpKind::BitAnd => BitAnd, - BinOpKind::BitXor => BitXor, - BinOpKind::BitOr => BitOr, - BinOpKind::And => LAnd, - BinOpKind::Or => LOr - } - } - - /// Gets the precedence of this operator - pub fn precedence(&self) -> usize { - use AssocOp::*; - match *self { - As | Colon => 14, - Multiply | Divide | Modulus => 13, - Add | Subtract => 12, - ShiftLeft | ShiftRight => 11, - BitAnd => 10, - BitXor => 9, - BitOr => 8, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, - LAnd => 6, - LOr => 5, - DotDot | DotDotEq => 4, - Assign | AssignOp(_) => 2, - } - } - - /// Gets the fixity of this operator - pub fn fixity(&self) -> Fixity { - use AssocOp::*; - // NOTE: it is a bug to have an operators that has same precedence but different fixities! - match *self { - Assign | AssignOp(_) => Fixity::Right, - As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | - BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | - LAnd | LOr | Colon => Fixity::Left, - DotDot | DotDotEq => Fixity::None - } - } - - pub fn is_comparison(&self) -> bool { - use AssocOp::*; - match *self { - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true, - Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | - Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | - DotDot | DotDotEq | Colon => false - } - } - - pub fn is_assign_like(&self) -> bool { - use AssocOp::*; - match *self { - Assign | AssignOp(_) => true, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide | - Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | - LOr | DotDot | DotDotEq | Colon => false - } - } - - pub fn to_ast_binop(&self) -> Option { - use AssocOp::*; - match *self { - Less => Some(BinOpKind::Lt), - Greater => Some(BinOpKind::Gt), - LessEqual => Some(BinOpKind::Le), - GreaterEqual => Some(BinOpKind::Ge), - Equal => Some(BinOpKind::Eq), - NotEqual => Some(BinOpKind::Ne), - Multiply => Some(BinOpKind::Mul), - Divide => Some(BinOpKind::Div), - Modulus => Some(BinOpKind::Rem), - Add => Some(BinOpKind::Add), - Subtract => Some(BinOpKind::Sub), - ShiftLeft => Some(BinOpKind::Shl), - ShiftRight => Some(BinOpKind::Shr), - BitAnd => Some(BinOpKind::BitAnd), - BitXor => Some(BinOpKind::BitXor), - BitOr => Some(BinOpKind::BitOr), - LAnd => Some(BinOpKind::And), - LOr => Some(BinOpKind::Or), - Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None - } - } - - /// This operator could be used to follow a block unambiguously. - /// - /// This is used for error recovery at the moment, providing a suggestion to wrap blocks with - /// parentheses while having a high degree of confidence on the correctness of the suggestion. - pub fn can_continue_expr_unambiguously(&self) -> bool { - use AssocOp::*; - match self { - BitXor | // `{ 42 } ^ 3` - Assign | // `{ 42 } = { 42 }` - Divide | // `{ 42 } / 42` - Modulus | // `{ 42 } % 2` - ShiftRight | // `{ 42 } >> 2` - LessEqual | // `{ 42 } <= 3` - Greater | // `{ 42 } > 3` - GreaterEqual | // `{ 42 } >= 3` - AssignOp(_) | // `{ 42 } +=` - LAnd | // `{ 42 } &&foo` - As | // `{ 42 } as usize` - // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect - // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. - Colon => true, // `{ 42 }: usize` - _ => false, - } - } -} - -pub const PREC_RESET: i8 = -100; -pub const PREC_CLOSURE: i8 = -40; -pub const PREC_JUMP: i8 = -30; -pub const PREC_RANGE: i8 = -10; -// The range 2..=14 is reserved for AssocOp binary operator precedences. -pub const PREC_PREFIX: i8 = 50; -pub const PREC_POSTFIX: i8 = 60; -pub const PREC_PAREN: i8 = 99; -pub const PREC_FORCE_PAREN: i8 = 100; - -#[derive(Debug, Clone, Copy)] -pub enum ExprPrecedence { - Closure, - Break, - Continue, - Ret, - Yield, - - Range, - - Binary(BinOpKind), - - Cast, - Type, - - Assign, - AssignOp, - - Box, - AddrOf, - Let, - Unary, - - Call, - MethodCall, - Field, - Index, - Try, - InlineAsm, - Mac, - - Array, - Repeat, - Tup, - Lit, - Path, - Paren, - If, - While, - ForLoop, - Loop, - Match, - Block, - TryBlock, - Struct, - Async, - Await, - Err, -} - -impl ExprPrecedence { - pub fn order(self) -> i8 { - match self { - ExprPrecedence::Closure => PREC_CLOSURE, - - ExprPrecedence::Break | - ExprPrecedence::Continue | - ExprPrecedence::Ret | - ExprPrecedence::Yield => PREC_JUMP, - - // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to - // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence - // ensures that `pprust` will add parentheses in the right places to get the desired - // parse. - ExprPrecedence::Range => PREC_RANGE, - - // Binop-like expr kinds, handled by `AssocOp`. - ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8, - ExprPrecedence::Cast => AssocOp::As.precedence() as i8, - ExprPrecedence::Type => AssocOp::Colon.precedence() as i8, - - ExprPrecedence::Assign | - ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8, - - // Unary, prefix - ExprPrecedence::Box | - ExprPrecedence::AddrOf | - // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`. - // However, this is not exactly right. When `let _ = a` is the LHS of a binop we - // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` - // but we need to print `(let _ = a) < b` as-is with parens. - ExprPrecedence::Let | - ExprPrecedence::Unary => PREC_PREFIX, - - // Unary, postfix - ExprPrecedence::Await | - ExprPrecedence::Call | - ExprPrecedence::MethodCall | - ExprPrecedence::Field | - ExprPrecedence::Index | - ExprPrecedence::Try | - ExprPrecedence::InlineAsm | - ExprPrecedence::Mac => PREC_POSTFIX, - - // Never need parens - ExprPrecedence::Array | - ExprPrecedence::Repeat | - ExprPrecedence::Tup | - ExprPrecedence::Lit | - ExprPrecedence::Path | - ExprPrecedence::Paren | - ExprPrecedence::If | - ExprPrecedence::While | - ExprPrecedence::ForLoop | - ExprPrecedence::Loop | - ExprPrecedence::Match | - ExprPrecedence::Block | - ExprPrecedence::TryBlock | - ExprPrecedence::Async | - ExprPrecedence::Struct | - ExprPrecedence::Err => PREC_PAREN, - } - } -} - -/// In `let p = e`, operators with precedence `<=` this one requires parenthesis in `e`. -crate fn prec_let_scrutinee_needs_par() -> usize { - AssocOp::LAnd.precedence() -} - -/// Suppose we have `let _ = e` and the `order` of `e`. -/// Is the `order` such that `e` in `let _ = e` needs parenthesis when it is on the RHS? -/// -/// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`. -/// Can we print this as `let _ = a OP b`? -crate fn needs_par_as_let_scrutinee(order: i8) -> bool { - order <= prec_let_scrutinee_needs_par() as i8 -} - -/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any -/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and -/// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. -pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { - match value.node { - ast::ExprKind::Struct(..) => true, - - ast::ExprKind::Assign(ref lhs, ref rhs) | - ast::ExprKind::AssignOp(_, ref lhs, ref rhs) | - ast::ExprKind::Binary(_, ref lhs, ref rhs) => { - // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) - } - ast::ExprKind::Await(_, ref x) | - ast::ExprKind::Unary(_, ref x) | - ast::ExprKind::Cast(ref x, _) | - ast::ExprKind::Type(ref x, _) | - ast::ExprKind::Field(ref x, _) | - ast::ExprKind::Index(ref x, _) => { - // &X { y: 1 }, X { y: 1 }.y - contains_exterior_struct_lit(&x) - } - - ast::ExprKind::MethodCall(.., ref exprs) => { - // X { y: 1 }.bar(...) - contains_exterior_struct_lit(&exprs[0]) - } - - _ => false, - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/util/parser_testing.rs b/gcc/rust/rustc_parser/libsyntax/util/parser_testing.rs deleted file mode 100644 index f850960..0000000 --- a/gcc/rust/rustc_parser/libsyntax/util/parser_testing.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::ast::{self, Ident}; -use crate::source_map::FilePathMapping; -use crate::parse::{ParseSess, PResult, source_file_to_stream}; -use crate::parse::{lexer, new_parser_from_source_str}; -use crate::parse::parser::Parser; -use crate::ptr::P; -use crate::tokenstream::TokenStream; - -use std::iter::Peekable; -use std::path::PathBuf; - -/// Map a string to tts, using a made-up filename: -pub fn string_to_stream(source_str: String) -> TokenStream { - let ps = ParseSess::new(FilePathMapping::empty()); - source_file_to_stream( - &ps, - ps.source_map().new_source_file(PathBuf::from("bogofile").into(), - source_str, - ), None).0 -} - -/// Map string to parser (via tts) -pub fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> { - new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str) -} - -fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T where - F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>, -{ - let mut p = string_to_parser(&ps, s); - let x = panictry!(f(&mut p)); - p.sess.span_diagnostic.abort_if_errors(); - x -} - -/// Parse a string, return a crate. -pub fn string_to_crate (source_str : String) -> ast::Crate { - let ps = ParseSess::new(FilePathMapping::empty()); - with_error_checking_parse(source_str, &ps, |p| { - p.parse_crate_mod() - }) -} - -/// Parse a string, return an expr -pub fn string_to_expr (source_str : String) -> P { - let ps = ParseSess::new(FilePathMapping::empty()); - with_error_checking_parse(source_str, &ps, |p| { - p.parse_expr() - }) -} - -/// Parse a string, return an item -pub fn string_to_item (source_str : String) -> Option> { - let ps = ParseSess::new(FilePathMapping::empty()); - with_error_checking_parse(source_str, &ps, |p| { - p.parse_item() - }) -} - -/// Parse a string, return a pat. Uses "irrefutable"... which doesn't -/// (currently) affect parsing. -pub fn string_to_pat(source_str: String) -> P { - let ps = ParseSess::new(FilePathMapping::empty()); - with_error_checking_parse(source_str, &ps, |p| { - p.parse_pat(None) - }) -} - -/// Converts a vector of strings to a vector of Ident's -pub fn strs_to_idents(ids: Vec<&str> ) -> Vec { - ids.iter().map(|u| Ident::from_str(*u)).collect() -} - -/// Does the given string match the pattern? whitespace in the first string -/// may be deleted or replaced with other whitespace to match the pattern. -/// This function is relatively Unicode-ignorant; fortunately, the careful design -/// of UTF-8 mitigates this ignorance. It doesn't do NKF-normalization(?). -pub fn matches_codepattern(a : &str, b : &str) -> bool { - let mut a_iter = a.chars().peekable(); - let mut b_iter = b.chars().peekable(); - - loop { - let (a, b) = match (a_iter.peek(), b_iter.peek()) { - (None, None) => return true, - (None, _) => return false, - (Some(&a), None) => { - if is_pattern_whitespace(a) { - break // trailing whitespace check is out of loop for borrowck - } else { - return false - } - } - (Some(&a), Some(&b)) => (a, b) - }; - - if is_pattern_whitespace(a) && is_pattern_whitespace(b) { - // skip whitespace for a and b - scan_for_non_ws_or_end(&mut a_iter); - scan_for_non_ws_or_end(&mut b_iter); - } else if is_pattern_whitespace(a) { - // skip whitespace for a - scan_for_non_ws_or_end(&mut a_iter); - } else if a == b { - a_iter.next(); - b_iter.next(); - } else { - return false - } - } - - // check if a has *only* trailing whitespace - a_iter.all(is_pattern_whitespace) -} - -/// Advances the given peekable `Iterator` until it reaches a non-whitespace character -fn scan_for_non_ws_or_end>(iter: &mut Peekable) { - while lexer::is_pattern_whitespace(iter.peek().cloned()) { - iter.next(); - } -} - -pub fn is_pattern_whitespace(c: char) -> bool { - lexer::is_pattern_whitespace(Some(c)) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn eqmodws() { - assert_eq!(matches_codepattern("",""),true); - assert_eq!(matches_codepattern("","a"),false); - assert_eq!(matches_codepattern("a",""),false); - assert_eq!(matches_codepattern("a","a"),true); - assert_eq!(matches_codepattern("a b","a \n\t\r b"),true); - assert_eq!(matches_codepattern("a b ","a \n\t\r b"),true); - assert_eq!(matches_codepattern("a b","a \n\t\r b "),false); - assert_eq!(matches_codepattern("a b","a b"),true); - assert_eq!(matches_codepattern("ab","a b"),false); - assert_eq!(matches_codepattern("a b","ab"),true); - assert_eq!(matches_codepattern(" a b","ab"),true); - } - - #[test] - fn pattern_whitespace() { - assert_eq!(matches_codepattern("","\x0C"), false); - assert_eq!(matches_codepattern("a b ","a \u{0085}\n\t\r b"),true); - assert_eq!(matches_codepattern("a b","a \u{0085}\n\t\r b "),false); - } - - #[test] - fn non_pattern_whitespace() { - // These have the property 'White_Space' but not 'Pattern_White_Space' - assert_eq!(matches_codepattern("a b","a\u{2002}b"), false); - assert_eq!(matches_codepattern("a b","a\u{2002}b"), false); - assert_eq!(matches_codepattern("\u{205F}a b","ab"), false); - assert_eq!(matches_codepattern("a \u{3000}b","ab"), false); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax/visit.rs b/gcc/rust/rustc_parser/libsyntax/visit.rs deleted file mode 100644 index 9ec9550..0000000 --- a/gcc/rust/rustc_parser/libsyntax/visit.rs +++ /dev/null @@ -1,857 +0,0 @@ -//! AST walker. Each overridden visit method has full control over what -//! happens with its node, it can do its own traversal of the node's children, -//! call `visit::walk_*` to apply the default traversal algorithm, or prevent -//! deeper traversal by doing nothing. -//! -//! Note: it is an important invariant that the default visitor walks the body -//! of a function in "execution order" (more concretely, reverse post-order -//! with respect to the CFG implied by the AST), meaning that if AST node A may -//! execute before AST node B, then A is visited first. The borrow checker in -//! particular relies on this property. -//! -//! Note: walking an AST before macro expansion is probably a bad idea. For -//! instance, a walker looking for item names in a module will miss all of -//! those that are created by the expansion of a macro. - -use crate::ast::*; -use crate::parse::token::Token; -use crate::tokenstream::{TokenTree, TokenStream}; - -use syntax_pos::Span; - -#[derive(Copy, Clone)] -pub enum FnKind<'a> { - /// fn foo() or extern "Abi" fn foo() - ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), - - /// fn foo(&self) - Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), - - /// |x, y| body - Closure(&'a Expr), -} - -impl<'a> FnKind<'a> { - pub fn header(&self) -> Option<&'a FnHeader> { - match *self { - FnKind::ItemFn(_, header, _, _) => Some(header), - FnKind::Method(_, sig, _, _) => Some(&sig.header), - FnKind::Closure(_) => None, - } - } -} - -/// Each method of the Visitor trait is a hook to be potentially -/// overridden. Each method's default implementation recursively visits -/// the substructure of the input via the corresponding `walk` method; -/// e.g., the `visit_mod` method by default calls `visit::walk_mod`. -/// -/// If you want to ensure that your code handles every variant -/// explicitly, you need to override each method. (And you also need -/// to monitor future changes to `Visitor` in case a new method with a -/// new default implementation gets introduced.) -pub trait Visitor<'ast>: Sized { - fn visit_name(&mut self, _span: Span, _name: Name) { - // Nothing to do. - } - fn visit_ident(&mut self, ident: Ident) { - walk_ident(self, ident); - } - fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) { - walk_mod(self, m); - } - fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) } - fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) } - fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) } - fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) } - fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) } - fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) } - fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) } - fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } - fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) } - fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } - fn visit_expr_post(&mut self, _ex: &'ast Expr) { } - fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } - fn visit_generic_param(&mut self, param: &'ast GenericParam) { - walk_generic_param(self, param) - } - fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } - fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { - walk_where_predicate(self, p) - } - fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) { - walk_fn(self, fk, fd, s) - } - fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) } - fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) } - fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) } - fn visit_param_bound(&mut self, bounds: &'ast GenericBound) { - walk_param_bound(self, bounds) - } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { - walk_poly_trait_ref(self, t, m) - } - fn visit_variant_data(&mut self, s: &'ast VariantData, _: Ident, - _: &'ast Generics, _: NodeId, _: Span) { - walk_struct_def(self, s) - } - fn visit_struct_field(&mut self, s: &'ast StructField) { walk_struct_field(self, s) } - fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef, - generics: &'ast Generics, item_id: NodeId, _: Span) { - walk_enum_def(self, enum_definition, generics, item_id) - } - fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) { - walk_variant(self, v, g, item_id) - } - fn visit_label(&mut self, label: &'ast Label) { - walk_label(self, label) - } - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { - walk_lifetime(self, lifetime) - } - fn visit_mac(&mut self, _mac: &'ast Mac) { - panic!("visit_mac disabled by default"); - // N.B., see note about macros above. - // if you really want a visitor that - // works on macros, use this - // definition in your trait impl: - // visit::walk_mac(self, _mac) - } - fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) { - // Nothing to do - } - fn visit_path(&mut self, path: &'ast Path, _id: NodeId) { - walk_path(self, path) - } - fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) { - walk_use_tree(self, use_tree, id) - } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { - walk_path_segment(self, path_span, path_segment) - } - fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) { - walk_generic_args(self, path_span, generic_args) - } - fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { - match generic_arg { - GenericArg::Lifetime(lt) => self.visit_lifetime(lt), - GenericArg::Type(ty) => self.visit_ty(ty), - GenericArg::Const(ct) => self.visit_anon_const(ct), - } - } - fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) { - walk_assoc_ty_constraint(self, constraint) - } - fn visit_attribute(&mut self, attr: &'ast Attribute) { - walk_attribute(self, attr) - } - fn visit_tt(&mut self, tt: TokenTree) { - walk_tt(self, tt) - } - fn visit_tts(&mut self, tts: TokenStream) { - walk_tts(self, tts) - } - fn visit_token(&mut self, _t: Token) {} - // FIXME: add `visit_interpolated` and `walk_interpolated` - fn visit_vis(&mut self, vis: &'ast Visibility) { - walk_vis(self, vis) - } - fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) { - walk_fn_ret_ty(self, ret_ty) - } - fn visit_fn_header(&mut self, _header: &'ast FnHeader) { - // Nothing to do - } -} - -#[macro_export] -macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list { - $visitor.$method(elem) - } - }; - ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => { - for elem in $list { - $visitor.$method(elem, $($extra_args,)*) - } - } -} - -pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) { - visitor.visit_name(ident.span, ident.name); -} - -pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { - visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID); - walk_list!(visitor, visit_attribute, &krate.attrs); -} - -pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) { - walk_list!(visitor, visit_item, &module.items); -} - -pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) { - for attr in local.attrs.iter() { - visitor.visit_attribute(attr); - } - visitor.visit_pat(&local.pat); - walk_list!(visitor, visit_ty, &local.ty); - walk_list!(visitor, visit_expr, &local.init); -} - -pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) { - visitor.visit_ident(label.ident); -} - -pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) { - visitor.visit_ident(lifetime.ident); -} - -pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, - trait_ref: &'a PolyTraitRef, - _: &TraitBoundModifier) - where V: Visitor<'a>, -{ - walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); - visitor.visit_trait_ref(&trait_ref.trait_ref); -} - -pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) { - visitor.visit_path(&trait_ref.path, trait_ref.ref_id) -} - -pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); - match item.node { - ItemKind::ExternCrate(orig_name) => { - if let Some(orig_name) = orig_name { - visitor.visit_name(item.span, orig_name); - } - } - ItemKind::Use(ref use_tree) => { - visitor.visit_use_tree(use_tree, item.id, false) - } - ItemKind::Static(ref typ, _, ref expr) | - ItemKind::Const(ref typ, ref expr) => { - visitor.visit_ty(typ); - visitor.visit_expr(expr); - } - ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => { - visitor.visit_generics(generics); - visitor.visit_fn_header(header); - visitor.visit_fn(FnKind::ItemFn(item.ident, header, - &item.vis, body), - declaration, - item.span, - item.id) - } - ItemKind::Mod(ref module) => { - visitor.visit_mod(module, item.span, &item.attrs, item.id) - } - ItemKind::ForeignMod(ref foreign_module) => { - walk_list!(visitor, visit_foreign_item, &foreign_module.items); - } - ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga), - ItemKind::Ty(ref typ, ref generics) => { - visitor.visit_ty(typ); - visitor.visit_generics(generics) - } - ItemKind::Existential(ref bounds, ref generics) => { - walk_list!(visitor, visit_param_bound, bounds); - visitor.visit_generics(generics) - } - ItemKind::Enum(ref enum_definition, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_enum_def(enum_definition, generics, item.id, item.span) - } - ItemKind::Impl(_, _, _, - ref generics, - ref opt_trait_reference, - ref typ, - ref impl_items) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, opt_trait_reference); - visitor.visit_ty(typ); - walk_list!(visitor, visit_impl_item, impl_items); - } - ItemKind::Struct(ref struct_definition, ref generics) | - ItemKind::Union(ref struct_definition, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition, item.ident, - generics, item.id, item.span); - } - ItemKind::Trait(.., ref generics, ref bounds, ref methods) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_trait_item, methods); - } - ItemKind::TraitAlias(ref generics, ref bounds) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_param_bound, bounds); - } - ItemKind::Mac(ref mac) => visitor.visit_mac(mac), - ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), - } - walk_list!(visitor, visit_attribute, &item.attrs); -} - -pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, - enum_definition: &'a EnumDef, - generics: &'a Generics, - item_id: NodeId) { - walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id); -} - -pub fn walk_variant<'a, V>(visitor: &mut V, - variant: &'a Variant, - generics: &'a Generics, - item_id: NodeId) - where V: Visitor<'a>, -{ - visitor.visit_ident(variant.node.ident); - visitor.visit_variant_data(&variant.node.data, variant.node.ident, - generics, item_id, variant.span); - walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); -} - -pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { - match typ.node { - TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => { - visitor.visit_ty(ty) - } - TyKind::Ptr(ref mutable_type) => { - visitor.visit_ty(&mutable_type.ty) - } - TyKind::Rptr(ref opt_lifetime, ref mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime); - visitor.visit_ty(&mutable_type.ty) - } - TyKind::Never | TyKind::CVarArgs => {} - TyKind::Tup(ref tuple_element_types) => { - walk_list!(visitor, visit_ty, tuple_element_types); - } - TyKind::BareFn(ref function_declaration) => { - walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); - walk_fn_decl(visitor, &function_declaration.decl); - } - TyKind::Path(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, typ.id); - } - TyKind::Array(ref ty, ref length) => { - visitor.visit_ty(ty); - visitor.visit_anon_const(length) - } - TyKind::TraitObject(ref bounds, ..) | - TyKind::ImplTrait(_, ref bounds) => { - walk_list!(visitor, visit_param_bound, bounds); - } - TyKind::Typeof(ref expression) => { - visitor.visit_anon_const(expression) - } - TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} - TyKind::Mac(ref mac) => { - visitor.visit_mac(mac) - } - } -} - -pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { - for segment in &path.segments { - visitor.visit_path_segment(path.span, segment); - } -} - -pub fn walk_use_tree<'a, V: Visitor<'a>>( - visitor: &mut V, use_tree: &'a UseTree, id: NodeId, -) { - visitor.visit_path(&use_tree.prefix, id); - match use_tree.kind { - UseTreeKind::Simple(rename, ..) => { - // the extra IDs are handled during HIR lowering - if let Some(rename) = rename { - visitor.visit_ident(rename); - } - } - UseTreeKind::Glob => {}, - UseTreeKind::Nested(ref use_trees) => { - for &(ref nested_tree, nested_id) in use_trees { - visitor.visit_use_tree(nested_tree, nested_id, true); - } - } - } -} - -pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, - path_span: Span, - segment: &'a PathSegment) { - visitor.visit_ident(segment.ident); - if let Some(ref args) = segment.args { - visitor.visit_generic_args(path_span, args); - } -} - -pub fn walk_generic_args<'a, V>(visitor: &mut V, - _path_span: Span, - generic_args: &'a GenericArgs) - where V: Visitor<'a>, -{ - match *generic_args { - GenericArgs::AngleBracketed(ref data) => { - walk_list!(visitor, visit_generic_arg, &data.args); - walk_list!(visitor, visit_assoc_ty_constraint, &data.constraints); - } - GenericArgs::Parenthesized(ref data) => { - walk_list!(visitor, visit_ty, &data.inputs); - walk_list!(visitor, visit_ty, &data.output); - } - } -} - -pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(visitor: &mut V, - constraint: &'a AssocTyConstraint) { - visitor.visit_ident(constraint.ident); - match constraint.kind { - AssocTyConstraintKind::Equality { ref ty } => { - visitor.visit_ty(ty); - } - AssocTyConstraintKind::Bound { ref bounds } => { - walk_list!(visitor, visit_param_bound, bounds); - } - } -} - -pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { - match pattern.node { - PatKind::TupleStruct(ref path, ref children, _) => { - visitor.visit_path(path, pattern.id); - walk_list!(visitor, visit_pat, children); - } - PatKind::Path(ref opt_qself, ref path) => { - if let Some(ref qself) = *opt_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, pattern.id) - } - PatKind::Struct(ref path, ref fields, _) => { - visitor.visit_path(path, pattern.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.node.attrs.iter()); - visitor.visit_ident(field.node.ident); - visitor.visit_pat(&field.node.pat) - } - } - PatKind::Tuple(ref tuple_elements, _) => { - walk_list!(visitor, visit_pat, tuple_elements); - } - PatKind::Box(ref subpattern) | - PatKind::Ref(ref subpattern, _) | - PatKind::Paren(ref subpattern) => { - visitor.visit_pat(subpattern) - } - PatKind::Ident(_, ident, ref optional_subpattern) => { - visitor.visit_ident(ident); - walk_list!(visitor, visit_pat, optional_subpattern); - } - PatKind::Lit(ref expression) => visitor.visit_expr(expression), - PatKind::Range(ref lower_bound, ref upper_bound, _) => { - visitor.visit_expr(lower_bound); - visitor.visit_expr(upper_bound); - } - PatKind::Wild => (), - PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => { - walk_list!(visitor, visit_pat, prepatterns); - walk_list!(visitor, visit_pat, slice_pattern); - walk_list!(visitor, visit_pat, postpatterns); - } - PatKind::Mac(ref mac) => visitor.visit_mac(mac), - } -} - -pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a ForeignItem) { - visitor.visit_vis(&foreign_item.vis); - visitor.visit_ident(foreign_item.ident); - - match foreign_item.node { - ForeignItemKind::Fn(ref function_declaration, ref generics) => { - walk_fn_decl(visitor, function_declaration); - visitor.visit_generics(generics) - } - ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), - ForeignItemKind::Ty => (), - ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac), - } - - walk_list!(visitor, visit_attribute, &foreign_item.attrs); -} - -pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { - // Empty! -} - -pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) { - match *bound { - GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier), - GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), - } -} - -pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { - visitor.visit_ident(param.ident); - walk_list!(visitor, visit_attribute, param.attrs.iter()); - walk_list!(visitor, visit_param_bound, ¶m.bounds); - match param.kind { - GenericParamKind::Lifetime => (), - GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty), - } -} - -pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) { - walk_list!(visitor, visit_generic_param, &generics.params); - walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); -} - -pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) { - match *predicate { - WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, - ref bounds, - ref bound_generic_params, - ..}) => { - visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_generic_param, bound_generic_params); - } - WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_param_bound, bounds); - } - WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, - ref rhs_ty, - ..}) => { - visitor.visit_ty(lhs_ty); - visitor.visit_ty(rhs_ty); - } - } -} - -pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionRetTy) { - if let FunctionRetTy::Ty(ref output_ty) = *ret_ty { - visitor.visit_ty(output_ty) - } -} - -pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { - for argument in &function_declaration.inputs { - walk_list!(visitor, visit_attribute, argument.attrs.iter()); - visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty); - } - visitor.visit_fn_ret_ty(&function_declaration.output) -} - -pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span) - where V: Visitor<'a>, -{ - match kind { - FnKind::ItemFn(_, header, _, body) => { - visitor.visit_fn_header(header); - walk_fn_decl(visitor, declaration); - visitor.visit_block(body); - } - FnKind::Method(_, sig, _, body) => { - visitor.visit_fn_header(&sig.header); - walk_fn_decl(visitor, declaration); - visitor.visit_block(body); - } - FnKind::Closure(body) => { - walk_fn_decl(visitor, declaration); - visitor.visit_expr(body); - } - } -} - -pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) { - visitor.visit_ident(trait_item.ident); - walk_list!(visitor, visit_attribute, &trait_item.attrs); - visitor.visit_generics(&trait_item.generics); - match trait_item.node { - TraitItemKind::Const(ref ty, ref default) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, default); - } - TraitItemKind::Method(ref sig, None) => { - visitor.visit_fn_header(&sig.header); - walk_fn_decl(visitor, &sig.decl); - } - TraitItemKind::Method(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body), - &sig.decl, trait_item.span, trait_item.id); - } - TraitItemKind::Type(ref bounds, ref default) => { - walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_ty, default); - } - TraitItemKind::Macro(ref mac) => { - visitor.visit_mac(mac); - } - } -} - -pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) { - visitor.visit_vis(&impl_item.vis); - visitor.visit_ident(impl_item.ident); - walk_list!(visitor, visit_attribute, &impl_item.attrs); - visitor.visit_generics(&impl_item.generics); - match impl_item.node { - ImplItemKind::Const(ref ty, ref expr) => { - visitor.visit_ty(ty); - visitor.visit_expr(expr); - } - ImplItemKind::Method(ref sig, ref body) => { - visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body), - &sig.decl, impl_item.span, impl_item.id); - } - ImplItemKind::Type(ref ty) => { - visitor.visit_ty(ty); - } - ImplItemKind::Existential(ref bounds) => { - walk_list!(visitor, visit_param_bound, bounds); - } - ImplItemKind::Macro(ref mac) => { - visitor.visit_mac(mac); - } - } -} - -pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &'a VariantData) { - walk_list!(visitor, visit_struct_field, struct_definition.fields()); -} - -pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) { - visitor.visit_vis(&struct_field.vis); - if let Some(ident) = struct_field.ident { - visitor.visit_ident(ident); - } - visitor.visit_ty(&struct_field.ty); - walk_list!(visitor, visit_attribute, &struct_field.attrs); -} - -pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) { - walk_list!(visitor, visit_stmt, &block.stmts); -} - -pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { - match statement.node { - StmtKind::Local(ref local) => visitor.visit_local(local), - StmtKind::Item(ref item) => visitor.visit_item(item), - StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { - visitor.visit_expr(expression) - } - StmtKind::Mac(ref mac) => { - let (ref mac, _, ref attrs) = **mac; - visitor.visit_mac(mac); - for attr in attrs.iter() { - visitor.visit_attribute(attr); - } - } - } -} - -pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) { - visitor.visit_path(&mac.node.path, DUMMY_NODE_ID); -} - -pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { - visitor.visit_expr(&constant.value); -} - -pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { - for attr in expression.attrs.iter() { - visitor.visit_attribute(attr); - } - match expression.node { - ExprKind::Box(ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprKind::Array(ref subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::Repeat(ref element, ref count) => { - visitor.visit_expr(element); - visitor.visit_anon_const(count) - } - ExprKind::Struct(ref path, ref fields, ref optional_base) => { - visitor.visit_path(path, expression.id); - for field in fields { - walk_list!(visitor, visit_attribute, field.attrs.iter()); - visitor.visit_ident(field.ident); - visitor.visit_expr(&field.expr) - } - walk_list!(visitor, visit_expr, optional_base); - } - ExprKind::Tup(ref subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::Call(ref callee_expression, ref arguments) => { - visitor.visit_expr(callee_expression); - walk_list!(visitor, visit_expr, arguments); - } - ExprKind::MethodCall(ref segment, ref arguments) => { - visitor.visit_path_segment(expression.span, segment); - walk_list!(visitor, visit_expr, arguments); - } - ExprKind::Binary(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression) - } - ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { - visitor.visit_expr(subexpression); - visitor.visit_ty(typ) - } - ExprKind::Let(ref pats, ref scrutinee) => { - walk_list!(visitor, visit_pat, pats); - visitor.visit_expr(scrutinee); - } - ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { - visitor.visit_expr(head_expression); - visitor.visit_block(if_block); - walk_list!(visitor, visit_expr, optional_else); - } - ExprKind::While(ref subexpression, ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_expr(subexpression); - visitor.visit_block(block); - } - ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_pat(pattern); - visitor.visit_expr(subexpression); - visitor.visit_block(block); - } - ExprKind::Loop(ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); - } - ExprKind::Match(ref subexpression, ref arms) => { - visitor.visit_expr(subexpression); - walk_list!(visitor, visit_arm, arms); - } - ExprKind::Closure(_, _, _, ref function_declaration, ref body, _decl_span) => { - visitor.visit_fn(FnKind::Closure(body), - function_declaration, - expression.span, - expression.id) - } - ExprKind::Block(ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); - } - ExprKind::Async(_, _, ref body) => { - visitor.visit_block(body); - } - ExprKind::Await(_, ref expr) => visitor.visit_expr(expr), - ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { - visitor.visit_expr(left_hand_expression); - visitor.visit_expr(right_hand_expression); - } - ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression); - } - ExprKind::Field(ref subexpression, ident) => { - visitor.visit_expr(subexpression); - visitor.visit_ident(ident); - } - ExprKind::Index(ref main_expression, ref index_expression) => { - visitor.visit_expr(main_expression); - visitor.visit_expr(index_expression) - } - ExprKind::Range(ref start, ref end, _) => { - walk_list!(visitor, visit_expr, start); - walk_list!(visitor, visit_expr, end); - } - ExprKind::Path(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, expression.id) - } - ExprKind::Break(ref opt_label, ref opt_expr) => { - walk_list!(visitor, visit_label, opt_label); - walk_list!(visitor, visit_expr, opt_expr); - } - ExprKind::Continue(ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - } - ExprKind::Ret(ref optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); - } - ExprKind::Mac(ref mac) => visitor.visit_mac(mac), - ExprKind::Paren(ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprKind::InlineAsm(ref ia) => { - for &(_, ref input) in &ia.inputs { - visitor.visit_expr(input) - } - for output in &ia.outputs { - visitor.visit_expr(&output.expr) - } - } - ExprKind::Yield(ref optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); - } - ExprKind::Try(ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprKind::TryBlock(ref body) => { - visitor.visit_block(body) - } - ExprKind::Lit(_) | ExprKind::Err => {} - } - - visitor.visit_expr_post(expression) -} - -pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { - walk_list!(visitor, visit_pat, &arm.pats); - if let Some(ref e) = &arm.guard { - visitor.visit_expr(e); - } - visitor.visit_expr(&arm.body); - walk_list!(visitor, visit_attribute, &arm.attrs); -} - -pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) { - if let VisibilityKind::Restricted { ref path, id } = vis.node { - visitor.visit_path(path, id); - } -} - -pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) { - visitor.visit_tts(attr.tokens.clone()); -} - -pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) { - match tt { - TokenTree::Token(token) => visitor.visit_token(token), - TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts), - } -} - -pub fn walk_tts<'a, V: Visitor<'a>>(visitor: &mut V, tts: TokenStream) { - for tt in tts.trees() { - visitor.visit_tt(tt); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/Cargo.toml b/gcc/rust/rustc_parser/libsyntax_ext/Cargo.toml deleted file mode 100644 index eafbe63..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "syntax_ext" -version = "0.0.0" -edition = "2018" - -[lib] -name = "syntax_ext" -path = "lib.rs" -doctest = false - -[dependencies] -fmt_macros = { path = "../libfmt_macros" } -errors = { path = "../librustc_errors", package = "rustc_errors" } -syntax = { path = "../libsyntax" } -syntax_pos = { path = "../libsyntax_pos" } -rustc_data_structures = { path = "../librustc_data_structures" } -rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } -log = "0.4" diff --git a/gcc/rust/rustc_parser/libsyntax_ext/asm.rs b/gcc/rust/rustc_parser/libsyntax_ext/asm.rs deleted file mode 100644 index c1c2732..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/asm.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Inline assembly support. -// -use State::*; - -use rustc_data_structures::thin_vec::ThinVec; - -use errors::DiagnosticBuilder; - -use syntax::ast; -use syntax::ext::base::{self, *}; -use syntax::parse; -use syntax::parse::token::{self, Token}; -use syntax::ptr::P; -use syntax::symbol::{kw, sym, Symbol}; -use syntax::ast::AsmDialect; -use syntax_pos::Span; -use syntax::tokenstream; -use syntax::{span_err, struct_span_err}; - -enum State { - Asm, - Outputs, - Inputs, - Clobbers, - Options, - StateNone, -} - -impl State { - fn next(&self) -> State { - match *self { - Asm => Outputs, - Outputs => Inputs, - Inputs => Clobbers, - Clobbers => Options, - Options => StateNone, - StateNone => StateNone, - } - } -} - -const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel]; - -pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) - -> Box { - let mut inline_asm = match parse_inline_asm(cx, sp, tts) { - Ok(Some(inline_asm)) => inline_asm, - Ok(None) => return DummyResult::expr(sp), - Err(mut err) => { - err.emit(); - return DummyResult::expr(sp); - } - }; - - // If there are no outputs, the inline assembly is executed just for its side effects, - // so ensure that it is volatile - if inline_asm.outputs.is_empty() { - inline_asm.volatile = true; - } - - MacEager::expr(P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp, - attrs: ThinVec::new(), - })) -} - -fn parse_inline_asm<'a>( - cx: &mut ExtCtxt<'a>, - sp: Span, - tts: &[tokenstream::TokenTree], -) -> Result, DiagnosticBuilder<'a>> { - // Split the tts before the first colon, to avoid `asm!("x": y)` being - // parsed as `asm!(z)` with `z = "x": y` which is type ascription. - let first_colon = tts.iter() - .position(|tt| { - match *tt { - tokenstream::TokenTree::Token(Token { kind: token::Colon, .. }) | - tokenstream::TokenTree::Token(Token { kind: token::ModSep, .. }) => true, - _ => false, - } - }) - .unwrap_or(tts.len()); - let mut p = cx.new_parser_from_tts(&tts[first_colon..]); - let mut asm = kw::Invalid; - let mut asm_str_style = None; - let mut outputs = Vec::new(); - let mut inputs = Vec::new(); - let mut clobs = Vec::new(); - let mut volatile = false; - let mut alignstack = false; - let mut dialect = AsmDialect::Att; - - let mut state = Asm; - - 'statement: loop { - match state { - Asm => { - if asm_str_style.is_some() { - // If we already have a string with instructions, - // ending up in Asm state again is an error. - return Err(struct_span_err!( - cx.parse_sess.span_diagnostic, - sp, - E0660, - "malformed inline assembly" - )); - } - // Nested parser, stop before the first colon (see above). - let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]); - - if p2.token == token::Eof { - let mut err = - cx.struct_span_err(sp, "macro requires a string literal as an argument"); - err.span_label(sp, "string literal required"); - return Err(err); - } - - let expr = p2.parse_expr()?; - let (s, style) = - match expr_to_string(cx, expr, "inline assembly must be a string literal") { - Some((s, st)) => (s, st), - None => return Ok(None), - }; - - // This is most likely malformed. - if p2.token != token::Eof { - let mut extra_tts = p2.parse_all_token_trees()?; - extra_tts.extend(tts[first_colon..].iter().cloned()); - p = parse::stream_to_parser( - cx.parse_sess, - extra_tts.into_iter().collect(), - Some("inline assembly"), - ); - } - - asm = s; - asm_str_style = Some(style); - } - Outputs => { - while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !outputs.is_empty() { - p.eat(&token::Comma); - } - - let (constraint, _) = p.parse_str()?; - - let span = p.prev_span; - - p.expect(&token::OpenDelim(token::Paren))?; - let expr = p.parse_expr()?; - p.expect(&token::CloseDelim(token::Paren))?; - - // Expands a read+write operand into two operands. - // - // Use '+' modifier when you want the same expression - // to be both an input and an output at the same time. - // It's the opposite of '=&' which means that the memory - // cannot be shared with any other operand (usually when - // a register is clobbered early.) - let constraint_str = constraint.as_str(); - let mut ch = constraint_str.chars(); - let output = match ch.next() { - Some('=') => None, - Some('+') => { - Some(Symbol::intern(&format!("={}", ch.as_str()))) - } - _ => { - span_err!(cx, span, E0661, - "output operand constraint lacks '=' or '+'"); - None - } - }; - - let is_rw = output.is_some(); - let is_indirect = constraint_str.contains("*"); - outputs.push(ast::InlineAsmOutput { - constraint: output.unwrap_or(constraint), - expr, - is_rw, - is_indirect, - }); - } - } - Inputs => { - while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !inputs.is_empty() { - p.eat(&token::Comma); - } - - let (constraint, _) = p.parse_str()?; - - if constraint.as_str().starts_with("=") { - span_err!(cx, p.prev_span, E0662, - "input operand constraint contains '='"); - } else if constraint.as_str().starts_with("+") { - span_err!(cx, p.prev_span, E0663, - "input operand constraint contains '+'"); - } - - p.expect(&token::OpenDelim(token::Paren))?; - let input = p.parse_expr()?; - p.expect(&token::CloseDelim(token::Paren))?; - - inputs.push((constraint, input)); - } - } - Clobbers => { - while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !clobs.is_empty() { - p.eat(&token::Comma); - } - - let (s, _) = p.parse_str()?; - - if OPTIONS.iter().any(|&opt| s == opt) { - cx.span_warn(p.prev_span, "expected a clobber, found an option"); - } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") { - span_err!(cx, p.prev_span, E0664, - "clobber should not be surrounded by braces"); - } - - clobs.push(s); - } - } - Options => { - let (option, _) = p.parse_str()?; - - if option == sym::volatile { - // Indicates that the inline assembly has side effects - // and must not be optimized out along with its outputs. - volatile = true; - } else if option == sym::alignstack { - alignstack = true; - } else if option == sym::intel { - dialect = AsmDialect::Intel; - } else { - cx.span_warn(p.prev_span, "unrecognized option"); - } - - if p.token == token::Comma { - p.eat(&token::Comma); - } - } - StateNone => (), - } - - loop { - // MOD_SEP is a double colon '::' without space in between. - // When encountered, the state must be advanced twice. - match (&p.token.kind, state.next(), state.next().next()) { - (&token::Colon, StateNone, _) | - (&token::ModSep, _, StateNone) => { - p.bump(); - break 'statement; - } - (&token::Colon, st, _) | - (&token::ModSep, _, st) => { - p.bump(); - state = st; - } - (&token::Eof, ..) => break 'statement, - _ => break, - } - } - } - - Ok(Some(ast::InlineAsm { - asm, - asm_str_style: asm_str_style.unwrap(), - outputs, - inputs, - clobbers: clobs, - volatile, - alignstack, - dialect, - ctxt: cx.backtrace(), - })) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/assert.rs b/gcc/rust/rustc_parser/libsyntax_ext/assert.rs deleted file mode 100644 index 637614a..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/assert.rs +++ /dev/null @@ -1,141 +0,0 @@ -use errors::{Applicability, DiagnosticBuilder}; - -use syntax::ast::{self, *}; -use syntax::source_map::Spanned; -use syntax::ext::base::*; -use syntax::ext::build::AstBuilder; -use syntax::parse::token::{self, TokenKind}; -use syntax::parse::parser::Parser; -use syntax::print::pprust; -use syntax::ptr::P; -use syntax::symbol::{sym, Symbol}; -use syntax::tokenstream::{TokenStream, TokenTree}; -use syntax_pos::{Span, DUMMY_SP}; - -pub fn expand_assert<'cx>( - cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[TokenTree], -) -> Box { - let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) { - Ok(assert) => assert, - Err(mut err) => { - err.emit(); - return DummyResult::expr(sp); - } - }; - - let sp = sp.apply_mark(cx.current_expansion.mark); - let panic_call = Mac_ { - path: Path::from_ident(Ident::new(sym::panic, sp)), - tts: custom_message.unwrap_or_else(|| { - TokenStream::from(TokenTree::token( - TokenKind::lit(token::Str, Symbol::intern(&format!( - "assertion failed: {}", - pprust::expr_to_string(&cond_expr).escape_debug() - )), None), - DUMMY_SP, - )) - }).into(), - delim: MacDelimiter::Parenthesis, - }; - let if_expr = cx.expr_if( - sp, - cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), - cx.expr( - sp, - ExprKind::Mac(Spanned { - span: sp, - node: panic_call, - }), - ), - None, - ); - MacEager::expr(if_expr) -} - -struct Assert { - cond_expr: P, - custom_message: Option, -} - -fn parse_assert<'a>( - cx: &mut ExtCtxt<'a>, - sp: Span, - tts: &[TokenTree] -) -> Result> { - let mut parser = cx.new_parser_from_tts(tts); - - if parser.token == token::Eof { - let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument"); - err.span_label(sp, "boolean expression required"); - return Err(err); - } - - let cond_expr = parser.parse_expr()?; - - // Some crates use the `assert!` macro in the following form (note extra semicolon): - // - // assert!( - // my_function(); - // ); - // - // Warn about semicolon and suggest removing it. Eventually, this should be turned into an - // error. - if parser.token == token::Semi { - let mut err = cx.struct_span_warn(sp, "macro requires an expression as an argument"); - err.span_suggestion( - parser.token.span, - "try removing semicolon", - String::new(), - Applicability::MaybeIncorrect - ); - err.note("this is going to be an error in the future"); - err.emit(); - - parser.bump(); - } - - // Some crates use the `assert!` macro in the following form (note missing comma before - // message): - // - // assert!(true "error message"); - // - // Parse this as an actual message, and suggest inserting a comma. Eventually, this should be - // turned into an error. - let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. }) - = parser.token.kind { - let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal"); - let comma_span = cx.source_map().next_point(parser.prev_span); - err.span_suggestion_short( - comma_span, - "try adding a comma", - ", ".to_string(), - Applicability::MaybeIncorrect - ); - err.note("this is going to be an error in the future"); - err.emit(); - - parse_custom_message(&mut parser) - } else if parser.eat(&token::Comma) { - parse_custom_message(&mut parser) - } else { - None - }; - - if parser.token != token::Eof { - parser.expect_one_of(&[], &[])?; - unreachable!(); - } - - Ok(Assert { cond_expr, custom_message }) -} - -fn parse_custom_message(parser: &mut Parser<'_>) -> Option { - let ts = parser.parse_tokens(); - if !ts.is_empty() { - Some(ts) - } else { - None - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/cfg.rs b/gcc/rust/rustc_parser/libsyntax_ext/cfg.rs deleted file mode 100644 index e952515..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/cfg.rs +++ /dev/null @@ -1,56 +0,0 @@ -/// The compiler code necessary to support the cfg! extension, which expands to -/// a literal `true` or `false` based on whether the given cfg matches the -/// current compilation environment. - -use errors::DiagnosticBuilder; - -use syntax::ast; -use syntax::ext::base::{self, *}; -use syntax::ext::build::AstBuilder; -use syntax::attr; -use syntax::tokenstream; -use syntax::parse::token; -use syntax_pos::Span; - -pub fn expand_cfg( - cx: &mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree], -) -> Box { - let sp = sp.apply_mark(cx.current_expansion.mark); - - match parse_cfg(cx, sp, tts) { - Ok(cfg) => { - let matches_cfg = attr::cfg_matches(&cfg, cx.parse_sess, cx.ecfg.features); - MacEager::expr(cx.expr_bool(sp, matches_cfg)) - } - Err(mut err) => { - err.emit(); - DummyResult::expr(sp) - } - } -} - -fn parse_cfg<'a>( - cx: &mut ExtCtxt<'a>, - sp: Span, - tts: &[tokenstream::TokenTree], -) -> Result> { - let mut p = cx.new_parser_from_tts(tts); - - if p.token == token::Eof { - let mut err = cx.struct_span_err(sp, "macro requires a cfg-pattern as an argument"); - err.span_label(sp, "cfg-pattern required"); - return Err(err); - } - - let cfg = p.parse_meta_item()?; - - let _ = p.eat(&token::Comma); - - if !p.eat(&token::Eof) { - return Err(cx.struct_span_err(sp, "expected 1 cfg-pattern")); - } - - Ok(cfg) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/compile_error.rs b/gcc/rust/rustc_parser/libsyntax_ext/compile_error.rs deleted file mode 100644 index 59d3f2c..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/compile_error.rs +++ /dev/null @@ -1,19 +0,0 @@ -// The compiler code necessary to support the compile_error! extension. - -use syntax::ext::base::{self, *}; -use syntax_pos::Span; -use syntax::tokenstream; - -pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) - -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { - None => return DummyResult::any(sp), - Some(v) => v, - }; - - cx.span_err(sp, &var); - - DummyResult::any(sp) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/concat.rs b/gcc/rust/rustc_parser/libsyntax_ext/concat.rs deleted file mode 100644 index 68d51783..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/concat.rs +++ /dev/null @@ -1,65 +0,0 @@ -use syntax::ast; -use syntax::ext::base; -use syntax::ext::build::AstBuilder; -use syntax::symbol::Symbol; -use syntax::tokenstream; - -use std::string::String; - -pub fn expand_syntax_ext( - cx: &mut base::ExtCtxt<'_>, - sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree], -) -> Box { - let es = match base::get_exprs_from_tts(cx, sp, tts) { - Some(e) => e, - None => return base::DummyResult::expr(sp), - }; - let mut accumulator = String::new(); - let mut missing_literal = vec![]; - let mut has_errors = false; - for e in es { - match e.node { - ast::ExprKind::Lit(ref lit) => match lit.node { - ast::LitKind::Str(ref s, _) - | ast::LitKind::Float(ref s, _) - | ast::LitKind::FloatUnsuffixed(ref s) => { - accumulator.push_str(&s.as_str()); - } - ast::LitKind::Char(c) => { - accumulator.push(c); - } - ast::LitKind::Int(i, ast::LitIntType::Unsigned(_)) - | ast::LitKind::Int(i, ast::LitIntType::Signed(_)) - | ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => { - accumulator.push_str(&i.to_string()); - } - ast::LitKind::Bool(b) => { - accumulator.push_str(&b.to_string()); - } - ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => { - cx.span_err(e.span, "cannot concatenate a byte string literal"); - } - ast::LitKind::Err(_) => { - has_errors = true; - } - }, - ast::ExprKind::Err => { - has_errors = true; - } - _ => { - missing_literal.push(e.span); - } - } - } - if missing_literal.len() > 0 { - let mut err = cx.struct_span_err(missing_literal, "expected a literal"); - err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); - err.emit(); - return base::DummyResult::expr(sp); - } else if has_errors { - return base::DummyResult::expr(sp); - } - let sp = sp.apply_mark(cx.current_expansion.mark); - base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/concat_idents.rs b/gcc/rust/rustc_parser/libsyntax_ext/concat_idents.rs deleted file mode 100644 index df91914..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/concat_idents.rs +++ /dev/null @@ -1,66 +0,0 @@ -use rustc_data_structures::thin_vec::ThinVec; - -use syntax::ast; -use syntax::ext::base::{self, *}; -use syntax::parse::token::{self, Token}; -use syntax::ptr::P; -use syntax_pos::Span; -use syntax_pos::symbol::Symbol; -use syntax::tokenstream::TokenTree; - -pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[TokenTree]) - -> Box { - if tts.is_empty() { - cx.span_err(sp, "concat_idents! takes 1 or more arguments."); - return DummyResult::any(sp); - } - - let mut res_str = String::new(); - for (i, e) in tts.iter().enumerate() { - if i & 1 == 1 { - match *e { - TokenTree::Token(Token { kind: token::Comma, .. }) => {} - _ => { - cx.span_err(sp, "concat_idents! expecting comma."); - return DummyResult::any(sp); - } - } - } else { - match *e { - TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => - res_str.push_str(&name.as_str()), - _ => { - cx.span_err(sp, "concat_idents! requires ident args."); - return DummyResult::any(sp); - } - } - } - } - - let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark)); - - struct ConcatIdentsResult { ident: ast::Ident } - - impl base::MacResult for ConcatIdentsResult { - fn make_expr(self: Box) -> Option> { - Some(P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)), - span: self.ident.span, - attrs: ThinVec::new(), - })) - } - - fn make_ty(self: Box) -> Option> { - Some(P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)), - span: self.ident.span, - })) - } - } - - Box::new(ConcatIdentsResult { ident }) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/bounds.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/bounds.rs deleted file mode 100644 index d5b8a00..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/bounds.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::MetaItem; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax_pos::Span; - -pub fn expand_deriving_copy(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, marker::Copy), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: true, - methods: Vec::new(), - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push); -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/clone.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/clone.rs deleted file mode 100644 index b3b6328..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/clone.rs +++ /dev/null @@ -1,216 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{self, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData}; -use syntax::attr; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::{kw, sym, Symbol}; -use syntax_pos::Span; - -pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - // check if we can use a short form - // - // the short form is `fn clone(&self) -> Self { *self }` - // - // we can use the short form if: - // - the item is Copy (unfortunately, all we can check is whether it's also deriving Copy) - // - there are no generic parameters (after specialization this limitation can be removed) - // if we used the short form with generics, we'd have to bound the generics with - // Clone + Copy, and then there'd be no Clone impl at all if the user fills in something - // that is Clone but not Copy. and until specialization we can't write both impls. - // - the item is a union with Copy fields - // Unions with generic parameters still can derive Clone because they require Copy - // for deriving, Clone alone is not enough. - // Whever Clone is implemented for fields is irrelevant so we don't assert it. - let bounds; - let substructure; - let is_shallow; - match *item { - Annotatable::Item(ref annitem) => { - match annitem.node { - ItemKind::Struct(_, Generics { ref params, .. }) | - ItemKind::Enum(_, Generics { ref params, .. }) => { - if attr::contains_name(&annitem.attrs, sym::rustc_copy_clone_marker) && - !params.iter().any(|param| match param.kind { - ast::GenericParamKind::Type { .. } => true, - _ => false, - }) - { - bounds = vec![]; - is_shallow = true; - substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, false) - })); - } else { - bounds = vec![]; - is_shallow = false; - substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone("Clone", c, s, sub) - })); - } - } - ItemKind::Union(..) => { - bounds = vec![Literal(path_std!(cx, marker::Copy))]; - is_shallow = true; - substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, true) - })); - } - _ => { - bounds = vec![]; - is_shallow = false; - substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone("Clone", c, s, sub) - })); - } - } - } - - _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"), - } - - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, clone::Clone), - additional_bounds: bounds, - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: true, - methods: vec![MethodDef { - name: "clone", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: Vec::new(), - ret_ty: Self_, - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: false, - combine_substructure: substructure, - }], - associated_types: Vec::new(), - }; - - trait_def.expand_ext(cx, mitem, item, push, is_shallow) -} - -fn cs_clone_shallow(name: &str, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, - is_union: bool) - -> P { - fn assert_ty_bounds(cx: &mut ExtCtxt<'_>, stmts: &mut Vec, - ty: P, span: Span, helper_name: &str) { - // Generate statement `let _: helper_name;`, - // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); - let assert_path = cx.path_all(span, true, - cx.std_path(&[sym::clone, Symbol::intern(helper_name)]), - vec![GenericArg::Type(ty)], vec![]); - stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); - } - fn process_variant(cx: &mut ExtCtxt<'_>, stmts: &mut Vec, variant: &VariantData) { - for field in variant.fields() { - // let _: AssertParamIsClone; - assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsClone"); - } - } - - let mut stmts = Vec::new(); - if is_union { - // let _: AssertParamIsCopy; - let self_ty = - cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_empty_ctxt(kw::SelfUpper))); - assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy"); - } else { - match *substr.fields { - StaticStruct(vdata, ..) => { - process_variant(cx, &mut stmts, vdata); - } - StaticEnum(enum_def, ..) => { - for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); - } - } - _ => cx.span_bug(trait_span, &format!("unexpected substructure in \ - shallow `derive({})`", name)) - } - } - stmts.push(cx.stmt_expr(cx.expr_deref(trait_span, cx.expr_self(trait_span)))); - cx.expr_block(cx.block(trait_span, stmts)) -} - -fn cs_clone(name: &str, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>) - -> P { - let ctor_path; - let all_fields; - let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]); - let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo<'_>| { - let args = vec![cx.expr_addr_of(field.span, field.self_.clone())]; - cx.expr_call_global(field.span, fn_path.clone(), args) - }; - - let vdata; - match *substr.fields { - Struct(vdata_, ref af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident]); - all_fields = af; - vdata = vdata_; - } - EnumMatching(.., variant, ref af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]); - all_fields = af; - vdata = &variant.node.data; - } - EnumNonMatchingCollapsed(..) => { - cx.span_bug(trait_span, - &format!("non-matching enum variants in \ - `derive({})`", - name)) - } - StaticEnum(..) | StaticStruct(..) => { - cx.span_bug(trait_span, &format!("static method in `derive({})`", name)) - } - } - - match *vdata { - VariantData::Struct(..) => { - let fields = all_fields.iter() - .map(|field| { - let ident = match field.name { - Some(i) => i, - None => { - cx.span_bug(trait_span, - &format!("unnamed field in normal struct in \ - `derive({})`", - name)) - } - }; - let call = subcall(cx, field); - cx.field_imm(field.span, ident, call) - }) - .collect::>(); - - cx.expr_struct(trait_span, ctor_path, fields) - } - VariantData::Tuple(..) => { - let subcalls = all_fields.iter().map(|f| subcall(cx, f)).collect(); - let path = cx.expr_path(ctor_path); - cx.expr_call(trait_span, path, subcalls) - } - VariantData::Unit(..) => cx.expr_path(ctor_path), - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/eq.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/eq.rs deleted file mode 100644 index 1d981e0..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/eq.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{self, Expr, MetaItem, GenericArg}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::{sym, Symbol}; -use syntax_pos::Span; - -pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - let inline = cx.meta_word(span, sym::inline); - let hidden = cx.meta_list_item_word(span, sym::hidden); - let doc = cx.meta_list(span, sym::doc, vec![hidden]); - let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)]; - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, cmp::Eq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: true, - methods: vec![MethodDef { - name: "assert_receiver_is_total_eq", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![], - ret_ty: nil_ty(), - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_total_eq_assert(a, b, c) - })), - }], - associated_types: Vec::new(), - }; - trait_def.expand_ext(cx, mitem, item, push, true) -} - -fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>) - -> P { - fn assert_ty_bounds(cx: &mut ExtCtxt<'_>, stmts: &mut Vec, - ty: P, span: Span, helper_name: &str) { - // Generate statement `let _: helper_name;`, - // set the expn ID so we can use the unstable struct. - let span = span.with_ctxt(cx.backtrace()); - let assert_path = cx.path_all(span, true, - cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]), - vec![GenericArg::Type(ty)], vec![]); - stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); - } - fn process_variant(cx: &mut ExtCtxt<'_>, - stmts: &mut Vec, - variant: &ast::VariantData) { - for field in variant.fields() { - // let _: AssertParamIsEq; - assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsEq"); - } - } - - let mut stmts = Vec::new(); - match *substr.fields { - StaticStruct(vdata, ..) => { - process_variant(cx, &mut stmts, vdata); - } - StaticEnum(enum_def, ..) => { - for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); - } - } - _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`") - } - cx.expr_block(cx.block(trait_span, stmts)) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/ord.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/ord.rs deleted file mode 100644 index 844865d..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/ord.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{self, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::sym; -use syntax_pos::Span; - -pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, cmp::Ord), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![MethodDef { - name: "cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], - ret_ty: Literal(path_std!(cx, cmp::Ordering)), - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_cmp(a, b, c) - })), - }], - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - - -pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - self_arg_tags: &[ast::Ident]) - -> P { - let lft = cx.expr_ident(span, self_arg_tags[0]); - let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) -} - -pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - let test_id = cx.ident_of("cmp").gensym(); - let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - - let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); - - // Builds: - // - // match ::std::cmp::Ord::cmp(&self_field1, &other_field1) { - // ::std::cmp::Ordering::Equal => - // match ::std::cmp::Ord::cmp(&self_field2, &other_field2) { - // ::std::cmp::Ordering::Equal => { - // ... - // } - // cmp => cmp - // }, - // cmp => cmp - // } - // - cs_fold(// foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - |cx, span, old, self_f, other_fs| { - // match new { - // ::std::cmp::Ordering::Equal => old, - // cmp => cmp - // } - - let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), - }; - - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; - - cx.expr_call_global(span, cmp_path.clone(), args) - }; - - let eq_arm = cx.arm(span, - vec![cx.pat_path(span, equals_path.clone())], - old); - let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], - cx.expr_ident(span, test_id)); - - cx.expr_match(span, new, vec![eq_arm, neq_arm]) - }, - cx.expr_path(equals_path.clone()), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`") - } else { - ordering_collapsed(cx, span, tag_tuple) - } - }), - cx, - span, - substr) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_eq.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_eq.rs deleted file mode 100644 index 732bb23..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_eq.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::deriving::{path_local, path_std}; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{BinOpKind, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::sym; -use syntax_pos::Span; - -pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - // structures are equal if all fields are equal, and non equal, if - // any fields are not equal or if the enum variants are different - fn cs_op(cx: &mut ExtCtxt<'_>, - span: Span, - substr: &Substructure<'_>, - op: BinOpKind, - combiner: BinOpKind, - base: bool) - -> P - { - let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P, other_fs: &[P]| { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"), - }; - - cx.expr_binary(span, op, self_f, other_f.clone()) - }; - - cs_fold1(true, // use foldl - |cx, span, subexpr, self_f, other_fs| { - let eq = op(cx, span, self_f, other_fs); - cx.expr_binary(span, combiner, subexpr, eq) - }, - |cx, args| { - match args { - Some((span, self_f, other_fs)) => { - // Special-case the base case to generate cleaner code. - op(cx, span, self_f, other_fs) - } - None => cx.expr_bool(span, base), - } - }, - Box::new(|cx, span, _, _| cx.expr_bool(span, !base)), - cx, - span, - substr) - } - - fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - cs_op(cx, span, substr, BinOpKind::Eq, BinOpKind::And, true) - } - fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - cs_op(cx, span, substr, BinOpKind::Ne, BinOpKind::Or, false) - } - - macro_rules! md { - ($name:expr, $f:ident) => { { - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - MethodDef { - name: $name, - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], - ret_ty: Literal(path_local!(bool)), - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - $f(a, b, c) - })) - } - } } - } - - // avoid defining `ne` if we can - // c-like enums, enums without any fields and structs without fields - // can safely define only `eq`. - let mut methods = vec![md!("eq", cs_eq)]; - if !is_type_without_fields(item) { - methods.push(md!("ne", cs_ne)); - } - - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, cmp::PartialEq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods, - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_ord.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_ord.rs deleted file mode 100644 index a30a7d7..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/cmp/partial_ord.rs +++ /dev/null @@ -1,301 +0,0 @@ -pub use OrderingOp::*; - -use crate::deriving::{path_local, pathvec_std, path_std}; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{self, BinOpKind, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::{sym, Symbol}; -use syntax_pos::Span; - -pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - macro_rules! md { - ($name:expr, $op:expr, $equal:expr) => { { - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - MethodDef { - name: $name, - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], - ret_ty: Literal(path_local!(bool)), - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_op($op, $equal, cx, span, substr) - })) - } - } } - } - - let ordering_ty = Literal(path_std!(cx, cmp::Ordering)); - let ret_ty = Literal(Path::new_(pathvec_std!(cx, option::Option), - None, - vec![Box::new(ordering_ty)], - PathKind::Std)); - - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - - let partial_cmp_def = MethodDef { - name: "partial_cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], - ret_ty, - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_partial_cmp(cx, span, substr) - })), - }; - - // avoid defining extra methods if we can - // c-like enums, enums without any fields and structs without fields - // can safely define only `partial_cmp`. - let methods = if is_type_without_fields(item) { - vec![partial_cmp_def] - } else { - vec![partial_cmp_def, - md!("lt", true, false), - md!("le", true, true), - md!("gt", false, false), - md!("ge", false, true)] - }; - - let trait_def = TraitDef { - span, - attributes: vec![], - path: path_std!(cx, cmp::PartialOrd), - additional_bounds: vec![], - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods, - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} - -#[derive(Copy, Clone)] -pub enum OrderingOp { - PartialCmpOp, - LtOp, - LeOp, - GtOp, - GeOp, -} - -pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - op: OrderingOp, - self_arg_tags: &[ast::Ident]) - -> P { - let lft = cx.expr_ident(span, self_arg_tags[0]); - let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - let op_str = match op { - PartialCmpOp => "partial_cmp", - LtOp => "lt", - LeOp => "le", - GtOp => "gt", - GeOp => "ge", - }; - cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) -} - -pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - let test_id = cx.ident_of("cmp").gensym(); - let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let ordering_expr = cx.expr_path(ordering.clone()); - let equals_expr = cx.expr_some(span, ordering_expr); - - let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]); - - // Builds: - // - // match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) { - // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => - // match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) { - // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => { - // ... - // } - // cmp => cmp - // }, - // cmp => cmp - // } - // - cs_fold(// foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - |cx, span, old, self_f, other_fs| { - // match new { - // Some(::std::cmp::Ordering::Equal) => old, - // cmp => cmp - // } - - let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => { - cx.span_bug(span, - "not exactly 2 arguments in `derive(PartialOrd)`") - } - }; - - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; - - cx.expr_call_global(span, partial_cmp_path.clone(), args) - }; - - let eq_arm = cx.arm(span, - vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))], - old); - let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], - cx.expr_ident(span, test_id)); - - cx.expr_match(span, new, vec![eq_arm, neq_arm]) - }, - equals_expr, - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - } else { - some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) - } - }), - cx, - span, - substr) -} - -/// Strict inequality. -fn cs_op(less: bool, - inclusive: bool, - cx: &mut ExtCtxt<'_>, - span: Span, - substr: &Substructure<'_>) -> P { - let ordering_path = |cx: &mut ExtCtxt<'_>, name: &str| { - cx.expr_path(cx.path_global( - span, cx.std_path(&[sym::cmp, sym::Ordering, Symbol::intern(name)]))) - }; - - let par_cmp = |cx: &mut ExtCtxt<'_>, span, self_f: P, other_fs: &[P], default| { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; - - // `PartialOrd::partial_cmp(self.fi, other.fi)` - let cmp_path = cx.expr_path(cx.path_global(span, cx.std_path(&[sym::cmp, - sym::PartialOrd, - sym::partial_cmp]))); - let cmp = cx.expr_call(span, - cmp_path, - vec![cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone())]); - - let default = ordering_path(cx, default); - // `Option::unwrap_or(_, Ordering::Equal)` - let unwrap_path = cx.expr_path(cx.path_global(span, cx.std_path(&[sym::option, - sym::Option, - sym::unwrap_or]))); - cx.expr_call(span, unwrap_path, vec![cmp, default]) - }; - - let fold = cs_fold1(false, // need foldr - |cx, span, subexpr, self_f, other_fs| { - // build up a series of `partial_cmp`s from the inside - // out (hence foldr) to get lexical ordering, i.e., for op == - // `ast::lt` - // - // ``` - // Ordering::then_with( - // Option::unwrap_or( - // PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal) - // ), - // Option::unwrap_or( - // PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater) - // ) - // ) - // == Ordering::Less - // ``` - // - // and for op == - // `ast::le` - // - // ``` - // Ordering::then_with( - // Option::unwrap_or( - // PartialOrd::partial_cmp(self.f1, other.f1), Ordering::Equal) - // ), - // Option::unwrap_or( - // PartialOrd::partial_cmp(self.f2, other.f2), Ordering::Greater) - // ) - // ) - // != Ordering::Greater - // ``` - // - // The optimiser should remove the redundancy. We explicitly - // get use the binops to avoid auto-deref dereferencing too many - // layers of pointers, if the type includes pointers. - - // `Option::unwrap_or(PartialOrd::partial_cmp(self.fi, other.fi), Ordering::Equal)` - let par_cmp = par_cmp(cx, span, self_f, other_fs, "Equal"); - - // `Ordering::then_with(Option::unwrap_or(..), ..)` - let then_with_path = cx.expr_path(cx.path_global(span, - cx.std_path(&[sym::cmp, - sym::Ordering, - sym::then_with]))); - cx.expr_call(span, then_with_path, vec![par_cmp, cx.lambda0(span, subexpr)]) - }, - |cx, args| { - match args { - Some((span, self_f, other_fs)) => { - let opposite = if less { "Greater" } else { "Less" }; - par_cmp(cx, span, self_f, other_fs, opposite) - }, - None => cx.expr_bool(span, inclusive) - } - }, - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - } else { - let op = match (less, inclusive) { - (false, false) => GtOp, - (false, true) => GeOp, - (true, false) => LtOp, - (true, true) => LeOp, - }; - some_ordering_collapsed(cx, span, op, tag_tuple) - } - }), - cx, - span, - substr); - - match *substr.fields { - EnumMatching(.., ref all_fields) | - Struct(.., ref all_fields) if !all_fields.is_empty() => { - let ordering = ordering_path(cx, if less ^ inclusive { "Less" } else { "Greater" }); - let comp_op = if inclusive { BinOpKind::Ne } else { BinOpKind::Eq }; - - cx.expr_binary(span, comp_op, fold, ordering) - } - _ => fold - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/custom.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/custom.rs deleted file mode 100644 index 98465d7..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/custom.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::proc_macro_impl::EXEC_STRATEGY; -use crate::proc_macro_server; - -use errors::FatalError; -use rustc_data_structures::sync::Lrc; -use syntax::ast::{self, ItemKind, Attribute, Mac}; -use syntax::attr::{mark_used, mark_known}; -use syntax::source_map::Span; -use syntax::ext::base::*; -use syntax::parse; -use syntax::parse::token; -use syntax::tokenstream; -use syntax::visit::Visitor; -use syntax_pos::DUMMY_SP; - -struct MarkAttrs<'a>(&'a [ast::Name]); - -impl<'a> Visitor<'a> for MarkAttrs<'a> { - fn visit_attribute(&mut self, attr: &Attribute) { - if let Some(ident) = attr.ident() { - if self.0.contains(&ident.name) { - mark_used(attr); - mark_known(attr); - } - } - } - - fn visit_mac(&mut self, _mac: &Mac) {} -} - -pub struct ProcMacroDerive { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream) -> proc_macro::TokenStream, - >, - pub attrs: Vec, -} - -impl MultiItemModifier for ProcMacroDerive { - fn expand(&self, - ecx: &mut ExtCtxt<'_>, - span: Span, - _meta_item: &ast::MetaItem, - item: Annotatable) - -> Vec { - let item = match item { - Annotatable::Item(item) => item, - Annotatable::ImplItem(_) | - Annotatable::TraitItem(_) | - Annotatable::ForeignItem(_) | - Annotatable::Stmt(_) | - Annotatable::Expr(_) => { - ecx.span_err(span, "proc-macro derives may only be \ - applied to a struct, enum, or union"); - return Vec::new() - } - }; - match item.node { - ItemKind::Struct(..) | - ItemKind::Enum(..) | - ItemKind::Union(..) => {}, - _ => { - ecx.span_err(span, "proc-macro derives may only be \ - applied to a struct, enum, or union"); - return Vec::new() - } - } - - // Mark attributes as known, and used. - MarkAttrs(&self.attrs).visit_item(&item); - - let token = token::Interpolated(Lrc::new(token::NtItem(item))); - let input = tokenstream::TokenTree::token(token, DUMMY_SP).into(); - - let server = proc_macro_server::Rustc::new(ecx); - let stream = match self.client.run(&EXEC_STRATEGY, server, input) { - Ok(stream) => stream, - Err(e) => { - let msg = "proc-macro derive panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); - } - }; - - let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparseable tokens"; - - let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); - let mut items = vec![]; - - loop { - match parser.parse_item() { - Ok(None) => break, - Ok(Some(item)) => { - items.push(Annotatable::Item(item)) - } - Err(mut err) => { - // FIXME: handle this better - err.cancel(); - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); - } - } - } - - - // fail if there have been errors emitted - if ecx.parse_sess.span_diagnostic.err_count() > error_count_before { - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); - } - - items - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/debug.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/debug.rs deleted file mode 100644 index 44ddbb9..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/debug.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use rustc_data_structures::thin_vec::ThinVec; - -use syntax::ast::{self, Ident}; -use syntax::ast::{Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, Span}; - -pub fn expand_deriving_debug(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - // &mut ::std::fmt::Formatter - let fmtr = Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))), - Borrowed(None, ast::Mutability::Mutable)); - - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, fmt::Debug), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![MethodDef { - name: "fmt", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(fmtr, "f")], - ret_ty: Literal(path_std!(cx, fmt::Result)), - attributes: Vec::new(), - is_unsafe: false, - unify_fieldless_variants: false, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - show_substructure(a, b, c) - })), - }], - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} - -/// We use the debug builders to do the heavy lifting here -fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P { - // build fmt.debug_struct().field(, &)....build() - // or fmt.debug_tuple().field(&)....build() - // based on the "shape". - let (ident, vdata, fields) = match substr.fields { - Struct(vdata, fields) => (substr.type_ident, *vdata, fields), - EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields), - EnumNonMatchingCollapsed(..) | - StaticStruct(..) | - StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), - }; - - // We want to make sure we have the ctxt set so that we can use unstable methods - let span = span.with_ctxt(cx.backtrace()); - let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); - let builder = Ident::from_str("debug_trait_builder").gensym(); - let builder_expr = cx.expr_ident(span, builder.clone()); - - let fmt = substr.nonself_args[0].clone(); - - let mut stmts = vec![]; - match vdata { - ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { - // tuple struct/"normal" variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), - vec![field]); - - // Use `let _ = expr;` to avoid triggering the - // unused_results lint. - stmts.push(stmt_let_undescore(cx, span, expr)); - } - } - ast::VariantData::Struct(..) => { - // normal struct/struct variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - let name = cx.expr_lit(field.span, - ast::LitKind::Str(field.name.unwrap().name, - ast::StrStyle::Cooked)); - - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), - vec![name, field]); - stmts.push(stmt_let_undescore(cx, span, expr)); - } - } - } - - let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]); - - stmts.push(cx.stmt_expr(expr)); - let block = cx.block(span, stmts); - cx.expr_block(block) -} - -fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> ast::Stmt { - let local = P(ast::Local { - pat: cx.pat_wild(sp), - ty: None, - init: Some(expr), - id: ast::DUMMY_NODE_ID, - span: sp, - attrs: ThinVec::new(), - }); - ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Local(local), - span: sp, - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/decodable.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/decodable.rs deleted file mode 100644 index 8009f42..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/decodable.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more. - -use crate::deriving::{self, pathvec_std}; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast; -use syntax::ast::{Expr, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::Symbol; -use syntax_pos::Span; - -pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize") -} - -pub fn expand_deriving_decodable(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") -} - -fn expand_deriving_decodable_imp(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - krate: &'static str) { - let typaram = &*deriving::hygienic_type_parameter(item, "__D"); - - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![MethodDef { - name: "decode", - generics: LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec![(typaram, - vec![Path::new_(vec![krate, "Decoder"], - None, - vec![], - PathKind::Global)])], - }, - explicit_self: None, - args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable)), "d")], - ret_ty: - Literal(Path::new_(pathvec_std!(cx, result::Result), - None, - vec![Box::new(Self_), Box::new(Literal(Path::new_( - vec![typaram, "Error"], None, vec![], PathKind::Local - )))], - PathKind::Std)), - attributes: Vec::new(), - is_unsafe: false, - unify_fieldless_variants: false, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - decodable_substructure(a, b, c, krate) - })), - }], - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - -fn decodable_substructure(cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, - krate: &str) - -> P { - let decoder = substr.nonself_args[0].clone(); - let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")]; - let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse)); - // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_d"); - let blkdecoder = cx.expr_ident(trait_span, blkarg); - - return match *substr.fields { - StaticStruct(_, ref summary) => { - let nfields = match *summary { - Unnamed(ref fields, _) => fields.len(), - Named(ref fields) => fields.len(), - }; - let read_struct_field = cx.ident_of("read_struct_field"); - - let path = cx.path_ident(trait_span, substr.type_ident); - let result = - decode_static_fields(cx, trait_span, path, summary, |cx, span, name, field| { - cx.expr_try(span, - cx.expr_method_call(span, - blkdecoder.clone(), - read_struct_field, - vec![cx.expr_str(span, name), - cx.expr_usize(span, field), - exprdecode.clone()])) - }); - let result = cx.expr_ok(trait_span, result); - cx.expr_method_call(trait_span, - decoder, - cx.ident_of("read_struct"), - vec![cx.expr_str(trait_span, substr.type_ident.name), - cx.expr_usize(trait_span, nfields), - cx.lambda1(trait_span, result, blkarg)]) - } - StaticEnum(_, ref fields) => { - let variant = cx.ident_of("i"); - - let mut arms = Vec::with_capacity(fields.len() + 1); - let mut variants = Vec::with_capacity(fields.len()); - let rvariant_arg = cx.ident_of("read_enum_variant_arg"); - - for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { - variants.push(cx.expr_str(v_span, ident.name)); - - let path = cx.path(trait_span, vec![substr.type_ident, ident]); - let decoded = decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| { - let idx = cx.expr_usize(span, field); - cx.expr_try(span, - cx.expr_method_call(span, - blkdecoder.clone(), - rvariant_arg, - vec![idx, exprdecode.clone()])) - }); - - arms.push(cx.arm(v_span, - vec![cx.pat_lit(v_span, cx.expr_usize(v_span, i))], - decoded)); - } - - arms.push(cx.arm_unreachable(trait_span)); - - let result = - cx.expr_ok(trait_span, - cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms)); - let lambda = cx.lambda(trait_span, vec![blkarg, variant], result); - let variant_vec = cx.expr_vec(trait_span, variants); - let variant_vec = cx.expr_addr_of(trait_span, variant_vec); - let result = cx.expr_method_call(trait_span, - blkdecoder, - cx.ident_of("read_enum_variant"), - vec![variant_vec, lambda]); - cx.expr_method_call(trait_span, - decoder, - cx.ident_of("read_enum"), - vec![cx.expr_str(trait_span, substr.type_ident.name), - cx.lambda1(trait_span, result, blkarg)]) - } - _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"), - }; -} - -/// Creates a decoder for a single enum variant/struct: -/// - `outer_pat_path` is the path to this enum variant/struct -/// - `getarg` should retrieve the `usize`-th field with name `@str`. -fn decode_static_fields(cx: &mut ExtCtxt<'_>, - trait_span: Span, - outer_pat_path: ast::Path, - fields: &StaticFields, - mut getarg: F) - -> P - where F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P -{ - match *fields { - Unnamed(ref fields, is_tuple) => { - let path_expr = cx.expr_path(outer_pat_path); - if !is_tuple { - path_expr - } else { - let fields = fields.iter() - .enumerate() - .map(|(i, &span)| { - getarg(cx, span, Symbol::intern(&format!("_field{}", i)), i) - }) - .collect(); - - cx.expr_call(trait_span, path_expr, fields) - } - } - Named(ref fields) => { - // use the field's span to get nicer error messages. - let fields = fields.iter() - .enumerate() - .map(|(i, &(ident, span))| { - let arg = getarg(cx, span, ident.name, i); - cx.field_imm(span, ident, arg) - }) - .collect(); - cx.expr_struct(trait_span, outer_pat_path, fields) - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/default.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/default.rs deleted file mode 100644 index fd8e87e..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/default.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::deriving::path_std; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{Expr, MetaItem}; -use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::{kw, sym}; -use syntax::span_err; -use syntax_pos::Span; - -pub fn expand_deriving_default(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(span, inline)]; - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: path_std!(cx, default::Default), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![MethodDef { - name: "default", - generics: LifetimeBounds::empty(), - explicit_self: None, - args: Vec::new(), - ret_ty: Self_, - attributes: attrs, - is_unsafe: false, - unify_fieldless_variants: false, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - default_substructure(a, b, c) - })), - }], - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} - -fn default_substructure(cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>) - -> P { - // Note that `kw::Default` is "default" and `sym::Default` is "Default"! - let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]); - let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); - - return match *substr.fields { - StaticStruct(_, ref summary) => { - match *summary { - Unnamed(ref fields, is_tuple) => { - if !is_tuple { - cx.expr_ident(trait_span, substr.type_ident) - } else { - let exprs = fields.iter().map(|sp| default_call(*sp)).collect(); - cx.expr_call_ident(trait_span, substr.type_ident, exprs) - } - } - Named(ref fields) => { - let default_fields = fields.iter() - .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span))) - .collect(); - cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) - } - } - } - StaticEnum(..) => { - span_err!(cx, trait_span, E0665, - "`Default` cannot be derived for enums, only structs"); - // let compilation continue - DummyResult::raw_expr(trait_span, true) - } - _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"), - }; -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/encodable.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/encodable.rs deleted file mode 100644 index cd89a42..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/encodable.rs +++ /dev/null @@ -1,277 +0,0 @@ -//! The compiler code necessary to implement the `#[derive(Encodable)]` -//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that -//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`. -//! -//! For example, a type like: -//! -//! ``` -//! #[derive(Encodable, Decodable)] -//! struct Node { id: usize } -//! ``` -//! -//! would generate two implementations like: -//! -//! ``` -//! # struct Node { id: usize } -//! impl, E> Encodable for Node { -//! fn encode(&self, s: &mut S) -> Result<(), E> { -//! s.emit_struct("Node", 1, |this| { -//! this.emit_struct_field("id", 0, |this| { -//! Encodable::encode(&self.id, this) -//! /* this.emit_usize(self.id) can also be used */ -//! }) -//! }) -//! } -//! } -//! -//! impl, E> Decodable for Node { -//! fn decode(d: &mut D) -> Result { -//! d.read_struct("Node", 1, |this| { -//! match this.read_struct_field("id", 0, |this| Decodable::decode(this)) { -//! Ok(id) => Ok(Node { id: id }), -//! Err(e) => Err(e), -//! } -//! }) -//! } -//! } -//! ``` -//! -//! Other interesting scenarios are when the item has type parameters or -//! references other non-built-in types. A type definition like: -//! -//! ``` -//! # #[derive(Encodable, Decodable)] struct Span; -//! #[derive(Encodable, Decodable)] -//! struct Spanned { node: T, span: Span } -//! ``` -//! -//! would yield functions like: -//! -//! ``` -//! # #[derive(Encodable, Decodable)] struct Span; -//! # struct Spanned { node: T, span: Span } -//! impl< -//! S: Encoder, -//! E, -//! T: Encodable -//! > Encodable for Spanned { -//! fn encode(&self, s: &mut S) -> Result<(), E> { -//! s.emit_struct("Spanned", 2, |this| { -//! this.emit_struct_field("node", 0, |this| self.node.encode(this)) -//! .unwrap(); -//! this.emit_struct_field("span", 1, |this| self.span.encode(this)) -//! }) -//! } -//! } -//! -//! impl< -//! D: Decoder, -//! E, -//! T: Decodable -//! > Decodable for Spanned { -//! fn decode(d: &mut D) -> Result, E> { -//! d.read_struct("Spanned", 2, |this| { -//! Ok(Spanned { -//! node: this.read_struct_field("node", 0, |this| Decodable::decode(this)) -//! .unwrap(), -//! span: this.read_struct_field("span", 1, |this| Decodable::decode(this)) -//! .unwrap(), -//! }) -//! }) -//! } -//! } -//! ``` - -use crate::deriving::{self, pathvec_std}; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::Symbol; -use syntax_pos::Span; - -pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") -} - -pub fn expand_deriving_encodable(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") -} - -fn expand_deriving_encodable_imp(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - krate: &'static str) { - let typaram = &*deriving::hygienic_type_parameter(item, "__S"); - - let trait_def = TraitDef { - span, - attributes: Vec::new(), - path: Path::new_(vec![krate, "Encodable"], None, vec![], PathKind::Global), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![ - MethodDef { - name: "encode", - generics: LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec![ - (typaram, - vec![Path::new_(vec![krate, "Encoder"], None, vec![], PathKind::Global)]) - ], - }, - explicit_self: borrowed_explicit_self(), - args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))), - Borrowed(None, Mutability::Mutable)), "s")], - ret_ty: Literal(Path::new_( - pathvec_std!(cx, result::Result), - None, - vec![Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_( - vec![typaram, "Error"], None, vec![], PathKind::Local - )))], - PathKind::Std - )), - attributes: Vec::new(), - is_unsafe: false, - unify_fieldless_variants: false, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - encodable_substructure(a, b, c, krate) - })), - } - ], - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - -fn encodable_substructure(cx: &mut ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, - krate: &'static str) - -> P { - let encoder = substr.nonself_args[0].clone(); - // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_e"); - let blkencoder = cx.expr_ident(trait_span, blkarg); - let fn_path = cx.expr_path(cx.path_global(trait_span, - vec![cx.ident_of(krate), - cx.ident_of("Encodable"), - cx.ident_of("encode")])); - - return match *substr.fields { - Struct(_, ref fields) => { - let emit_struct_field = cx.ident_of("emit_struct_field"); - let mut stmts = Vec::new(); - for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { - let name = match name { - Some(id) => id.name, - None => Symbol::intern(&format!("_field{}", i)), - }; - let self_ref = cx.expr_addr_of(span, self_.clone()); - let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]); - let lambda = cx.lambda1(span, enc, blkarg); - let call = cx.expr_method_call(span, - blkencoder.clone(), - emit_struct_field, - vec![cx.expr_str(span, name), - cx.expr_usize(span, i), - lambda]); - - // last call doesn't need a try! - let last = fields.len() - 1; - let call = if i != last { - cx.expr_try(span, call) - } else { - cx.expr(span, ExprKind::Ret(Some(call))) - }; - - let stmt = cx.stmt_expr(call); - stmts.push(stmt); - } - - // unit structs have no fields and need to return Ok() - let blk = if stmts.is_empty() { - let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![])); - cx.lambda1(trait_span, ok, blkarg) - } else { - cx.lambda_stmts_1(trait_span, stmts, blkarg) - }; - - cx.expr_method_call(trait_span, - encoder, - cx.ident_of("emit_struct"), - vec![cx.expr_str(trait_span, substr.type_ident.name), - cx.expr_usize(trait_span, fields.len()), - blk]) - } - - EnumMatching(idx, _, variant, ref fields) => { - // We're not generating an AST that the borrow checker is expecting, - // so we need to generate a unique local variable to take the - // mutable loan out on, otherwise we get conflicts which don't - // actually exist. - let me = cx.stmt_let(trait_span, false, blkarg, encoder); - let encoder = cx.expr_ident(trait_span, blkarg); - let emit_variant_arg = cx.ident_of("emit_enum_variant_arg"); - let mut stmts = Vec::new(); - if !fields.is_empty() { - let last = fields.len() - 1; - for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() { - let self_ref = cx.expr_addr_of(span, self_.clone()); - let enc = - cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]); - let lambda = cx.lambda1(span, enc, blkarg); - let call = cx.expr_method_call(span, - blkencoder.clone(), - emit_variant_arg, - vec![cx.expr_usize(span, i), lambda]); - let call = if i != last { - cx.expr_try(span, call) - } else { - cx.expr(span, ExprKind::Ret(Some(call))) - }; - stmts.push(cx.stmt_expr(call)); - } - } else { - let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![])); - let ret_ok = cx.expr(trait_span, ExprKind::Ret(Some(ok))); - stmts.push(cx.stmt_expr(ret_ok)); - } - - let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); - let name = cx.expr_str(trait_span, variant.node.ident.name); - let call = cx.expr_method_call(trait_span, - blkencoder, - cx.ident_of("emit_enum_variant"), - vec![name, - cx.expr_usize(trait_span, idx), - cx.expr_usize(trait_span, fields.len()), - blk]); - let blk = cx.lambda1(trait_span, call, blkarg); - let ret = cx.expr_method_call(trait_span, - encoder, - cx.ident_of("emit_enum"), - vec![cx.expr_str(trait_span ,substr.type_ident.name), - blk]); - cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) - } - - _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"), - }; -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/mod.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/mod.rs deleted file mode 100644 index 12482f7..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/mod.rs +++ /dev/null @@ -1,1831 +0,0 @@ -//! Some code that abstracts away much of the boilerplate of writing -//! `derive` instances for traits. Among other things it manages getting -//! access to the fields of the 4 different sorts of structs and enum -//! variants, as well as creating the method and impl ast instances. -//! -//! Supported features (fairly exhaustive): -//! -//! - Methods taking any number of parameters of any type, and returning -//! any type, other than vectors, bottom and closures. -//! - Generating `impl`s for types with type parameters and lifetimes -//! (e.g., `Option`), the parameters are automatically given the -//! current trait as a bound. (This includes separate type parameters -//! and lifetimes for methods.) -//! - Additional bounds on the type parameters (`TraitDef.additional_bounds`) -//! -//! The most important thing for implementors is the `Substructure` and -//! `SubstructureFields` objects. The latter groups 5 possibilities of the -//! arguments: -//! -//! - `Struct`, when `Self` is a struct (including tuple structs, e.g -//! `struct T(i32, char)`). -//! - `EnumMatching`, when `Self` is an enum and all the arguments are the -//! same variant of the enum (e.g., `Some(1)`, `Some(3)` and `Some(4)`) -//! - `EnumNonMatchingCollapsed` when `Self` is an enum and the arguments -//! are not the same variant (e.g., `None`, `Some(1)` and `None`). -//! - `StaticEnum` and `StaticStruct` for static methods, where the type -//! being derived upon is either an enum or struct respectively. (Any -//! argument with type Self is just grouped among the non-self -//! arguments.) -//! -//! In the first two cases, the values from the corresponding fields in -//! all the arguments are grouped together. For `EnumNonMatchingCollapsed` -//! this isn't possible (different variants have different fields), so the -//! fields are inaccessible. (Previous versions of the deriving infrastructure -//! had a way to expand into code that could access them, at the cost of -//! generating exponential amounts of code; see issue #15375). There are no -//! fields with values in the static cases, so these are treated entirely -//! differently. -//! -//! The non-static cases have `Option` in several places associated -//! with field `expr`s. This represents the name of the field it is -//! associated with. It is only not `None` when the associated field has -//! an identifier in the source code. For example, the `x`s in the -//! following snippet -//! -//! ```rust -//! # #![allow(dead_code)] -//! struct A { x : i32 } -//! -//! struct B(i32); -//! -//! enum C { -//! C0(i32), -//! C1 { x: i32 } -//! } -//! ``` -//! -//! The `i32`s in `B` and `C0` don't have an identifier, so the -//! `Option`s would be `None` for them. -//! -//! In the static cases, the structure is summarized, either into the just -//! spans of the fields or a list of spans and the field idents (for tuple -//! structs and record structs, respectively), or a list of these, for -//! enums (one for each variant). For empty struct and empty enum -//! variants, it is represented as a count of 0. -//! -//! # "`cs`" functions -//! -//! The `cs_...` functions ("combine substructure) are designed to -//! make life easier by providing some pre-made recipes for common -//! threads; mostly calling the function being derived on all the -//! arguments and then combining them back together in some way (or -//! letting the user chose that). They are not meant to be the only -//! way to handle the structures that this code creates. -//! -//! # Examples -//! -//! The following simplified `PartialEq` is used for in-code examples: -//! -//! ```rust -//! trait PartialEq { -//! fn eq(&self, other: &Self) -> bool; -//! } -//! impl PartialEq for i32 { -//! fn eq(&self, other: &i32) -> bool { -//! *self == *other -//! } -//! } -//! ``` -//! -//! Some examples of the values of `SubstructureFields` follow, using the -//! above `PartialEq`, `A`, `B` and `C`. -//! -//! ## Structs -//! -//! When generating the `expr` for the `A` impl, the `SubstructureFields` is -//! -//! ```{.text} -//! Struct(vec![FieldInfo { -//! span: -//! name: Some(), -//! self_: , -//! other: vec![, -//! name: None, -//! self_: -//! other: vec![] -//! }]) -//! ``` -//! -//! ## Enums -//! -//! When generating the `expr` for a call with `self == C0(a)` and `other -//! == C0(b)`, the SubstructureFields is -//! -//! ```{.text} -//! EnumMatching(0, , -//! vec![FieldInfo { -//! span: -//! name: None, -//! self_: , -//! other: vec![] -//! }]) -//! ``` -//! -//! For `C1 {x}` and `C1 {x}`, -//! -//! ```{.text} -//! EnumMatching(1, , -//! vec![FieldInfo { -//! span: -//! name: Some(), -//! self_: , -//! other: vec![] -//! }]) -//! ``` -//! -//! For `C0(a)` and `C1 {x}` , -//! -//! ```{.text} -//! EnumNonMatchingCollapsed( -//! vec![, ], -//! &[, ], -//! &[, ]) -//! ``` -//! -//! It is the same for when the arguments are flipped to `C1 {x}` and -//! `C0(a)`; the only difference is what the values of the identifiers -//! and will -//! be in the generated code. -//! -//! `EnumNonMatchingCollapsed` deliberately provides far less information -//! than is generally available for a given pair of variants; see #15375 -//! for discussion. -//! -//! ## Static -//! -//! A static method on the types above would result in, -//! -//! ```{.text} -//! StaticStruct(, Named(vec![(, )])) -//! -//! StaticStruct(, Unnamed(vec![])) -//! -//! StaticEnum(, -//! vec![(, , Unnamed(vec![])), -//! (, , Named(vec![(, )]))]) -//! ``` - -pub use StaticFields::*; -pub use SubstructureFields::*; - -use std::cell::RefCell; -use std::iter; -use std::vec; - -use rustc_data_structures::thin_vec::ThinVec; -use rustc_target::spec::abi::Abi; -use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; -use syntax::ast::{VariantData, GenericParamKind, GenericArg}; -use syntax::attr; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::source_map::{self, respan}; -use syntax::util::map_in_place::MapInPlace; -use syntax::ptr::P; -use syntax::symbol::{Symbol, kw, sym}; -use syntax::parse::ParseSess; -use syntax_pos::{DUMMY_SP, Span}; - -use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; - -use crate::deriving; - -pub mod ty; - -pub struct TraitDef<'a> { - /// The span for the current #[derive(Foo)] header. - pub span: Span, - - pub attributes: Vec, - - /// Path of the trait, including any type parameters - pub path: Path<'a>, - - /// Additional bounds required of any type parameters of the type, - /// other than the current trait - pub additional_bounds: Vec>, - - /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` - pub generics: LifetimeBounds<'a>, - - /// Is it an `unsafe` trait? - pub is_unsafe: bool, - - /// Can this trait be derived for unions? - pub supports_unions: bool, - - pub methods: Vec>, - - pub associated_types: Vec<(ast::Ident, Ty<'a>)>, -} - - -pub struct MethodDef<'a> { - /// name of the method - pub name: &'a str, - /// List of generics, e.g., `R: rand::Rng` - pub generics: LifetimeBounds<'a>, - - /// Whether there is a self argument (outer Option) i.e., whether - /// this is a static function, and whether it is a pointer (inner - /// Option) - pub explicit_self: Option>>, - - /// Arguments other than the self argument - pub args: Vec<(Ty<'a>, &'a str)>, - - /// Returns type - pub ret_ty: Ty<'a>, - - pub attributes: Vec, - - // Is it an `unsafe fn`? - pub is_unsafe: bool, - - /// Can we combine fieldless variants for enums into a single match arm? - pub unify_fieldless_variants: bool, - - pub combine_substructure: RefCell>, -} - -/// All the data about the data structure/method being derived upon. -pub struct Substructure<'a> { - /// ident of self - pub type_ident: Ident, - /// ident of the method - pub method_ident: Ident, - /// dereferenced access to any `Self_` or `Ptr(Self_, _)` arguments - pub self_args: &'a [P], - /// verbatim access to any other arguments - pub nonself_args: &'a [P], - pub fields: &'a SubstructureFields<'a>, -} - -/// Summary of the relevant parts of a struct/enum field. -pub struct FieldInfo<'a> { - pub span: Span, - /// None for tuple structs/normal enum variants, Some for normal - /// structs/struct enum variants. - pub name: Option, - /// The expression corresponding to this field of `self` - /// (specifically, a reference to it). - pub self_: P, - /// The expressions corresponding to references to this field in - /// the other `Self` arguments. - pub other: Vec>, - /// The attributes on the field - pub attrs: &'a [ast::Attribute], -} - -/// Fields for a static method -pub enum StaticFields { - /// Tuple and unit structs/enum variants like this. - Unnamed(Vec, bool /*is tuple*/), - /// Normal structs/struct variants. - Named(Vec<(Ident, Span)>), -} - -/// A summary of the possible sets of fields. -pub enum SubstructureFields<'a> { - Struct(&'a ast::VariantData, Vec>), - /// Matching variants of the enum: variant index, variant count, ast::Variant, - /// fields: the field name is only non-`None` in the case of a struct - /// variant. - EnumMatching(usize, usize, &'a ast::Variant, Vec>), - - /// Non-matching variants of the enum, but with all state hidden from - /// the consequent code. The first component holds `Ident`s for all of - /// the `Self` arguments; the second component is a slice of all of the - /// variants for the enum itself, and the third component is a list of - /// `Ident`s bound to the variant index values for each of the actual - /// input `Self` arguments. - EnumNonMatchingCollapsed(Vec, &'a [ast::Variant], &'a [Ident]), - - /// A static method where `Self` is a struct. - StaticStruct(&'a ast::VariantData, StaticFields), - /// A static method where `Self` is an enum. - StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)>), -} - - - -/// Combine the values of all the fields together. The last argument is -/// all the fields of all the structures. -pub type CombineSubstructureFunc<'a> = - Box, Span, &Substructure<'_>) -> P + 'a>; - -/// Deal with non-matching enum variants. The tuple is a list of -/// identifiers (one for each `Self` argument, which could be any of the -/// variants since they have been collapsed together) and the identifiers -/// holding the variant index value for each of the `Self` arguments. The -/// last argument is all the non-`Self` args of the method being derived. -pub type EnumNonMatchCollapsedFunc<'a> = - Box, Span, (&[Ident], &[Ident]), &[P]) -> P + 'a>; - -pub fn combine_substructure(f: CombineSubstructureFunc<'_>) - -> RefCell> { - RefCell::new(f) -} - -/// This method helps to extract all the type parameters referenced from a -/// type. For a type parameter ``, it looks for either a `TyPath` that -/// is not global and starts with `T`, or a `TyQPath`. -fn find_type_parameters( - ty: &ast::Ty, - ty_param_names: &[ast::Name], - span: Span, - cx: &ExtCtxt<'_>, -) -> Vec> { - use syntax::visit; - - struct Visitor<'a, 'b> { - cx: &'a ExtCtxt<'b>, - span: Span, - ty_param_names: &'a [ast::Name], - types: Vec>, - } - - impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { - fn visit_ty(&mut self, ty: &'a ast::Ty) { - if let ast::TyKind::Path(_, ref path) = ty.node { - if let Some(segment) = path.segments.first() { - if self.ty_param_names.contains(&segment.ident.name) { - self.types.push(P(ty.clone())); - } - } - } - - visit::walk_ty(self, ty) - } - - fn visit_mac(&mut self, mac: &ast::Mac) { - let span = mac.span.with_ctxt(self.span.ctxt()); - self.cx.span_err(span, "`derive` cannot be used on items with type macros"); - } - } - - let mut visitor = Visitor { - ty_param_names, - types: Vec::new(), - span, - cx, - }; - - visit::Visitor::visit_ty(&mut visitor, ty); - - visitor.types -} - -impl<'a> TraitDef<'a> { - pub fn expand(self, - cx: &mut ExtCtxt<'_>, - mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable)) { - self.expand_ext(cx, mitem, item, push, false); - } - - pub fn expand_ext(self, - cx: &mut ExtCtxt<'_>, - mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable), - from_scratch: bool) { - match *item { - Annotatable::Item(ref item) => { - let is_packed = item.attrs.iter().any(|attr| { - for r in attr::find_repr_attrs(&cx.parse_sess, attr) { - if let attr::ReprPacked(_) = r { - return true; - } - } - false - }); - let has_no_type_params = match item.node { - ast::ItemKind::Struct(_, ref generics) | - ast::ItemKind::Enum(_, ref generics) | - ast::ItemKind::Union(_, ref generics) => { - !generics.params.iter().any(|param| match param.kind { - ast::GenericParamKind::Type { .. } => true, - _ => false, - }) - } - _ => { - // Non-ADT derive is an error, but it should have been - // set earlier; see - // libsyntax/ext/expand.rs:MacroExpander::expand() - return; - } - }; - let is_always_copy = - attr::contains_name(&item.attrs, sym::rustc_copy_clone_marker) && - has_no_type_params; - let use_temporaries = is_packed && is_always_copy; - - let newitem = match item.node { - ast::ItemKind::Struct(ref struct_def, ref generics) => { - self.expand_struct_def(cx, &struct_def, item.ident, generics, from_scratch, - use_temporaries) - } - ast::ItemKind::Enum(ref enum_def, ref generics) => { - // We ignore `use_temporaries` here, because - // `repr(packed)` enums cause an error later on. - // - // This can only cause further compilation errors - // downstream in blatantly illegal code, so it - // is fine. - self.expand_enum_def(cx, enum_def, &item.attrs, - item.ident, generics, from_scratch) - } - ast::ItemKind::Union(ref struct_def, ref generics) => { - if self.supports_unions { - self.expand_struct_def(cx, &struct_def, item.ident, - generics, from_scratch, - use_temporaries) - } else { - cx.span_err(mitem.span, - "this trait cannot be derived for unions"); - return; - } - } - _ => unreachable!(), - }; - // Keep the lint attributes of the previous item to control how the - // generated implementations are linted - let mut attrs = newitem.attrs.clone(); - attrs.extend(item.attrs - .iter() - .filter(|a| { - [sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable] - .contains(&a.name_or_empty()) - }) - .cloned()); - push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) - } - _ => { - // Non-Item derive is an error, but it should have been - // set earlier; see - // libsyntax/ext/expand.rs:MacroExpander::expand() - return; - } - } - } - - /// Given that we are deriving a trait `DerivedTrait` for a type like: - /// - /// ```ignore (only-for-syntax-highlight) - /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { - /// a: A, - /// b: B::Item, - /// b1: ::Item, - /// c1: ::Item, - /// c2: Option<::Item>, - /// ... - /// } - /// ``` - /// - /// create an impl like: - /// - /// ```ignore (only-for-syntax-highlight) - /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where - /// C: WhereTrait, - /// A: DerivedTrait + B1 + ... + BN, - /// B: DerivedTrait + B1 + ... + BN, - /// C: DerivedTrait + B1 + ... + BN, - /// B::Item: DerivedTrait + B1 + ... + BN, - /// ::Item: DerivedTrait + B1 + ... + BN, - /// ... - /// { - /// ... - /// } - /// ``` - /// - /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and - /// therefore does not get bound by the derived trait. - fn create_derived_impl(&self, - cx: &mut ExtCtxt<'_>, - type_ident: Ident, - generics: &Generics, - field_tys: Vec>, - methods: Vec) - -> P { - let trait_path = self.path.to_path(cx, self.span, type_ident, generics); - - // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem` - let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { - ast::ImplItem { - id: ast::DUMMY_NODE_ID, - span: self.span, - ident, - vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, - attrs: Vec::new(), - generics: Generics::default(), - node: ast::ImplItemKind::Type(type_def.to_ty(cx, self.span, type_ident, generics)), - tokens: None, - } - }); - - let Generics { mut params, mut where_clause, span } = self.generics - .to_generics(cx, self.span, type_ident, generics); - - // Create the generic parameters - params.extend(generics.params.iter().map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => param.clone(), - GenericParamKind::Type { .. } => { - // I don't think this can be moved out of the loop, since - // a GenericBound requires an ast id - let bounds: Vec<_> = - // extra restrictions on the generics parameters to the - // type being derived upon - self.additional_bounds.iter().map(|p| { - cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) - }).chain( - // require the current trait - iter::once(cx.trait_bound(trait_path.clone())) - ).chain( - // also add in any bounds from the declaration - param.bounds.iter().cloned() - ).collect(); - - cx.typaram(self.span, param.ident, vec![], bounds, None) - } - GenericParamKind::Const { .. } => param.clone(), - })); - - // and similarly for where clauses - where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { - match *clause { - ast::WherePredicate::BoundPredicate(ref wb) => { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: self.span, - bound_generic_params: wb.bound_generic_params.clone(), - bounded_ty: wb.bounded_ty.clone(), - bounds: wb.bounds.iter().cloned().collect(), - }) - } - ast::WherePredicate::RegionPredicate(ref rb) => { - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - span: self.span, - lifetime: rb.lifetime, - bounds: rb.bounds.iter().cloned().collect(), - }) - } - ast::WherePredicate::EqPredicate(ref we) => { - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - id: ast::DUMMY_NODE_ID, - span: self.span, - lhs_ty: we.lhs_ty.clone(), - rhs_ty: we.rhs_ty.clone(), - }) - } - } - })); - - { - // Extra scope required here so ty_params goes out of scope before params is moved - - let mut ty_params = params.iter() - .filter_map(|param| match param.kind { - ast::GenericParamKind::Type { .. } => Some(param), - _ => None, - }) - .peekable(); - - if ty_params.peek().is_some() { - let ty_param_names: Vec = ty_params - .map(|ty_param| ty_param.ident.name) - .collect(); - - for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); - - for ty in tys { - // if we have already handled this type, skip it - if let ast::TyKind::Path(_, ref p) = ty.node { - if p.segments.len() == 1 && - ty_param_names.contains(&p.segments[0].ident.name) { - continue; - }; - } - let mut bounds: Vec<_> = self.additional_bounds - .iter() - .map(|p| { - cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) - }) - .collect(); - - // require the current trait - bounds.push(cx.trait_bound(trait_path.clone())); - - let predicate = ast::WhereBoundPredicate { - span: self.span, - bound_generic_params: Vec::new(), - bounded_ty: ty, - bounds, - }; - - let predicate = ast::WherePredicate::BoundPredicate(predicate); - where_clause.predicates.push(predicate); - } - } - } - } - - let trait_generics = Generics { - params, - where_clause, - span, - }; - - // Create the reference to the trait. - let trait_ref = cx.trait_ref(trait_path); - - let self_params: Vec<_> = generics.params.iter().map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) - } - GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(self.span, param.ident)) - } - GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(self.span, param.ident)) - } - }).collect(); - - // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]); - let self_type = cx.ty_path(path); - - let attr = cx.attribute(self.span, - cx.meta_word(self.span, sym::automatically_derived)); - // Just mark it now since we know that it'll end up used downstream - attr::mark_used(&attr); - let opt_trait_ref = Some(trait_ref); - let unused_qual = { - let word = cx.meta_list_item_word(self.span, Symbol::intern("unused_qualifications")); - cx.attribute(self.span, cx.meta_list(self.span, sym::allow, vec![word])) - }; - - let mut a = vec![attr, unused_qual]; - a.extend(self.attributes.iter().cloned()); - - let unsafety = if self.is_unsafe { - ast::Unsafety::Unsafe - } else { - ast::Unsafety::Normal - }; - - cx.item(self.span, - Ident::invalid(), - a, - ast::ItemKind::Impl(unsafety, - ast::ImplPolarity::Positive, - ast::Defaultness::Final, - trait_generics, - opt_trait_ref, - self_type, - methods.into_iter().chain(associated_types).collect())) - } - - fn expand_struct_def(&self, - cx: &mut ExtCtxt<'_>, - struct_def: &'a VariantData, - type_ident: Ident, - generics: &Generics, - from_scratch: bool, - use_temporaries: bool) - -> P { - let field_tys: Vec> = struct_def.fields() - .iter() - .map(|field| field.ty.clone()) - .collect(); - - let methods = self.methods - .iter() - .map(|method_def| { - let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(cx, self, type_ident, generics); - - let body = if from_scratch || method_def.is_static() { - method_def.expand_static_struct_method_body(cx, - self, - struct_def, - type_ident, - &self_args[..], - &nonself_args[..]) - } else { - method_def.expand_struct_method_body(cx, - self, - struct_def, - type_ident, - &self_args[..], - &nonself_args[..], - use_temporaries) - }; - - method_def.create_method(cx, - self, - type_ident, - generics, - Abi::Rust, - explicit_self, - tys, - body) - }) - .collect(); - - self.create_derived_impl(cx, type_ident, generics, field_tys, methods) - } - - fn expand_enum_def(&self, - cx: &mut ExtCtxt<'_>, - enum_def: &'a EnumDef, - type_attrs: &[ast::Attribute], - type_ident: Ident, - generics: &Generics, - from_scratch: bool) - -> P { - let mut field_tys = Vec::new(); - - for variant in &enum_def.variants { - field_tys.extend(variant.node - .data - .fields() - .iter() - .map(|field| field.ty.clone())); - } - - let methods = self.methods - .iter() - .map(|method_def| { - let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(cx, self, type_ident, generics); - - let body = if from_scratch || method_def.is_static() { - method_def.expand_static_enum_method_body(cx, - self, - enum_def, - type_ident, - &self_args[..], - &nonself_args[..]) - } else { - method_def.expand_enum_method_body(cx, - self, - enum_def, - type_attrs, - type_ident, - self_args, - &nonself_args[..]) - }; - - method_def.create_method(cx, - self, - type_ident, - generics, - Abi::Rust, - explicit_self, - tys, - body) - }) - .collect(); - - self.create_derived_impl(cx, type_ident, generics, field_tys, methods) - } -} - -fn find_repr_type_name(sess: &ParseSess, type_attrs: &[ast::Attribute]) -> &'static str { - let mut repr_type_name = "isize"; - for a in type_attrs { - for r in &attr::find_repr_attrs(sess, a) { - repr_type_name = match *r { - attr::ReprPacked(_) | attr::ReprSimd | attr::ReprAlign(_) | attr::ReprTransparent => - continue, - - attr::ReprC => "i32", - - attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize", - attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8", - attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16", - attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32", - attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64", - attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128", - - attr::ReprInt(attr::UnsignedInt(ast::UintTy::Usize)) => "usize", - attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8", - attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16", - attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32", - attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64", - attr::ReprInt(attr::UnsignedInt(ast::UintTy::U128)) => "u128", - } - } - } - repr_type_name -} - -impl<'a> MethodDef<'a> { - fn call_substructure_method(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - type_ident: Ident, - self_args: &[P], - nonself_args: &[P], - fields: &SubstructureFields<'_>) - -> P { - let substructure = Substructure { - type_ident, - method_ident: cx.ident_of(self.name), - self_args, - nonself_args, - fields, - }; - let mut f = self.combine_substructure.borrow_mut(); - let f: &mut CombineSubstructureFunc<'_> = &mut *f; - f(cx, trait_.span, &substructure) - } - - fn get_ret_ty(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - generics: &Generics, - type_ident: Ident) - -> P { - self.ret_ty.to_ty(cx, trait_.span, type_ident, generics) - } - - fn is_static(&self) -> bool { - self.explicit_self.is_none() - } - - fn split_self_nonself_args - (&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - type_ident: Ident, - generics: &Generics) - -> (Option, Vec>, Vec>, Vec<(Ident, P)>) { - - let mut self_args = Vec::new(); - let mut nonself_args = Vec::new(); - let mut arg_tys = Vec::new(); - let mut nonstatic = false; - - let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr); - - self_args.push(self_expr); - nonstatic = true; - - explicit_self - }); - - for (ty, name) in self.args.iter() { - let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(name).gensym(); - arg_tys.push((ident, ast_ty)); - - let arg_expr = cx.expr_ident(trait_.span, ident); - - match *ty { - // for static methods, just treat any Self - // arguments as a normal arg - Self_ if nonstatic => { - self_args.push(arg_expr); - } - Ptr(ref ty, _) if (if let Self_ = **ty { true } else { false }) && nonstatic => { - self_args.push(cx.expr_deref(trait_.span, arg_expr)) - } - _ => { - nonself_args.push(arg_expr); - } - } - } - - (ast_explicit_self, self_args, nonself_args, arg_tys) - } - - fn create_method(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - type_ident: Ident, - generics: &Generics, - abi: Abi, - explicit_self: Option, - arg_types: Vec<(Ident, P)>, - body: P) - -> ast::ImplItem { - // Create the generics that aren't for `Self`. - let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); - - let args = { - let self_args = explicit_self.map(|explicit_self| { - let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span); - ast::Arg::from_self(ThinVec::default(), explicit_self, ident) - }); - let nonself_args = arg_types.into_iter() - .map(|(name, ty)| cx.arg(trait_.span, name, ty)); - self_args.into_iter().chain(nonself_args).collect() - }; - - let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); - - let method_ident = cx.ident_of(self.name); - let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type)); - let body_block = cx.block_expr(body); - - let unsafety = if self.is_unsafe { - ast::Unsafety::Unsafe - } else { - ast::Unsafety::Normal - }; - - // Create the method. - ast::ImplItem { - id: ast::DUMMY_NODE_ID, - attrs: self.attributes.clone(), - generics: fn_generics, - span: trait_.span, - vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, - ident: method_ident, - node: ast::ImplItemKind::Method(ast::MethodSig { - header: ast::FnHeader { - unsafety, abi, - ..ast::FnHeader::default() - }, - decl: fn_decl, - }, - body_block), - tokens: None, - } - } - - /// ``` - /// #[derive(PartialEq)] - /// # struct Dummy; - /// struct A { x: i32, y: i32 } - /// - /// // equivalent to: - /// impl PartialEq for A { - /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: ref __self_0_0, y: ref __self_0_1} => { - /// match *other { - /// A {x: ref __self_1_0, y: ref __self_1_1} => { - /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1) - /// } - /// } - /// } - /// } - /// } - /// } - /// - /// // or if A is repr(packed) - note fields are matched by-value - /// // instead of by-reference. - /// impl PartialEq for A { - /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: __self_0_0, y: __self_0_1} => { - /// match other { - /// A {x: __self_1_0, y: __self_1_1} => { - /// __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1) - /// } - /// } - /// } - /// } - /// } - /// } - /// ``` - fn expand_struct_method_body<'b>(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'b>, - struct_def: &'b VariantData, - type_ident: Ident, - self_args: &[P], - nonself_args: &[P], - use_temporaries: bool) - -> P { - - let mut raw_fields = Vec::new(); // Vec<[fields of self], - // [fields of next Self arg], [etc]> - let mut patterns = Vec::new(); - for i in 0..self_args.len() { - let struct_path = cx.path(DUMMY_SP, vec![type_ident]); - let (pat, ident_expr) = trait_.create_struct_pattern(cx, - struct_path, - struct_def, - &format!("__self_{}", i), - ast::Mutability::Immutable, - use_temporaries); - patterns.push(pat); - raw_fields.push(ident_expr); - } - - // transpose raw_fields - let fields = if !raw_fields.is_empty() { - let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter()); - let first_field = raw_fields.next().unwrap(); - let mut other_fields: Vec> = raw_fields.collect(); - first_field.map(|(span, opt_id, field, attrs)| { - FieldInfo { - span, - name: opt_id, - self_: field, - other: other_fields.iter_mut() - .map(|l| { - match l.next().unwrap() { - (.., ex, _) => ex, - } - }) - .collect(), - attrs, - } - }) - .collect() - } else { - cx.span_bug(trait_.span, - "no self arguments to non-static method in generic \ - `derive`") - }; - - // body of the inner most destructuring match - let mut body = self.call_substructure_method(cx, - trait_, - type_ident, - self_args, - nonself_args, - &Struct(struct_def, fields)); - - // make a series of nested matches, to destructure the - // structs. This is actually right-to-left, but it shouldn't - // matter. - for (arg_expr, pat) in self_args.iter().zip(patterns) { - body = cx.expr_match(trait_.span, - arg_expr.clone(), - vec![cx.arm(trait_.span, vec![pat.clone()], body)]) - } - - body - } - - fn expand_static_struct_method_body(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - struct_def: &VariantData, - type_ident: Ident, - self_args: &[P], - nonself_args: &[P]) - -> P { - let summary = trait_.summarise_struct(cx, struct_def); - - self.call_substructure_method(cx, - trait_, - type_ident, - self_args, - nonself_args, - &StaticStruct(struct_def, summary)) - } - - /// ``` - /// #[derive(PartialEq)] - /// # struct Dummy; - /// enum A { - /// A1, - /// A2(i32) - /// } - /// - /// // is equivalent to - /// - /// impl PartialEq for A { - /// fn eq(&self, other: &A) -> ::bool { - /// match (&*self, &*other) { - /// (&A1, &A1) => true, - /// (&A2(ref self_0), - /// &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)), - /// _ => { - /// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 }; - /// let __arg_1_vi = match *other { A1(..) => 0, A2(..) => 1 }; - /// false - /// } - /// } - /// } - /// } - /// ``` - /// - /// (Of course `__self_vi` and `__arg_1_vi` are unused for - /// `PartialEq`, and those subcomputations will hopefully be removed - /// as their results are unused. The point of `__self_vi` and - /// `__arg_1_vi` is for `PartialOrd`; see #15503.) - fn expand_enum_method_body<'b>(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'b>, - enum_def: &'b EnumDef, - type_attrs: &[ast::Attribute], - type_ident: Ident, - self_args: Vec>, - nonself_args: &[P]) - -> P { - self.build_enum_match_tuple(cx, - trait_, - enum_def, - type_attrs, - type_ident, - self_args, - nonself_args) - } - - - /// Creates a match for a tuple of all `self_args`, where either all - /// variants match, or it falls into a catch-all for when one variant - /// does not match. - - /// There are N + 1 cases because is a case for each of the N - /// variants where all of the variants match, and one catch-all for - /// when one does not match. - - /// As an optimization we generate code which checks whether all variants - /// match first which makes llvm see that C-like enums can be compiled into - /// a simple equality check (for PartialEq). - - /// The catch-all handler is provided access the variant index values - /// for each of the self-args, carried in precomputed variables. - - /// ```{.text} - /// let __self0_vi = unsafe { - /// std::intrinsics::discriminant_value(&self) } as i32; - /// let __self1_vi = unsafe { - /// std::intrinsics::discriminant_value(&arg1) } as i32; - /// let __self2_vi = unsafe { - /// std::intrinsics::discriminant_value(&arg2) } as i32; - /// - /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... { - /// match (...) { - /// (Variant1, Variant1, ...) => Body1 - /// (Variant2, Variant2, ...) => Body2, - /// ... - /// _ => ::core::intrinsics::unreachable() - /// } - /// } - /// else { - /// ... // catch-all remainder can inspect above variant index values. - /// } - /// ``` - fn build_enum_match_tuple<'b>(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'b>, - enum_def: &'b EnumDef, - type_attrs: &[ast::Attribute], - type_ident: Ident, - mut self_args: Vec>, - nonself_args: &[P]) - -> P { - let sp = trait_.span; - let variants = &enum_def.variants; - - let self_arg_names = iter::once("__self".to_string()).chain( - self_args.iter() - .enumerate() - .skip(1) - .map(|(arg_count, _self_arg)| - format!("__arg_{}", arg_count) - ) - ).collect::>(); - - let self_arg_idents = self_arg_names.iter() - .map(|name| cx.ident_of(&name[..])) - .collect::>(); - - // The `vi_idents` will be bound, solely in the catch-all, to - // a series of let statements mapping each self_arg to an int - // value corresponding to its discriminant. - let vi_idents = self_arg_names.iter() - .map(|name| { - let vi_suffix = format!("{}_vi", &name[..]); - cx.ident_of(&vi_suffix[..]).gensym() - }) - .collect::>(); - - // Builds, via callback to call_substructure_method, the - // delegated expression that handles the catch-all case, - // using `__variants_tuple` to drive logic if necessary. - let catch_all_substructure = - EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]); - - let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty()); - - // These arms are of the form: - // (Variant1, Variant1, ...) => Body1 - // (Variant2, Variant2, ...) => Body2 - // ... - // where each tuple has length = self_args.len() - let mut match_arms: Vec = variants.iter() - .enumerate() - .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty())) - .map(|(index, variant)| { - let mk_self_pat = |cx: &mut ExtCtxt<'_>, self_arg_name: &str| { - let (p, idents) = trait_.create_enum_variant_pattern(cx, - type_ident, - variant, - self_arg_name, - ast::Mutability::Immutable); - (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Immutable)), idents) - }; - - // A single arm has form (&VariantK, &VariantK, ...) => BodyK - // (see "Final wrinkle" note below for why.) - let mut subpats = Vec::with_capacity(self_arg_names.len()); - let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1); - let first_self_pat_idents = { - let (p, idents) = mk_self_pat(cx, &self_arg_names[0]); - subpats.push(p); - idents - }; - for self_arg_name in &self_arg_names[1..] { - let (p, idents) = mk_self_pat(cx, &self_arg_name[..]); - subpats.push(p); - self_pats_idents.push(idents); - } - - // Here is the pat = `(&VariantK, &VariantK, ...)` - let single_pat = cx.pat_tuple(sp, subpats); - - // For the BodyK, we need to delegate to our caller, - // passing it an EnumMatching to indicate which case - // we are in. - - // All of the Self args have the same variant in these - // cases. So we transpose the info in self_pats_idents - // to gather the getter expressions together, in the - // form that EnumMatching expects. - - // The transposition is driven by walking across the - // arg fields of the variant for the first self pat. - let field_tuples = first_self_pat_idents.into_iter().enumerate() - // For each arg field of self, pull out its getter expr ... - .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| { - // ... but FieldInfo also wants getter expr - // for matching other arguments of Self type; - // so walk across the *other* self_pats_idents - // and pull out getter for same field in each - // of them (using `field_index` tracked above). - // That is the heart of the transposition. - let others = self_pats_idents.iter().map(|fields| { - let (_, _opt_ident, ref other_getter_expr, _) = - fields[field_index]; - - // All Self args have same variant, so - // opt_idents are the same. (Assert - // here to make it self-evident that - // it is okay to ignore `_opt_ident`.) - assert!(opt_ident == _opt_ident); - - other_getter_expr.clone() - }).collect::>>(); - - FieldInfo { span: sp, - name: opt_ident, - self_: self_getter_expr, - other: others, - attrs, - } - }).collect::>>(); - - // Now, for some given VariantK, we have built up - // expressions for referencing every field of every - // Self arg, assuming all are instances of VariantK. - // Build up code associated with such a case. - let substructure = EnumMatching(index, variants.len(), variant, field_tuples); - let arm_expr = self.call_substructure_method(cx, - trait_, - type_ident, - &self_args[..], - nonself_args, - &substructure); - - cx.arm(sp, vec![single_pat], arm_expr) - }) - .collect(); - - let default = match first_fieldless { - Some(v) if self.unify_fieldless_variants => { - // We need a default case that handles the fieldless variants. - // The index and actual variant aren't meaningful in this case, - // so just use whatever - let substructure = EnumMatching(0, variants.len(), v, Vec::new()); - Some(self.call_substructure_method(cx, - trait_, - type_ident, - &self_args[..], - nonself_args, - &substructure)) - } - _ if variants.len() > 1 && self_args.len() > 1 => { - // Since we know that all the arguments will match if we reach - // the match expression we add the unreachable intrinsics as the - // result of the catch all which should help llvm in optimizing it - Some(deriving::call_intrinsic(cx, sp, "unreachable", vec![])) - } - _ => None, - }; - if let Some(arm) = default { - match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm)); - } - - // We will usually need the catch-all after matching the - // tuples `(VariantK, VariantK, ...)` for each VariantK of the - // enum. But: - // - // * when there is only one Self arg, the arms above suffice - // (and the deriving we call back into may not be prepared to - // handle EnumNonMatchCollapsed), and, - // - // * when the enum has only one variant, the single arm that - // is already present always suffices. - // - // * In either of the two cases above, if we *did* add a - // catch-all `_` match, it would trigger the - // unreachable-pattern error. - // - if variants.len() > 1 && self_args.len() > 1 { - // Build a series of let statements mapping each self_arg - // to its discriminant value. If this is a C-style enum - // with a specific repr type, then casts the values to - // that type. Otherwise casts to `i32` (the default repr - // type). - // - // i.e., for `enum E { A, B(1), C(T, T) }`, and a deriving - // with three Self args, builds three statements: - // - // ``` - // let __self0_vi = unsafe { - // std::intrinsics::discriminant_value(&self) } as i32; - // let __self1_vi = unsafe { - // std::intrinsics::discriminant_value(&arg1) } as i32; - // let __self2_vi = unsafe { - // std::intrinsics::discriminant_value(&arg2) } as i32; - // ``` - let mut index_let_stmts: Vec = Vec::with_capacity(vi_idents.len() + 1); - - // We also build an expression which checks whether all discriminants are equal - // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... - let mut discriminant_test = cx.expr_bool(sp, true); - - let target_type_name = find_repr_type_name(&cx.parse_sess, type_attrs); - - let mut first_ident = None; - for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { - let self_addr = cx.expr_addr_of(sp, self_arg.clone()); - let variant_value = - deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]); - - let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); - let variant_disr = cx.expr_cast(sp, variant_value, target_ty); - let let_stmt = cx.stmt_let(sp, false, ident, variant_disr); - index_let_stmts.push(let_stmt); - - match first_ident { - Some(first) => { - let first_expr = cx.expr_ident(sp, first); - let id = cx.expr_ident(sp, ident); - let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id); - discriminant_test = - cx.expr_binary(sp, BinOpKind::And, discriminant_test, test) - } - None => { - first_ident = Some(ident); - } - } - } - - let arm_expr = self.call_substructure_method(cx, - trait_, - type_ident, - &self_args[..], - nonself_args, - &catch_all_substructure); - - // Final wrinkle: the self_args are expressions that deref - // down to desired places, but we cannot actually deref - // them when they are fed as r-values into a tuple - // expression; here add a layer of borrowing, turning - // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); - - // Lastly we create an expression which branches on all discriminants being equal - // if discriminant_test { - // match (...) { - // (Variant1, Variant1, ...) => Body1 - // (Variant2, Variant2, ...) => Body2, - // ... - // _ => ::core::intrinsics::unreachable() - // } - // } - // else { - // - // } - let all_match = cx.expr_match(sp, match_arg, match_arms); - let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); - index_let_stmts.push(cx.stmt_expr(arm_expr)); - cx.expr_block(cx.block(sp, index_let_stmts)) - } else if variants.is_empty() { - // As an additional wrinkle, For a zero-variant enum A, - // currently the compiler - // will accept `fn (a: &Self) { match *a { } }` - // but rejects `fn (a: &Self) { match (&*a,) { } }` - // as well as `fn (a: &Self) { match ( *a,) { } }` - // - // This means that the strategy of building up a tuple of - // all Self arguments fails when Self is a zero variant - // enum: rustc rejects the expanded program, even though - // the actual code tends to be impossible to execute (at - // least safely), according to the type system. - // - // The most expedient fix for this is to just let the - // code fall through to the catch-all. But even this is - // error-prone, since the catch-all as defined above would - // generate code like this: - // - // _ => { let __self0 = match *self { }; - // let __self1 = match *__arg_0 { }; - // } - // - // Which is yields bindings for variables which type - // inference cannot resolve to unique types. - // - // One option to the above might be to add explicit type - // annotations. But the *only* reason to go down that path - // would be to try to make the expanded output consistent - // with the case when the number of enum variants >= 1. - // - // That just isn't worth it. In fact, trying to generate - // sensible code for *any* deriving on a zero-variant enum - // does not make sense. But at the same time, for now, we - // do not want to cause a compile failure just because the - // user happened to attach a deriving to their - // zero-variant enum. - // - // Instead, just generate a failing expression for the - // zero variant case, skipping matches and also skipping - // delegating back to the end user code entirely. - // - // (See also #4499 and #12609; note that some of the - // discussions there influence what choice we make here; - // e.g., if we feature-gate `match x { ... }` when x refers - // to an uninhabited type (e.g., a zero-variant enum or a - // type holding such an enum), but do not feature-gate - // zero-variant enums themselves, then attempting to - // derive Debug on such a type could here generate code - // that needs the feature gate enabled.) - - deriving::call_intrinsic(cx, sp, "unreachable", vec![]) - } else { - - // Final wrinkle: the self_args are expressions that deref - // down to desired places, but we cannot actually deref - // them when they are fed as r-values into a tuple - // expression; here add a layer of borrowing, turning - // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); - cx.expr_match(sp, match_arg, match_arms) - } - } - - fn expand_static_enum_method_body(&self, - cx: &mut ExtCtxt<'_>, - trait_: &TraitDef<'_>, - enum_def: &EnumDef, - type_ident: Ident, - self_args: &[P], - nonself_args: &[P]) - -> P { - let summary = enum_def.variants - .iter() - .map(|v| { - let sp = v.span.with_ctxt(trait_.span.ctxt()); - let summary = trait_.summarise_struct(cx, &v.node.data); - (v.node.ident, sp, summary) - }) - .collect(); - self.call_substructure_method(cx, - trait_, - type_ident, - self_args, - nonself_args, - &StaticEnum(enum_def, summary)) - } -} - -// general helper methods. -impl<'a> TraitDef<'a> { - fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields { - let mut named_idents = Vec::new(); - let mut just_spans = Vec::new(); - for field in struct_def.fields() { - let sp = field.span.with_ctxt(self.span.ctxt()); - match field.ident { - Some(ident) => named_idents.push((ident, sp)), - _ => just_spans.push(sp), - } - } - - let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false }; - match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => { - cx.span_bug(self.span, - "a struct with named and unnamed \ - fields in generic `derive`") - } - // named fields - (_, false) => Named(named_idents), - // unnamed fields - (false, _) => Unnamed(just_spans, is_tuple), - // empty - _ => Named(Vec::new()), - } - } - - fn create_subpatterns(&self, - cx: &mut ExtCtxt<'_>, - field_paths: Vec, - mutbl: ast::Mutability, - use_temporaries: bool) - -> Vec> { - field_paths.iter() - .map(|path| { - let binding_mode = if use_temporaries { - ast::BindingMode::ByValue(ast::Mutability::Immutable) - } else { - ast::BindingMode::ByRef(mutbl) - }; - cx.pat(path.span, - PatKind::Ident(binding_mode, (*path).clone(), None)) - }) - .collect() - } - - fn create_struct_pattern - (&self, - cx: &mut ExtCtxt<'_>, - struct_path: ast::Path, - struct_def: &'a VariantData, - prefix: &str, - mutbl: ast::Mutability, - use_temporaries: bool) - -> (P, Vec<(Span, Option, P, &'a [ast::Attribute])>) - { - let mut paths = Vec::new(); - let mut ident_exprs = Vec::new(); - for (i, struct_field) in struct_def.fields().iter().enumerate() { - let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym(); - paths.push(ident.with_span_pos(sp)); - let val = cx.expr_path(cx.path_ident(sp, ident)); - let val = if use_temporaries { - val - } else { - cx.expr_deref(sp, val) - }; - let val = cx.expr(sp, ast::ExprKind::Paren(val)); - - ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..])); - } - - let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries); - let pattern = match *struct_def { - VariantData::Struct(..) => { - let field_pats = subpats.into_iter() - .zip(&ident_exprs) - .map(|(pat, &(sp, ident, ..))| { - if ident.is_none() { - cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); - } - source_map::Spanned { - span: pat.span.with_ctxt(self.span.ctxt()), - node: ast::FieldPat { - ident: ident.unwrap(), - pat, - is_shorthand: false, - attrs: ThinVec::new(), - }, - } - }) - .collect(); - cx.pat_struct(self.span, struct_path, field_pats) - } - VariantData::Tuple(..) => { - cx.pat_tuple_struct(self.span, struct_path, subpats) - } - VariantData::Unit(..) => { - cx.pat_path(self.span, struct_path) - } - }; - - (pattern, ident_exprs) - } - - fn create_enum_variant_pattern - (&self, - cx: &mut ExtCtxt<'_>, - enum_ident: ast::Ident, - variant: &'a ast::Variant, - prefix: &str, - mutbl: ast::Mutability) - -> (P, Vec<(Span, Option, P, &'a [ast::Attribute])>) { - let sp = variant.span.with_ctxt(self.span.ctxt()); - let variant_path = cx.path(sp, vec![enum_ident, variant.node.ident]); - let use_temporaries = false; // enums can't be repr(packed) - self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl, - use_temporaries) - } -} - -// helpful premade recipes - -pub fn cs_fold_fields<'a, F>(use_foldl: bool, - mut f: F, - base: P, - cx: &mut ExtCtxt<'_>, - all_fields: &[FieldInfo<'a>]) - -> P - where F: FnMut(&mut ExtCtxt<'_>, Span, P, P, &[P]) -> P -{ - if use_foldl { - all_fields.iter().fold(base, |old, field| { - f(cx, field.span, old, field.self_.clone(), &field.other) - }) - } else { - all_fields.iter().rev().fold(base, |old, field| { - f(cx, field.span, old, field.self_.clone(), &field.other) - }) - } -} - -pub fn cs_fold_enumnonmatch(mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substructure: &Substructure<'_>) - -> P -{ - match *substructure.fields { - EnumNonMatchingCollapsed(ref all_args, _, tuple) => { - enum_nonmatch_f(cx, - trait_span, - (&all_args[..], tuple), - substructure.nonself_args) - } - _ => cx.span_bug(trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed") - } -} - -pub fn cs_fold_static(cx: &mut ExtCtxt<'_>, - trait_span: Span) - -> P -{ - cx.span_bug(trait_span, "static function in `derive`") -} - -/// Fold the fields. `use_foldl` controls whether this is done -/// left-to-right (`true`) or right-to-left (`false`). -pub fn cs_fold(use_foldl: bool, - f: F, - base: P, - enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substructure: &Substructure<'_>) - -> P - where F: FnMut(&mut ExtCtxt<'_>, Span, P, P, &[P]) -> P -{ - match *substructure.fields { - EnumMatching(.., ref all_fields) | - Struct(_, ref all_fields) => { - cs_fold_fields(use_foldl, f, base, cx, all_fields) - } - EnumNonMatchingCollapsed(..) => { - cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure) - } - StaticEnum(..) | StaticStruct(..) => { - cs_fold_static(cx, trait_span) - } - } -} - -/// Function to fold over fields, with three cases, to generate more efficient and concise code. -/// When the `substructure` has grouped fields, there are two cases: -/// Zero fields: call the base case function with `None` (like the usual base case of `cs_fold`). -/// One or more fields: call the base case function on the first value (which depends on -/// `use_fold`), and use that as the base case. Then perform `cs_fold` on the remainder of the -/// fields. -/// When the `substructure` is a `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f` -/// is returned. Statics may not be folded over. -/// See `cs_op` in `partial_ord.rs` for a model example. -pub fn cs_fold1(use_foldl: bool, - f: F, - mut b: B, - enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substructure: &Substructure<'_>) - -> P - where F: FnMut(&mut ExtCtxt<'_>, Span, P, P, &[P]) -> P, - B: FnMut(&mut ExtCtxt<'_>, Option<(Span, P, &[P])>) -> P -{ - match *substructure.fields { - EnumMatching(.., ref all_fields) | - Struct(_, ref all_fields) => { - let (base, all_fields) = match (all_fields.is_empty(), use_foldl) { - (false, true) => { - let field = &all_fields[0]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[1..]) - } - (false, false) => { - let idx = all_fields.len() - 1; - let field = &all_fields[idx]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[..idx]) - } - (true, _) => (b(cx, None), &all_fields[..]) - }; - - cs_fold_fields(use_foldl, f, base, cx, all_fields) - } - EnumNonMatchingCollapsed(..) => { - cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure) - } - StaticEnum(..) | StaticStruct(..) => { - cs_fold_static(cx, trait_span) - } - } -} - -/// Call the method that is being derived on all the fields, and then -/// process the collected results. i.e. -/// -/// ```ignore (only-for-syntax-highlight) -/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1), -/// self_2.method(__arg_1_2, __arg_2_2)]) -/// ``` -#[inline] -pub fn cs_same_method(f: F, - mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, - cx: &mut ExtCtxt<'_>, - trait_span: Span, - substructure: &Substructure<'_>) - -> P - where F: FnOnce(&mut ExtCtxt<'_>, Span, Vec>) -> P -{ - match *substructure.fields { - EnumMatching(.., ref all_fields) | - Struct(_, ref all_fields) => { - // call self_n.method(other_1_n, other_2_n, ...) - let called = all_fields.iter() - .map(|field| { - cx.expr_method_call(field.span, - field.self_.clone(), - substructure.method_ident, - field.other - .iter() - .map(|e| cx.expr_addr_of(field.span, e.clone())) - .collect()) - }) - .collect(); - - f(cx, trait_span, called) - } - EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => { - enum_nonmatch_f(cx, - trait_span, - (&all_self_args[..], tuple), - substructure.nonself_args) - } - StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"), - } -} - -/// Returns `true` if the type has no value fields -/// (for an enum, no variant has any fields) -pub fn is_type_without_fields(item: &Annotatable) -> bool { - if let Annotatable::Item(ref item) = *item { - match item.node { - ast::ItemKind::Enum(ref enum_def, _) => { - enum_def.variants.iter().all(|v| v.node.data.fields().is_empty()) - } - ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(), - _ => false, - } - } else { - false - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/ty.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/ty.rs deleted file mode 100644 index 02b02e9..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/generic/ty.rs +++ /dev/null @@ -1,297 +0,0 @@ -//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use -//! when specifying impls to be derived. - -pub use PtrTy::*; -pub use Ty::*; - -use syntax::ast::{self, Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg}; -use syntax::ext::base::ExtCtxt; -use syntax::ext::build::AstBuilder; -use syntax::source_map::{respan, DUMMY_SP}; -use syntax::ptr::P; -use syntax_pos::Span; -use syntax_pos::symbol::kw; - -/// The types of pointers -#[derive(Clone)] -pub enum PtrTy<'a> { - /// &'lifetime mut - Borrowed(Option<&'a str>, ast::Mutability), - /// *mut - Raw(ast::Mutability), -} - -/// A path, e.g., `::std::option::Option::` (global). Has support -/// for type parameters and a lifetime. -#[derive(Clone)] -pub struct Path<'a> { - path: Vec<&'a str>, - lifetime: Option<&'a str>, - params: Vec>>, - kind: PathKind, -} - -#[derive(Clone)] -pub enum PathKind { - Local, - Global, - Std, -} - -impl<'a> Path<'a> { - pub fn new(path: Vec<&str>) -> Path<'_> { - Path::new_(path, None, Vec::new(), PathKind::Std) - } - pub fn new_local(path: &str) -> Path<'_> { - Path::new_(vec![path], None, Vec::new(), PathKind::Local) - } - pub fn new_<'r>(path: Vec<&'r str>, - lifetime: Option<&'r str>, - params: Vec>>, - kind: PathKind) - -> Path<'r> { - Path { - path, - lifetime, - params, - kind, - } - } - - pub fn to_ty(&self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics) - -> P { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) - } - pub fn to_path(&self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics) - -> ast::Path { - let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect(); - let lt = mk_lifetimes(cx, span, &self.lifetime); - let tys: Vec> = - self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); - let params = lt.into_iter() - .map(|lt| GenericArg::Lifetime(lt)) - .chain(tys.into_iter().map(|ty| GenericArg::Type(ty))) - .collect(); - - match self.kind { - PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()), - PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()), - PathKind::Std => { - let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark); - idents.insert(0, Ident::new(kw::DollarCrate, def_site)); - cx.path_all(span, false, idents, params, Vec::new()) - } - } - - } -} - -/// A type. Supports pointers, Self, and literals. -#[derive(Clone)] -pub enum Ty<'a> { - Self_, - /// &/Box/ Ty - Ptr(Box>, PtrTy<'a>), - /// mod::mod::Type<[lifetime], [Params...]>, including a plain type - /// parameter, and things like `i32` - Literal(Path<'a>), - /// includes unit - Tuple(Vec>), -} - -/// A const expression. Supports literals and blocks. -#[derive(Clone, Eq, PartialEq)] -pub enum Const { - Literal, - Block, -} - -pub fn borrowed_ptrty<'r>() -> PtrTy<'r> { - Borrowed(None, ast::Mutability::Immutable) -} -pub fn borrowed(ty: Box>) -> Ty<'_> { - Ptr(ty, borrowed_ptrty()) -} - -pub fn borrowed_explicit_self<'r>() -> Option>> { - Some(Some(borrowed_ptrty())) -} - -pub fn borrowed_self<'r>() -> Ty<'r> { - borrowed(Box::new(Self_)) -} - -pub fn nil_ty<'r>() -> Ty<'r> { - Tuple(Vec::new()) -} - -fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option { - lt.map(|s| - cx.lifetime(span, Ident::from_str(s)) - ) -} - -fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec { - mk_lifetime(cx, span, lt).into_iter().collect() -} - -impl<'a> Ty<'a> { - pub fn to_ty(&self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics) - -> P { - match *self { - Ptr(ref ty, ref ptr) => { - let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = mk_lifetime(cx, span, lt); - cx.ty_rptr(span, raw_ty, lt, mutbl) - } - Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl), - } - } - Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics), - Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), - Tuple(ref fields) => { - let ty = ast::TyKind::Tup(fields.iter() - .map(|f| f.to_ty(cx, span, self_ty, self_generics)) - .collect()); - cx.ty(span, ty) - } - } - } - - pub fn to_path(&self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - generics: &Generics) - -> ast::Path { - match *self { - Self_ => { - let params: Vec<_> = generics.params.iter().map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident }) - } - GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(span, param.ident)) - } - GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(span, param.ident)) - } - }).collect(); - - cx.path_all(span, false, vec![self_ty], params, vec![]) - } - Literal(ref p) => p.to_path(cx, span, self_ty, generics), - Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"), - Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"), - } - } -} - - -fn mk_ty_param(cx: &ExtCtxt<'_>, - span: Span, - name: &str, - attrs: &[ast::Attribute], - bounds: &[Path<'_>], - self_ident: Ident, - self_generics: &Generics) - -> ast::GenericParam { - let bounds = bounds.iter() - .map(|b| { - let path = b.to_path(cx, span, self_ident, self_generics); - cx.trait_bound(path) - }) - .collect(); - cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) -} - -fn mk_generics(params: Vec, span: Span) -> Generics { - Generics { - params, - where_clause: ast::WhereClause { - predicates: Vec::new(), - span, - }, - span, - } -} - -/// Lifetimes and bounds on type parameters -#[derive(Clone)] -pub struct LifetimeBounds<'a> { - pub lifetimes: Vec<(&'a str, Vec<&'a str>)>, - pub bounds: Vec<(&'a str, Vec>)>, -} - -impl<'a> LifetimeBounds<'a> { - pub fn empty() -> LifetimeBounds<'a> { - LifetimeBounds { - lifetimes: Vec::new(), - bounds: Vec::new(), - } - } - pub fn to_generics(&self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics) - -> Generics { - let generic_params = self.lifetimes - .iter() - .map(|&(lt, ref bounds)| { - let bounds = bounds.iter() - .map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b)))); - cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect()) - }) - .chain(self.bounds - .iter() - .map(|t| { - let (name, ref bounds) = *t; - mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics) - }) - ) - .collect(); - - mk_generics(generic_params, span) - } -} - -pub fn get_explicit_self(cx: &ExtCtxt<'_>, - span: Span, - self_ptr: &Option>) - -> (P, ast::ExplicitSelf) { - // this constructs a fresh `self` path - let self_path = cx.expr_self(span); - match *self_ptr { - None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))), - Some(ref ptr) => { - let self_ty = - respan(span, - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s))); - SelfKind::Region(lt, mutbl) - } - Raw(_) => { - cx.span_bug(span, "attempted to use *self in deriving definition") - } - }); - let self_expr = cx.expr_deref(span, self_path); - (self_expr, self_ty) - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/hash.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/hash.rs deleted file mode 100644 index 7ad04ae..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/hash.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::deriving::{self, pathvec_std, path_std}; -use crate::deriving::generic::*; -use crate::deriving::generic::ty::*; - -use syntax::ast::{Expr, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::sym; -use syntax_pos::Span; - -pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable)) { - - let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std); - - let typaram = &*deriving::hygienic_type_parameter(item, "__H"); - - let arg = Path::new_local(typaram); - let hash_trait_def = TraitDef { - span, - attributes: Vec::new(), - path, - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - supports_unions: false, - methods: vec![MethodDef { - name: "hash", - generics: LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])], - }, - explicit_self: borrowed_explicit_self(), - args: vec![(Ptr(Box::new(Literal(arg)), - Borrowed(None, Mutability::Mutable)), "state")], - ret_ty: nil_ty(), - attributes: vec![], - is_unsafe: false, - unify_fieldless_variants: true, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - hash_substructure(a, b, c) - })), - }], - associated_types: Vec::new(), - }; - - hash_trait_def.expand(cx, mitem, item, push); -} - -fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P { - let state_expr = match &substr.nonself_args { - &[o_f] => o_f, - _ => { - cx.span_bug(trait_span, - "incorrect number of arguments in `derive(Hash)`") - } - }; - let call_hash = |span, thing_expr| { - let hash_path = { - let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]); - - cx.expr_path(cx.path_global(span, strs)) - }; - let ref_thing = cx.expr_addr_of(span, thing_expr); - let expr = cx.expr_call(span, hash_path, vec![ref_thing, state_expr.clone()]); - cx.stmt_expr(expr) - }; - let mut stmts = Vec::new(); - - let fields = match *substr.fields { - Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs, - EnumMatching(.., ref fs) => { - let variant_value = deriving::call_intrinsic(cx, - trait_span, - "discriminant_value", - vec![cx.expr_self(trait_span)]); - - stmts.push(call_hash(trait_span, variant_value)); - - fs - } - _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"), - }; - - stmts.extend(fields.iter().map(|FieldInfo { ref self_, span, .. }| - call_hash(*span, self_.clone()))); - - cx.expr_block(cx.block(trait_span, stmts)) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/deriving/mod.rs b/gcc/rust/rustc_parser/libsyntax_ext/deriving/mod.rs deleted file mode 100644 index e491e93..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/deriving/mod.rs +++ /dev/null @@ -1,182 +0,0 @@ -//! The compiler code necessary to implement the `#[derive]` extensions. - -use rustc_data_structures::sync::Lrc; -use syntax::ast::{self, MetaItem}; -use syntax::attr::Deprecation; -use syntax::edition::Edition; -use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use syntax::ext::build::AstBuilder; -use syntax::ptr::P; -use syntax::symbol::{Symbol, sym}; -use syntax_pos::Span; - -macro path_local($x:ident) { - generic::ty::Path::new_local(stringify!($x)) -} - -macro pathvec_std($cx:expr, $($rest:ident)::+) {{ - vec![ $( stringify!($rest) ),+ ] -}} - -macro path_std($($x:tt)*) { - generic::ty::Path::new( pathvec_std!( $($x)* ) ) -} - -pub mod bounds; -pub mod clone; -pub mod encodable; -pub mod decodable; -pub mod hash; -pub mod debug; -pub mod default; -pub mod custom; - -#[path="cmp/partial_eq.rs"] -pub mod partial_eq; -#[path="cmp/eq.rs"] -pub mod eq; -#[path="cmp/partial_ord.rs"] -pub mod partial_ord; -#[path="cmp/ord.rs"] -pub mod ord; - -pub mod generic; - -struct BuiltinDerive( - fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) -); - -impl MultiItemModifier for BuiltinDerive { - fn expand(&self, - ecx: &mut ExtCtxt<'_>, - span: Span, - meta_item: &MetaItem, - item: Annotatable) - -> Vec { - let mut items = Vec::new(); - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); - items - } -} - -macro_rules! derive_traits { - ($( [$deprecation:expr] $name:ident => $func:path, )+) => { - pub fn is_builtin_trait(name: ast::Name) -> bool { - match name { - $( sym::$name )|+ => true, - _ => false, - } - } - - pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { - let allow_internal_unstable = Some([ - sym::core_intrinsics, - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize - ][..].into()); - - $( - resolver.add_builtin( - ast::Ident::with_empty_ctxt(sym::$name), - Lrc::new(SyntaxExtension { - deprecation: $deprecation.map(|msg| Deprecation { - since: Some(Symbol::intern("1.0.0")), - note: Some(Symbol::intern(msg)), - }), - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))), - edition, - ) - }), - ); - )+ - } - } -} - -derive_traits! { - [None] - Clone => clone::expand_deriving_clone, - - [None] - Hash => hash::expand_deriving_hash, - - [None] - RustcEncodable => encodable::expand_deriving_rustc_encodable, - - [None] - RustcDecodable => decodable::expand_deriving_rustc_decodable, - - [None] - PartialEq => partial_eq::expand_deriving_partial_eq, - [None] - Eq => eq::expand_deriving_eq, - [None] - PartialOrd => partial_ord::expand_deriving_partial_ord, - [None] - Ord => ord::expand_deriving_ord, - - [None] - Debug => debug::expand_deriving_debug, - - [None] - Default => default::expand_deriving_default, - - [None] - Copy => bounds::expand_deriving_copy, - - // deprecated - [Some("derive(Encodable) is deprecated in favor of derive(RustcEncodable)")] - Encodable => encodable::expand_deriving_encodable, - [Some("derive(Decodable) is deprecated in favor of derive(RustcDecodable)")] - Decodable => decodable::expand_deriving_decodable, -} - -/// Construct a name for the inner type parameter that can't collide with any type parameters of -/// the item. This is achieved by starting with a base and then concatenating the names of all -/// other type parameters. -// FIXME(aburka): use real hygiene when that becomes possible -fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { - let mut typaram = String::from(base); - if let Annotatable::Item(ref item) = *item { - match item.node { - ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) | - ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { - for param in params { - match param.kind { - ast::GenericParamKind::Type { .. } => { - typaram.push_str(¶m.ident.as_str()); - } - _ => {} - } - } - } - - _ => {} - } - } - - typaram -} - -/// Constructs an expression that calls an intrinsic -fn call_intrinsic(cx: &ExtCtxt<'_>, - span: Span, - intrinsic: &str, - args: Vec>) - -> P { - let span = span.with_ctxt(cx.backtrace()); - let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]); - let call = cx.expr_call_global(span, path, args); - - cx.expr_block(P(ast::Block { - stmts: vec![cx.stmt_expr(call)], - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span, - })) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/env.rs b/gcc/rust/rustc_parser/libsyntax_ext/env.rs deleted file mode 100644 index b7f2ecf..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/env.rs +++ /dev/null @@ -1,87 +0,0 @@ -// The compiler code necessary to support the env! extension. Eventually this -// should all get sucked into either the compiler syntax extension plugin -// interface. -// - -use syntax::ast::{self, Ident, GenericArg}; -use syntax::ext::base::{self, *}; -use syntax::ext::build::AstBuilder; -use syntax::symbol::{kw, sym, Symbol}; -use syntax_pos::Span; -use syntax::tokenstream; - -use std::env; - -pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) - -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return DummyResult::expr(sp), - Some(v) => v, - }; - - let sp = sp.apply_mark(cx.current_expansion.mark); - let e = match env::var(&*var.as_str()) { - Err(..) => { - let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime)); - cx.expr_path(cx.path_all(sp, - true, - cx.std_path(&[sym::option, sym::Option, sym::None]), - vec![GenericArg::Type(cx.ty_rptr(sp, - cx.ty_ident(sp, - Ident::with_empty_ctxt(sym::str)), - Some(lt), - ast::Mutability::Immutable))], - vec![])) - } - Ok(s) => { - cx.expr_call_global(sp, - cx.std_path(&[sym::option, sym::Option, sym::Some]), - vec![cx.expr_str(sp, Symbol::intern(&s))]) - } - }; - MacEager::expr(e) -} - -pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) - -> Box { - let mut exprs = match get_exprs_from_tts(cx, sp, tts) { - Some(ref exprs) if exprs.is_empty() => { - cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); - } - None => return DummyResult::expr(sp), - Some(exprs) => exprs.into_iter(), - }; - - let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") { - None => return DummyResult::expr(sp), - Some((v, _style)) => v, - }; - let msg = match exprs.next() { - None => Symbol::intern(&format!("environment variable `{}` not defined", var)), - Some(second) => { - match expr_to_string(cx, second, "expected string literal") { - None => return DummyResult::expr(sp), - Some((s, _style)) => s, - } - } - }; - - if exprs.next().is_some() { - cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); - } - - let e = match env::var(&*var.as_str()) { - Err(_) => { - cx.span_err(sp, &msg.as_str()); - return DummyResult::expr(sp); - } - Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), - }; - MacEager::expr(e) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/error_codes.rs b/gcc/rust/rustc_parser/libsyntax_ext/error_codes.rs deleted file mode 100644 index 9bbd9fd..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/error_codes.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![allow(non_snake_case)] - -use syntax::{register_diagnostic, register_long_diagnostics}; - -// Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 characters. -// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { -E0660: r##" -The argument to the `asm` macro is not well-formed. - -Erroneous code example: - -```compile_fail,E0660 -asm!("nop" "nop"); -``` - -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html -"##, - -E0661: r##" -An invalid syntax was passed to the second argument of an `asm` macro line. - -Erroneous code example: - -```compile_fail,E0661 -let a; -asm!("nop" : "r"(a)); -``` - -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html -"##, - -E0662: r##" -An invalid input operand constraint was passed to the `asm` macro (third line). - -Erroneous code example: - -```compile_fail,E0662 -asm!("xor %eax, %eax" - : - : "=test"("a") - ); -``` - -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html -"##, - -E0663: r##" -An invalid input operand constraint was passed to the `asm` macro (third line). - -Erroneous code example: - -```compile_fail,E0663 -asm!("xor %eax, %eax" - : - : "+test"("a") - ); -``` - -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html -"##, - -E0664: r##" -A clobber was surrounded by braces in the `asm` macro. - -Erroneous code example: - -```compile_fail,E0664 -asm!("mov $$0x200, %eax" - : - : - : "{eax}" - ); -``` - -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html -"##, - -E0665: r##" -The `Default` trait was derived on an enum. - -Erroneous code example: - -```compile_fail,E0665 -#[derive(Default)] -enum Food { - Sweet, - Salty, -} -``` - -The `Default` cannot be derived on an enum for the simple reason that the -compiler doesn't know which value to pick by default whereas it can for a -struct as long as all its fields implement the `Default` trait as well. - -If you still want to implement `Default` on your enum, you'll have to do it "by -hand": - -``` -enum Food { - Sweet, - Salty, -} - -impl Default for Food { - fn default() -> Food { - Food::Sweet - } -} -``` -"##, -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/format.rs b/gcc/rust/rustc_parser/libsyntax_ext/format.rs deleted file mode 100644 index c3dbd48..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/format.rs +++ /dev/null @@ -1,1090 +0,0 @@ -use ArgumentType::*; -use Position::*; - -use fmt_macros as parse; - -use errors::DiagnosticBuilder; -use errors::Applicability; - -use syntax::ast; -use syntax::ext::base::{self, *}; -use syntax::ext::build::AstBuilder; -use syntax::parse::token; -use syntax::ptr::P; -use syntax::symbol::{Symbol, sym}; -use syntax::tokenstream; -use syntax_pos::{MultiSpan, Span, DUMMY_SP}; - -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::borrow::Cow; -use std::collections::hash_map::Entry; - -#[derive(PartialEq)] -enum ArgumentType { - Placeholder(String), - Count, -} - -enum Position { - Exact(usize), - Named(Symbol), -} - -struct Context<'a, 'b> { - ecx: &'a mut ExtCtxt<'b>, - /// The macro's call site. References to unstable formatting internals must - /// use this span to pass the stability checker. - macsp: Span, - /// The span of the format string literal. - fmtsp: Span, - - /// List of parsed argument expressions. - /// Named expressions are resolved early, and are appended to the end of - /// argument expressions. - /// - /// Example showing the various data structures in motion: - /// - /// * Original: `"{foo:o} {:o} {foo:x} {0:x} {1:o} {:x} {1:x} {0:o}"` - /// * Implicit argument resolution: `"{foo:o} {0:o} {foo:x} {0:x} {1:o} {1:x} {1:x} {0:o}"` - /// * Name resolution: `"{2:o} {0:o} {2:x} {0:x} {1:o} {1:x} {1:x} {0:o}"` - /// * `arg_types` (in JSON): `[[0, 1, 0], [0, 1, 1], [0, 1]]` - /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]` - /// * `names` (in JSON): `{"foo": 2}` - args: Vec>, - /// Placeholder slot numbers indexed by argument. - arg_types: Vec>, - /// Unique format specs seen for each argument. - arg_unique_types: Vec>, - /// Map from named arguments to their resolved indices. - names: FxHashMap, - - /// The latest consecutive literal strings, or empty if there weren't any. - literal: String, - - /// Collection of the compiled `rt::Argument` structures - pieces: Vec>, - /// Collection of string literals - str_pieces: Vec>, - /// Stays `true` if all formatting parameters are default (as in "{}{}"). - all_pieces_simple: bool, - - /// Mapping between positional argument references and indices into the - /// final generated static argument array. We record the starting indices - /// corresponding to each positional argument, and number of references - /// consumed so far for each argument, to facilitate correct `Position` - /// mapping in `build_piece`. In effect this can be seen as a "flattened" - /// version of `arg_unique_types`. - /// - /// Again with the example described above in docstring for `args`: - /// - /// * `arg_index_map` (in JSON): `[[0, 1, 0], [2, 3, 3], [4, 5]]` - arg_index_map: Vec>, - - /// Starting offset of count argument slots. - count_args_index_offset: usize, - - /// Count argument slots and tracking data structures. - /// Count arguments are separately tracked for de-duplication in case - /// multiple references are made to one argument. For example, in this - /// format string: - /// - /// * Original: `"{:.*} {:.foo$} {1:.*} {:.0$}"` - /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"` - /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"` - /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}` - /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]` - count_args: Vec, - /// Relative slot numbers for count arguments. - count_positions: FxHashMap, - /// Number of count slots assigned. - count_positions_count: usize, - - /// Current position of the implicit positional arg pointer, as if it - /// still existed in this phase of processing. - /// Used only for `all_pieces_simple` tracking in `build_piece`. - curarg: usize, - /// Current piece being evaluated, used for error reporting. - curpiece: usize, - /// Keep track of invalid references to positional arguments. - invalid_refs: Vec<(usize, usize)>, - /// Spans of all the formatting arguments, in order. - arg_spans: Vec, - /// Whether this formatting string is a literal or it comes from a macro. - is_literal: bool, -} - -/// Parses the arguments from the given list of tokens, returning the diagnostic -/// if there's a parse error so we can continue parsing other format! -/// expressions. -/// -/// If parsing succeeds, the return value is: -/// -/// ```text -/// Some((fmtstr, parsed arguments, index map for named arguments)) -/// ``` -fn parse_args<'a>( - ecx: &mut ExtCtxt<'a>, - sp: Span, - tts: &[tokenstream::TokenTree] -) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { - let mut args = Vec::>::new(); - let mut names = FxHashMap::::default(); - - let mut p = ecx.new_parser_from_tts(tts); - - if p.token == token::Eof { - return Err(ecx.struct_span_err(sp, "requires at least a format string argument")); - } - - let fmtstr = p.parse_expr()?; - let mut named = false; - - while p.token != token::Eof { - if !p.eat(&token::Comma) { - return Err(ecx.struct_span_err(p.token.span, "expected token: `,`")); - } - if p.token == token::Eof { - break; - } // accept trailing commas - if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) { - named = true; - let name = if let token::Ident(name, _) = p.token.kind { - p.bump(); - name - } else { - return Err(ecx.struct_span_err( - p.token.span, - "expected ident, positional arguments cannot follow named arguments", - )); - }; - - p.expect(&token::Eq)?; - let e = p.parse_expr()?; - if let Some(prev) = names.get(&name) { - ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name)) - .span_note(args[*prev].span, "previously here") - .emit(); - continue; - } - - // Resolve names into slots early. - // Since all the positional args are already seen at this point - // if the input is valid, we can simply append to the positional - // args. And remember the names. - let slot = args.len(); - names.insert(name, slot); - args.push(e); - } else { - let e = p.parse_expr()?; - args.push(e); - } - } - Ok((fmtstr, args, names)) -} - -impl<'a, 'b> Context<'a, 'b> { - fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) { - // NOTE: the `unwrap_or` branch is needed in case of invalid format - // arguments, e.g., `format_args!("{foo}")`. - let lookup = |s: Symbol| *self.names.get(&s).unwrap_or(&0); - - match *p { - parse::String(_) => {} - parse::NextArgument(ref mut arg) => { - if let parse::ArgumentNamed(s) = arg.position { - arg.position = parse::ArgumentIs(lookup(s)); - } - if let parse::CountIsName(s) = arg.format.width { - arg.format.width = parse::CountIsParam(lookup(s)); - } - if let parse::CountIsName(s) = arg.format.precision { - arg.format.precision = parse::CountIsParam(lookup(s)); - } - } - } - } - - /// Verifies one piece of a parse string, and remembers it if valid. - /// All errors are not emitted as fatal so we can continue giving errors - /// about this and possibly other format strings. - fn verify_piece(&mut self, p: &parse::Piece<'_>) { - match *p { - parse::String(..) => {} - parse::NextArgument(ref arg) => { - // width/precision first, if they have implicit positional - // parameters it makes more sense to consume them first. - self.verify_count(arg.format.width); - self.verify_count(arg.format.precision); - - // argument second, if it's an implicit positional parameter - // it's written second, so it should come after width/precision. - let pos = match arg.position { - parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i), - parse::ArgumentNamed(s) => Named(s), - }; - - let ty = Placeholder(arg.format.ty.to_string()); - self.verify_arg_type(pos, ty); - self.curpiece += 1; - } - } - } - - fn verify_count(&mut self, c: parse::Count) { - match c { - parse::CountImplied | - parse::CountIs(..) => {} - parse::CountIsParam(i) => { - self.verify_arg_type(Exact(i), Count); - } - parse::CountIsName(s) => { - self.verify_arg_type(Named(s), Count); - } - } - } - - fn describe_num_args(&self) -> Cow<'_, str> { - match self.args.len() { - 0 => "no arguments were given".into(), - 1 => "there is 1 argument".into(), - x => format!("there are {} arguments", x).into(), - } - } - - /// Handle invalid references to positional arguments. Output different - /// errors for the case where all arguments are positional and for when - /// there are named arguments or numbered positional arguments in the - /// format string. - fn report_invalid_references(&self, numbered_position_args: bool) { - let mut e; - let sp = if self.is_literal { - MultiSpan::from_spans(self.arg_spans.clone()) - } else { - MultiSpan::from_span(self.fmtsp) - }; - let refs_len = self.invalid_refs.len(); - let mut refs = self - .invalid_refs - .iter() - .map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos))); - - if self.names.is_empty() && !numbered_position_args { - e = self.ecx.mut_span_err( - sp, - &format!( - "{} positional argument{} in format string, but {}", - self.pieces.len(), - if self.pieces.len() > 1 { "s" } else { "" }, - self.describe_num_args() - ), - ); - } else { - let (arg_list, mut sp) = if refs_len == 1 { - let (reg, pos) = refs.next().unwrap(); - ( - format!("argument {}", reg), - MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)), - ) - } else { - let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); - let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect()); - let reg = refs.pop().unwrap(); - ( - format!( - "arguments {head} and {tail}", - head = refs.join(", "), - tail = reg, - ), - pos, - ) - }; - if !self.is_literal { - sp = MultiSpan::from_span(self.fmtsp); - } - - e = self.ecx.mut_span_err(sp, - &format!("invalid reference to positional {} ({})", - arg_list, - self.describe_num_args())); - e.note("positional arguments are zero-based"); - }; - - e.emit(); - } - - /// Actually verifies and tracks a given format placeholder - /// (a.k.a. argument). - fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { - match arg { - Exact(arg) => { - if self.args.len() <= arg { - self.invalid_refs.push((arg, self.curpiece)); - return; - } - match ty { - Placeholder(_) => { - // record every (position, type) combination only once - let ref mut seen_ty = self.arg_unique_types[arg]; - let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| { - let i = seen_ty.len(); - seen_ty.push(ty); - i - }); - self.arg_types[arg].push(i); - } - Count => { - if let Entry::Vacant(e) = self.count_positions.entry(arg) { - let i = self.count_positions_count; - e.insert(i); - self.count_args.push(Exact(arg)); - self.count_positions_count += 1; - } - } - } - } - - Named(name) => { - match self.names.get(&name) { - Some(&idx) => { - // Treat as positional arg. - self.verify_arg_type(Exact(idx), ty) - } - None => { - let msg = format!("there is no argument named `{}`", name); - let sp = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) - } else { - self.fmtsp - }; - let mut err = self.ecx.struct_span_err(sp, &msg[..]); - err.emit(); - } - } - } - } - } - - /// Builds the mapping between format placeholders and argument objects. - fn build_index_map(&mut self) { - // NOTE: Keep the ordering the same as `into_expr`'s expansion would do! - let args_len = self.args.len(); - self.arg_index_map.reserve(args_len); - - let mut sofar = 0usize; - - // Map the arguments - for i in 0..args_len { - let ref arg_types = self.arg_types[i]; - let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::>(); - self.arg_index_map.push(arg_offsets); - sofar += self.arg_unique_types[i].len(); - } - - // Record starting index for counts, which appear just after arguments - self.count_args_index_offset = sofar; - } - - fn rtpath(ecx: &ExtCtxt<'_>, s: &str) -> Vec { - ecx.std_path(&[sym::fmt, sym::rt, sym::v1, Symbol::intern(s)]) - } - - fn build_count(&self, c: parse::Count) -> P { - let sp = self.macsp; - let count = |c, arg| { - let mut path = Context::rtpath(self.ecx, "Count"); - path.push(self.ecx.ident_of(c)); - match arg { - Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]), - None => self.ecx.expr_path(self.ecx.path_global(sp, path)), - } - }; - match c { - parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))), - parse::CountIsParam(i) => { - // This needs mapping too, as `i` is referring to a macro - // argument. If `i` is not found in `count_positions` then - // the error had already been emitted elsewhere. - let i = self.count_positions.get(&i).cloned().unwrap_or(0) - + self.count_args_index_offset; - count("Param", Some(self.ecx.expr_usize(sp, i))) - } - parse::CountImplied => count("Implied", None), - // should never be the case, names are already resolved - parse::CountIsName(_) => panic!("should never happen"), - } - } - - /// Build a literal expression from the accumulated string literals - fn build_literal_string(&mut self) -> P { - let sp = self.fmtsp; - let s = Symbol::intern(&self.literal); - self.literal.clear(); - self.ecx.expr_str(sp, s) - } - - /// Builds a static `rt::Argument` from a `parse::Piece` or append - /// to the `literal` string. - fn build_piece(&mut self, - piece: &parse::Piece<'_>, - arg_index_consumed: &mut Vec) - -> Option> { - let sp = self.macsp; - match *piece { - parse::String(s) => { - self.literal.push_str(s); - None - } - parse::NextArgument(ref arg) => { - // Build the position - let pos = { - let pos = |c, arg| { - let mut path = Context::rtpath(self.ecx, "Position"); - path.push(self.ecx.ident_of(c)); - match arg { - Some(i) => { - let arg = self.ecx.expr_usize(sp, i); - self.ecx.expr_call_global(sp, path, vec![arg]) - } - None => self.ecx.expr_path(self.ecx.path_global(sp, path)), - } - }; - match arg.position { - parse::ArgumentIs(i) - | parse::ArgumentImplicitlyIs(i) => { - // Map to index in final generated argument array - // in case of multiple types specified - let arg_idx = match arg_index_consumed.get_mut(i) { - None => 0, // error already emitted elsewhere - Some(offset) => { - let ref idx_map = self.arg_index_map[i]; - // unwrap_or branch: error already emitted elsewhere - let arg_idx = *idx_map.get(*offset).unwrap_or(&0); - *offset += 1; - arg_idx - } - }; - pos("At", Some(arg_idx)) - } - - // should never be the case, because names are already - // resolved. - parse::ArgumentNamed(_) => panic!("should never happen"), - } - }; - - let simple_arg = parse::Argument { - position: { - // We don't have ArgumentNext any more, so we have to - // track the current argument ourselves. - let i = self.curarg; - self.curarg += 1; - parse::ArgumentIs(i) - }, - format: parse::FormatSpec { - fill: arg.format.fill, - align: parse::AlignUnknown, - flags: 0, - precision: parse::CountImplied, - width: parse::CountImplied, - ty: arg.format.ty, - }, - }; - - let fill = arg.format.fill.unwrap_or(' '); - - let pos_simple = - arg.position.index() == simple_arg.position.index(); - - if !pos_simple || arg.format != simple_arg.format || fill != ' ' { - self.all_pieces_simple = false; - } - - // Build the format - let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill)); - let align = |name| { - let mut p = Context::rtpath(self.ecx, "Alignment"); - p.push(self.ecx.ident_of(name)); - self.ecx.path_global(sp, p) - }; - let align = match arg.format.align { - parse::AlignLeft => align("Left"), - parse::AlignRight => align("Right"), - parse::AlignCenter => align("Center"), - parse::AlignUnknown => align("Unknown"), - }; - let align = self.ecx.expr_path(align); - let flags = self.ecx.expr_u32(sp, arg.format.flags); - let prec = self.build_count(arg.format.precision); - let width = self.build_count(arg.format.width); - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); - let fmt = self.ecx.expr_struct( - sp, - path, - vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill), - self.ecx.field_imm(sp, self.ecx.ident_of("align"), align), - self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags), - self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec), - self.ecx.field_imm(sp, self.ecx.ident_of("width"), width), - ], - ); - - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "Argument")); - Some(self.ecx.expr_struct( - sp, - path, - vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos), - self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt), - ], - )) - } - } - } - - /// Actually builds the expression which the format_args! block will be - /// expanded to. - fn into_expr(self) -> P { - let mut locals = Vec::with_capacity( - (0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum() - ); - let mut counts = Vec::with_capacity(self.count_args.len()); - let mut pats = Vec::with_capacity(self.args.len()); - let mut heads = Vec::with_capacity(self.args.len()); - - let names_pos: Vec<_> = (0..self.args.len()) - .map(|i| self.ecx.ident_of(&format!("arg{}", i)).gensym()) - .collect(); - - // First, build up the static array which will become our precompiled - // format "string" - let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces); - - // Before consuming the expressions, we have to remember spans for - // count arguments as they are now generated separate from other - // arguments, hence have no access to the `P`'s. - let spans_pos: Vec<_> = self.args.iter().map(|e| e.span.clone()).collect(); - - // Right now there is a bug such that for the expression: - // foo(bar(&1)) - // the lifetime of `1` doesn't outlast the call to `bar`, so it's not - // valid for the call to `foo`. To work around this all arguments to the - // format! string are shoved into locals. Furthermore, we shove the address - // of each variable because we don't want to move out of the arguments - // passed to this function. - for (i, e) in self.args.into_iter().enumerate() { - let name = names_pos[i]; - let span = - DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark)); - pats.push(self.ecx.pat_ident(span, name)); - for ref arg_ty in self.arg_unique_types[i].iter() { - locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name)); - } - heads.push(self.ecx.expr_addr_of(e.span, e)); - } - for pos in self.count_args { - let index = match pos { - Exact(i) => i, - _ => panic!("should never happen"), - }; - let name = names_pos[index]; - let span = spans_pos[index]; - counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name)); - } - - // Now create a vector containing all the arguments - let args = locals.into_iter().chain(counts.into_iter()); - - let args_array = self.ecx.expr_vec(self.fmtsp, args.collect()); - - // Constructs an AST equivalent to: - // - // match (&arg0, &arg1) { - // (tmp0, tmp1) => args_array - // } - // - // It was: - // - // let tmp0 = &arg0; - // let tmp1 = &arg1; - // args_array - // - // Because of #11585 the new temporary lifetime rule, the enclosing - // statements for these temporaries become the let's themselves. - // If one or more of them are RefCell's, RefCell borrow() will also - // end there; they don't last long enough for args_array to use them. - // The match expression solves the scope problem. - // - // Note, it may also very well be transformed to: - // - // match arg0 { - // ref tmp0 => { - // match arg1 => { - // ref tmp1 => args_array } } } - // - // But the nested match expression is proved to perform not as well - // as series of let's; the first approach does. - let pat = self.ecx.pat_tuple(self.fmtsp, pats); - let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array); - let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads)); - let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]); - - let args_slice = self.ecx.expr_addr_of(self.fmtsp, result); - - // Now create the fmt::Arguments struct with all our locals we created. - let (fn_name, fn_args) = if self.all_pieces_simple { - ("new_v1", vec![pieces, args_slice]) - } else { - // Build up the static array which will store our precompiled - // nonstandard placeholders, if there are any. - let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces); - - ("new_v1_formatted", vec![pieces, args_slice, fmt]) - }; - - let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]); - self.ecx.expr_call_global(self.macsp, path, fn_args) - } - - fn format_arg(ecx: &ExtCtxt<'_>, - macsp: Span, - mut sp: Span, - ty: &ArgumentType, - arg: ast::Ident) - -> P { - sp = sp.apply_mark(ecx.current_expansion.mark); - let arg = ecx.expr_ident(sp, arg); - let trait_ = match *ty { - Placeholder(ref tyname) => { - match &tyname[..] { - "" => "Display", - "?" => "Debug", - "e" => "LowerExp", - "E" => "UpperExp", - "o" => "Octal", - "p" => "Pointer", - "b" => "Binary", - "x" => "LowerHex", - "X" => "UpperHex", - _ => { - ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname)); - return DummyResult::raw_expr(sp, true); - } - } - } - Count => { - let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]); - return ecx.expr_call_global(macsp, path, vec![arg]); - } - }; - - let path = ecx.std_path(&[sym::fmt, Symbol::intern(trait_), sym::fmt]); - let format_fn = ecx.path_global(sp, path); - let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::new]); - ecx.expr_call_global(macsp, path, vec![arg, ecx.expr_path(format_fn)]) - } -} - -fn expand_format_args_impl<'cx>( - ecx: &'cx mut ExtCtxt<'_>, - mut sp: Span, - tts: &[tokenstream::TokenTree], - nl: bool, -) -> Box { - sp = sp.apply_mark(ecx.current_expansion.mark); - match parse_args(ecx, sp, tts) { - Ok((efmt, args, names)) => { - MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl)) - } - Err(mut err) => { - err.emit(); - DummyResult::expr(sp) - } - } -} - -pub fn expand_format_args<'cx>( - ecx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree], -) -> Box { - expand_format_args_impl(ecx, sp, tts, false) -} - -pub fn expand_format_args_nl<'cx>( - ecx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree], -) -> Box { - expand_format_args_impl(ecx, sp, tts, true) -} - -/// Take the various parts of `format_args!(efmt, args..., name=names...)` -/// and construct the appropriate formatting expression. -pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, - sp: Span, - efmt: P, - args: Vec>, - names: FxHashMap, - append_newline: bool) - -> P { - // NOTE: this verbose way of initializing `Vec>` is because - // `ArgumentType` does not derive `Clone`. - let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); - let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); - - let mut macsp = ecx.call_site(); - macsp = macsp.apply_mark(ecx.current_expansion.mark); - - let msg = "format argument must be a string literal"; - let fmt_sp = efmt.span; - let fmt = match expr_to_spanned_string(ecx, efmt, msg) { - Ok(mut fmt) if append_newline => { - fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0)); - fmt - } - Ok(fmt) => fmt, - Err(err) => { - if let Some(mut err) = err { - let sugg_fmt = match args.len() { - 0 => "{}".to_string(), - _ => format!("{}{{}}", "{} ".repeat(args.len())), - }; - err.span_suggestion( - fmt_sp.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{}\", ", sugg_fmt), - Applicability::MaybeIncorrect, - ); - err.emit(); - } - return DummyResult::raw_expr(sp, true); - } - }; - - let (is_literal, fmt_snippet) = match ecx.source_map().span_to_snippet(fmt_sp) { - Ok(s) => (s.starts_with("\"") || s.starts_with("r#"), Some(s)), - _ => (false, None), - }; - - let str_style = match fmt.node.1 { - ast::StrStyle::Cooked => None, - ast::StrStyle::Raw(raw) => { - Some(raw as usize) - }, - }; - - /// Finds the indices of all characters that have been processed and differ between the actual - /// written code (code snippet) and the `InternedString` that get's processed in the `Parser` - /// in order to properly synthethise the intra-string `Span`s for error diagnostics. - fn find_skips(snippet: &str, is_raw: bool) -> Vec { - let mut eat_ws = false; - let mut s = snippet.chars().enumerate().peekable(); - let mut skips = vec![]; - while let Some((pos, c)) = s.next() { - match (c, s.peek()) { - // skip whitespace and empty lines ending in '\\' - ('\\', Some((next_pos, '\n'))) if !is_raw => { - eat_ws = true; - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - ('\\', Some((next_pos, '\n'))) | - ('\\', Some((next_pos, 'n'))) | - ('\\', Some((next_pos, 't'))) if eat_ws => { - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - (' ', _) | - ('\n', _) | - ('\t', _) if eat_ws => { - skips.push(pos); - } - ('\\', Some((next_pos, 'n'))) | - ('\\', Some((next_pos, 't'))) | - ('\\', Some((next_pos, '0'))) | - ('\\', Some((next_pos, '\\'))) | - ('\\', Some((next_pos, '\''))) | - ('\\', Some((next_pos, '\"'))) => { - skips.push(*next_pos); - let _ = s.next(); - } - ('\\', Some((_, 'x'))) if !is_raw => { - for _ in 0..3 { // consume `\xAB` literal - if let Some((pos, _)) = s.next() { - skips.push(pos); - } else { - break; - } - } - } - ('\\', Some((_, 'u'))) if !is_raw => { - if let Some((pos, _)) = s.next() { - skips.push(pos); - } - if let Some((next_pos, next_c)) = s.next() { - if next_c == '{' { - skips.push(next_pos); - let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` - while let (Some((next_pos, c)), true) = (s.next(), i < 7) { - if c.is_digit(16) { - skips.push(next_pos); - } else if c == '}' { - skips.push(next_pos); - break; - } else { - break; - } - i += 1; - } - } else if next_c.is_digit(16) { - skips.push(next_pos); - // We suggest adding `{` and `}` when appropriate, accept it here as if - // it were correct - let mut i = 0; // consume up to 6 hexanumeric chars - while let (Some((next_pos, c)), _) = (s.next(), i < 6) { - if c.is_digit(16) { - skips.push(next_pos); - } else { - break; - } - i += 1; - } - } - } - } - _ if eat_ws => { // `take_while(|c| c.is_whitespace())` - eat_ws = false; - } - _ => {} - } - } - skips - } - - let skips = if let (true, Some(ref snippet)) = (is_literal, fmt_snippet.as_ref()) { - let r_start = str_style.map(|r| r + 1).unwrap_or(0); - let r_end = str_style.map(|r| r).unwrap_or(0); - let s = &snippet[r_start + 1..snippet.len() - r_end - 1]; - find_skips(s, str_style.is_some()) - } else { - vec![] - }; - - let fmt_str = &*fmt.node.0.as_str(); // for the suggestions below - let mut parser = parse::Parser::new(fmt_str, str_style, skips, append_newline); - - let mut unverified_pieces = Vec::new(); - while let Some(piece) = parser.next() { - if !parser.errors.is_empty() { - break; - } else { - unverified_pieces.push(piece); - } - } - - if !parser.errors.is_empty() { - let err = parser.errors.remove(0); - let sp = fmt.span.from_inner(err.span); - let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", - err.description)); - e.span_label(sp, err.label + " in format string"); - if let Some(note) = err.note { - e.note(¬e); - } - if let Some((label, span)) = err.secondary_label { - let sp = fmt.span.from_inner(span); - e.span_label(sp, label); - } - e.emit(); - return DummyResult::raw_expr(sp, true); - } - - let arg_spans = parser.arg_places.iter() - .map(|span| fmt.span.from_inner(*span)) - .collect(); - - let mut cx = Context { - ecx, - args, - arg_types, - arg_unique_types, - names, - curarg: 0, - curpiece: 0, - arg_index_map: Vec::new(), - count_args: Vec::new(), - count_positions: FxHashMap::default(), - count_positions_count: 0, - count_args_index_offset: 0, - literal: String::new(), - pieces: Vec::with_capacity(unverified_pieces.len()), - str_pieces: Vec::with_capacity(unverified_pieces.len()), - all_pieces_simple: true, - macsp, - fmtsp: fmt.span, - invalid_refs: Vec::new(), - arg_spans, - is_literal, - }; - - // This needs to happen *after* the Parser has consumed all pieces to create all the spans - let pieces = unverified_pieces.into_iter().map(|mut piece| { - cx.verify_piece(&piece); - cx.resolve_name_inplace(&mut piece); - piece - }).collect::>(); - - let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| { - match *arg { - parse::String(_) => false, - parse::NextArgument(arg) => { - match arg.position { - parse::Position::ArgumentIs(_) => true, - _ => false, - } - } - } - }); - - cx.build_index_map(); - - let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()]; - - for piece in pieces { - if let Some(piece) = cx.build_piece(&piece, &mut arg_index_consumed) { - let s = cx.build_literal_string(); - cx.str_pieces.push(s); - cx.pieces.push(piece); - } - } - - if !cx.literal.is_empty() { - let s = cx.build_literal_string(); - cx.str_pieces.push(s); - } - - if cx.invalid_refs.len() >= 1 { - cx.report_invalid_references(numbered_position_args); - } - - // Make sure that all arguments were used and all arguments have types. - let num_pos_args = cx.args.len() - cx.names.len(); - - let errs = cx.arg_types - .iter() - .enumerate() - .filter(|(i, ty)| ty.is_empty() && !cx.count_positions.contains_key(&i)) - .map(|(i, _)| { - let msg = if i >= num_pos_args { - // named argument - "named argument never used" - } else { - // positional argument - "argument never used" - }; - (cx.args[i].span, msg) - }) - .collect::>(); - - let errs_len = errs.len(); - if !errs.is_empty() { - let args_used = cx.arg_types.len() - errs_len; - let args_unused = errs_len; - - let mut diag = { - if errs_len == 1 { - let (sp, msg) = errs.into_iter().next().unwrap(); - let mut diag = cx.ecx.struct_span_err(sp, msg); - diag.span_label(sp, msg); - diag - } else { - let mut diag = cx.ecx.struct_span_err( - errs.iter().map(|&(sp, _)| sp).collect::>(), - "multiple unused formatting arguments", - ); - diag.span_label(cx.fmtsp, "multiple missing formatting specifiers"); - for (sp, msg) in errs { - diag.span_label(sp, msg); - } - diag - } - }; - - // Used to ensure we only report translations for *one* kind of foreign format. - let mut found_foreign = false; - // Decide if we want to look for foreign formatting directives. - if args_used < args_unused { - use super::format_foreign as foreign; - - // The set of foreign substitutions we've explained. This prevents spamming the user - // with `%d should be written as {}` over and over again. - let mut explained = FxHashSet::default(); - - macro_rules! check_foreign { - ($kind:ident) => {{ - let mut show_doc_note = false; - - let mut suggestions = vec![]; - // account for `"` and account for raw strings `r#` - let padding = str_style.map(|i| i + 2).unwrap_or(1); - for sub in foreign::$kind::iter_subs(fmt_str, padding) { - let trn = match sub.translate() { - Some(trn) => trn, - - // If it has no translation, don't call it out specifically. - None => continue, - }; - - let pos = sub.position(); - let sub = String::from(sub.as_str()); - if explained.contains(&sub) { - continue; - } - explained.insert(sub.clone()); - - if !found_foreign { - found_foreign = true; - show_doc_note = true; - } - - if let Some(inner_sp) = pos { - let sp = fmt_sp.from_inner(inner_sp); - suggestions.push((sp, trn)); - } else { - diag.help(&format!("`{}` should be written as `{}`", sub, trn)); - } - } - - if show_doc_note { - diag.note(concat!( - stringify!($kind), - " formatting not supported; see the documentation for `std::fmt`", - )); - } - if suggestions.len() > 0 { - diag.multipart_suggestion( - "format specifiers use curly braces", - suggestions, - Applicability::MachineApplicable, - ); - } - }}; - } - - check_foreign!(printf); - if !found_foreign { - check_foreign!(shell); - } - } - if !found_foreign && errs_len == 1 { - diag.span_label(cx.fmtsp, "formatting specifier missing"); - } - - diag.emit(); - } - - cx.into_expr() -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign.rs b/gcc/rust/rustc_parser/libsyntax_ext/format_foreign.rs deleted file mode 100644 index 3d4f827..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign.rs +++ /dev/null @@ -1,836 +0,0 @@ -pub mod printf { - use super::strcursor::StrCursor as Cur; - use syntax_pos::InnerSpan; - - /// Represents a single `printf`-style substitution. - #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { - /// A formatted output substitution with its internal byte offset. - Format(Format<'a>), - /// A literal `%%` escape. - Escape, - } - - impl<'a> Substitution<'a> { - pub fn as_str(&self) -> &str { - match *self { - Substitution::Format(ref fmt) => fmt.span, - Substitution::Escape => "%%", - } - } - - pub fn position(&self) -> Option { - match *self { - Substitution::Format(ref fmt) => Some(fmt.position), - _ => None, - } - } - - pub fn set_position(&mut self, start: usize, end: usize) { - match self { - Substitution::Format(ref mut fmt) => { - fmt.position = InnerSpan::new(start, end); - } - _ => {} - } - } - - - /// Translate this substitution into an equivalent Rust formatting directive. - /// - /// This ignores cases where the substitution does not have an exact equivalent, or where - /// the substitution would be unnecessary. - pub fn translate(&self) -> Option { - match *self { - Substitution::Format(ref fmt) => fmt.translate(), - Substitution::Escape => None, - } - } - } - - #[derive(Clone, PartialEq, Debug)] - /// A single `printf`-style formatting directive. - pub struct Format<'a> { - /// The entire original formatting directive. - pub span: &'a str, - /// The (1-based) parameter to be converted. - pub parameter: Option, - /// Formatting flags. - pub flags: &'a str, - /// Minimum width of the output. - pub width: Option, - /// Precision of the conversion. - pub precision: Option, - /// Length modifier for the conversion. - pub length: Option<&'a str>, - /// Type of parameter being converted. - pub type_: &'a str, - /// Byte offset for the start and end of this formatting directive. - pub position: InnerSpan, - } - - impl Format<'_> { - /// Translate this directive into an equivalent Rust formatting directive. - /// - /// Returns `None` in cases where the `printf` directive does not have an exact Rust - /// equivalent, rather than guessing. - pub fn translate(&self) -> Option { - use std::fmt::Write; - - let (c_alt, c_zero, c_left, c_plus) = { - let mut c_alt = false; - let mut c_zero = false; - let mut c_left = false; - let mut c_plus = false; - for c in self.flags.chars() { - match c { - '#' => c_alt = true, - '0' => c_zero = true, - '-' => c_left = true, - '+' => c_plus = true, - _ => return None - } - } - (c_alt, c_zero, c_left, c_plus) - }; - - // Has a special form in Rust for numbers. - let fill = if c_zero { Some("0") } else { None }; - - let align = if c_left { Some("<") } else { None }; - - // Rust doesn't have an equivalent to the `' '` flag. - let sign = if c_plus { Some("+") } else { None }; - - // Not *quite* the same, depending on the type... - let alt = c_alt; - - let width = match self.width { - Some(Num::Next) => { - // NOTE: Rust doesn't support this. - return None; - } - w @ Some(Num::Arg(_)) => w, - w @ Some(Num::Num(_)) => w, - None => None, - }; - - let precision = self.precision; - - // NOTE: although length *can* have an effect, we can't duplicate the effect in Rust, so - // we just ignore it. - - let (type_, use_zero_fill, is_int) = match self.type_ { - "d" | "i" | "u" => (None, true, true), - "f" | "F" => (None, false, false), - "s" | "c" => (None, false, false), - "e" | "E" => (Some(self.type_), true, false), - "x" | "X" | "o" => (Some(self.type_), true, true), - "p" => (Some(self.type_), false, true), - "g" => (Some("e"), true, false), - "G" => (Some("E"), true, false), - _ => return None, - }; - - let (fill, width, precision) = match (is_int, width, precision) { - (true, Some(_), Some(_)) => { - // Rust can't duplicate this insanity. - return None; - }, - (true, None, Some(p)) => (Some("0"), Some(p), None), - (true, w, None) => (fill, w, None), - (false, w, p) => (fill, w, p), - }; - - let align = match (self.type_, width.is_some(), align.is_some()) { - ("s", true, false) => Some(">"), - _ => align, - }; - - let (fill, zero_fill) = match (fill, use_zero_fill) { - (Some("0"), true) => (None, true), - (fill, _) => (fill, false), - }; - - let alt = match type_ { - Some("x") | Some("X") => alt, - _ => false, - }; - - let has_options = fill.is_some() - || align.is_some() - || sign.is_some() - || alt - || zero_fill - || width.is_some() - || precision.is_some() - || type_.is_some() - ; - - // Initialise with a rough guess. - let cap = self.span.len() + if has_options { 2 } else { 0 }; - let mut s = String::with_capacity(cap); - - s.push_str("{"); - - if let Some(arg) = self.parameter { - write!(s, "{}", arg.checked_sub(1)?).ok()?; - } - - if has_options { - s.push_str(":"); - - let align = if let Some(fill) = fill { - s.push_str(fill); - align.or(Some(">")) - } else { - align - }; - - if let Some(align) = align { - s.push_str(align); - } - - if let Some(sign) = sign { - s.push_str(sign); - } - - if alt { - s.push_str("#"); - } - - if zero_fill { - s.push_str("0"); - } - - if let Some(width) = width { - width.translate(&mut s).ok()?; - } - - if let Some(precision) = precision { - s.push_str("."); - precision.translate(&mut s).ok()?; - } - - if let Some(type_) = type_ { - s.push_str(type_); - } - } - - s.push_str("}"); - Some(s) - } - } - - /// A general number used in a `printf` formatting directive. - #[derive(Copy, Clone, PartialEq, Debug)] - pub enum Num { - // The range of these values is technically bounded by `NL_ARGMAX`... but, at least for GNU - // libc, it apparently has no real fixed limit. A `u16` is used here on the basis that it - // is *vanishingly* unlikely that *anyone* is going to try formatting something wider, or - // with more precision, than 32 thousand positions which is so wide it couldn't possibly fit - // on a screen. - - /// A specific, fixed value. - Num(u16), - /// The value is derived from a positional argument. - Arg(u16), - /// The value is derived from the "next" unconverted argument. - Next, - } - - impl Num { - fn from_str(s: &str, arg: Option<&str>) -> Self { - if let Some(arg) = arg { - Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{:?}`", arg))) - } else if s == "*" { - Num::Next - } else { - Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{:?}`", s))) - } - } - - fn translate(&self, s: &mut String) -> std::fmt::Result { - use std::fmt::Write; - match *self { - Num::Num(n) => write!(s, "{}", n), - Num::Arg(n) => { - let n = n.checked_sub(1).ok_or(std::fmt::Error)?; - write!(s, "{}$", n) - }, - Num::Next => write!(s, "*"), - } - } - } - - /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { - Substitutions { - s, - pos: start_pos, - } - } - - /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { - s: &'a str, - pos: usize, - } - - impl<'a> Iterator for Substitutions<'a> { - type Item = Substitution<'a>; - fn next(&mut self) -> Option { - let (mut sub, tail) = parse_next_substitution(self.s)?; - self.s = tail; - match sub { - Substitution::Format(_) => if let Some(inner_span) = sub.position() { - sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos); - self.pos += inner_span.end; - } - Substitution::Escape => self.pos += 2, - } - Some(sub) - } - - fn size_hint(&self) -> (usize, Option) { - // Substitutions are at least 2 characters long. - (0, Some(self.s.len() / 2)) - } - } - - enum State { - Start, - Flags, - Width, - WidthArg, - Prec, - PrecInner, - Length, - Type, - } - - /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { - use self::State::*; - - let at = { - let start = s.find('%')?; - match s[start+1..].chars().next()? { - '%' => return Some((Substitution::Escape, &s[start+2..])), - _ => {/* fall-through */}, - } - - Cur::new_at(&s[..], start) - }; - - // This is meant to be a translation of the following regex: - // - // ```regex - // (?x) - // ^ % - // (?: (?P \d+) \$ )? - // (?P [-+ 0\#']* ) - // (?P \d+ | \* (?: (?P \d+) \$ )? )? - // (?: \. (?P \d+ | \* (?: (?P \d+) \$ )? ) )? - // (?P - // # Standard - // hh | h | ll | l | L | z | j | t - // - // # Other - // | I32 | I64 | I | q - // )? - // (?P . ) - // ``` - - // Used to establish the full span at the end. - let start = at; - // The current position within the string. - let mut at = at.at_next_cp()?; - // `c` is the next codepoint, `next` is a cursor after it. - let (mut c, mut next) = at.next_cp()?; - - // Update `at`, `c`, and `next`, exiting if we're out of input. - macro_rules! move_to { - ($cur:expr) => { - { - at = $cur; - let (c_, next_) = at.next_cp()?; - c = c_; - next = next_; - } - }; - } - - // Constructs a result when parsing fails. - // - // Note: `move` used to capture copies of the cursors as they are *now*. - let fallback = move || { - return Some(( - Substitution::Format(Format { - span: start.slice_between(next).unwrap(), - parameter: None, - flags: "", - width: None, - precision: None, - length: None, - type_: at.slice_between(next).unwrap(), - position: InnerSpan::new(start.at, next.at), - }), - next.slice_after() - )); - }; - - // Next parsing state. - let mut state = Start; - - // Sadly, Rust isn't *quite* smart enough to know these *must* be initialised by the end. - let mut parameter: Option = None; - let mut flags: &str = ""; - let mut width: Option = None; - let mut precision: Option = None; - let mut length: Option<&str> = None; - let mut type_: &str = ""; - let end: Cur<'_>; - - if let Start = state { - match c { - '1'..='9' => { - let end = at_next_cp_while(next, is_digit); - match end.next_cp() { - // Yes, this *is* the parameter. - Some(('$', end2)) => { - state = Flags; - parameter = Some(at.slice_between(end).unwrap().parse().unwrap()); - move_to!(end2); - }, - // Wait, no, actually, it's the width. - Some(_) => { - state = Prec; - parameter = None; - flags = ""; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); - move_to!(end); - }, - // It's invalid, is what it is. - None => return fallback(), - } - }, - _ => { - state = Flags; - parameter = None; - move_to!(at); - } - } - } - - if let Flags = state { - let end = at_next_cp_while(at, is_flag); - state = Width; - flags = at.slice_between(end).unwrap(); - move_to!(end); - } - - if let Width = state { - match c { - '*' => { - state = WidthArg; - move_to!(next); - }, - '1' ..= '9' => { - let end = at_next_cp_while(next, is_digit); - state = Prec; - width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); - move_to!(end); - }, - _ => { - state = Prec; - width = None; - move_to!(at); - } - } - } - - if let WidthArg = state { - let end = at_next_cp_while(at, is_digit); - match end.next_cp() { - Some(('$', end2)) => { - state = Prec; - width = Some(Num::from_str("", Some(at.slice_between(end).unwrap()))); - move_to!(end2); - }, - _ => { - state = Prec; - width = Some(Num::Next); - move_to!(end); - } - } - } - - if let Prec = state { - match c { - '.' => { - state = PrecInner; - move_to!(next); - }, - _ => { - state = Length; - precision = None; - move_to!(at); - } - } - } - - if let PrecInner = state { - match c { - '*' => { - let end = at_next_cp_while(next, is_digit); - match end.next_cp() { - Some(('$', end2)) => { - state = Length; - precision = Some(Num::from_str("*", next.slice_between(end))); - move_to!(end2); - }, - _ => { - state = Length; - precision = Some(Num::Next); - move_to!(end); - } - } - }, - '0' ..= '9' => { - let end = at_next_cp_while(next, is_digit); - state = Length; - precision = Some(Num::from_str(at.slice_between(end).unwrap(), None)); - move_to!(end); - }, - _ => return fallback(), - } - } - - if let Length = state { - let c1_next1 = next.next_cp(); - match (c, c1_next1) { - ('h', Some(('h', next1))) - | ('l', Some(('l', next1))) - => { - state = Type; - length = Some(at.slice_between(next1).unwrap()); - move_to!(next1); - }, - - ('h', _) | ('l', _) | ('L', _) - | ('z', _) | ('j', _) | ('t', _) - | ('q', _) - => { - state = Type; - length = Some(at.slice_between(next).unwrap()); - move_to!(next); - }, - - ('I', _) => { - let end = next.at_next_cp() - .and_then(|end| end.at_next_cp()) - .map(|end| (next.slice_between(end).unwrap(), end)); - let end = match end { - Some(("32", end)) => end, - Some(("64", end)) => end, - _ => next - }; - state = Type; - length = Some(at.slice_between(end).unwrap()); - move_to!(end); - }, - - _ => { - state = Type; - length = None; - move_to!(at); - } - } - } - - if let Type = state { - drop(c); - type_ = at.slice_between(next).unwrap(); - - // Don't use `move_to!` here, as we *can* be at the end of the input. - at = next; - } - - drop(c); - drop(next); - - end = at; - let position = InnerSpan::new(start.at, end.at); - - let f = Format { - span: start.slice_between(end).unwrap(), - parameter, - flags, - width, - precision, - length, - type_, - position, - }; - Some((Substitution::Format(f), end.slice_after())) - } - - fn at_next_cp_while(mut cur: Cur<'_>, mut pred: F) -> Cur<'_> - where F: FnMut(char) -> bool { - loop { - match cur.next_cp() { - Some((c, next)) => if pred(c) { - cur = next; - } else { - return cur; - }, - None => return cur, - } - } - } - - fn is_digit(c: char) -> bool { - match c { - '0' ..= '9' => true, - _ => false - } - } - - fn is_flag(c: char) -> bool { - match c { - '0' | '-' | '+' | ' ' | '#' | '\'' => true, - _ => false - } - } - - #[cfg(test)] - mod tests; -} - -pub mod shell { - use super::strcursor::StrCursor as Cur; - use syntax_pos::InnerSpan; - - #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { - Ordinal(u8, (usize, usize)), - Name(&'a str, (usize, usize)), - Escape((usize, usize)), - } - - impl Substitution<'_> { - pub fn as_str(&self) -> String { - match self { - Substitution::Ordinal(n, _) => format!("${}", n), - Substitution::Name(n, _) => format!("${}", n), - Substitution::Escape(_) => "$$".into(), - } - } - - pub fn position(&self) -> Option { - match self { - Substitution::Ordinal(_, pos) | - Substitution::Name(_, pos) | - Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)), - } - } - - pub fn set_position(&mut self, start: usize, end: usize) { - match self { - Substitution::Ordinal(_, ref mut pos) | - Substitution::Name(_, ref mut pos) | - Substitution::Escape(ref mut pos) => *pos = (start, end), - } - } - - pub fn translate(&self) -> Option { - match *self { - Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)), - Substitution::Name(n, _) => Some(format!("{{{}}}", n)), - Substitution::Escape(_) => None, - } - } - } - - /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { - Substitutions { - s, - pos: start_pos, - } - } - - /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { - s: &'a str, - pos: usize, - } - - impl<'a> Iterator for Substitutions<'a> { - type Item = Substitution<'a>; - fn next(&mut self) -> Option { - match parse_next_substitution(self.s) { - Some((mut sub, tail)) => { - self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } - Some(sub) - }, - None => None, - } - } - - fn size_hint(&self) -> (usize, Option) { - (0, Some(self.s.len())) - } - } - - /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { - let at = { - let start = s.find('$')?; - match s[start+1..].chars().next()? { - '$' => return Some((Substitution::Escape((start, start+2)), &s[start+2..])), - c @ '0' ..= '9' => { - let n = (c as u8) - b'0'; - return Some((Substitution::Ordinal(n, (start, start+2)), &s[start+2..])); - }, - _ => {/* fall-through */}, - } - - Cur::new_at(&s[..], start) - }; - - let at = at.at_next_cp()?; - let (c, inner) = at.next_cp()?; - - if !is_ident_head(c) { - None - } else { - let end = at_next_cp_while(inner, is_ident_tail); - let slice = at.slice_between(end).unwrap(); - let start = at.at - 1; - let end_pos = at.at + slice.len(); - Some((Substitution::Name(slice, (start, end_pos)), end.slice_after())) - } - } - - fn at_next_cp_while(mut cur: Cur<'_>, mut pred: F) -> Cur<'_> - where F: FnMut(char) -> bool { - loop { - match cur.next_cp() { - Some((c, next)) => if pred(c) { - cur = next; - } else { - return cur; - }, - None => return cur, - } - } - } - - fn is_ident_head(c: char) -> bool { - match c { - 'a' ..= 'z' | 'A' ..= 'Z' | '_' => true, - _ => false - } - } - - fn is_ident_tail(c: char) -> bool { - match c { - '0' ..= '9' => true, - c => is_ident_head(c) - } - } - - #[cfg(test)] - mod tests; -} - -mod strcursor { - pub struct StrCursor<'a> { - s: &'a str, - pub at: usize, - } - - impl<'a> StrCursor<'a> { - pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { - StrCursor { - s, - at, - } - } - - pub fn at_next_cp(mut self) -> Option> { - match self.try_seek_right_cp() { - true => Some(self), - false => None - } - } - - pub fn next_cp(mut self) -> Option<(char, StrCursor<'a>)> { - let cp = self.cp_after()?; - self.seek_right(cp.len_utf8()); - Some((cp, self)) - } - - fn slice_before(&self) -> &'a str { - &self.s[0..self.at] - } - - pub fn slice_after(&self) -> &'a str { - &self.s[self.at..] - } - - pub fn slice_between(&self, until: StrCursor<'a>) -> Option<&'a str> { - if !str_eq_literal(self.s, until.s) { - None - } else { - use std::cmp::{max, min}; - let beg = min(self.at, until.at); - let end = max(self.at, until.at); - Some(&self.s[beg..end]) - } - } - - fn cp_after(&self) -> Option { - self.slice_after().chars().next() - } - - fn try_seek_right_cp(&mut self) -> bool { - match self.slice_after().chars().next() { - Some(c) => { - self.at += c.len_utf8(); - true - }, - None => false, - } - } - - fn seek_right(&mut self, bytes: usize) { - self.at += bytes; - } - } - - impl Copy for StrCursor<'_> {} - - impl<'a> Clone for StrCursor<'a> { - fn clone(&self) -> StrCursor<'a> { - *self - } - } - - impl std::fmt::Debug for StrCursor<'_> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "StrCursor({:?} | {:?})", self.slice_before(), self.slice_after()) - } - } - - fn str_eq_literal(a: &str, b: &str) -> bool { - a.as_bytes().as_ptr() == b.as_bytes().as_ptr() - && a.len() == b.len() - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/printf/tests.rs b/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/printf/tests.rs deleted file mode 100644 index 87021f1..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/printf/tests.rs +++ /dev/null @@ -1,151 +0,0 @@ -use super::{ - Format as F, - Num as N, - Substitution as S, - iter_subs, - parse_next_substitution as pns, -}; - -macro_rules! assert_eq_pnsat { - ($lhs:expr, $rhs:expr) => { - assert_eq!( - pns($lhs).and_then(|(s, _)| s.translate()), - $rhs.map(>::from) - ) - }; -} - -#[test] -fn test_escape() { - assert_eq!(pns("has no escapes"), None); - assert_eq!(pns("has no escapes, either %"), None); - assert_eq!(pns("*so* has a %% escape"), Some((S::Escape," escape"))); - assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); - assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); -} - -#[test] -fn test_parse() { - macro_rules! assert_pns_eq_sub { - ($in_:expr, { - $param:expr, $flags:expr, - $width:expr, $prec:expr, $len:expr, $type_:expr, - $pos:expr, - }) => { - assert_eq!( - pns(concat!($in_, "!")), - Some(( - S::Format(F { - span: $in_, - parameter: $param, - flags: $flags, - width: $width, - precision: $prec, - length: $len, - type_: $type_, - position: syntax_pos::InnerSpan::new($pos.0, $pos.1), - }), - "!" - )) - ) - }; - } - - assert_pns_eq_sub!("%!", - { None, "", None, None, None, "!", (0, 2), }); - assert_pns_eq_sub!("%c", - { None, "", None, None, None, "c", (0, 2), }); - assert_pns_eq_sub!("%s", - { None, "", None, None, None, "s", (0, 2), }); - assert_pns_eq_sub!("%06d", - { None, "0", Some(N::Num(6)), None, None, "d", (0, 4), }); - assert_pns_eq_sub!("%4.2f", - { None, "", Some(N::Num(4)), Some(N::Num(2)), None, "f", (0, 5), }); - assert_pns_eq_sub!("%#x", - { None, "#", None, None, None, "x", (0, 3), }); - assert_pns_eq_sub!("%-10s", - { None, "-", Some(N::Num(10)), None, None, "s", (0, 5), }); - assert_pns_eq_sub!("%*s", - { None, "", Some(N::Next), None, None, "s", (0, 3), }); - assert_pns_eq_sub!("%-10.*s", - { None, "-", Some(N::Num(10)), Some(N::Next), None, "s", (0, 7), }); - assert_pns_eq_sub!("%-*.*s", - { None, "-", Some(N::Next), Some(N::Next), None, "s", (0, 6), }); - assert_pns_eq_sub!("%.6i", - { None, "", None, Some(N::Num(6)), None, "i", (0, 4), }); - assert_pns_eq_sub!("%+i", - { None, "+", None, None, None, "i", (0, 3), }); - assert_pns_eq_sub!("%08X", - { None, "0", Some(N::Num(8)), None, None, "X", (0, 4), }); - assert_pns_eq_sub!("%lu", - { None, "", None, None, Some("l"), "u", (0, 3), }); - assert_pns_eq_sub!("%Iu", - { None, "", None, None, Some("I"), "u", (0, 3), }); - assert_pns_eq_sub!("%I32u", - { None, "", None, None, Some("I32"), "u", (0, 5), }); - assert_pns_eq_sub!("%I64u", - { None, "", None, None, Some("I64"), "u", (0, 5), }); - assert_pns_eq_sub!("%'d", - { None, "'", None, None, None, "d", (0, 3), }); - assert_pns_eq_sub!("%10s", - { None, "", Some(N::Num(10)), None, None, "s", (0, 4), }); - assert_pns_eq_sub!("%-10.10s", - { None, "-", Some(N::Num(10)), Some(N::Num(10)), None, "s", (0, 8), }); - assert_pns_eq_sub!("%1$d", - { Some(1), "", None, None, None, "d", (0, 4), }); - assert_pns_eq_sub!("%2$.*3$d", - { Some(2), "", None, Some(N::Arg(3)), None, "d", (0, 8), }); - assert_pns_eq_sub!("%1$*2$.*3$d", - { Some(1), "", Some(N::Arg(2)), Some(N::Arg(3)), None, "d", (0, 11), }); - assert_pns_eq_sub!("%-8ld", - { None, "-", Some(N::Num(8)), None, Some("l"), "d", (0, 5), }); -} - -#[test] -fn test_iter() { - let s = "The %d'th word %% is: `%.*s` %!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); - assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), - vec![Some("{}"), None, Some("{:.*}"), None] - ); -} - -/// Checks that the translations are what we expect. -#[test] -fn test_translation() { - assert_eq_pnsat!("%c", Some("{}")); - assert_eq_pnsat!("%d", Some("{}")); - assert_eq_pnsat!("%u", Some("{}")); - assert_eq_pnsat!("%x", Some("{:x}")); - assert_eq_pnsat!("%X", Some("{:X}")); - assert_eq_pnsat!("%e", Some("{:e}")); - assert_eq_pnsat!("%E", Some("{:E}")); - assert_eq_pnsat!("%f", Some("{}")); - assert_eq_pnsat!("%g", Some("{:e}")); - assert_eq_pnsat!("%G", Some("{:E}")); - assert_eq_pnsat!("%s", Some("{}")); - assert_eq_pnsat!("%p", Some("{:p}")); - - assert_eq_pnsat!("%06d", Some("{:06}")); - assert_eq_pnsat!("%4.2f", Some("{:4.2}")); - assert_eq_pnsat!("%#x", Some("{:#x}")); - assert_eq_pnsat!("%-10s", Some("{:<10}")); - assert_eq_pnsat!("%*s", None); - assert_eq_pnsat!("%-10.*s", Some("{:<10.*}")); - assert_eq_pnsat!("%-*.*s", None); - assert_eq_pnsat!("%.6i", Some("{:06}")); - assert_eq_pnsat!("%+i", Some("{:+}")); - assert_eq_pnsat!("%08X", Some("{:08X}")); - assert_eq_pnsat!("%lu", Some("{}")); - assert_eq_pnsat!("%Iu", Some("{}")); - assert_eq_pnsat!("%I32u", Some("{}")); - assert_eq_pnsat!("%I64u", Some("{}")); - assert_eq_pnsat!("%'d", None); - assert_eq_pnsat!("%10s", Some("{:>10}")); - assert_eq_pnsat!("%-10.10s", Some("{:<10.10}")); - assert_eq_pnsat!("%1$d", Some("{0}")); - assert_eq_pnsat!("%2$.*3$d", Some("{1:02$}")); - assert_eq_pnsat!("%1$*2$.*3$s", Some("{0:>1$.2$}")); - assert_eq_pnsat!("%-8ld", Some("{:<8}")); -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/shell/tests.rs b/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/shell/tests.rs deleted file mode 100644 index 8ef58b8..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/format_foreign/shell/tests.rs +++ /dev/null @@ -1,59 +0,0 @@ -use super::{ - Substitution as S, - parse_next_substitution as pns, -}; - -macro_rules! assert_eq_pnsat { - ($lhs:expr, $rhs:expr) => { - assert_eq!( - pns($lhs).and_then(|(f, _)| f.translate()), - $rhs.map(>::from) - ) - }; -} - -#[test] -fn test_escape() { - assert_eq!(pns("has no escapes"), None); - assert_eq!(pns("has no escapes, either $"), None); - assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape"))); - assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape"))); - assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), ""))); -} - -#[test] -fn test_parse() { - macro_rules! assert_pns_eq_sub { - ($in_:expr, $kind:ident($arg:expr, $pos:expr)) => { - assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!"))) - }; - } - - assert_pns_eq_sub!("$0", Ordinal(0, (0, 2))); - assert_pns_eq_sub!("$1", Ordinal(1, (0, 2))); - assert_pns_eq_sub!("$9", Ordinal(9, (0, 2))); - assert_pns_eq_sub!("$N", Name("N", (0, 2))); - assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5))); -} - -#[test] -fn test_iter() { - use super::iter_subs; - let s = "The $0'th word $$ is: `$WORD` $!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); - assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), - vec![Some("{0}"), None, Some("{WORD}")] - ); -} - -#[test] -fn test_translation() { - assert_eq_pnsat!("$0", Some("{0}")); - assert_eq_pnsat!("$9", Some("{9}")); - assert_eq_pnsat!("$1", Some("{1}")); - assert_eq_pnsat!("$10", Some("{1}")); - assert_eq_pnsat!("$stuff", Some("{stuff}")); - assert_eq_pnsat!("$NAME", Some("{NAME}")); - assert_eq_pnsat!("$PREFIX/bin", Some("{PREFIX}")); -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/global_asm.rs b/gcc/rust/rustc_parser/libsyntax_ext/global_asm.rs deleted file mode 100644 index 112192f..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/global_asm.rs +++ /dev/null @@ -1,68 +0,0 @@ -/// Module-level assembly support. -/// -/// The macro defined here allows you to specify "top-level", -/// "file-scoped", or "module-level" assembly. These synonyms -/// all correspond to LLVM's module-level inline assembly instruction. -/// -/// For example, `global_asm!("some assembly here")` codegens to -/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats -/// therefore apply. - -use errors::DiagnosticBuilder; - -use syntax::ast; -use syntax::source_map::respan; -use syntax::ext::base::{self, *}; -use syntax::parse::token; -use syntax::ptr::P; -use syntax_pos::Span; -use syntax::tokenstream; -use smallvec::smallvec; - -pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: &[tokenstream::TokenTree]) -> Box { - match parse_global_asm(cx, sp, tts) { - Ok(Some(global_asm)) => { - MacEager::items(smallvec![P(ast::Item { - ident: ast::Ident::invalid(), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::GlobalAsm(P(global_asm)), - vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - span: sp, - tokens: None, - })]) - } - Ok(None) => DummyResult::any(sp), - Err(mut err) => { - err.emit(); - DummyResult::any(sp) - } - } -} - -fn parse_global_asm<'a>( - cx: &mut ExtCtxt<'a>, - sp: Span, - tts: &[tokenstream::TokenTree] -) -> Result, DiagnosticBuilder<'a>> { - let mut p = cx.new_parser_from_tts(tts); - - if p.token == token::Eof { - let mut err = cx.struct_span_err(sp, "macro requires a string literal as an argument"); - err.span_label(sp, "string literal required"); - return Err(err); - } - - let expr = p.parse_expr()?; - let (asm, _) = match expr_to_string(cx, expr, "inline assembly must be a string literal") { - Some((s, st)) => (s, st), - None => return Ok(None), - }; - - Ok(Some(ast::GlobalAsm { - asm, - ctxt: cx.backtrace(), - })) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/lib.rs b/gcc/rust/rustc_parser/libsyntax_ext/lib.rs deleted file mode 100644 index 62530f4..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/lib.rs +++ /dev/null @@ -1,168 +0,0 @@ -//! Syntax extensions in the Rust compiler. - -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] - -#![deny(rust_2018_idioms)] -#![deny(unused_lifetimes)] - -#![feature(in_band_lifetimes)] -#![feature(proc_macro_diagnostic)] -#![feature(proc_macro_internals)] -#![feature(proc_macro_span)] -#![feature(decl_macro)] -#![feature(nll)] -#![feature(rustc_diagnostic_macros)] - -#![recursion_limit="256"] - -extern crate proc_macro; - -mod error_codes; - -mod asm; -mod assert; -mod cfg; -mod compile_error; -mod concat; -mod concat_idents; -mod env; -mod format; -mod format_foreign; -mod global_asm; -mod log_syntax; -mod proc_macro_server; -mod test; -mod test_case; -mod trace_macros; - -pub mod deriving; -pub mod proc_macro_decls; -pub mod proc_macro_impl; - -use rustc_data_structures::sync::Lrc; -use syntax::ast; -use syntax::attr::Stability; -use syntax::ext::base::MacroExpanderFn; -use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind}; -use syntax::edition::Edition; -use syntax::symbol::{sym, Symbol}; - -const EXPLAIN_ASM: &str = - "inline assembly is not stable enough for use and is subject to change"; -const EXPLAIN_GLOBAL_ASM: &str = - "`global_asm!` is not stable enough for use and is subject to change"; -const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str = - "custom test frameworks are an unstable feature"; -const EXPLAIN_LOG_SYNTAX: &str = - "`log_syntax!` is not stable enough for use and is subject to change"; -const EXPLAIN_CONCAT_IDENTS: &str = - "`concat_idents` is not stable enough for use and is subject to change"; -const EXPLAIN_FORMAT_ARGS_NL: &str = - "`format_args_nl` is only for internal language use and is subject to change"; -const EXPLAIN_TRACE_MACROS: &str = - "`trace_macros` is not stable enough for use and is subject to change"; -const EXPLAIN_UNSTABLE_COLUMN: &str = - "internal implementation detail of the `column` macro"; - -pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, - user_exts: Vec, - edition: Edition) { - deriving::register_builtin_derives(resolver, edition); - - let mut register = |name, ext| { - resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); - }; - macro_rules! register { - ($( $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - )); - )* } - } - macro_rules! register_unstable { - ($( [$feature:expr, $reason:expr, $issue:expr] $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension { - stability: Some(Stability::unstable( - $feature, Some(Symbol::intern($reason)), $issue - )), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - ) - }); - )* } - } - - use syntax::ext::source_util::*; - register! { - line: expand_line, - column: expand_column, - file: expand_file, - stringify: expand_stringify, - include: expand_include, - include_str: expand_include_str, - include_bytes: expand_include_bytes, - module_path: expand_mod, - cfg: cfg::expand_cfg, - concat: concat::expand_syntax_ext, - env: env::expand_env, - option_env: env::expand_option_env, - compile_error: compile_error::expand_compile_error, - assert: assert::expand_assert, - } - - register_unstable! { - [sym::__rust_unstable_column, EXPLAIN_UNSTABLE_COLUMN, 0] - __rust_unstable_column: expand_column, - [sym::asm, EXPLAIN_ASM, 29722] - asm: asm::expand_asm, - [sym::global_asm, EXPLAIN_GLOBAL_ASM, 35119] - global_asm: global_asm::expand_global_asm, - [sym::concat_idents, EXPLAIN_CONCAT_IDENTS, 29599] - concat_idents: concat_idents::expand_syntax_ext, - [sym::log_syntax, EXPLAIN_LOG_SYNTAX, 29598] - log_syntax: log_syntax::expand_syntax_ext, - [sym::trace_macros, EXPLAIN_TRACE_MACROS, 29598] - trace_macros: trace_macros::expand_trace_macros, - } - - register(sym::test_case, SyntaxExtension { - stability: Some(Stability::unstable( - sym::custom_test_frameworks, - Some(Symbol::intern(EXPLAIN_CUSTOM_TEST_FRAMEWORKS)), - 50297, - )), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition - ) - }); - register(sym::test, SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition - )); - register(sym::bench, SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition - )); - - // format_args uses `unstable` things internally. - let allow_internal_unstable = Some([sym::fmt_internals][..].into()); - register(sym::format_args, SyntaxExtension { - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition - ) - }); - register(sym::format_args_nl, SyntaxExtension { - stability: Some(Stability::unstable( - sym::format_args_nl, - Some(Symbol::intern(EXPLAIN_FORMAT_ARGS_NL)), - 0, - )), - allow_internal_unstable, - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition - ) - }); - - for (name, ext) in user_exts { - register(name, ext); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/log_syntax.rs b/gcc/rust/rustc_parser/libsyntax_ext/log_syntax.rs deleted file mode 100644 index cbdfd08..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/log_syntax.rs +++ /dev/null @@ -1,14 +0,0 @@ -use syntax::ext::base; -use syntax::print; -use syntax::tokenstream; -use syntax_pos; - -pub fn expand_syntax_ext<'cx>(_cx: &'cx mut base::ExtCtxt<'_>, - sp: syntax_pos::Span, - tts: &[tokenstream::TokenTree]) - -> Box { - println!("{}", print::pprust::tts_to_string(tts)); - - // any so that `log_syntax` can be invoked as an expression and item. - base::DummyResult::any_valid(sp) -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_decls.rs b/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_decls.rs deleted file mode 100644 index 45e6528..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_decls.rs +++ /dev/null @@ -1,432 +0,0 @@ -use std::mem; - -use crate::deriving; - -use syntax::ast::{self, Ident}; -use syntax::attr; -use syntax::source_map::{ExpnInfo, MacroAttribute, respan}; -use syntax::ext::base::ExtCtxt; -use syntax::ext::build::AstBuilder; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::Mark; -use syntax::mut_visit::MutVisitor; -use syntax::parse::ParseSess; -use syntax::ptr::P; -use syntax::symbol::Symbol; -use syntax::symbol::{kw, sym}; -use syntax::visit::{self, Visitor}; - -use syntax_pos::{Span, DUMMY_SP}; - -const PROC_MACRO_KINDS: [Symbol; 3] = [ - sym::proc_macro_derive, - sym::proc_macro_attribute, - sym::proc_macro -]; - -struct ProcMacroDerive { - trait_name: ast::Name, - function_name: Ident, - span: Span, - attrs: Vec, -} - -struct ProcMacroDef { - function_name: Ident, - span: Span, -} - -struct CollectProcMacros<'a> { - derives: Vec, - attr_macros: Vec, - bang_macros: Vec, - in_root: bool, - handler: &'a errors::Handler, - is_proc_macro_crate: bool, - is_test_crate: bool, -} - -pub fn modify(sess: &ParseSess, - resolver: &mut dyn (::syntax::ext::base::Resolver), - mut krate: ast::Crate, - is_proc_macro_crate: bool, - has_proc_macro_decls: bool, - is_test_crate: bool, - num_crate_types: usize, - handler: &errors::Handler) -> ast::Crate { - let ecfg = ExpansionConfig::default("proc_macro".to_string()); - let mut cx = ExtCtxt::new(sess, ecfg, resolver); - - let (derives, attr_macros, bang_macros) = { - let mut collect = CollectProcMacros { - derives: Vec::new(), - attr_macros: Vec::new(), - bang_macros: Vec::new(), - in_root: true, - handler, - is_proc_macro_crate, - is_test_crate, - }; - if has_proc_macro_decls || is_proc_macro_crate { - visit::walk_crate(&mut collect, &krate); - } - (collect.derives, collect.attr_macros, collect.bang_macros) - }; - - if !is_proc_macro_crate { - return krate - } - - if num_crate_types > 1 { - handler.err("cannot mix `proc-macro` crate type with others"); - } - - if is_test_crate { - return krate; - } - - krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros)); - - krate -} - -pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool { - PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind)) -} - -impl<'a> CollectProcMacros<'a> { - fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) { - if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() { - self.handler.span_err(sp, - "`proc-macro` crate types cannot \ - export any items other than functions \ - tagged with `#[proc_macro_derive]` currently"); - } - } - - fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { - // Once we've located the `#[proc_macro_derive]` attribute, verify - // that it's of the form `#[proc_macro_derive(Foo)]` or - // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = match attr.meta_item_list() { - Some(list) => list, - None => return, - }; - if list.len() != 1 && list.len() != 2 { - self.handler.span_err(attr.span, - "attribute must have either one or two arguments"); - return - } - let trait_attr = match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(list[0].span(), "not a meta item"); - return - } - }; - let trait_ident = match trait_attr.ident() { - Some(trait_ident) if trait_attr.is_word() => trait_ident, - _ => { - self.handler.span_err(trait_attr.span, "must only be one word"); - return - } - }; - - if !trait_ident.name.can_be_raw() { - self.handler.span_err(trait_attr.span, - &format!("`{}` cannot be a name of derive macro", trait_ident)); - } - if deriving::is_builtin_trait(trait_ident.name) { - self.handler.span_err(trait_attr.span, - "cannot override a built-in derive macro"); - } - - let attributes_attr = list.get(1); - let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.check_name(sym::attributes) { - self.handler.span_err(attr.span(), "second argument must be `attributes`") - } - attr.meta_item_list().unwrap_or_else(|| { - self.handler.span_err(attr.span(), - "attribute must be of form: `attributes(foo, bar)`"); - &[] - }).into_iter().filter_map(|attr| { - let attr = match attr.meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(attr.span(), "not a meta item"); - return None; - } - }; - - let ident = match attr.ident() { - Some(ident) if attr.is_word() => ident, - _ => { - self.handler.span_err(attr.span, "must only be one word"); - return None; - } - }; - if !ident.name.can_be_raw() { - self.handler.span_err( - attr.span, - &format!("`{}` cannot be a name of derive helper attribute", ident), - ); - } - - Some(ident.name) - }).collect() - } else { - Vec::new() - }; - - if self.in_root && item.vis.node.is_pub() { - self.derives.push(ProcMacroDerive { - span: item.span, - trait_name: trait_ident.name, - function_name: item.ident, - attrs: proc_attrs, - }); - } else { - let msg = if !self.in_root { - "functions tagged with `#[proc_macro_derive]` must \ - currently reside in the root of the crate" - } else { - "functions tagged with `#[proc_macro_derive]` must be `pub`" - }; - self.handler.span_err(item.span, msg); - } - } - - fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { - if self.in_root && item.vis.node.is_pub() { - self.attr_macros.push(ProcMacroDef { - span: item.span, - function_name: item.ident, - }); - } else { - let msg = if !self.in_root { - "functions tagged with `#[proc_macro_attribute]` must \ - currently reside in the root of the crate" - } else { - "functions tagged with `#[proc_macro_attribute]` must be `pub`" - }; - self.handler.span_err(item.span, msg); - } - } - - fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) { - if self.in_root && item.vis.node.is_pub() { - self.bang_macros.push(ProcMacroDef { - span: item.span, - function_name: item.ident, - }); - } else { - let msg = if !self.in_root { - "functions tagged with `#[proc_macro]` must \ - currently reside in the root of the crate" - } else { - "functions tagged with `#[proc_macro]` must be `pub`" - }; - self.handler.span_err(item.span, msg); - } - } -} - -impl<'a> Visitor<'a> for CollectProcMacros<'a> { - fn visit_item(&mut self, item: &'a ast::Item) { - if let ast::ItemKind::MacroDef(..) = item.node { - if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) { - let msg = - "cannot export macro_rules! macros from a `proc-macro` crate type currently"; - self.handler.span_err(item.span, msg); - } - } - - // First up, make sure we're checking a bare function. If we're not then - // we're just not interested in this item. - // - // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. - let is_fn = match item.node { - ast::ItemKind::Fn(..) => true, - _ => false, - }; - - let mut found_attr: Option<&'a ast::Attribute> = None; - - for attr in &item.attrs { - if is_proc_macro_attr(&attr) { - if let Some(prev_attr) = found_attr { - let msg = if attr.path.segments[0].ident.name == - prev_attr.path.segments[0].ident.name { - format!("only one `#[{}]` attribute is allowed on any given function", - attr.path) - } else { - format!("`#[{}]` and `#[{}]` attributes cannot both be applied \ - to the same function", attr.path, prev_attr.path) - }; - - self.handler.struct_span_err(attr.span, &msg) - .span_note(prev_attr.span, "previous attribute here") - .emit(); - - return; - } - - found_attr = Some(attr); - } - } - - let attr = match found_attr { - None => { - self.check_not_pub_in_root(&item.vis, item.span); - let prev_in_root = mem::replace(&mut self.in_root, false); - visit::walk_item(self, item); - self.in_root = prev_in_root; - return; - }, - Some(attr) => attr, - }; - - if !is_fn { - let msg = format!("the `#[{}]` attribute may only be used on bare functions", - attr.path); - - self.handler.span_err(attr.span, &msg); - return; - } - - if self.is_test_crate { - return; - } - - if !self.is_proc_macro_crate { - let msg = format!("the `#[{}]` attribute is only usable with crates of the \ - `proc-macro` crate type", attr.path); - - self.handler.span_err(attr.span, &msg); - return; - } - - if attr.check_name(sym::proc_macro_derive) { - self.collect_custom_derive(item, attr); - } else if attr.check_name(sym::proc_macro_attribute) { - self.collect_attr_proc_macro(item); - } else if attr.check_name(sym::proc_macro) { - self.collect_bang_proc_macro(item); - }; - - let prev_in_root = mem::replace(&mut self.in_root, false); - visit::walk_item(self, item); - self.in_root = prev_in_root; - } - - fn visit_mac(&mut self, mac: &'a ast::Mac) { - visit::walk_mac(self, mac) - } -} - -// Creates a new module which looks like: -// -// #[doc(hidden)] -// mod $gensym { -// extern crate proc_macro; -// -// use proc_macro::bridge::client::ProcMacro; -// -// #[rustc_proc_macro_decls] -// static DECLS: &[ProcMacro] = &[ -// ProcMacro::custom_derive($name_trait1, &[], ::$name1); -// ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2); -// // ... -// ]; -// } -fn mk_decls( - cx: &mut ExtCtxt<'_>, - custom_derives: &[ProcMacroDerive], - custom_attrs: &[ProcMacroDef], - custom_macros: &[ProcMacroDef], -) -> P { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo::with_unstable( - MacroAttribute(sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, - &[sym::rustc_attrs, Symbol::intern("proc_macro_internals")], - )); - let span = DUMMY_SP.apply_mark(mark); - - let hidden = cx.meta_list_item_word(span, sym::hidden); - let doc = cx.meta_list(span, sym::doc, vec![hidden]); - let doc_hidden = cx.attribute(span, doc); - - let proc_macro = Ident::with_empty_ctxt(sym::proc_macro); - let krate = cx.item(span, - proc_macro, - Vec::new(), - ast::ItemKind::ExternCrate(None)); - - let bridge = Ident::from_str("bridge"); - let client = Ident::from_str("client"); - let proc_macro_ty = Ident::from_str("ProcMacro"); - let custom_derive = Ident::from_str("custom_derive"); - let attr = Ident::from_str("attr"); - let bang = Ident::from_str("bang"); - let crate_kw = Ident::with_empty_ctxt(kw::Crate); - - let decls = { - let local_path = |sp: Span, name| { - cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name])) - }; - let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![ - proc_macro, bridge, client, proc_macro_ty, method, - ])); - custom_derives.iter().map(|cd| { - cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ - cx.expr_str(cd.span, cd.trait_name), - cx.expr_vec_slice( - span, - cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::>() - ), - local_path(cd.span, cd.function_name), - ]) - }).chain(custom_attrs.iter().map(|ca| { - cx.expr_call(span, proc_macro_ty_method_path(attr), vec![ - cx.expr_str(ca.span, ca.function_name.name), - local_path(ca.span, ca.function_name), - ]) - })).chain(custom_macros.iter().map(|cm| { - cx.expr_call(span, proc_macro_ty_method_path(bang), vec![ - cx.expr_str(cm.span, cm.function_name.name), - local_path(cm.span, cm.function_name), - ]) - })).collect() - }; - - let decls_static = cx.item_static( - span, - Ident::from_str("_DECLS"), - cx.ty_rptr(span, - cx.ty(span, ast::TyKind::Slice( - cx.ty_path(cx.path(span, - vec![proc_macro, bridge, client, proc_macro_ty])))), - None, ast::Mutability::Immutable), - ast::Mutability::Immutable, - cx.expr_vec_slice(span, decls), - ).map(|mut i| { - let attr = cx.meta_word(span, sym::rustc_proc_macro_decls); - i.attrs.push(cx.attribute(span, attr)); - i.vis = respan(span, ast::VisibilityKind::Public); - i - }); - - let module = cx.item_mod( - span, - span, - ast::Ident::from_str("decls").gensym(), - vec![doc_hidden], - vec![krate, decls_static], - ).map(|mut i| { - i.vis = respan(span, ast::VisibilityKind::Public); - i - }); - - cx.monotonic_expander().flat_map_item(module).pop().unwrap() -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_impl.rs b/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_impl.rs deleted file mode 100644 index f0fc639..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_impl.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::proc_macro_server; - -use errors::FatalError; -use syntax::source_map::Span; -use syntax::ext::base::{self, *}; -use syntax::tokenstream::TokenStream; - -pub const EXEC_STRATEGY: proc_macro::bridge::server::SameThread = - proc_macro::bridge::server::SameThread; - -pub struct AttrProcMacro { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream, - >, -} - -impl base::AttrProcMacro for AttrProcMacro { - fn expand<'cx>(&self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - annotation: TokenStream, - annotated: TokenStream) - -> TokenStream { - let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) { - Ok(stream) => stream, - Err(e) => { - let msg = "custom attribute panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); - } - } - } -} - -pub struct BangProcMacro { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream) -> proc_macro::TokenStream, - >, -} - -impl base::ProcMacro for BangProcMacro { - fn expand<'cx>(&self, - ecx: &'cx mut ExtCtxt<'_>, - span: Span, - input: TokenStream) - -> TokenStream { - let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, input) { - Ok(stream) => stream, - Err(e) => { - let msg = "proc macro panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); - } - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_server.rs b/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_server.rs deleted file mode 100644 index e502735..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/proc_macro_server.rs +++ /dev/null @@ -1,717 +0,0 @@ -use errors::{Diagnostic, DiagnosticBuilder}; - -use std::panic; - -use proc_macro::bridge::{server, TokenTree}; -use proc_macro::{Delimiter, Level, LineColumn, Spacing}; - -use rustc_data_structures::sync::Lrc; -use std::ascii; -use std::ops::Bound; -use syntax::ast; -use syntax::ext::base::ExtCtxt; -use syntax::parse::lexer::comments; -use syntax::parse::{self, token, ParseSess}; -use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; -use syntax_pos::hygiene::{SyntaxContext, Transparency}; -use syntax_pos::symbol::{kw, sym, Symbol}; -use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; - -trait FromInternal { - fn from_internal(x: T) -> Self; -} - -trait ToInternal { - fn to_internal(self) -> T; -} - -impl FromInternal for Delimiter { - fn from_internal(delim: token::DelimToken) -> Delimiter { - match delim { - token::Paren => Delimiter::Parenthesis, - token::Brace => Delimiter::Brace, - token::Bracket => Delimiter::Bracket, - token::NoDelim => Delimiter::None, - } - } -} - -impl ToInternal for Delimiter { - fn to_internal(self) -> token::DelimToken { - match self { - Delimiter::Parenthesis => token::Paren, - Delimiter::Brace => token::Brace, - Delimiter::Bracket => token::Bracket, - Delimiter::None => token::NoDelim, - } - } -} - -impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> - for TokenTree -{ - fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec)) - -> Self { - use syntax::parse::token::*; - - let joint = is_joint == Joint; - let Token { kind, span } = match tree { - tokenstream::TokenTree::Delimited(span, delim, tts) => { - let delimiter = Delimiter::from_internal(delim); - return TokenTree::Group(Group { - delimiter, - stream: tts.into(), - span, - }); - } - tokenstream::TokenTree::Token(token) => token, - }; - - macro_rules! tt { - ($ty:ident { $($field:ident $(: $value:expr)*),+ $(,)? }) => ( - TokenTree::$ty(self::$ty { - $($field $(: $value)*,)+ - span, - }) - ); - ($ty:ident::$method:ident($($value:expr),*)) => ( - TokenTree::$ty(self::$ty::$method($($value,)* span)) - ); - } - macro_rules! op { - ($a:expr) => { - tt!(Punct::new($a, joint)) - }; - ($a:expr, $b:expr) => {{ - stack.push(tt!(Punct::new($b, joint))); - tt!(Punct::new($a, true)) - }}; - ($a:expr, $b:expr, $c:expr) => {{ - stack.push(tt!(Punct::new($c, joint))); - stack.push(tt!(Punct::new($b, true))); - tt!(Punct::new($a, true)) - }}; - } - - match kind { - Eq => op!('='), - Lt => op!('<'), - Le => op!('<', '='), - EqEq => op!('=', '='), - Ne => op!('!', '='), - Ge => op!('>', '='), - Gt => op!('>'), - AndAnd => op!('&', '&'), - OrOr => op!('|', '|'), - Not => op!('!'), - Tilde => op!('~'), - BinOp(Plus) => op!('+'), - BinOp(Minus) => op!('-'), - BinOp(Star) => op!('*'), - BinOp(Slash) => op!('/'), - BinOp(Percent) => op!('%'), - BinOp(Caret) => op!('^'), - BinOp(And) => op!('&'), - BinOp(Or) => op!('|'), - BinOp(Shl) => op!('<', '<'), - BinOp(Shr) => op!('>', '>'), - BinOpEq(Plus) => op!('+', '='), - BinOpEq(Minus) => op!('-', '='), - BinOpEq(Star) => op!('*', '='), - BinOpEq(Slash) => op!('/', '='), - BinOpEq(Percent) => op!('%', '='), - BinOpEq(Caret) => op!('^', '='), - BinOpEq(And) => op!('&', '='), - BinOpEq(Or) => op!('|', '='), - BinOpEq(Shl) => op!('<', '<', '='), - BinOpEq(Shr) => op!('>', '>', '='), - At => op!('@'), - Dot => op!('.'), - DotDot => op!('.', '.'), - DotDotDot => op!('.', '.', '.'), - DotDotEq => op!('.', '.', '='), - Comma => op!(','), - Semi => op!(';'), - Colon => op!(':'), - ModSep => op!(':', ':'), - RArrow => op!('-', '>'), - LArrow => op!('<', '-'), - FatArrow => op!('=', '>'), - Pound => op!('#'), - Dollar => op!('$'), - Question => op!('?'), - SingleQuote => op!('\''), - - Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()), - Ident(name, is_raw) => tt!(Ident::new(name, is_raw)), - Lifetime(name) => { - let ident = ast::Ident::new(name, span).without_first_quote(); - stack.push(tt!(Ident::new(ident.name, false))); - tt!(Punct::new('\'', true)) - } - Literal(lit) => tt!(Literal { lit }), - DocComment(c) => { - let style = comments::doc_comment_style(&c.as_str()); - let stripped = comments::strip_doc_comment_decoration(&c.as_str()); - let mut escaped = String::new(); - for ch in stripped.chars() { - escaped.extend(ch.escape_debug()); - } - let stream = vec![ - Ident(sym::doc, false), - Eq, - TokenKind::lit(token::Str, Symbol::intern(&escaped), None), - ] - .into_iter() - .map(|kind| tokenstream::TokenTree::token(kind, span)) - .collect(); - stack.push(TokenTree::Group(Group { - delimiter: Delimiter::Bracket, - stream, - span: DelimSpan::from_single(span), - })); - if style == ast::AttrStyle::Inner { - stack.push(tt!(Punct::new('!', false))); - } - tt!(Punct::new('#', false)) - } - - Interpolated(nt) => { - let stream = nt.to_tokenstream(sess, span); - TokenTree::Group(Group { - delimiter: Delimiter::None, - stream, - span: DelimSpan::from_single(span), - }) - } - - OpenDelim(..) | CloseDelim(..) => unreachable!(), - Whitespace | Comment | Shebang(..) | Eof => unreachable!(), - } - } -} - -impl ToInternal for TokenTree { - fn to_internal(self) -> TokenStream { - use syntax::parse::token::*; - - let (ch, joint, span) = match self { - TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span), - TokenTree::Group(Group { - delimiter, - stream, - span, - }) => { - return tokenstream::TokenTree::Delimited( - span, - delimiter.to_internal(), - stream.into(), - ) - .into(); - } - TokenTree::Ident(self::Ident { sym, is_raw, span }) => { - return tokenstream::TokenTree::token(Ident(sym, is_raw), span).into(); - } - TokenTree::Literal(self::Literal { - lit: token::Lit { kind: token::Integer, symbol, suffix }, - span, - }) if symbol.as_str().starts_with("-") => { - let minus = BinOp(BinOpToken::Minus); - let symbol = Symbol::intern(&symbol.as_str()[1..]); - let integer = TokenKind::lit(token::Integer, symbol, suffix); - let a = tokenstream::TokenTree::token(minus, span); - let b = tokenstream::TokenTree::token(integer, span); - return vec![a, b].into_iter().collect(); - } - TokenTree::Literal(self::Literal { - lit: token::Lit { kind: token::Float, symbol, suffix }, - span, - }) if symbol.as_str().starts_with("-") => { - let minus = BinOp(BinOpToken::Minus); - let symbol = Symbol::intern(&symbol.as_str()[1..]); - let float = TokenKind::lit(token::Float, symbol, suffix); - let a = tokenstream::TokenTree::token(minus, span); - let b = tokenstream::TokenTree::token(float, span); - return vec![a, b].into_iter().collect(); - } - TokenTree::Literal(self::Literal { lit, span }) => { - return tokenstream::TokenTree::token(Literal(lit), span).into() - } - }; - - let kind = match ch { - '=' => Eq, - '<' => Lt, - '>' => Gt, - '!' => Not, - '~' => Tilde, - '+' => BinOp(Plus), - '-' => BinOp(Minus), - '*' => BinOp(Star), - '/' => BinOp(Slash), - '%' => BinOp(Percent), - '^' => BinOp(Caret), - '&' => BinOp(And), - '|' => BinOp(Or), - '@' => At, - '.' => Dot, - ',' => Comma, - ';' => Semi, - ':' => Colon, - '#' => Pound, - '$' => Dollar, - '?' => Question, - '\'' => SingleQuote, - _ => unreachable!(), - }; - - let tree = tokenstream::TokenTree::token(kind, span); - TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })]) - } -} - -impl ToInternal for Level { - fn to_internal(self) -> errors::Level { - match self { - Level::Error => errors::Level::Error, - Level::Warning => errors::Level::Warning, - Level::Note => errors::Level::Note, - Level::Help => errors::Level::Help, - _ => unreachable!("unknown proc_macro::Level variant: {:?}", self), - } - } -} - -#[derive(Clone)] -pub struct TokenStreamIter { - cursor: tokenstream::Cursor, - stack: Vec>, -} - -#[derive(Clone)] -pub struct Group { - delimiter: Delimiter, - stream: TokenStream, - span: DelimSpan, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct Punct { - ch: char, - // NB. not using `Spacing` here because it doesn't implement `Hash`. - joint: bool, - span: Span, -} - -impl Punct { - fn new(ch: char, joint: bool, span: Span) -> Punct { - const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^', - '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\'']; - if !LEGAL_CHARS.contains(&ch) { - panic!("unsupported character `{:?}`", ch) - } - Punct { ch, joint, span } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct Ident { - sym: Symbol, - is_raw: bool, - span: Span, -} - -impl Ident { - fn is_valid(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() { - (start == '_' || start.is_xid_start()) - && chars.all(|cont| cont == '_' || cont.is_xid_continue()) - } else { - false - } - } - fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident { - let string = sym.as_str(); - if !Self::is_valid(&string) { - panic!("`{:?}` is not a valid identifier", string) - } - // Get rid of gensyms to conservatively check rawness on the string contents only. - if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() { - panic!("`{}` cannot be a raw identifier", string); - } - Ident { sym, is_raw, span } - } - fn dollar_crate(span: Span) -> Ident { - // `$crate` is accepted as an ident only if it comes from the compiler. - Ident { sym: kw::DollarCrate, is_raw: false, span } - } -} - -// FIXME(eddyb) `Literal` should not expose internal `Debug` impls. -#[derive(Clone, Debug)] -pub struct Literal { - lit: token::Lit, - span: Span, -} - -pub(crate) struct Rustc<'a> { - sess: &'a ParseSess, - def_site: Span, - call_site: Span, -} - -impl<'a> Rustc<'a> { - pub fn new(cx: &'a ExtCtxt<'_>) -> Self { - // No way to determine def location for a proc macro right now, so use call location. - let location = cx.current_expansion.mark.expn_info().unwrap().call_site; - let to_span = |transparency| { - location.with_ctxt( - SyntaxContext::empty() - .apply_mark_with_transparency(cx.current_expansion.mark, transparency), - ) - }; - Rustc { - sess: cx.parse_sess, - def_site: to_span(Transparency::Opaque), - call_site: to_span(Transparency::Transparent), - } - } - - fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option) -> Literal { - Literal { - lit: token::Lit::new(kind, symbol, suffix), - span: server::Span::call_site(self), - } - } -} - -impl server::Types for Rustc<'_> { - type TokenStream = TokenStream; - type TokenStreamBuilder = tokenstream::TokenStreamBuilder; - type TokenStreamIter = TokenStreamIter; - type Group = Group; - type Punct = Punct; - type Ident = Ident; - type Literal = Literal; - type SourceFile = Lrc; - type MultiSpan = Vec; - type Diagnostic = Diagnostic; - type Span = Span; -} - -impl server::TokenStream for Rustc<'_> { - fn new(&mut self) -> Self::TokenStream { - TokenStream::empty() - } - fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { - stream.is_empty() - } - fn from_str(&mut self, src: &str) -> Self::TokenStream { - parse::parse_stream_from_source_str( - FileName::proc_macro_source_code(src), - src.to_string(), - self.sess, - Some(self.call_site), - ) - } - fn to_string(&mut self, stream: &Self::TokenStream) -> String { - stream.to_string() - } - fn from_token_tree( - &mut self, - tree: TokenTree, - ) -> Self::TokenStream { - tree.to_internal() - } - fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter { - TokenStreamIter { - cursor: stream.trees(), - stack: vec![], - } - } -} - -impl server::TokenStreamBuilder for Rustc<'_> { - fn new(&mut self) -> Self::TokenStreamBuilder { - tokenstream::TokenStreamBuilder::new() - } - fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) { - builder.push(stream); - } - fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream { - builder.build() - } -} - -impl server::TokenStreamIter for Rustc<'_> { - fn next( - &mut self, - iter: &mut Self::TokenStreamIter, - ) -> Option> { - loop { - let tree = iter.stack.pop().or_else(|| { - let next = iter.cursor.next_with_joint()?; - Some(TokenTree::from_internal((next, self.sess, &mut iter.stack))) - })?; - // HACK: The condition "dummy span + group with empty delimiter" represents an AST - // fragment approximately converted into a token stream. This may happen, for - // example, with inputs to proc macro attributes, including derives. Such "groups" - // need to flattened during iteration over stream's token trees. - // Eventually this needs to be removed in favor of keeping original token trees - // and not doing the roundtrip through AST. - if let TokenTree::Group(ref group) = tree { - if group.delimiter == Delimiter::None && group.span.entire().is_dummy() { - iter.cursor.append(group.stream.clone()); - continue; - } - } - return Some(tree); - } - } -} - -impl server::Group for Rustc<'_> { - fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group { - Group { - delimiter, - stream, - span: DelimSpan::from_single(server::Span::call_site(self)), - } - } - fn delimiter(&mut self, group: &Self::Group) -> Delimiter { - group.delimiter - } - fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { - group.stream.clone() - } - fn span(&mut self, group: &Self::Group) -> Self::Span { - group.span.entire() - } - fn span_open(&mut self, group: &Self::Group) -> Self::Span { - group.span.open - } - fn span_close(&mut self, group: &Self::Group) -> Self::Span { - group.span.close - } - fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) { - group.span = DelimSpan::from_single(span); - } -} - -impl server::Punct for Rustc<'_> { - fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct { - Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self)) - } - fn as_char(&mut self, punct: Self::Punct) -> char { - punct.ch - } - fn spacing(&mut self, punct: Self::Punct) -> Spacing { - if punct.joint { - Spacing::Joint - } else { - Spacing::Alone - } - } - fn span(&mut self, punct: Self::Punct) -> Self::Span { - punct.span - } - fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct { - Punct { span, ..punct } - } -} - -impl server::Ident for Rustc<'_> { - fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident { - Ident::new(Symbol::intern(string), is_raw, span) - } - fn span(&mut self, ident: Self::Ident) -> Self::Span { - ident.span - } - fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident { - Ident { span, ..ident } - } -} - -impl server::Literal for Rustc<'_> { - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. - fn debug(&mut self, literal: &Self::Literal) -> String { - format!("{:?}", literal) - } - fn integer(&mut self, n: &str) -> Self::Literal { - self.lit(token::Integer, Symbol::intern(n), None) - } - fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal { - self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind))) - } - fn float(&mut self, n: &str) -> Self::Literal { - self.lit(token::Float, Symbol::intern(n), None) - } - fn f32(&mut self, n: &str) -> Self::Literal { - self.lit(token::Float, Symbol::intern(n), Some(sym::f32)) - } - fn f64(&mut self, n: &str) -> Self::Literal { - self.lit(token::Float, Symbol::intern(n), Some(sym::f64)) - } - fn string(&mut self, string: &str) -> Self::Literal { - let mut escaped = String::new(); - for ch in string.chars() { - escaped.extend(ch.escape_debug()); - } - self.lit(token::Str, Symbol::intern(&escaped), None) - } - fn character(&mut self, ch: char) -> Self::Literal { - let mut escaped = String::new(); - escaped.extend(ch.escape_unicode()); - self.lit(token::Char, Symbol::intern(&escaped), None) - } - fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal { - let string = bytes - .iter() - .cloned() - .flat_map(ascii::escape_default) - .map(Into::::into) - .collect::(); - self.lit(token::ByteStr, Symbol::intern(&string), None) - } - fn span(&mut self, literal: &Self::Literal) -> Self::Span { - literal.span - } - fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) { - literal.span = span; - } - fn subspan( - &mut self, - literal: &Self::Literal, - start: Bound, - end: Bound, - ) -> Option { - let span = literal.span; - let length = span.hi().to_usize() - span.lo().to_usize(); - - let start = match start { - Bound::Included(lo) => lo, - Bound::Excluded(lo) => lo + 1, - Bound::Unbounded => 0, - }; - - let end = match end { - Bound::Included(hi) => hi + 1, - Bound::Excluded(hi) => hi, - Bound::Unbounded => length, - }; - - // Bounds check the values, preventing addition overflow and OOB spans. - if start > u32::max_value() as usize - || end > u32::max_value() as usize - || (u32::max_value() - start as u32) < span.lo().to_u32() - || (u32::max_value() - end as u32) < span.lo().to_u32() - || start >= end - || end > length - { - return None; - } - - let new_lo = span.lo() + BytePos::from_usize(start); - let new_hi = span.lo() + BytePos::from_usize(end); - Some(span.with_lo(new_lo).with_hi(new_hi)) - } -} - -impl server::SourceFile for Rustc<'_> { - fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool { - Lrc::ptr_eq(file1, file2) - } - fn path(&mut self, file: &Self::SourceFile) -> String { - match file.name { - FileName::Real(ref path) => path - .to_str() - .expect("non-UTF8 file path in `proc_macro::SourceFile::path`") - .to_string(), - _ => file.name.to_string(), - } - } - fn is_real(&mut self, file: &Self::SourceFile) -> bool { - file.is_real_file() - } -} - -impl server::MultiSpan for Rustc<'_> { - fn new(&mut self) -> Self::MultiSpan { - vec![] - } - fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) { - spans.push(span) - } -} - -impl server::Diagnostic for Rustc<'_> { - fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic { - let mut diag = Diagnostic::new(level.to_internal(), msg); - diag.set_span(MultiSpan::from_spans(spans)); - diag - } - fn sub( - &mut self, - diag: &mut Self::Diagnostic, - level: Level, - msg: &str, - spans: Self::MultiSpan, - ) { - diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None); - } - fn emit(&mut self, diag: Self::Diagnostic) { - DiagnosticBuilder::new_diagnostic(&self.sess.span_diagnostic, diag).emit() - } -} - -impl server::Span for Rustc<'_> { - fn debug(&mut self, span: Self::Span) -> String { - format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0) - } - fn def_site(&mut self) -> Self::Span { - self.def_site - } - fn call_site(&mut self) -> Self::Span { - self.call_site - } - fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { - self.sess.source_map().lookup_char_pos(span.lo()).file - } - fn parent(&mut self, span: Self::Span) -> Option { - span.ctxt().outer_expn_info().map(|i| i.call_site) - } - fn source(&mut self, span: Self::Span) -> Self::Span { - span.source_callsite() - } - fn start(&mut self, span: Self::Span) -> LineColumn { - let loc = self.sess.source_map().lookup_char_pos(span.lo()); - LineColumn { - line: loc.line, - column: loc.col.to_usize(), - } - } - fn end(&mut self, span: Self::Span) -> LineColumn { - let loc = self.sess.source_map().lookup_char_pos(span.hi()); - LineColumn { - line: loc.line, - column: loc.col.to_usize(), - } - } - fn join(&mut self, first: Self::Span, second: Self::Span) -> Option { - let self_loc = self.sess.source_map().lookup_char_pos(first.lo()); - let other_loc = self.sess.source_map().lookup_char_pos(second.lo()); - - if self_loc.file.name != other_loc.file.name { - return None; - } - - Some(first.to(second)) - } - fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span { - span.with_ctxt(at.ctxt()) - } - fn source_text(&mut self, span: Self::Span) -> Option { - self.sess.source_map().span_to_snippet(span).ok() - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/test.rs b/gcc/rust/rustc_parser/libsyntax_ext/test.rs deleted file mode 100644 index 24d3055..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/test.rs +++ /dev/null @@ -1,309 +0,0 @@ -/// The expansion from a test function to the appropriate test struct for libtest -/// Ideally, this code would be in libtest but for efficiency and error messages it lives here. - -use syntax::ext::base::*; -use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{Mark, SyntaxContext}; -use syntax::attr; -use syntax::ast; -use syntax::print::pprust; -use syntax::symbol::{Symbol, sym}; -use syntax_pos::Span; -use syntax::source_map::{ExpnInfo, MacroAttribute}; -use std::iter; - -pub fn expand_test( - cx: &mut ExtCtxt<'_>, - attr_sp: Span, - _meta_item: &ast::MetaItem, - item: Annotatable, -) -> Vec { - expand_test_or_bench(cx, attr_sp, item, false) -} - -pub fn expand_bench( - cx: &mut ExtCtxt<'_>, - attr_sp: Span, - _meta_item: &ast::MetaItem, - item: Annotatable, -) -> Vec { - expand_test_or_bench(cx, attr_sp, item, true) -} - -pub fn expand_test_or_bench( - cx: &mut ExtCtxt<'_>, - attr_sp: Span, - item: Annotatable, - is_bench: bool -) -> Vec { - // If we're not in test configuration, remove the annotated item - if !cx.ecfg.should_test { return vec![]; } - - let item = - if let Annotatable::Item(i) = item { i } - else { - cx.parse_sess.span_diagnostic.span_fatal(item.span(), - "#[test] attribute is only allowed on non associated functions").raise(); - }; - - if let ast::ItemKind::Mac(_) = item.node { - cx.parse_sess.span_diagnostic.span_warn(item.span, - "#[test] attribute should not be used on macros. Use #[cfg(test)] instead."); - return vec![Annotatable::Item(item)]; - } - - // has_*_signature will report any errors in the type so compilation - // will fail. We shouldn't try to expand in this case because the errors - // would be spurious. - if (!is_bench && !has_test_signature(cx, &item)) || - (is_bench && !has_bench_signature(cx, &item)) { - return vec![Annotatable::Item(item)]; - } - - let (sp, attr_sp) = { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo::with_unstable( - MacroAttribute(sym::test), attr_sp, cx.parse_sess.edition, - &[sym::rustc_attrs, sym::test], - )); - (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)), - attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))) - }; - - // Gensym "test" so we can extern crate without conflicting with any local names - let test_id = cx.ident_of("test").gensym(); - - // creates test::$name - let test_path = |name| { - cx.path(sp, vec![test_id, cx.ident_of(name)]) - }; - - // creates test::ShouldPanic::$name - let should_panic_path = |name| { - cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)]) - }; - - // creates $name: $expr - let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr); - - let test_fn = if is_bench { - // A simple ident for a lambda - let b = cx.ident_of("b"); - - cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![ - // |b| self::test::assert_test_result( - cx.lambda1(sp, - cx.expr_call(sp, cx.expr_path(test_path("assert_test_result")), vec![ - // super::$test_fn(b) - cx.expr_call(sp, - cx.expr_path(cx.path(sp, vec![item.ident])), - vec![cx.expr_ident(sp, b)]) - ]), - b - ) - // ) - ]) - } else { - cx.expr_call(sp, cx.expr_path(test_path("StaticTestFn")), vec![ - // || { - cx.lambda0(sp, - // test::assert_test_result( - cx.expr_call(sp, cx.expr_path(test_path("assert_test_result")), vec![ - // $test_fn() - cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]) - // ) - ]) - // } - ) - // ) - ]) - }; - - let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(), - vec![ - // #[cfg(test)] - cx.attribute(attr_sp, cx.meta_list(attr_sp, sym::cfg, vec![ - cx.meta_list_item_word(attr_sp, sym::test) - ])), - // #[rustc_test_marker] - cx.attribute(attr_sp, cx.meta_word(attr_sp, sym::rustc_test_marker)), - ], - // const $ident: test::TestDescAndFn = - ast::ItemKind::Const(cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), - // test::TestDescAndFn { - cx.expr_struct(sp, test_path("TestDescAndFn"), vec![ - // desc: test::TestDesc { - field("desc", cx.expr_struct(sp, test_path("TestDesc"), vec![ - // name: "path::to::test" - field("name", cx.expr_call(sp, cx.expr_path(test_path("StaticTestName")), - vec![ - cx.expr_str(sp, Symbol::intern(&item_path( - // skip the name of the root module - &cx.current_expansion.module.mod_path[1..], - &item.ident - ))) - ])), - // ignore: true | false - field("ignore", cx.expr_bool(sp, should_ignore(&item))), - // allow_fail: true | false - field("allow_fail", cx.expr_bool(sp, should_fail(&item))), - // should_panic: ... - field("should_panic", match should_panic(cx, &item) { - // test::ShouldPanic::No - ShouldPanic::No => cx.expr_path(should_panic_path("No")), - // test::ShouldPanic::Yes - ShouldPanic::Yes(None) => cx.expr_path(should_panic_path("Yes")), - // test::ShouldPanic::YesWithMessage("...") - ShouldPanic::Yes(Some(sym)) => cx.expr_call(sp, - cx.expr_path(should_panic_path("YesWithMessage")), - vec![cx.expr_str(sp, sym)]), - }), - // }, - ])), - // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) - field("testfn", test_fn) - // } - ]) - // } - )); - test_const = test_const.map(|mut tc| { tc.vis.node = ast::VisibilityKind::Public; tc}); - - // extern crate test as test_gensym - let test_extern = cx.item(sp, - test_id, - vec![], - ast::ItemKind::ExternCrate(Some(sym::test)) - ); - - log::debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); - - vec![ - // Access to libtest under a gensymed name - Annotatable::Item(test_extern), - // The generated test case - Annotatable::Item(test_const), - // The original item - Annotatable::Item(item) - ] -} - -fn item_path(mod_path: &[ast::Ident], item_ident: &ast::Ident) -> String { - mod_path.iter().chain(iter::once(item_ident)) - .map(|x| x.to_string()).collect::>().join("::") -} - -enum ShouldPanic { - No, - Yes(Option), -} - -fn should_ignore(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, sym::ignore) -} - -fn should_fail(i: &ast::Item) -> bool { - attr::contains_name(&i.attrs, sym::allow_fail) -} - -fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { - match attr::find_by_name(&i.attrs, sym::should_panic) { - Some(attr) => { - let ref sd = cx.parse_sess.span_diagnostic; - - match attr.meta_item_list() { - // Handle #[should_panic(expected = "foo")] - Some(list) => { - let msg = list.iter() - .find(|mi| mi.check_name(sym::expected)) - .and_then(|mi| mi.meta_item()) - .and_then(|mi| mi.value_str()); - if list.len() != 1 || msg.is_none() { - sd.struct_span_warn( - attr.span, - "argument must be of the form: \ - `expected = \"error message\"`" - ).note("Errors in this attribute were erroneously \ - allowed and will become a hard error in a \ - future release.").emit(); - ShouldPanic::Yes(None) - } else { - ShouldPanic::Yes(msg) - } - }, - // Handle #[should_panic] and #[should_panic = "expected"] - None => ShouldPanic::Yes(attr.value_str()) - } - } - None => ShouldPanic::No, - } -} - -fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); - let ref sd = cx.parse_sess.span_diagnostic; - if let ast::ItemKind::Fn(ref decl, ref header, ref generics, _) = i.node { - if header.unsafety == ast::Unsafety::Unsafe { - sd.span_err( - i.span, - "unsafe functions cannot be used for tests" - ); - return false - } - if header.asyncness.node.is_async() { - sd.span_err( - i.span, - "async functions cannot be used for tests" - ); - return false - } - - - // If the termination trait is active, the compiler will check that the output - // type implements the `Termination` trait as `libtest` enforces that. - let has_output = match decl.output { - ast::FunctionRetTy::Default(..) => false, - ast::FunctionRetTy::Ty(ref t) if t.node.is_unit() => false, - _ => true - }; - - if !decl.inputs.is_empty() { - sd.span_err(i.span, "functions used as tests can not have any arguments"); - return false; - } - - match (has_output, has_should_panic_attr) { - (true, true) => { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - false - }, - (true, false) => if !generics.params.is_empty() { - sd.span_err(i.span, - "functions used as tests must have signature fn() -> ()"); - false - } else { - true - }, - (false, _) => true - } - } else { - sd.span_err(i.span, "only functions may be used as tests"); - false - } -} - -fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = if let ast::ItemKind::Fn(ref decl, _, _, _) = i.node { - // N.B., inadequate check, but we're running - // well before resolve, can't get too deep. - decl.inputs.len() == 1 - } else { - false - }; - - if !has_sig { - cx.parse_sess.span_diagnostic.span_err(i.span, "functions used as benches must have \ - signature `fn(&mut Bencher) -> impl Termination`"); - } - - has_sig -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/test_case.rs b/gcc/rust/rustc_parser/libsyntax_ext/test_case.rs deleted file mode 100644 index 186673c..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/test_case.rs +++ /dev/null @@ -1,51 +0,0 @@ -// http://rust-lang.org/COPYRIGHT. -// - -// #[test_case] is used by custom test authors to mark tests -// When building for test, it needs to make the item public and gensym the name -// Otherwise, we'll omit the item. This behavior means that any item annotated -// with #[test_case] is never addressable. -// -// We mark item with an inert attribute "rustc_test_marker" which the test generation -// logic will pick up on. - -use syntax::ext::base::*; -use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{Mark, SyntaxContext}; -use syntax::ast; -use syntax::source_map::respan; -use syntax::symbol::sym; -use syntax_pos::Span; -use syntax::source_map::{ExpnInfo, MacroAttribute}; - -pub fn expand( - ecx: &mut ExtCtxt<'_>, - attr_sp: Span, - _meta_item: &ast::MetaItem, - anno_item: Annotatable -) -> Vec { - if !ecx.ecfg.should_test { return vec![]; } - - let sp = { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo::with_unstable( - MacroAttribute(sym::test_case), attr_sp, ecx.parse_sess.edition, - &[sym::test, sym::rustc_attrs], - )); - attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) - }; - - let mut item = anno_item.expect_item(); - - item = item.map(|mut item| { - item.vis = respan(item.vis.span, ast::VisibilityKind::Public); - item.ident = item.ident.gensym(); - item.attrs.push( - ecx.attribute(sp, - ecx.meta_word(sp, sym::rustc_test_marker)) - ); - item - }); - - return vec![Annotatable::Item(item)] -} diff --git a/gcc/rust/rustc_parser/libsyntax_ext/trace_macros.rs b/gcc/rust/rustc_parser/libsyntax_ext/trace_macros.rs deleted file mode 100644 index 0dce8a3..0000000 --- a/gcc/rust/rustc_parser/libsyntax_ext/trace_macros.rs +++ /dev/null @@ -1,21 +0,0 @@ -use syntax::ext::base::{self, ExtCtxt}; -use syntax::symbol::kw; -use syntax_pos::Span; -use syntax::tokenstream::TokenTree; - -pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>, - sp: Span, - tt: &[TokenTree]) - -> Box { - match tt { - [TokenTree::Token(token)] if token.is_keyword(kw::True) => { - cx.set_trace_macros(true); - } - [TokenTree::Token(token)] if token.is_keyword(kw::False) => { - cx.set_trace_macros(false); - } - _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), - } - - base::DummyResult::any_valid(sp) -} diff --git a/gcc/rust/rustc_parser/libsyntax_pos/Cargo.toml b/gcc/rust/rustc_parser/libsyntax_pos/Cargo.toml deleted file mode 100644 index eebd25d..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "syntax_pos" -version = "0.0.0" -edition = "2018" - -[lib] -name = "syntax_pos" -path = "lib.rs" -doctest = false - -[dependencies] -serialize = { path = "../libserialize" } -rustc_macros = { path = "../librustc_macros" } -rustc_data_structures = { path = "../librustc_data_structures" } -arena = { path = "../libarena" } -scoped-tls = "1.0" -unicode-width = "0.1.4" -cfg-if = "0.1.2" diff --git a/gcc/rust/rustc_parser/libsyntax_pos/analyze_source_file.rs b/gcc/rust/rustc_parser/libsyntax_pos/analyze_source_file.rs deleted file mode 100644 index 353b4e4..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/analyze_source_file.rs +++ /dev/null @@ -1,425 +0,0 @@ -use unicode_width::UnicodeWidthChar; -use super::*; - -/// Finds all newlines, multi-byte characters, and non-narrow characters in a -/// SourceFile. -/// -/// This function will use an SSE2 enhanced implementation if hardware support -/// is detected at runtime. -pub fn analyze_source_file( - src: &str, - source_file_start_pos: BytePos) - -> (Vec, Vec, Vec) -{ - let mut lines = vec![source_file_start_pos]; - let mut multi_byte_chars = vec![]; - let mut non_narrow_chars = vec![]; - - // Calls the right implementation, depending on hardware support available. - analyze_source_file_dispatch(src, - source_file_start_pos, - &mut lines, - &mut multi_byte_chars, - &mut non_narrow_chars); - - // The code above optimistically registers a new line *after* each \n - // it encounters. If that point is already outside the source_file, remove - // it again. - if let Some(&last_line_start) = lines.last() { - let source_file_end = source_file_start_pos + BytePos::from_usize(src.len()); - assert!(source_file_end >= last_line_start); - if last_line_start == source_file_end { - lines.pop(); - } - } - - (lines, multi_byte_chars, non_narrow_chars) -} - -cfg_if::cfg_if! { - if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64")))] { - fn analyze_source_file_dispatch(src: &str, - source_file_start_pos: BytePos, - lines: &mut Vec, - multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec) { - if is_x86_feature_detected!("sse2") { - unsafe { - analyze_source_file_sse2(src, - source_file_start_pos, - lines, - multi_byte_chars, - non_narrow_chars); - } - } else { - analyze_source_file_generic(src, - src.len(), - source_file_start_pos, - lines, - multi_byte_chars, - non_narrow_chars); - - } - } - - /// Checks 16 byte chunks of text at a time. If the chunk contains - /// something other than printable ASCII characters and newlines, the - /// function falls back to the generic implementation. Otherwise it uses - /// SSE2 intrinsics to quickly find all newlines. - #[target_feature(enable = "sse2")] - unsafe fn analyze_source_file_sse2(src: &str, - output_offset: BytePos, - lines: &mut Vec, - multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec) { - #[cfg(target_arch = "x86")] - use std::arch::x86::*; - #[cfg(target_arch = "x86_64")] - use std::arch::x86_64::*; - - const CHUNK_SIZE: usize = 16; - - let src_bytes = src.as_bytes(); - - let chunk_count = src.len() / CHUNK_SIZE; - - // This variable keeps track of where we should start decoding a - // chunk. If a multi-byte character spans across chunk boundaries, - // we need to skip that part in the next chunk because we already - // handled it. - let mut intra_chunk_offset = 0; - - for chunk_index in 0 .. chunk_count { - let ptr = src_bytes.as_ptr() as *const __m128i; - // We don't know if the pointer is aligned to 16 bytes, so we - // use `loadu`, which supports unaligned loading. - let chunk = _mm_loadu_si128(ptr.offset(chunk_index as isize)); - - // For character in the chunk, see if its byte value is < 0, which - // indicates that it's part of a UTF-8 char. - let multibyte_test = _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)); - // Create a bit mask from the comparison results. - let multibyte_mask = _mm_movemask_epi8(multibyte_test); - - // If the bit mask is all zero, we only have ASCII chars here: - if multibyte_mask == 0 { - assert!(intra_chunk_offset == 0); - - // Check if there are any control characters in the chunk. All - // control characters that we can encounter at this point have a - // byte value less than 32 or ... - let control_char_test0 = _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)); - let control_char_mask0 = _mm_movemask_epi8(control_char_test0); - - // ... it's the ASCII 'DEL' character with a value of 127. - let control_char_test1 = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)); - let control_char_mask1 = _mm_movemask_epi8(control_char_test1); - - let control_char_mask = control_char_mask0 | control_char_mask1; - - if control_char_mask != 0 { - // Check for newlines in the chunk - let newlines_test = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)); - let newlines_mask = _mm_movemask_epi8(newlines_test); - - if control_char_mask == newlines_mask { - // All control characters are newlines, record them - let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32; - let output_offset = output_offset + - BytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - - loop { - let index = newlines_mask.trailing_zeros(); - - if index >= CHUNK_SIZE as u32 { - // We have arrived at the end of the chunk. - break - } - - lines.push(BytePos(index) + output_offset); - - // Clear the bit, so we can find the next one. - newlines_mask &= (!1) << index; - } - - // We are done for this chunk. All control characters were - // newlines and we took care of those. - continue - } else { - // Some of the control characters are not newlines, - // fall through to the slow path below. - } - } else { - // No control characters, nothing to record for this chunk - continue - } - } - - // The slow path. - // There are control chars in here, fallback to generic decoding. - let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; - intra_chunk_offset = analyze_source_file_generic( - &src[scan_start .. ], - CHUNK_SIZE - intra_chunk_offset, - BytePos::from_usize(scan_start) + output_offset, - lines, - multi_byte_chars, - non_narrow_chars - ); - } - - // There might still be a tail left to analyze - let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset; - if tail_start < src.len() { - analyze_source_file_generic(&src[tail_start as usize ..], - src.len() - tail_start, - output_offset + BytePos::from_usize(tail_start), - lines, - multi_byte_chars, - non_narrow_chars); - } - } - } else { - - // The target (or compiler version) does not support SSE2 ... - fn analyze_source_file_dispatch(src: &str, - source_file_start_pos: BytePos, - lines: &mut Vec, - multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec) { - analyze_source_file_generic(src, - src.len(), - source_file_start_pos, - lines, - multi_byte_chars, - non_narrow_chars); - } - } -} - -// `scan_len` determines the number of bytes in `src` to scan. Note that the -// function can read past `scan_len` if a multi-byte character start within the -// range but extends past it. The overflow is returned by the function. -fn analyze_source_file_generic(src: &str, - scan_len: usize, - output_offset: BytePos, - lines: &mut Vec, - multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec) - -> usize -{ - assert!(src.len() >= scan_len); - let mut i = 0; - let src_bytes = src.as_bytes(); - - while i < scan_len { - let byte = unsafe { - // We verified that i < scan_len <= src.len() - *src_bytes.get_unchecked(i as usize) - }; - - // How much to advance in order to get to the next UTF-8 char in the - // string. - let mut char_len = 1; - - if byte < 32 { - // This is an ASCII control character, it could be one of the cases - // that are interesting to us. - - let pos = BytePos::from_usize(i) + output_offset; - - match byte { - b'\n' => { - lines.push(pos + BytePos(1)); - } - b'\t' => { - non_narrow_chars.push(NonNarrowChar::Tab(pos)); - } - _ => { - non_narrow_chars.push(NonNarrowChar::ZeroWidth(pos)); - } - } - } else if byte >= 127 { - // The slow path: - // This is either ASCII control character "DEL" or the beginning of - // a multibyte char. Just decode to `char`. - let c = (&src[i..]).chars().next().unwrap(); - char_len = c.len_utf8(); - - let pos = BytePos::from_usize(i) + output_offset; - - if char_len > 1 { - assert!(char_len >=2 && char_len <= 4); - let mbc = MultiByteChar { - pos, - bytes: char_len as u8, - }; - multi_byte_chars.push(mbc); - } - - // Assume control characters are zero width. - // FIXME: How can we decide between `width` and `width_cjk`? - let char_width = UnicodeWidthChar::width(c).unwrap_or(0); - - if char_width != 1 { - non_narrow_chars.push(NonNarrowChar::new(pos, char_width)); - } - } - - i += char_len; - } - - i - scan_len -} - - - -macro_rules! test { - (case: $test_name:ident, - text: $text:expr, - source_file_start_pos: $source_file_start_pos:expr, - lines: $lines:expr, - multi_byte_chars: $multi_byte_chars:expr, - non_narrow_chars: $non_narrow_chars:expr,) => ( - - #[test] - fn $test_name() { - - let (lines, multi_byte_chars, non_narrow_chars) = - analyze_source_file($text, BytePos($source_file_start_pos)); - - let expected_lines: Vec = $lines - .into_iter() - .map(|pos| BytePos(pos)) - .collect(); - - assert_eq!(lines, expected_lines); - - let expected_mbcs: Vec = $multi_byte_chars - .into_iter() - .map(|(pos, bytes)| MultiByteChar { - pos: BytePos(pos), - bytes, - }) - .collect(); - - assert_eq!(multi_byte_chars, expected_mbcs); - - let expected_nncs: Vec = $non_narrow_chars - .into_iter() - .map(|(pos, width)| { - NonNarrowChar::new(BytePos(pos), width) - }) - .collect(); - - assert_eq!(non_narrow_chars, expected_nncs); - }) -} - -test!( - case: empty_text, - text: "", - source_file_start_pos: 0, - lines: vec![], - multi_byte_chars: vec![], - non_narrow_chars: vec![], -); - -test!( - case: newlines_short, - text: "a\nc", - source_file_start_pos: 0, - lines: vec![0, 2], - multi_byte_chars: vec![], - non_narrow_chars: vec![], -); - -test!( - case: newlines_long, - text: "012345678\nabcdef012345678\na", - source_file_start_pos: 0, - lines: vec![0, 10, 26], - multi_byte_chars: vec![], - non_narrow_chars: vec![], -); - -test!( - case: newline_and_multi_byte_char_in_same_chunk, - text: "01234β789\nbcdef0123456789abcdef", - source_file_start_pos: 0, - lines: vec![0, 11], - multi_byte_chars: vec![(5, 2)], - non_narrow_chars: vec![], -); - -test!( - case: newline_and_control_char_in_same_chunk, - text: "01234\u{07}6789\nbcdef0123456789abcdef", - source_file_start_pos: 0, - lines: vec![0, 11], - multi_byte_chars: vec![], - non_narrow_chars: vec![(5, 0)], -); - -test!( - case: multi_byte_char_short, - text: "aβc", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![(1, 2)], - non_narrow_chars: vec![], -); - -test!( - case: multi_byte_char_long, - text: "0123456789abcΔf012345β", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![(13, 2), (22, 2)], - non_narrow_chars: vec![], -); - -test!( - case: multi_byte_char_across_chunk_boundary, - text: "0123456789abcdeΔ123456789abcdef01234", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![(15, 2)], - non_narrow_chars: vec![], -); - -test!( - case: multi_byte_char_across_chunk_boundary_tail, - text: "0123456789abcdeΔ....", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![(15, 2)], - non_narrow_chars: vec![], -); - -test!( - case: non_narrow_short, - text: "0\t2", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![], - non_narrow_chars: vec![(1, 4)], -); - -test!( - case: non_narrow_long, - text: "01\t3456789abcdef01234567\u{07}9", - source_file_start_pos: 0, - lines: vec![0], - multi_byte_chars: vec![], - non_narrow_chars: vec![(2, 4), (24, 0)], -); - -test!( - case: output_offset_all, - text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf", - source_file_start_pos: 1000, - lines: vec![0 + 1000, 7 + 1000, 27 + 1000], - multi_byte_chars: vec![(13 + 1000, 2), (29 + 1000, 2)], - non_narrow_chars: vec![(2 + 1000, 4), (24 + 1000, 0)], -); diff --git a/gcc/rust/rustc_parser/libsyntax_pos/edition.rs b/gcc/rust/rustc_parser/libsyntax_pos/edition.rs deleted file mode 100644 index 2021656..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/edition.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::symbol::{Symbol, sym}; -use std::fmt; -use std::str::FromStr; -use crate::GLOBALS; - -/// The edition of the compiler (RFC 2052) -#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] -pub enum Edition { - // editions must be kept in order, oldest to newest - - /// The 2015 edition - Edition2015, - /// The 2018 edition - Edition2018, - - // when adding new editions, be sure to update: - // - // - Update the `ALL_EDITIONS` const - // - Update the EDITION_NAME_LIST const - // - add a `rust_####()` function to the session - // - update the enum in Cargo's sources as well -} - -// must be in order from oldest to newest -pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018]; - -pub const EDITION_NAME_LIST: &str = "2015|2018"; - -pub const DEFAULT_EDITION: Edition = Edition::Edition2015; - -impl fmt::Display for Edition { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - Edition::Edition2015 => "2015", - Edition::Edition2018 => "2018", - }; - write!(f, "{}", s) - } -} - -impl Edition { - pub fn from_session() -> Edition { - GLOBALS.with(|globals| globals.edition) - } - - pub fn lint_name(&self) -> &'static str { - match *self { - Edition::Edition2015 => "rust_2015_compatibility", - Edition::Edition2018 => "rust_2018_compatibility", - } - } - - pub fn feature_name(&self) -> Symbol { - match *self { - Edition::Edition2015 => sym::rust_2015_preview, - Edition::Edition2018 => sym::rust_2018_preview, - } - } - - pub fn is_stable(&self) -> bool { - match *self { - Edition::Edition2015 => true, - Edition::Edition2018 => true, - } - } -} - -impl FromStr for Edition { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "2015" => Ok(Edition::Edition2015), - "2018" => Ok(Edition::Edition2018), - _ => Err(()) - } - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_pos/hygiene.rs b/gcc/rust/rustc_parser/libsyntax_pos/hygiene.rs deleted file mode 100644 index a6c8c76..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/hygiene.rs +++ /dev/null @@ -1,763 +0,0 @@ -//! Machinery for hygienic macros, inspired by the `MTWT[1]` paper. -//! -//! `[1]` Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012. -//! *Macros that work together: Compile-time bindings, partial expansion, -//! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216. -//! DOI=10.1017/S0956796812000093 - -// Hygiene data is stored in a global variable and accessed via TLS, which -// means that accesses are somewhat expensive. (`HygieneData::with` -// encapsulates a single access.) Therefore, on hot code paths it is worth -// ensuring that multiple HygieneData accesses are combined into a single -// `HygieneData::with`. -// -// This explains why `HygieneData`, `SyntaxContext` and `Mark` have interfaces -// with a certain amount of redundancy in them. For example, -// `SyntaxContext::outer_expn_info` combines `SyntaxContext::outer` and -// `Mark::expn_info` so that two `HygieneData` accesses can be performed within -// a single `HygieneData::with` call. -// -// It also explains why many functions appear in `HygieneData` and again in -// `SyntaxContext` or `Mark`. For example, `HygieneData::outer` and -// `SyntaxContext::outer` do the same thing, but the former is for use within a -// `HygieneData::with` call while the latter is for use outside such a call. -// When modifying this file it is important to understand this distinction, -// because getting it wrong can lead to nested `HygieneData::with` calls that -// trigger runtime aborts. (Fortunately these are obvious and easy to fix.) - -use crate::GLOBALS; -use crate::Span; -use crate::edition::Edition; -use crate::symbol::{kw, Symbol}; - -use serialize::{Encodable, Decodable, Encoder, Decoder}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::Lrc; -use std::{fmt, mem}; - -/// A SyntaxContext represents a chain of macro expansions (represented by marks). -#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] -pub struct SyntaxContext(u32); - -#[derive(Copy, Clone, Debug)] -struct SyntaxContextData { - outer_mark: Mark, - transparency: Transparency, - prev_ctxt: SyntaxContext, - /// This context, but with all transparent and semi-transparent marks filtered away. - opaque: SyntaxContext, - /// This context, but with all transparent marks filtered away. - opaque_and_semitransparent: SyntaxContext, - /// Name of the crate to which `$crate` with this context would resolve. - dollar_crate_name: Symbol, -} - -/// A mark is a unique ID associated with a macro expansion. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Mark(u32); - -#[derive(Clone, Debug)] -struct MarkData { - parent: Mark, - expn_info: Option, -} - -/// A property of a macro expansion that determines how identifiers -/// produced by that expansion are resolved. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] -pub enum Transparency { - /// Identifier produced by a transparent expansion is always resolved at call-site. - /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. - Transparent, - /// Identifier produced by a semi-transparent expansion may be resolved - /// either at call-site or at definition-site. - /// If it's a local variable, label or `$crate` then it's resolved at def-site. - /// Otherwise it's resolved at call-site. - /// `macro_rules` macros behave like this, built-in macros currently behave like this too, - /// but that's an implementation detail. - SemiTransparent, - /// Identifier produced by an opaque expansion is always resolved at definition-site. - /// Def-site spans in procedural macros, identifiers from `macro` by default use this. - Opaque, -} - -impl Mark { - pub fn fresh(parent: Mark) -> Self { - HygieneData::with(|data| { - data.marks.push(MarkData { parent, expn_info: None }); - Mark(data.marks.len() as u32 - 1) - }) - } - - /// The mark of the theoretical expansion that generates freshly parsed, unexpanded AST. - #[inline] - pub fn root() -> Self { - Mark(0) - } - - #[inline] - pub fn as_u32(self) -> u32 { - self.0 - } - - #[inline] - pub fn from_u32(raw: u32) -> Mark { - Mark(raw) - } - - #[inline] - pub fn parent(self) -> Mark { - HygieneData::with(|data| data.marks[self.0 as usize].parent) - } - - #[inline] - pub fn expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(self).cloned()) - } - - #[inline] - pub fn set_expn_info(self, info: ExpnInfo) { - HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info)) - } - - pub fn is_descendant_of(self, ancestor: Mark) -> bool { - HygieneData::with(|data| data.is_descendant_of(self, ancestor)) - } - - /// `mark.outer_is_descendant_of(ctxt)` is equivalent to but faster than - /// `mark.is_descendant_of(ctxt.outer())`. - pub fn outer_is_descendant_of(self, ctxt: SyntaxContext) -> bool { - HygieneData::with(|data| data.is_descendant_of(self, data.outer(ctxt))) - } - - /// Computes a mark such that both input marks are descendants of (or equal to) the returned - /// mark. That is, the following holds: - /// - /// ```rust - /// let la = least_ancestor(a, b); - /// assert!(a.is_descendant_of(la)) - /// assert!(b.is_descendant_of(la)) - /// ``` - pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark { - HygieneData::with(|data| { - // Compute the path from a to the root - let mut a_path = FxHashSet::::default(); - while a != Mark::root() { - a_path.insert(a); - a = data.marks[a.0 as usize].parent; - } - - // While the path from b to the root hasn't intersected, move up the tree - while !a_path.contains(&b) { - b = data.marks[b.0 as usize].parent; - } - - b - }) - } - - // Used for enabling some compatibility fallback in resolve. - #[inline] - pub fn looks_like_proc_macro_derive(self) -> bool { - HygieneData::with(|data| { - if data.default_transparency(self) == Transparency::Opaque { - if let Some(expn_info) = &data.marks[self.0 as usize].expn_info { - if let ExpnFormat::MacroAttribute(name) = expn_info.format { - if name.as_str().starts_with("derive(") { - return true; - } - } - } - } - false - }) - } -} - -#[derive(Debug)] -crate struct HygieneData { - marks: Vec, - syntax_contexts: Vec, - markings: FxHashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>, -} - -impl HygieneData { - crate fn new() -> Self { - HygieneData { - marks: vec![MarkData { - parent: Mark::root(), - expn_info: None, - }], - syntax_contexts: vec![SyntaxContextData { - outer_mark: Mark::root(), - transparency: Transparency::Opaque, - prev_ctxt: SyntaxContext(0), - opaque: SyntaxContext(0), - opaque_and_semitransparent: SyntaxContext(0), - dollar_crate_name: kw::DollarCrate, - }], - markings: FxHashMap::default(), - } - } - - fn with T>(f: F) -> T { - GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) - } - - fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> { - self.marks[mark.0 as usize].expn_info.as_ref() - } - - fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool { - while mark != ancestor { - if mark == Mark::root() { - return false; - } - mark = self.marks[mark.0 as usize].parent; - } - true - } - - fn default_transparency(&self, mark: Mark) -> Transparency { - self.marks[mark.0 as usize].expn_info.as_ref().map_or( - Transparency::SemiTransparent, |einfo| einfo.default_transparency - ) - } - - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { - self.syntax_contexts[ctxt.0 as usize].opaque - } - - fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext { - self.syntax_contexts[ctxt.0 as usize].opaque_and_semitransparent - } - - fn outer(&self, ctxt: SyntaxContext) -> Mark { - self.syntax_contexts[ctxt.0 as usize].outer_mark - } - - fn transparency(&self, ctxt: SyntaxContext) -> Transparency { - self.syntax_contexts[ctxt.0 as usize].transparency - } - - fn prev_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext { - self.syntax_contexts[ctxt.0 as usize].prev_ctxt - } - - fn remove_mark(&self, ctxt: &mut SyntaxContext) -> Mark { - let outer_mark = self.syntax_contexts[ctxt.0 as usize].outer_mark; - *ctxt = self.prev_ctxt(*ctxt); - outer_mark - } - - fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(Mark, Transparency)> { - let mut marks = Vec::new(); - while ctxt != SyntaxContext::empty() { - let outer_mark = self.outer(ctxt); - let transparency = self.transparency(ctxt); - let prev_ctxt = self.prev_ctxt(ctxt); - marks.push((outer_mark, transparency)); - ctxt = prev_ctxt; - } - marks.reverse(); - marks - } - - fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span { - while span.ctxt() != crate::NO_EXPANSION && span.ctxt() != to { - if let Some(info) = self.expn_info(self.outer(span.ctxt())) { - span = info.call_site; - } else { - break; - } - } - span - } - - fn adjust(&self, ctxt: &mut SyntaxContext, expansion: Mark) -> Option { - let mut scope = None; - while !self.is_descendant_of(expansion, self.outer(*ctxt)) { - scope = Some(self.remove_mark(ctxt)); - } - scope - } - - fn apply_mark(&mut self, ctxt: SyntaxContext, mark: Mark) -> SyntaxContext { - assert_ne!(mark, Mark::root()); - self.apply_mark_with_transparency(ctxt, mark, self.default_transparency(mark)) - } - - fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, mark: Mark, - transparency: Transparency) -> SyntaxContext { - assert_ne!(mark, Mark::root()); - if transparency == Transparency::Opaque { - return self.apply_mark_internal(ctxt, mark, transparency); - } - - let call_site_ctxt = - self.expn_info(mark).map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()); - let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { - self.modern(call_site_ctxt) - } else { - self.modern_and_legacy(call_site_ctxt) - }; - - if call_site_ctxt == SyntaxContext::empty() { - return self.apply_mark_internal(ctxt, mark, transparency); - } - - // Otherwise, `mark` is a macros 1.0 definition and the call site is in a - // macros 2.0 expansion, i.e., a macros 1.0 invocation is in a macros 2.0 definition. - // - // In this case, the tokens from the macros 1.0 definition inherit the hygiene - // at their invocation. That is, we pretend that the macros 1.0 definition - // was defined at its invocation (i.e., inside the macros 2.0 definition) - // so that the macros 2.0 definition remains hygienic. - // - // See the example at `test/run-pass/hygiene/legacy_interaction.rs`. - for (mark, transparency) in self.marks(ctxt) { - call_site_ctxt = self.apply_mark_internal(call_site_ctxt, mark, transparency); - } - self.apply_mark_internal(call_site_ctxt, mark, transparency) - } - - fn apply_mark_internal(&mut self, ctxt: SyntaxContext, mark: Mark, transparency: Transparency) - -> SyntaxContext { - let syntax_contexts = &mut self.syntax_contexts; - let mut opaque = syntax_contexts[ctxt.0 as usize].opaque; - let mut opaque_and_semitransparent = - syntax_contexts[ctxt.0 as usize].opaque_and_semitransparent; - - if transparency >= Transparency::Opaque { - let prev_ctxt = opaque; - opaque = *self.markings.entry((prev_ctxt, mark, transparency)).or_insert_with(|| { - let new_opaque = SyntaxContext(syntax_contexts.len() as u32); - syntax_contexts.push(SyntaxContextData { - outer_mark: mark, - transparency, - prev_ctxt, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque - }); - } - - if transparency >= Transparency::SemiTransparent { - let prev_ctxt = opaque_and_semitransparent; - opaque_and_semitransparent = - *self.markings.entry((prev_ctxt, mark, transparency)).or_insert_with(|| { - let new_opaque_and_semitransparent = - SyntaxContext(syntax_contexts.len() as u32); - syntax_contexts.push(SyntaxContextData { - outer_mark: mark, - transparency, - prev_ctxt, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent - }); - } - - let prev_ctxt = ctxt; - *self.markings.entry((prev_ctxt, mark, transparency)).or_insert_with(|| { - let new_opaque_and_semitransparent_and_transparent = - SyntaxContext(syntax_contexts.len() as u32); - syntax_contexts.push(SyntaxContextData { - outer_mark: mark, - transparency, - prev_ctxt, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent_and_transparent - }) - } -} - -pub fn clear_markings() { - HygieneData::with(|data| data.markings = FxHashMap::default()); -} - -pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { - HygieneData::with(|data| data.walk_chain(span, to)) -} - -impl SyntaxContext { - #[inline] - pub const fn empty() -> Self { - SyntaxContext(0) - } - - #[inline] - crate fn as_u32(self) -> u32 { - self.0 - } - - #[inline] - crate fn from_u32(raw: u32) -> SyntaxContext { - SyntaxContext(raw) - } - - // Allocate a new SyntaxContext with the given ExpnInfo. This is used when - // deserializing Spans from the incr. comp. cache. - // FIXME(mw): This method does not restore MarkData::parent or - // SyntaxContextData::prev_ctxt or SyntaxContextData::opaque. These things - // don't seem to be used after HIR lowering, so everything should be fine - // as long as incremental compilation does not kick in before that. - pub fn allocate_directly(expansion_info: ExpnInfo) -> Self { - HygieneData::with(|data| { - data.marks.push(MarkData { - parent: Mark::root(), - expn_info: Some(expansion_info), - }); - - let mark = Mark(data.marks.len() as u32 - 1); - - data.syntax_contexts.push(SyntaxContextData { - outer_mark: mark, - transparency: Transparency::SemiTransparent, - prev_ctxt: SyntaxContext::empty(), - opaque: SyntaxContext::empty(), - opaque_and_semitransparent: SyntaxContext::empty(), - dollar_crate_name: kw::DollarCrate, - }); - SyntaxContext(data.syntax_contexts.len() as u32 - 1) - }) - } - - /// Extend a syntax context with a given mark and default transparency for that mark. - pub fn apply_mark(self, mark: Mark) -> SyntaxContext { - HygieneData::with(|data| data.apply_mark(self, mark)) - } - - /// Extend a syntax context with a given mark and transparency - pub fn apply_mark_with_transparency(self, mark: Mark, transparency: Transparency) - -> SyntaxContext { - HygieneData::with(|data| data.apply_mark_with_transparency(self, mark, transparency)) - } - - /// Pulls a single mark off of the syntax context. This effectively moves the - /// context up one macro definition level. That is, if we have a nested macro - /// definition as follows: - /// - /// ```rust - /// macro_rules! f { - /// macro_rules! g { - /// ... - /// } - /// } - /// ``` - /// - /// and we have a SyntaxContext that is referring to something declared by an invocation - /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the - /// invocation of f that created g1. - /// Returns the mark that was removed. - pub fn remove_mark(&mut self) -> Mark { - HygieneData::with(|data| data.remove_mark(self)) - } - - pub fn marks(self) -> Vec<(Mark, Transparency)> { - HygieneData::with(|data| data.marks(self)) - } - - /// Adjust this context for resolution in a scope created by the given expansion. - /// For example, consider the following three resolutions of `f`: - /// - /// ```rust - /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty. - /// m!(f); - /// macro m($f:ident) { - /// mod bar { - /// pub fn f() {} // `f`'s `SyntaxContext` has a single `Mark` from `m`. - /// pub fn $f() {} // `$f`'s `SyntaxContext` is empty. - /// } - /// foo::f(); // `f`'s `SyntaxContext` has a single `Mark` from `m` - /// //^ Since `mod foo` is outside this expansion, `adjust` removes the mark from `f`, - /// //| and it resolves to `::foo::f`. - /// bar::f(); // `f`'s `SyntaxContext` has a single `Mark` from `m` - /// //^ Since `mod bar` not outside this expansion, `adjust` does not change `f`, - /// //| and it resolves to `::bar::f`. - /// bar::$f(); // `f`'s `SyntaxContext` is empty. - /// //^ Since `mod bar` is not outside this expansion, `adjust` does not change `$f`, - /// //| and it resolves to `::bar::$f`. - /// } - /// ``` - /// This returns the expansion whose definition scope we use to privacy check the resolution, - /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope). - pub fn adjust(&mut self, expansion: Mark) -> Option { - HygieneData::with(|data| data.adjust(self, expansion)) - } - - /// Like `SyntaxContext::adjust`, but also modernizes `self`. - pub fn modernize_and_adjust(&mut self, expansion: Mark) -> Option { - HygieneData::with(|data| { - *self = data.modern(*self); - data.adjust(self, expansion) - }) - } - - /// Adjust this context for resolution in a scope created by the given expansion - /// via a glob import with the given `SyntaxContext`. - /// For example: - /// - /// ```rust - /// m!(f); - /// macro m($i:ident) { - /// mod foo { - /// pub fn f() {} // `f`'s `SyntaxContext` has a single `Mark` from `m`. - /// pub fn $i() {} // `$i`'s `SyntaxContext` is empty. - /// } - /// n(f); - /// macro n($j:ident) { - /// use foo::*; - /// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n` - /// //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::f`. - /// $i(); // `$i`'s `SyntaxContext` has a mark from `n` - /// //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::$i`. - /// $j(); // `$j`'s `SyntaxContext` has a mark from `m` - /// //^ This cannot be glob-adjusted, so this is a resolution error. - /// } - /// } - /// ``` - /// This returns `None` if the context cannot be glob-adjusted. - /// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details). - pub fn glob_adjust(&mut self, expansion: Mark, glob_span: Span) -> Option> { - HygieneData::with(|data| { - let mut scope = None; - let mut glob_ctxt = data.modern(glob_span.ctxt()); - while !data.is_descendant_of(expansion, data.outer(glob_ctxt)) { - scope = Some(data.remove_mark(&mut glob_ctxt)); - if data.remove_mark(self) != scope.unwrap() { - return None; - } - } - if data.adjust(self, expansion).is_some() { - return None; - } - Some(scope) - }) - } - - /// Undo `glob_adjust` if possible: - /// - /// ```rust - /// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) { - /// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope)); - /// } - /// ``` - pub fn reverse_glob_adjust(&mut self, expansion: Mark, glob_span: Span) - -> Option> { - HygieneData::with(|data| { - if data.adjust(self, expansion).is_some() { - return None; - } - - let mut glob_ctxt = data.modern(glob_span.ctxt()); - let mut marks = Vec::new(); - while !data.is_descendant_of(expansion, data.outer(glob_ctxt)) { - marks.push(data.remove_mark(&mut glob_ctxt)); - } - - let scope = marks.last().cloned(); - while let Some(mark) = marks.pop() { - *self = data.apply_mark(*self, mark); - } - Some(scope) - }) - } - - pub fn hygienic_eq(self, other: SyntaxContext, mark: Mark) -> bool { - HygieneData::with(|data| { - let mut self_modern = data.modern(self); - data.adjust(&mut self_modern, mark); - self_modern == data.modern(other) - }) - } - - #[inline] - pub fn modern(self) -> SyntaxContext { - HygieneData::with(|data| data.modern(self)) - } - - #[inline] - pub fn modern_and_legacy(self) -> SyntaxContext { - HygieneData::with(|data| data.modern_and_legacy(self)) - } - - #[inline] - pub fn outer(self) -> Mark { - HygieneData::with(|data| data.outer(self)) - } - - /// `ctxt.outer_expn_info()` is equivalent to but faster than - /// `ctxt.outer().expn_info()`. - #[inline] - pub fn outer_expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(data.outer(self)).cloned()) - } - - /// `ctxt.outer_and_expn_info()` is equivalent to but faster than - /// `{ let outer = ctxt.outer(); (outer, outer.expn_info()) }`. - #[inline] - pub fn outer_and_expn_info(self) -> (Mark, Option) { - HygieneData::with(|data| { - let outer = data.outer(self); - (outer, data.expn_info(outer).cloned()) - }) - } - - pub fn dollar_crate_name(self) -> Symbol { - HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name) - } - - pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) { - HygieneData::with(|data| { - let prev_dollar_crate_name = mem::replace( - &mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name - ); - assert!(dollar_crate_name == prev_dollar_crate_name || - prev_dollar_crate_name == kw::DollarCrate, - "$crate name is reset for a syntax context"); - }) - } -} - -impl fmt::Debug for SyntaxContext { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "#{}", self.0) - } -} - -/// Extra information for tracking spans of macro and syntax sugar expansion -#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct ExpnInfo { - // --- The part unique to each expansion. - /// The location of the actual macro invocation or syntax sugar , e.g. - /// `let x = foo!();` or `if let Some(y) = x {}` - /// - /// This may recursively refer to other macro invocations, e.g., if - /// `foo!()` invoked `bar!()` internally, and there was an - /// expression inside `bar!`; the call_site of the expression in - /// the expansion would point to the `bar!` invocation; that - /// call_site span would have its own ExpnInfo, with the call_site - /// pointing to the `foo!` invocation. - pub call_site: Span, - /// The format with which the macro was invoked. - pub format: ExpnFormat, - - // --- The part specific to the macro/desugaring definition. - // --- FIXME: Share it between expansions with the same definition. - /// The span of the macro definition itself. The macro may not - /// have a sensible definition span (e.g., something defined - /// completely inside libsyntax) in which case this is None. - /// This span serves only informational purpose and is not used for resolution. - pub def_site: Option, - /// Transparency used by `apply_mark` for mark with this expansion info by default. - pub default_transparency: Transparency, - /// List of #[unstable]/feature-gated features that the macro is allowed to use - /// internally without forcing the whole crate to opt-in - /// to them. - pub allow_internal_unstable: Option>, - /// Whether the macro is allowed to use `unsafe` internally - /// even if the user crate has `#![forbid(unsafe_code)]`. - pub allow_internal_unsafe: bool, - /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) - /// for a given macro. - pub local_inner_macros: bool, - /// Edition of the crate in which the macro is defined. - pub edition: Edition, -} - -impl ExpnInfo { - /// Constructs an expansion info with default properties. - pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo { - ExpnInfo { - call_site, - format, - def_site: None, - default_transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - edition, - } - } - - pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition, - allow_internal_unstable: &[Symbol]) -> ExpnInfo { - ExpnInfo { - allow_internal_unstable: Some(allow_internal_unstable.into()), - ..ExpnInfo::default(format, call_site, edition) - } - } -} - -/// The source of expansion. -#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] -pub enum ExpnFormat { - /// e.g., #[derive(...)] - MacroAttribute(Symbol), - /// e.g., `format!()` - MacroBang(Symbol), - /// Desugaring done by the compiler during HIR lowering. - CompilerDesugaring(CompilerDesugaringKind) -} - -impl ExpnFormat { - pub fn name(&self) -> Symbol { - match *self { - ExpnFormat::MacroBang(name) | ExpnFormat::MacroAttribute(name) => name, - ExpnFormat::CompilerDesugaring(kind) => kind.name(), - } - } -} - -/// The kind of compiler desugaring. -#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] -pub enum CompilerDesugaringKind { - /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`. - /// However, we do not want to blame `c` for unreachability but rather say that `i` - /// is unreachable. This desugaring kind allows us to avoid blaming `c`. - /// This also applies to `while` loops. - CondTemporary, - QuestionMark, - TryBlock, - /// Desugaring of an `impl Trait` in return type position - /// to an `existential type Foo: Trait;` and replacing the - /// `impl Trait` with `Foo`. - ExistentialType, - Async, - Await, - ForLoop, -} - -impl CompilerDesugaringKind { - pub fn name(self) -> Symbol { - Symbol::intern(match self { - CompilerDesugaringKind::CondTemporary => "if and while condition", - CompilerDesugaringKind::Async => "async", - CompilerDesugaringKind::Await => "await", - CompilerDesugaringKind::QuestionMark => "?", - CompilerDesugaringKind::TryBlock => "try block", - CompilerDesugaringKind::ExistentialType => "existential type", - CompilerDesugaringKind::ForLoop => "for loop", - }) - } -} - -impl Encodable for SyntaxContext { - fn encode(&self, _: &mut E) -> Result<(), E::Error> { - Ok(()) // FIXME(jseyfried) intercrate hygiene - } -} - -impl Decodable for SyntaxContext { - fn decode(_: &mut D) -> Result { - Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_pos/lib.rs b/gcc/rust/rustc_parser/libsyntax_pos/lib.rs deleted file mode 100644 index 07b9f60..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/lib.rs +++ /dev/null @@ -1,1446 +0,0 @@ -//! The source positions and related helper functions. -//! -//! ## Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] - -#![deny(rust_2018_idioms)] -#![deny(unused_lifetimes)] - -#![feature(const_fn)] -#![feature(crate_visibility_modifier)] -#![feature(nll)] -#![feature(non_exhaustive)] -#![feature(optin_builtin_traits)] -#![feature(rustc_attrs)] -#![feature(proc_macro_hygiene)] -#![feature(specialization)] -#![feature(step_trait)] - -use serialize::{Encodable, Decodable, Encoder, Decoder}; - -#[allow(unused_extern_crates)] -extern crate serialize as rustc_serialize; // used by deriving - -pub mod edition; -use edition::Edition; -pub mod hygiene; -pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind}; - -mod span_encoding; -pub use span_encoding::{Span, DUMMY_SP}; - -pub mod symbol; -pub use symbol::{Symbol, sym}; - -mod analyze_source_file; - -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::{Lrc, Lock}; - -use std::borrow::Cow; -use std::cell::Cell; -use std::cmp::{self, Ordering}; -use std::fmt; -use std::hash::{Hasher, Hash}; -use std::ops::{Add, Sub}; -use std::path::PathBuf; - -pub struct Globals { - symbol_interner: Lock, - span_interner: Lock, - hygiene_data: Lock, - edition: Edition, -} - -impl Globals { - pub fn new(edition: Edition) -> Globals { - Globals { - symbol_interner: Lock::new(symbol::Interner::fresh()), - span_interner: Lock::new(span_encoding::SpanInterner::default()), - hygiene_data: Lock::new(hygiene::HygieneData::new()), - edition, - } - } -} - -scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); - -/// Differentiates between real files and common virtual files. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] -pub enum FileName { - Real(PathBuf), - /// A macro. This includes the full name of the macro, so that there are no clashes. - Macros(String), - /// Call to `quote!`. - QuoteExpansion(u64), - /// Command line. - Anon(u64), - /// Hack in `src/libsyntax/parse.rs`. - // FIXME(jseyfried) - MacroExpansion(u64), - ProcMacroSourceCode(u64), - /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`. - CfgSpec(u64), - /// Strings provided as crate attributes in the CLI. - CliCrateAttr(u64), - /// Custom sources for explicit parser calls from plugins and drivers. - Custom(String), - DocTest(PathBuf, isize), -} - -impl std::fmt::Display for FileName { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use FileName::*; - match *self { - Real(ref path) => write!(fmt, "{}", path.display()), - Macros(ref name) => write!(fmt, "<{} macros>", name), - QuoteExpansion(_) => write!(fmt, ""), - MacroExpansion(_) => write!(fmt, ""), - Anon(_) => write!(fmt, ""), - ProcMacroSourceCode(_) => - write!(fmt, ""), - CfgSpec(_) => write!(fmt, ""), - CliCrateAttr(_) => write!(fmt, ""), - Custom(ref s) => write!(fmt, "<{}>", s), - DocTest(ref path, _) => write!(fmt, "{}", path.display()), - } - } -} - -impl From for FileName { - fn from(p: PathBuf) -> Self { - assert!(!p.to_string_lossy().ends_with('>')); - FileName::Real(p) - } -} - -impl FileName { - pub fn is_real(&self) -> bool { - use FileName::*; - match *self { - Real(_) => true, - Macros(_) | - Anon(_) | - MacroExpansion(_) | - ProcMacroSourceCode(_) | - CfgSpec(_) | - CliCrateAttr(_) | - Custom(_) | - QuoteExpansion(_) | - DocTest(_, _) => false, - } - } - - pub fn is_macros(&self) -> bool { - use FileName::*; - match *self { - Real(_) | - Anon(_) | - MacroExpansion(_) | - ProcMacroSourceCode(_) | - CfgSpec(_) | - CliCrateAttr(_) | - Custom(_) | - QuoteExpansion(_) | - DocTest(_, _) => false, - Macros(_) => true, - } - } - - pub fn quote_expansion_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::QuoteExpansion(hasher.finish()) - } - - pub fn macro_expansion_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::MacroExpansion(hasher.finish()) - } - - pub fn anon_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::Anon(hasher.finish()) - } - - pub fn proc_macro_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::ProcMacroSourceCode(hasher.finish()) - } - - pub fn cfg_spec_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::QuoteExpansion(hasher.finish()) - } - - pub fn cli_crate_attr_source_code(src: &str) -> FileName { - let mut hasher = StableHasher::new(); - src.hash(&mut hasher); - FileName::CliCrateAttr(hasher.finish()) - } - - pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName{ - FileName::DocTest(path, line) - } -} - -/// Spans represent a region of code, used for error reporting. Positions in spans -/// are *absolute* positions from the beginning of the source_map, not positions -/// relative to `SourceFile`s. Methods on the `SourceMap` can be used to relate spans back -/// to the original source. -/// You must be careful if the span crosses more than one file - you will not be -/// able to use many of the functions on spans in source_map and you cannot assume -/// that the length of the `span = hi - lo`; there may be space in the `BytePos` -/// range between files. -/// -/// `SpanData` is public because `Span` uses a thread-local interner and can't be -/// sent to other threads, but some pieces of performance infra run in a separate thread. -/// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] -pub struct SpanData { - pub lo: BytePos, - pub hi: BytePos, - /// Information about where the macro came from, if this piece of - /// code was created by a macro expansion. - pub ctxt: SyntaxContext, -} - -impl SpanData { - #[inline] - pub fn with_lo(&self, lo: BytePos) -> Span { - Span::new(lo, self.hi, self.ctxt) - } - #[inline] - pub fn with_hi(&self, hi: BytePos) -> Span { - Span::new(self.lo, hi, self.ctxt) - } - #[inline] - pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span { - Span::new(self.lo, self.hi, ctxt) - } -} - -// The interner is pointed to by a thread local value which is only set on the main thread -// with parallelization is disabled. So we don't allow `Span` to transfer between threads -// to avoid panics and other errors, even though it would be memory safe to do so. -#[cfg(not(parallel_compiler))] -impl !Send for Span {} -#[cfg(not(parallel_compiler))] -impl !Sync for Span {} - -impl PartialOrd for Span { - fn partial_cmp(&self, rhs: &Self) -> Option { - PartialOrd::partial_cmp(&self.data(), &rhs.data()) - } -} -impl Ord for Span { - fn cmp(&self, rhs: &Self) -> Ordering { - Ord::cmp(&self.data(), &rhs.data()) - } -} - -/// A collection of spans. Spans have two orthogonal attributes: -/// -/// - They can be *primary spans*. In this case they are the locus of -/// the error, and would be rendered with `^^^`. -/// - They can have a *label*. In this case, the label is written next -/// to the mark in the snippet when we render. -#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)] -pub struct MultiSpan { - primary_spans: Vec, - span_labels: Vec<(Span, String)>, -} - -impl Span { - #[inline] - pub fn lo(self) -> BytePos { - self.data().lo - } - #[inline] - pub fn with_lo(self, lo: BytePos) -> Span { - self.data().with_lo(lo) - } - #[inline] - pub fn hi(self) -> BytePos { - self.data().hi - } - #[inline] - pub fn with_hi(self, hi: BytePos) -> Span { - self.data().with_hi(hi) - } - #[inline] - pub fn ctxt(self) -> SyntaxContext { - self.data().ctxt - } - #[inline] - pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span { - self.data().with_ctxt(ctxt) - } - - /// Returns `true` if this is a dummy span with any hygienic context. - #[inline] - pub fn is_dummy(self) -> bool { - let span = self.data(); - span.lo.0 == 0 && span.hi.0 == 0 - } - - /// Returns a new span representing an empty span at the beginning of this span - #[inline] - pub fn shrink_to_lo(self) -> Span { - let span = self.data(); - span.with_hi(span.lo) - } - /// Returns a new span representing an empty span at the end of this span. - #[inline] - pub fn shrink_to_hi(self) -> Span { - let span = self.data(); - span.with_lo(span.hi) - } - - /// Returns `self` if `self` is not the dummy span, and `other` otherwise. - pub fn substitute_dummy(self, other: Span) -> Span { - if self.is_dummy() { other } else { self } - } - - /// Returns `true` if `self` fully encloses `other`. - pub fn contains(self, other: Span) -> bool { - let span = self.data(); - let other = other.data(); - span.lo <= other.lo && other.hi <= span.hi - } - - /// Returns `true` if `self` touches `other`. - pub fn overlaps(self, other: Span) -> bool { - let span = self.data(); - let other = other.data(); - span.lo < other.hi && other.lo < span.hi - } - - /// Returns `true` if the spans are equal with regards to the source text. - /// - /// Use this instead of `==` when either span could be generated code, - /// and you only care that they point to the same bytes of source text. - pub fn source_equal(&self, other: &Span) -> bool { - let span = self.data(); - let other = other.data(); - span.lo == other.lo && span.hi == other.hi - } - - /// Returns `Some(span)`, where the start is trimmed by the end of `other`. - pub fn trim_start(self, other: Span) -> Option { - let span = self.data(); - let other = other.data(); - if span.hi > other.hi { - Some(span.with_lo(cmp::max(span.lo, other.hi))) - } else { - None - } - } - - /// Returns the source span -- this is either the supplied span, or the span for - /// the macro callsite that expanded to it. - pub fn source_callsite(self) -> Span { - self.ctxt().outer_expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) - } - - /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, - /// if any. - pub fn parent(self) -> Option { - self.ctxt().outer_expn_info().map(|i| i.call_site) - } - - /// Edition of the crate from which this span came. - pub fn edition(self) -> edition::Edition { - self.ctxt().outer_expn_info().map_or_else(|| { - Edition::from_session() - }, |einfo| einfo.edition) - } - - #[inline] - pub fn rust_2015(&self) -> bool { - self.edition() == edition::Edition::Edition2015 - } - - #[inline] - pub fn rust_2018(&self) -> bool { - self.edition() >= edition::Edition::Edition2018 - } - - /// Returns the source callee. - /// - /// Returns `None` if the supplied span has no expansion trace, - /// else returns the `ExpnInfo` for the macro definition - /// corresponding to the source callsite. - pub fn source_callee(self) -> Option { - fn source_callee(info: ExpnInfo) -> ExpnInfo { - match info.call_site.ctxt().outer_expn_info() { - Some(info) => source_callee(info), - None => info, - } - } - self.ctxt().outer_expn_info().map(source_callee) - } - - /// Checks if a span is "internal" to a macro in which `#[unstable]` - /// items can be used (that is, a macro marked with - /// `#[allow_internal_unstable]`). - pub fn allows_unstable(&self, feature: Symbol) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info - .allow_internal_unstable - .map_or(false, |features| features.iter().any(|&f| - f == feature || f == sym::allow_internal_unstable_backcompat_hack - )), - None => false, - } - } - - /// Checks if this span arises from a compiler desugaring of kind `kind`. - pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => match info.format { - ExpnFormat::CompilerDesugaring(k) => k == kind, - _ => false, - }, - None => false, - } - } - - /// Returns the compiler desugaring that created this span, or `None` - /// if this span is not from a desugaring. - pub fn compiler_desugaring_kind(&self) -> Option { - match self.ctxt().outer_expn_info() { - Some(info) => match info.format { - ExpnFormat::CompilerDesugaring(k) => Some(k), - _ => None - }, - None => None - } - } - - /// Checks if a span is "internal" to a macro in which `unsafe` - /// can be used without triggering the `unsafe_code` lint - // (that is, a macro marked with `#[allow_internal_unsafe]`). - pub fn allows_unsafe(&self) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info.allow_internal_unsafe, - None => false, - } - } - - pub fn macro_backtrace(mut self) -> Vec { - let mut prev_span = DUMMY_SP; - let mut result = vec![]; - while let Some(info) = self.ctxt().outer_expn_info() { - // Don't print recursive invocations. - if !info.call_site.source_equal(&prev_span) { - let (pre, post) = match info.format { - ExpnFormat::MacroAttribute(..) => ("#[", "]"), - ExpnFormat::MacroBang(..) => ("", "!"), - ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"), - }; - result.push(MacroBacktrace { - call_site: info.call_site, - macro_decl_name: format!("{}{}{}", pre, info.format.name(), post), - def_site_span: info.def_site, - }); - } - - prev_span = self; - self = info.call_site; - } - result - } - - /// Returns a `Span` that would enclose both `self` and `end`. - pub fn to(self, end: Span) -> Span { - let span_data = self.data(); - let end_data = end.data(); - // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). - // Return the macro span on its own to avoid weird diagnostic output. It is preferable to - // have an incomplete span than a completely nonsensical one. - if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::empty() { - return end; - } else if end_data.ctxt == SyntaxContext::empty() { - return self; - } - // Both spans fall within a macro. - // FIXME(estebank): check if it is the *same* macro. - } - Span::new( - cmp::min(span_data.lo, end_data.lo), - cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt }, - ) - } - - /// Returns a `Span` between the end of `self` to the beginning of `end`. - pub fn between(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); - Span::new( - span.hi, - end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, - ) - } - - /// Returns a `Span` between the beginning of `self` to the beginning of `end`. - pub fn until(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); - Span::new( - span.lo, - end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, - ) - } - - pub fn from_inner(self, inner: InnerSpan) -> Span { - let span = self.data(); - Span::new(span.lo + BytePos::from_usize(inner.start), - span.lo + BytePos::from_usize(inner.end), - span.ctxt) - } - - #[inline] - pub fn apply_mark(self, mark: Mark) -> Span { - let span = self.data(); - span.with_ctxt(span.ctxt.apply_mark(mark)) - } - - #[inline] - pub fn remove_mark(&mut self) -> Mark { - let mut span = self.data(); - let mark = span.ctxt.remove_mark(); - *self = Span::new(span.lo, span.hi, span.ctxt); - mark - } - - #[inline] - pub fn adjust(&mut self, expansion: Mark) -> Option { - let mut span = self.data(); - let mark = span.ctxt.adjust(expansion); - *self = Span::new(span.lo, span.hi, span.ctxt); - mark - } - - #[inline] - pub fn modernize_and_adjust(&mut self, expansion: Mark) -> Option { - let mut span = self.data(); - let mark = span.ctxt.modernize_and_adjust(expansion); - *self = Span::new(span.lo, span.hi, span.ctxt); - mark - } - - #[inline] - pub fn glob_adjust(&mut self, expansion: Mark, glob_span: Span) -> Option> { - let mut span = self.data(); - let mark = span.ctxt.glob_adjust(expansion, glob_span); - *self = Span::new(span.lo, span.hi, span.ctxt); - mark - } - - #[inline] - pub fn reverse_glob_adjust(&mut self, expansion: Mark, glob_span: Span) - -> Option> { - let mut span = self.data(); - let mark = span.ctxt.reverse_glob_adjust(expansion, glob_span); - *self = Span::new(span.lo, span.hi, span.ctxt); - mark - } - - #[inline] - pub fn modern(self) -> Span { - let span = self.data(); - span.with_ctxt(span.ctxt.modern()) - } - - #[inline] - pub fn modern_and_legacy(self) -> Span { - let span = self.data(); - span.with_ctxt(span.ctxt.modern_and_legacy()) - } -} - -#[derive(Clone, Debug)] -pub struct SpanLabel { - /// The span we are going to include in the final snippet. - pub span: Span, - - /// Is this a primary span? This is the "locus" of the message, - /// and is indicated with a `^^^^` underline, versus `----`. - pub is_primary: bool, - - /// What label should we attach to this span (if any)? - pub label: Option, -} - -impl Default for Span { - fn default() -> Self { - DUMMY_SP - } -} - -impl serialize::UseSpecializedEncodable for Span { - fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { - let span = self.data(); - s.emit_struct("Span", 2, |s| { - s.emit_struct_field("lo", 0, |s| { - span.lo.encode(s) - })?; - - s.emit_struct_field("hi", 1, |s| { - span.hi.encode(s) - }) - }) - } -} - -impl serialize::UseSpecializedDecodable for Span { - fn default_decode(d: &mut D) -> Result { - d.read_struct("Span", 2, |d| { - let lo = d.read_struct_field("lo", 0, Decodable::decode)?; - let hi = d.read_struct_field("hi", 1, Decodable::decode)?; - Ok(Span::new(lo, hi, NO_EXPANSION)) - }) - } -} - -pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Span") - .field("lo", &span.lo()) - .field("hi", &span.hi()) - .field("ctxt", &span.ctxt()) - .finish() -} - -impl fmt::Debug for Span { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - SPAN_DEBUG.with(|span_debug| span_debug.get()(*self, f)) - } -} - -impl fmt::Debug for SpanData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - SPAN_DEBUG.with(|span_debug| span_debug.get()(Span::new(self.lo, self.hi, self.ctxt), f)) - } -} - -impl MultiSpan { - #[inline] - pub fn new() -> MultiSpan { - MultiSpan { - primary_spans: vec![], - span_labels: vec![] - } - } - - pub fn from_span(primary_span: Span) -> MultiSpan { - MultiSpan { - primary_spans: vec![primary_span], - span_labels: vec![] - } - } - - pub fn from_spans(vec: Vec) -> MultiSpan { - MultiSpan { - primary_spans: vec, - span_labels: vec![] - } - } - - pub fn push_span_label(&mut self, span: Span, label: String) { - self.span_labels.push((span, label)); - } - - /// Selects the first primary span (if any). - pub fn primary_span(&self) -> Option { - self.primary_spans.first().cloned() - } - - /// Returns all primary spans. - pub fn primary_spans(&self) -> &[Span] { - &self.primary_spans - } - - /// Returns `true` if any of the primary spans are displayable. - pub fn has_primary_spans(&self) -> bool { - self.primary_spans.iter().any(|sp| !sp.is_dummy()) - } - - /// Returns `true` if this contains only a dummy primary span with any hygienic context. - pub fn is_dummy(&self) -> bool { - let mut is_dummy = true; - for span in &self.primary_spans { - if !span.is_dummy() { - is_dummy = false; - } - } - is_dummy - } - - /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't - /// display well (like std macros). Returns whether replacements occurred. - pub fn replace(&mut self, before: Span, after: Span) -> bool { - let mut replacements_occurred = false; - for primary_span in &mut self.primary_spans { - if *primary_span == before { - *primary_span = after; - replacements_occurred = true; - } - } - for span_label in &mut self.span_labels { - if span_label.0 == before { - span_label.0 = after; - replacements_occurred = true; - } - } - replacements_occurred - } - - /// Returns the strings to highlight. We always ensure that there - /// is an entry for each of the primary spans -- for each primary - /// span `P`, if there is at least one label with span `P`, we return - /// those labels (marked as primary). But otherwise we return - /// `SpanLabel` instances with empty labels. - pub fn span_labels(&self) -> Vec { - let is_primary = |span| self.primary_spans.contains(&span); - - let mut span_labels = self.span_labels.iter().map(|&(span, ref label)| - SpanLabel { - span, - is_primary: is_primary(span), - label: Some(label.clone()) - } - ).collect::>(); - - for &span in &self.primary_spans { - if !span_labels.iter().any(|sl| sl.span == span) { - span_labels.push(SpanLabel { - span, - is_primary: true, - label: None - }); - } - } - - span_labels - } - - /// Returns `true` if any of the span labels is displayable. - pub fn has_span_labels(&self) -> bool { - self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) - } -} - -impl From for MultiSpan { - fn from(span: Span) -> MultiSpan { - MultiSpan::from_span(span) - } -} - -impl From> for MultiSpan { - fn from(spans: Vec) -> MultiSpan { - MultiSpan::from_spans(spans) - } -} - -pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty(); - -/// Identifies an offset of a multi-byte character in a `SourceFile`. -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] -pub struct MultiByteChar { - /// The absolute offset of the character in the `SourceMap`. - pub pos: BytePos, - /// The number of bytes, `>= 2`. - pub bytes: u8, -} - -/// Identifies an offset of a non-narrow character in a `SourceFile`. -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] -pub enum NonNarrowChar { - /// Represents a zero-width character. - ZeroWidth(BytePos), - /// Represents a wide (full-width) character. - Wide(BytePos), - /// Represents a tab character, represented visually with a width of 4 characters. - Tab(BytePos), -} - -impl NonNarrowChar { - fn new(pos: BytePos, width: usize) -> Self { - match width { - 0 => NonNarrowChar::ZeroWidth(pos), - 2 => NonNarrowChar::Wide(pos), - 4 => NonNarrowChar::Tab(pos), - _ => panic!("width {} given for non-narrow character", width), - } - } - - /// Returns the absolute offset of the character in the `SourceMap`. - pub fn pos(&self) -> BytePos { - match *self { - NonNarrowChar::ZeroWidth(p) | - NonNarrowChar::Wide(p) | - NonNarrowChar::Tab(p) => p, - } - } - - /// Returns the width of the character, 0 (zero-width) or 2 (wide). - pub fn width(&self) -> usize { - match *self { - NonNarrowChar::ZeroWidth(_) => 0, - NonNarrowChar::Wide(_) => 2, - NonNarrowChar::Tab(_) => 4, - } - } -} - -impl Add for NonNarrowChar { - type Output = Self; - - fn add(self, rhs: BytePos) -> Self { - match self { - NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs), - NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs), - NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs), - } - } -} - -impl Sub for NonNarrowChar { - type Output = Self; - - fn sub(self, rhs: BytePos) -> Self { - match self { - NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs), - NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs), - NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs), - } - } -} - -/// The state of the lazy external source loading mechanism of a `SourceFile`. -#[derive(PartialEq, Eq, Clone)] -pub enum ExternalSource { - /// The external source has been loaded already. - Present(String), - /// No attempt has been made to load the external source. - AbsentOk, - /// A failed attempt has been made to load the external source. - AbsentErr, - /// No external source has to be loaded, since the `SourceFile` represents a local crate. - Unneeded, -} - -impl ExternalSource { - pub fn is_absent(&self) -> bool { - match *self { - ExternalSource::Present(_) => false, - _ => true, - } - } - - pub fn get_source(&self) -> Option<&str> { - match *self { - ExternalSource::Present(ref src) => Some(src), - _ => None, - } - } -} - -#[derive(Debug)] -pub struct OffsetOverflowError; - -/// A single source in the `SourceMap`. -#[derive(Clone)] -pub struct SourceFile { - /// The name of the file that the source came from, source that doesn't - /// originate from files has names between angle brackets by convention - /// (e.g., ``). - pub name: FileName, - /// `true` if the `name` field above has been modified by `--remap-path-prefix`. - pub name_was_remapped: bool, - /// The unmapped path of the file that the source came from. - /// Set to `None` if the `SourceFile` was imported from an external crate. - pub unmapped_path: Option, - /// Indicates which crate this `SourceFile` was imported from. - pub crate_of_origin: u32, - /// The complete source code. - pub src: Option>, - /// The source code's hash. - pub src_hash: u128, - /// The external source code (used for external crates, which will have a `None` - /// value as `self.src`. - pub external_src: Lock, - /// The start position of this source in the `SourceMap`. - pub start_pos: BytePos, - /// The end position of this source in the `SourceMap`. - pub end_pos: BytePos, - /// Locations of lines beginnings in the source code. - pub lines: Vec, - /// Locations of multi-byte characters in the source code. - pub multibyte_chars: Vec, - /// Width of characters that are not narrow in the source code. - pub non_narrow_chars: Vec, - /// A hash of the filename, used for speeding up hashing in incremental compilation. - pub name_hash: u128, -} - -impl Encodable for SourceFile { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_struct("SourceFile", 8, |s| { - s.emit_struct_field("name", 0, |s| self.name.encode(s))?; - s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?; - s.emit_struct_field("src_hash", 2, |s| self.src_hash.encode(s))?; - s.emit_struct_field("start_pos", 4, |s| self.start_pos.encode(s))?; - s.emit_struct_field("end_pos", 5, |s| self.end_pos.encode(s))?; - s.emit_struct_field("lines", 6, |s| { - let lines = &self.lines[..]; - // Store the length. - s.emit_u32(lines.len() as u32)?; - - if !lines.is_empty() { - // In order to preserve some space, we exploit the fact that - // the lines list is sorted and individual lines are - // probably not that long. Because of that we can store lines - // as a difference list, using as little space as possible - // for the differences. - let max_line_length = if lines.len() == 1 { - 0 - } else { - lines.windows(2) - .map(|w| w[1] - w[0]) - .map(|bp| bp.to_usize()) - .max() - .unwrap() - }; - - let bytes_per_diff: u8 = match max_line_length { - 0 ..= 0xFF => 1, - 0x100 ..= 0xFFFF => 2, - _ => 4 - }; - - // Encode the number of bytes used per diff. - bytes_per_diff.encode(s)?; - - // Encode the first element. - lines[0].encode(s)?; - - let diff_iter = (&lines[..]).windows(2) - .map(|w| (w[1] - w[0])); - - match bytes_per_diff { - 1 => for diff in diff_iter { (diff.0 as u8).encode(s)? }, - 2 => for diff in diff_iter { (diff.0 as u16).encode(s)? }, - 4 => for diff in diff_iter { diff.0.encode(s)? }, - _ => unreachable!() - } - } - - Ok(()) - })?; - s.emit_struct_field("multibyte_chars", 7, |s| { - self.multibyte_chars.encode(s) - })?; - s.emit_struct_field("non_narrow_chars", 8, |s| { - self.non_narrow_chars.encode(s) - })?; - s.emit_struct_field("name_hash", 9, |s| { - self.name_hash.encode(s) - }) - }) - } -} - -impl Decodable for SourceFile { - fn decode(d: &mut D) -> Result { - - d.read_struct("SourceFile", 8, |d| { - let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?; - let name_was_remapped: bool = - d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?; - let src_hash: u128 = - d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?; - let start_pos: BytePos = - d.read_struct_field("start_pos", 4, |d| Decodable::decode(d))?; - let end_pos: BytePos = d.read_struct_field("end_pos", 5, |d| Decodable::decode(d))?; - let lines: Vec = d.read_struct_field("lines", 6, |d| { - let num_lines: u32 = Decodable::decode(d)?; - let mut lines = Vec::with_capacity(num_lines as usize); - - if num_lines > 0 { - // Read the number of bytes used per diff. - let bytes_per_diff: u8 = Decodable::decode(d)?; - - // Read the first element. - let mut line_start: BytePos = Decodable::decode(d)?; - lines.push(line_start); - - for _ in 1..num_lines { - let diff = match bytes_per_diff { - 1 => d.read_u8()? as u32, - 2 => d.read_u16()? as u32, - 4 => d.read_u32()?, - _ => unreachable!() - }; - - line_start = line_start + BytePos(diff); - - lines.push(line_start); - } - } - - Ok(lines) - })?; - let multibyte_chars: Vec = - d.read_struct_field("multibyte_chars", 7, |d| Decodable::decode(d))?; - let non_narrow_chars: Vec = - d.read_struct_field("non_narrow_chars", 8, |d| Decodable::decode(d))?; - let name_hash: u128 = - d.read_struct_field("name_hash", 9, |d| Decodable::decode(d))?; - Ok(SourceFile { - name, - name_was_remapped, - unmapped_path: None, - // `crate_of_origin` has to be set by the importer. - // This value matches up with rustc::hir::def_id::INVALID_CRATE. - // That constant is not available here unfortunately :( - crate_of_origin: std::u32::MAX - 1, - start_pos, - end_pos, - src: None, - src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), - lines, - multibyte_chars, - non_narrow_chars, - name_hash, - }) - }) - } -} - -impl fmt::Debug for SourceFile { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "SourceFile({})", self.name) - } -} - -impl SourceFile { - pub fn new(name: FileName, - name_was_remapped: bool, - unmapped_path: FileName, - mut src: String, - start_pos: BytePos) -> Result { - remove_bom(&mut src); - - let src_hash = { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - hasher.finish() - }; - let name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - name.hash(&mut hasher); - hasher.finish() - }; - let end_pos = start_pos.to_usize() + src.len(); - if end_pos > u32::max_value() as usize { - return Err(OffsetOverflowError); - } - - let (lines, multibyte_chars, non_narrow_chars) = - analyze_source_file::analyze_source_file(&src[..], start_pos); - - Ok(SourceFile { - name, - name_was_remapped, - unmapped_path: Some(unmapped_path), - crate_of_origin: 0, - src: Some(Lrc::new(src)), - src_hash, - external_src: Lock::new(ExternalSource::Unneeded), - start_pos, - end_pos: Pos::from_usize(end_pos), - lines, - multibyte_chars, - non_narrow_chars, - name_hash, - }) - } - - /// Returns the `BytePos` of the beginning of the current line. - pub fn line_begin_pos(&self, pos: BytePos) -> BytePos { - let line_index = self.lookup_line(pos).unwrap(); - self.lines[line_index] - } - - /// Add externally loaded source. - /// If the hash of the input doesn't match or no input is supplied via None, - /// it is interpreted as an error and the corresponding enum variant is set. - /// The return value signifies whether some kind of source is present. - pub fn add_external_src(&self, get_src: F) -> bool - where F: FnOnce() -> Option - { - if *self.external_src.borrow() == ExternalSource::AbsentOk { - let src = get_src(); - let mut external_src = self.external_src.borrow_mut(); - // Check that no-one else have provided the source while we were getting it - if *external_src == ExternalSource::AbsentOk { - if let Some(src) = src { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - - if hasher.finish() == self.src_hash { - *external_src = ExternalSource::Present(src); - return true; - } - } else { - *external_src = ExternalSource::AbsentErr; - } - - false - } else { - self.src.is_some() || external_src.get_source().is_some() - } - } else { - self.src.is_some() || self.external_src.borrow().get_source().is_some() - } - } - - /// Gets a line from the list of pre-computed line-beginnings. - /// The line number here is 0-based. - pub fn get_line(&self, line_number: usize) -> Option> { - fn get_until_newline(src: &str, begin: usize) -> &str { - // We can't use `lines.get(line_number+1)` because we might - // be parsing when we call this function and thus the current - // line is the last one we have line info for. - let slice = &src[begin..]; - match slice.find('\n') { - Some(e) => &slice[..e], - None => slice - } - } - - let begin = { - let line = if let Some(line) = self.lines.get(line_number) { - line - } else { - return None; - }; - let begin: BytePos = *line - self.start_pos; - begin.to_usize() - }; - - if let Some(ref src) = self.src { - Some(Cow::from(get_until_newline(src, begin))) - } else if let Some(src) = self.external_src.borrow().get_source() { - Some(Cow::Owned(String::from(get_until_newline(src, begin)))) - } else { - None - } - } - - pub fn is_real_file(&self) -> bool { - self.name.is_real() - } - - pub fn is_imported(&self) -> bool { - self.src.is_none() - } - - pub fn byte_length(&self) -> u32 { - self.end_pos.0 - self.start_pos.0 - } - pub fn count_lines(&self) -> usize { - self.lines.len() - } - - /// Finds the line containing the given position. The return value is the - /// index into the `lines` array of this `SourceFile`, not the 1-based line - /// number. If the source_file is empty or the position is located before the - /// first line, `None` is returned. - pub fn lookup_line(&self, pos: BytePos) -> Option { - if self.lines.len() == 0 { - return None; - } - - let line_index = lookup_line(&self.lines[..], pos); - assert!(line_index < self.lines.len() as isize); - if line_index >= 0 { - Some(line_index as usize) - } else { - None - } - } - - pub fn line_bounds(&self, line_index: usize) -> (BytePos, BytePos) { - if self.start_pos == self.end_pos { - return (self.start_pos, self.end_pos); - } - - assert!(line_index < self.lines.len()); - if line_index == (self.lines.len() - 1) { - (self.lines[line_index], self.end_pos) - } else { - (self.lines[line_index], self.lines[line_index + 1]) - } - } - - #[inline] - pub fn contains(&self, byte_pos: BytePos) -> bool { - byte_pos >= self.start_pos && byte_pos <= self.end_pos - } -} - -/// Removes UTF-8 BOM, if any. -fn remove_bom(src: &mut String) { - if src.starts_with("\u{feff}") { - src.drain(..3); - } -} - -// _____________________________________________________________________________ -// Pos, BytePos, CharPos -// - -pub trait Pos { - fn from_usize(n: usize) -> Self; - fn to_usize(&self) -> usize; - fn from_u32(n: u32) -> Self; - fn to_u32(&self) -> u32; -} - -/// A byte offset. Keep this small (currently 32-bits), as AST contains -/// a lot of them. -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct BytePos(pub u32); - -/// A character offset. Because of multibyte UTF-8 characters, a byte offset -/// is not equivalent to a character offset. The `SourceMap` will convert `BytePos` -/// values to `CharPos` values as necessary. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct CharPos(pub usize); - -// FIXME: lots of boilerplate in these impls, but so far my attempts to fix -// have been unsuccessful. - -impl Pos for BytePos { - #[inline(always)] - fn from_usize(n: usize) -> BytePos { BytePos(n as u32) } - - #[inline(always)] - fn to_usize(&self) -> usize { self.0 as usize } - - #[inline(always)] - fn from_u32(n: u32) -> BytePos { BytePos(n) } - - #[inline(always)] - fn to_u32(&self) -> u32 { self.0 } -} - -impl Add for BytePos { - type Output = BytePos; - - #[inline(always)] - fn add(self, rhs: BytePos) -> BytePos { - BytePos((self.to_usize() + rhs.to_usize()) as u32) - } -} - -impl Sub for BytePos { - type Output = BytePos; - - #[inline(always)] - fn sub(self, rhs: BytePos) -> BytePos { - BytePos((self.to_usize() - rhs.to_usize()) as u32) - } -} - -impl Encodable for BytePos { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_u32(self.0) - } -} - -impl Decodable for BytePos { - fn decode(d: &mut D) -> Result { - Ok(BytePos(d.read_u32()?)) - } -} - -impl Pos for CharPos { - #[inline(always)] - fn from_usize(n: usize) -> CharPos { CharPos(n) } - - #[inline(always)] - fn to_usize(&self) -> usize { self.0 } - - #[inline(always)] - fn from_u32(n: u32) -> CharPos { CharPos(n as usize) } - - #[inline(always)] - fn to_u32(&self) -> u32 { self.0 as u32} -} - -impl Add for CharPos { - type Output = CharPos; - - #[inline(always)] - fn add(self, rhs: CharPos) -> CharPos { - CharPos(self.to_usize() + rhs.to_usize()) - } -} - -impl Sub for CharPos { - type Output = CharPos; - - #[inline(always)] - fn sub(self, rhs: CharPos) -> CharPos { - CharPos(self.to_usize() - rhs.to_usize()) - } -} - -// _____________________________________________________________________________ -// Loc, SourceFileAndLine, SourceFileAndBytePos -// - -/// A source code location used for error reporting. -#[derive(Debug, Clone)] -pub struct Loc { - /// Information about the original source. - pub file: Lrc, - /// The (1-based) line number. - pub line: usize, - /// The (0-based) column offset. - pub col: CharPos, - /// The (0-based) column offset when displayed. - pub col_display: usize, -} - -// Used to be structural records. -#[derive(Debug)] -pub struct SourceFileAndLine { pub sf: Lrc, pub line: usize } -#[derive(Debug)] -pub struct SourceFileAndBytePos { pub sf: Lrc, pub pos: BytePos } - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct LineInfo { - /// Index of line, starting from 0. - pub line_index: usize, - - /// Column in line where span begins, starting from 0. - pub start_col: CharPos, - - /// Column in line where span ends, starting from 0, exclusive. - pub end_col: CharPos, -} - -pub struct FileLines { - pub file: Lrc, - pub lines: Vec -} - -thread_local!(pub static SPAN_DEBUG: Cell) -> fmt::Result> = - Cell::new(default_span_debug)); - -#[derive(Debug)] -pub struct MacroBacktrace { - /// span where macro was applied to generate this code - pub call_site: Span, - - /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") - pub macro_decl_name: String, - - /// span where macro was defined (if known) - pub def_site_span: Option, -} - -// _____________________________________________________________________________ -// SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions -// - -pub type FileLinesResult = Result; - -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum SpanLinesError { - IllFormedSpan(Span), - DistinctSources(DistinctSources), -} - -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum SpanSnippetError { - IllFormedSpan(Span), - DistinctSources(DistinctSources), - MalformedForSourcemap(MalformedSourceMapPositions), - SourceNotAvailable { filename: FileName } -} - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct DistinctSources { - pub begin: (FileName, BytePos), - pub end: (FileName, BytePos) -} - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct MalformedSourceMapPositions { - pub name: FileName, - pub source_len: usize, - pub begin_pos: BytePos, - pub end_pos: BytePos -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct InnerSpan { - pub start: usize, - pub end: usize, -} - -impl InnerSpan { - pub fn new(start: usize, end: usize) -> InnerSpan { - InnerSpan { start, end } - } -} - -// Given a slice of line start positions and a position, returns the index of -// the line the position is on. Returns -1 if the position is located before -// the first line. -fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize { - match lines.binary_search(&pos) { - Ok(line) => line as isize, - Err(line) => line as isize - 1 - } -} - -#[cfg(test)] -mod tests { - use super::{lookup_line, BytePos}; - - #[test] - fn test_lookup_line() { - - let lines = &[BytePos(3), BytePos(17), BytePos(28)]; - - assert_eq!(lookup_line(lines, BytePos(0)), -1); - assert_eq!(lookup_line(lines, BytePos(3)), 0); - assert_eq!(lookup_line(lines, BytePos(4)), 0); - - assert_eq!(lookup_line(lines, BytePos(16)), 0); - assert_eq!(lookup_line(lines, BytePos(17)), 1); - assert_eq!(lookup_line(lines, BytePos(18)), 1); - - assert_eq!(lookup_line(lines, BytePos(28)), 2); - assert_eq!(lookup_line(lines, BytePos(29)), 2); - } -} diff --git a/gcc/rust/rustc_parser/libsyntax_pos/span_encoding.rs b/gcc/rust/rustc_parser/libsyntax_pos/span_encoding.rs deleted file mode 100644 index 525ec13..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/span_encoding.rs +++ /dev/null @@ -1,140 +0,0 @@ -// Spans are encoded using 1-bit tag and 2 different encoding formats (one for each tag value). -// One format is used for keeping span data inline, -// another contains index into an out-of-line span interner. -// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. -// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 - -use crate::GLOBALS; -use crate::{BytePos, SpanData}; -use crate::hygiene::SyntaxContext; - -use rustc_data_structures::fx::FxHashMap; - -/// A compressed span. -/// -/// `SpanData` is 12 bytes, which is a bit too big to stick everywhere. `Span` -/// is a form that only takes up 8 bytes, with less space for the length and -/// context. The vast majority (99.9%+) of `SpanData` instances will fit within -/// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are -/// stored in a separate interner table, and the `Span` will index into that -/// table. Interning is rare enough that the cost is low, but common enough -/// that the code is exercised regularly. -/// -/// An earlier version of this code used only 4 bytes for `Span`, but that was -/// slower because only 80--90% of spans could be stored inline (even less in -/// very large crates) and so the interner was used a lot more. -/// -/// Inline (compressed) format: -/// - `span.base_or_index == span_data.lo` -/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) -/// - `span.ctxt == span_data.ctxt` (must be `<= MAX_CTXT`) -/// -/// Interned format: -/// - `span.base_or_index == index` (indexes into the interner table) -/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) -/// - `span.ctxt == 0` -/// -/// The inline form uses 0 for the tag value (rather than 1) so that we don't -/// need to mask out the tag bit when getting the length, and so that the -/// dummy span can be all zeroes. -/// -/// Notes about the choice of field sizes: -/// - `base` is 32 bits in both `Span` and `SpanData`, which means that `base` -/// values never cause interning. The number of bits needed for `base` -/// depends on the crate size. 32 bits allows up to 4 GiB of code in a crate. -/// `script-servo` is the largest crate in `rustc-perf`, requiring 26 bits -/// for some spans. -/// - `len` is 15 bits in `Span` (a u16, minus 1 bit for the tag) and 32 bits -/// in `SpanData`, which means that large `len` values will cause interning. -/// The number of bits needed for `len` does not depend on the crate size. -/// The most common number of bits for `len` are 0--7, with a peak usually at -/// 3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough -/// for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur -/// dozens of times in a typical crate. -/// - `ctxt` is 16 bits in `Span` and 32 bits in `SpanData`, which means that -/// large `ctxt` values will cause interning. The number of bits needed for -/// `ctxt` values depend partly on the crate size and partly on the form of -/// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`, -/// but larger crates might need more than 16 bits. -/// -#[derive(Clone, Copy, Eq, PartialEq, Hash)] -pub struct Span { - base_or_index: u32, - len_or_tag: u16, - ctxt_or_zero: u16 -} - -const LEN_TAG: u16 = 0b1000_0000_0000_0000; -const MAX_LEN: u32 = 0b0111_1111_1111_1111; -const MAX_CTXT: u32 = 0b1111_1111_1111_1111; - -/// Dummy span, both position and length are zero, syntax context is zero as well. -pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_zero: 0 }; - -impl Span { - #[inline] - pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self { - if lo > hi { - std::mem::swap(&mut lo, &mut hi); - } - - let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32()); - - if len <= MAX_LEN && ctxt2 <= MAX_CTXT { - // Inline format. - Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 } - } else { - // Interned format. - let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt })); - Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 } - } - } - - #[inline] - pub fn data(self) -> SpanData { - if self.len_or_tag != LEN_TAG { - // Inline format. - debug_assert!(self.len_or_tag as u32 <= MAX_LEN); - SpanData { - lo: BytePos(self.base_or_index), - hi: BytePos(self.base_or_index + self.len_or_tag as u32), - ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32), - } - } else { - // Interned format. - debug_assert!(self.ctxt_or_zero == 0); - let index = self.base_or_index; - with_span_interner(|interner| *interner.get(index)) - } - } -} - -#[derive(Default)] -pub struct SpanInterner { - spans: FxHashMap, - span_data: Vec, -} - -impl SpanInterner { - fn intern(&mut self, span_data: &SpanData) -> u32 { - if let Some(index) = self.spans.get(span_data) { - return *index; - } - - let index = self.spans.len() as u32; - self.span_data.push(*span_data); - self.spans.insert(*span_data, index); - index - } - - #[inline] - fn get(&self, index: u32) -> &SpanData { - &self.span_data[index as usize] - } -} - -// If an interner exists, return it. Otherwise, prepare a fresh one. -#[inline] -fn with_span_interner T>(f: F) -> T { - GLOBALS.with(|globals| f(&mut *globals.span_interner.lock())) -} diff --git a/gcc/rust/rustc_parser/libsyntax_pos/symbol.rs b/gcc/rust/rustc_parser/libsyntax_pos/symbol.rs deleted file mode 100644 index 89fcf3b..0000000 --- a/gcc/rust/rustc_parser/libsyntax_pos/symbol.rs +++ /dev/null @@ -1,1380 +0,0 @@ -//! An "interner" is a data structure that associates values with usize tags and -//! allows bidirectional lookup; i.e., given a value, one can easily find the -//! type, and vice versa. - -use arena::DroplessArena; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::newtype_index; -use rustc_macros::symbols; -use serialize::{Decodable, Decoder, Encodable, Encoder}; - -use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::str; - -use crate::hygiene::SyntaxContext; -use crate::{Span, DUMMY_SP, GLOBALS}; - -symbols! { - // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, - // this should be rarely necessary though if the keywords are kept in alphabetic order. - Keywords { - // Special reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. - Invalid: "", - PathRoot: "{{root}}", - DollarCrate: "$crate", - Underscore: "_", - - // Keywords that are used in stable Rust. - As: "as", - Break: "break", - Const: "const", - Continue: "continue", - Crate: "crate", - Else: "else", - Enum: "enum", - Extern: "extern", - False: "false", - Fn: "fn", - For: "for", - If: "if", - Impl: "impl", - In: "in", - Let: "let", - Loop: "loop", - Match: "match", - Mod: "mod", - Move: "move", - Mut: "mut", - Pub: "pub", - Ref: "ref", - Return: "return", - SelfLower: "self", - SelfUpper: "Self", - Static: "static", - Struct: "struct", - Super: "super", - Trait: "trait", - True: "true", - Type: "type", - Unsafe: "unsafe", - Use: "use", - Where: "where", - While: "while", - - // Keywords that are used in unstable Rust or reserved for future use. - Abstract: "abstract", - Become: "become", - Box: "box", - Do: "do", - Final: "final", - Macro: "macro", - Override: "override", - Priv: "priv", - Typeof: "typeof", - Unsized: "unsized", - Virtual: "virtual", - Yield: "yield", - - // Edition-specific keywords that are used in stable Rust. - Dyn: "dyn", // >= 2018 Edition only - - // Edition-specific keywords that are used in unstable Rust or reserved for future use. - Async: "async", // >= 2018 Edition only - Await: "await", // >= 2018 Edition only - Try: "try", // >= 2018 Edition only - - // Special lifetime names - UnderscoreLifetime: "'_", - StaticLifetime: "'static", - - // Weak keywords, have special meaning only in specific contexts. - Auto: "auto", - Catch: "catch", - Default: "default", - Existential: "existential", - Union: "union", - } - - // Symbols that can be referred to with syntax_pos::sym::*. The symbol is - // the stringified identifier unless otherwise specified (e.g. - // `proc_dash_macro` represents "proc-macro"). - // - // As well as the symbols listed, there are symbols for the the strings - // "0", "1", ..., "9", which are accessible via `sym::integer`. - Symbols { - aarch64_target_feature, - abi, - abi_amdgpu_kernel, - abi_msp430_interrupt, - abi_ptx, - abi_sysv64, - abi_thiscall, - abi_unadjusted, - abi_vectorcall, - abi_x86_interrupt, - aborts, - advanced_slice_patterns, - adx_target_feature, - alias, - align, - alignstack, - all, - allocator, - allocator_internals, - alloc_error_handler, - allow, - allowed, - allow_fail, - allow_internal_unsafe, - allow_internal_unstable, - allow_internal_unstable_backcompat_hack, - always, - and, - any, - arbitrary_enum_discriminant, - arbitrary_self_types, - Arguments, - ArgumentV1, - arm_target_feature, - asm, - assert, - associated_consts, - associated_type_bounds, - associated_type_defaults, - associated_types, - async_await, - async_closure, - attr, - attributes, - attr_literals, - augmented_assignments, - automatically_derived, - avx512_target_feature, - await_macro, - begin_panic, - bench, - bin, - bind_by_move_pattern_guards, - block, - bool, - borrowck_graphviz_postflow, - borrowck_graphviz_preflow, - box_patterns, - box_syntax, - braced_empty_structs, - C, - cdylib, - cfg, - cfg_attr, - cfg_attr_multi, - cfg_doctest, - cfg_target_feature, - cfg_target_has_atomic, - cfg_target_thread_local, - cfg_target_vendor, - char, - clippy, - clone, - Clone, - clone_closures, - clone_from, - closure_to_fn_coercion, - cmp, - cmpxchg16b_target_feature, - cold, - column, - compile_error, - compiler_builtins, - concat, - concat_idents, - conservative_impl_trait, - console, - const_compare_raw_pointers, - const_constructor, - const_fn, - const_fn_union, - const_generics, - const_indexing, - const_let, - const_panic, - const_raw_ptr_deref, - const_raw_ptr_to_usize_cast, - const_transmute, - contents, - context, - convert, - Copy, - copy_closures, - core, - core_intrinsics, - crate_id, - crate_in_paths, - crate_local, - crate_name, - crate_type, - crate_visibility_modifier, - custom_attribute, - custom_derive, - custom_inner_attributes, - custom_test_frameworks, - c_variadic, - Debug, - declare_lint_pass, - decl_macro, - Decodable, - Default, - default_lib_allocator, - default_type_parameter_fallback, - default_type_params, - deny, - deprecated, - deref, - deref_mut, - derive, - direct, - doc, - doc_alias, - doc_cfg, - doc_keyword, - doc_masked, - doc_spotlight, - doctest, - document_private_items, - dotdoteq_in_patterns, - dotdot_in_tuple_patterns, - double_braced_crate: "{{crate}}", - double_braced_impl: "{{impl}}", - double_braced_misc: "{{misc}}", - double_braced_closure: "{{closure}}", - double_braced_constructor: "{{constructor}}", - double_braced_constant: "{{constant}}", - double_braced_opaque: "{{opaque}}", - dropck_eyepatch, - dropck_parametricity, - drop_types_in_const, - dylib, - dyn_trait, - eh_personality, - eh_unwind_resume, - enable, - Encodable, - env, - eq, - err, - Err, - Eq, - Equal, - except, - exclusive_range_pattern, - exhaustive_integer_patterns, - exhaustive_patterns, - existential_type, - expected, - export_name, - expr, - extern_absolute_paths, - external_doc, - extern_crate_item_prelude, - extern_crate_self, - extern_in_paths, - extern_prelude, - extern_types, - f16c_target_feature, - f32, - f64, - feature, - ffi_returns_twice, - field, - field_init_shorthand, - file, - fmt, - fmt_internals, - fn_must_use, - forbid, - format_args, - format_args_nl, - from, - From, - from_desugaring, - from_error, - from_generator, - from_method, - from_ok, - from_usize, - fundamental, - future, - Future, - FxHashSet, - FxHashMap, - gen_future, - generators, - generic_associated_types, - generic_param_attrs, - global_allocator, - global_asm, - globs, - hash, - Hash, - HashSet, - HashMap, - hexagon_target_feature, - hidden, - homogeneous_aggregate, - html_favicon_url, - html_logo_url, - html_no_source, - html_playground_url, - html_root_url, - i128, - i128_type, - i16, - i32, - i64, - i8, - ident, - if_let, - if_while_or_patterns, - ignore, - impl_header_lifetime_elision, - impl_lint_pass, - impl_trait_in_bindings, - import_shadowing, - index, - index_mut, - in_band_lifetimes, - include, - include_bytes, - include_str, - inclusive_range_syntax, - infer_outlives_requirements, - infer_static_outlives_requirements, - inline, - intel, - into_iter, - IntoIterator, - into_result, - intrinsics, - irrefutable_let_patterns, - isize, - issue, - issue_5723_bootstrap, - issue_tracker_base_url, - item, - item_like_imports, - iter, - Iterator, - keyword, - kind, - label, - label_break_value, - lang, - lang_items, - let_chains, - lhs, - lib, - lifetime, - line, - link, - linkage, - link_args, - link_cfg, - link_llvm_intrinsics, - link_name, - link_section, - LintPass, - lint_reasons, - literal, - local_inner_macros, - log_syntax, - loop_break_value, - macro_at_most_once_rep, - macro_escape, - macro_export, - macro_lifetime_matcher, - macro_literal_matcher, - macro_reexport, - macro_rules, - macros_in_extern, - macro_use, - macro_vis_matcher, - main, - managed_boxes, - marker, - marker_trait_attr, - masked, - match_beginning_vert, - match_default_bindings, - may_dangle, - member_constraints, - message, - meta, - min_const_fn, - min_const_unsafe_fn, - mips_target_feature, - mmx_target_feature, - module, - module_path, - more_struct_aliases, - movbe_target_feature, - must_use, - naked, - naked_functions, - name, - needs_allocator, - needs_panic_runtime, - negate_unsigned, - never, - never_type, - new, - next, - __next, - nll, - no_builtins, - no_core, - no_crate_inject, - no_debug, - no_default_passes, - no_implicit_prelude, - no_inline, - no_link, - no_main, - no_mangle, - non_ascii_idents, - None, - non_exhaustive, - non_modrs_mods, - no_stack_check, - no_start, - no_std, - not, - note, - Ok, - omit_gdb_pretty_printer_section, - on, - on_unimplemented, - oom, - ops, - optimize, - optimize_attribute, - optin_builtin_traits, - option, - Option, - option_env, - opt_out_copy, - or, - Ord, - Ordering, - Output, - overlapping_marker_traits, - packed, - panic, - panic_handler, - panic_impl, - panic_implementation, - panic_runtime, - parent_trait, - partial_cmp, - param_attrs, - PartialEq, - PartialOrd, - passes, - pat, - path, - pattern_parentheses, - Pending, - pin, - Pin, - pinned, - platform_intrinsics, - plugin, - plugin_registrar, - plugins, - Poll, - poll_with_tls_context, - powerpc_target_feature, - precise_pointer_size_matching, - prelude, - prelude_import, - primitive, - proc_dash_macro: "proc-macro", - proc_macro, - proc_macro_attribute, - proc_macro_def_site, - proc_macro_derive, - proc_macro_expr, - proc_macro_gen, - proc_macro_hygiene, - proc_macro_mod, - proc_macro_non_items, - proc_macro_path_invoc, - profiler_runtime, - pub_restricted, - pushpop_unsafe, - quad_precision_float, - question_mark, - quote, - Range, - RangeFrom, - RangeFull, - RangeInclusive, - RangeTo, - RangeToInclusive, - raw_identifiers, - Ready, - reason, - recursion_limit, - reexport_test_harness_main, - reflect, - relaxed_adts, - repr, - repr128, - repr_align, - repr_align_enum, - repr_packed, - repr_simd, - repr_transparent, - re_rebalance_coherence, - result, - Result, - Return, - rhs, - rlib, - rt, - rtm_target_feature, - rust, - rust_2015_preview, - rust_2018_preview, - rust_begin_unwind, - rustc, - RustcDecodable, - RustcEncodable, - rustc_allocator, - rustc_allocator_nounwind, - rustc_allow_const_fn_ptr, - rustc_args_required_const, - rustc_attrs, - rustc_builtin_macro, - rustc_clean, - rustc_const_unstable, - rustc_conversion_suggestion, - rustc_copy_clone_marker, - rustc_def_path, - rustc_deprecated, - rustc_diagnostic_macros, - rustc_dirty, - rustc_dummy, - rustc_dump_env_program_clauses, - rustc_dump_program_clauses, - rustc_dump_user_substs, - rustc_error, - rustc_expected_cgu_reuse, - rustc_if_this_changed, - rustc_inherit_overflow_checks, - rustc_layout, - rustc_layout_scalar_valid_range_end, - rustc_layout_scalar_valid_range_start, - rustc_macro_transparency, - rustc_mir, - rustc_nonnull_optimization_guaranteed, - rustc_object_lifetime_default, - rustc_on_unimplemented, - rustc_outlives, - rustc_paren_sugar, - rustc_partition_codegened, - rustc_partition_reused, - rustc_peek, - rustc_peek_definite_init, - rustc_peek_maybe_init, - rustc_peek_maybe_uninit, - rustc_private, - rustc_proc_macro_decls, - rustc_promotable, - rustc_regions, - rustc_stable, - rustc_std_internal_symbol, - rustc_symbol_name, - rustc_synthetic, - rustc_test_marker, - rustc_then_this_would_need, - rustc_variance, - rustdoc, - rust_eh_personality, - rust_eh_unwind_resume, - rust_oom, - __rust_unstable_column, - rvalue_static_promotion, - sanitizer_runtime, - _Self, - self_in_typedefs, - self_struct_ctor, - should_panic, - simd, - simd_ffi, - since, - size, - slice_patterns, - slicing_syntax, - Some, - specialization, - speed, - spotlight, - sse4a_target_feature, - stable, - staged_api, - start, - static_in_const, - staticlib, - static_nobundle, - static_recursion, - std, - str, - stringify, - stmt, - stmt_expr_attributes, - stop_after_dataflow, - struct_field_attributes, - struct_inherit, - structural_match, - struct_variant, - sty, - suggestion, - target_feature, - target_has_atomic, - target_thread_local, - task, - tbm_target_feature, - termination_trait, - termination_trait_test, - test, - test_2018_feature, - test_accepted_feature, - test_case, - test_removed_feature, - test_runner, - then_with, - thread_local, - tool_attributes, - tool_lints, - trace_macros, - trait_alias, - transmute, - transparent, - transparent_enums, - transparent_unions, - trivial_bounds, - Try, - try_blocks, - try_trait, - tt, - tuple_indexing, - Ty, - ty, - TyCtxt, - TyKind, - type_alias_enum_variants, - type_ascription, - type_length_limit, - type_macros, - u128, - u16, - u32, - u64, - u8, - unboxed_closures, - underscore_const_names, - underscore_imports, - underscore_lifetimes, - uniform_paths, - universal_impl_trait, - unmarked_api, - unreachable_code, - unrestricted_attribute_tokens, - unsafe_destructor_blind_to_params, - unsafe_no_drop_flag, - unsized_locals, - unsized_tuple_coercion, - unstable, - untagged_unions, - unwind, - unwind_attributes, - unwrap_or, - used, - use_extern_macros, - use_nested_groups, - usize, - v1, - val, - vec, - Vec, - vis, - visible_private_types, - volatile, - warn, - warn_directory_ownership, - wasm_import_module, - wasm_target_feature, - while_let, - windows, - windows_subsystem, - Yield, - } -} - -#[derive(Copy, Clone, Eq)] -pub struct Ident { - pub name: Symbol, - pub span: Span, -} - -impl Ident { - #[inline] - /// Constructs a new identifier from a symbol and a span. - pub const fn new(name: Symbol, span: Span) -> Ident { - Ident { name, span } - } - - /// Constructs a new identifier with an empty syntax context. - #[inline] - pub const fn with_empty_ctxt(name: Symbol) -> Ident { - Ident::new(name, DUMMY_SP) - } - - #[inline] - pub fn invalid() -> Ident { - Ident::with_empty_ctxt(kw::Invalid) - } - - /// Maps an interned string to an identifier with an empty syntax context. - pub fn from_interned_str(string: InternedString) -> Ident { - Ident::with_empty_ctxt(string.as_symbol()) - } - - /// Maps a string to an identifier with an empty span. - pub fn from_str(string: &str) -> Ident { - Ident::with_empty_ctxt(Symbol::intern(string)) - } - - /// Maps a string and a span to an identifier. - pub fn from_str_and_span(string: &str, span: Span) -> Ident { - Ident::new(Symbol::intern(string), span) - } - - /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context. - pub fn with_span_pos(self, span: Span) -> Ident { - Ident::new(self.name, span.with_ctxt(self.span.ctxt())) - } - - pub fn without_first_quote(self) -> Ident { - Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span) - } - - /// "Normalize" ident for use in comparisons using "item hygiene". - /// Identifiers with same string value become same if they came from the same "modern" macro - /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from - /// different "modern" macros. - /// Technically, this operation strips all non-opaque marks from ident's syntactic context. - pub fn modern(self) -> Ident { - Ident::new(self.name, self.span.modern()) - } - - /// "Normalize" ident for use in comparisons using "local variable hygiene". - /// Identifiers with same string value become same if they came from the same non-transparent - /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different - /// non-transparent macros. - /// Technically, this operation strips all transparent marks from ident's syntactic context. - pub fn modern_and_legacy(self) -> Ident { - Ident::new(self.name, self.span.modern_and_legacy()) - } - - /// Transforms an identifier into one with the same name, but gensymed. - pub fn gensym(self) -> Ident { - let name = with_interner(|interner| interner.gensymed(self.name)); - Ident::new(name, self.span) - } - - /// Transforms an underscore identifier into one with the same name, but - /// gensymed. Leaves non-underscore identifiers unchanged. - pub fn gensym_if_underscore(self) -> Ident { - if self.name == kw::Underscore { self.gensym() } else { self } - } - - // WARNING: this function is deprecated and will be removed in the future. - pub fn is_gensymed(self) -> bool { - with_interner(|interner| interner.is_gensymed(self.name)) - } - - pub fn as_str(self) -> LocalInternedString { - self.name.as_str() - } - - pub fn as_interned_str(self) -> InternedString { - self.name.as_interned_str() - } -} - -impl PartialEq for Ident { - fn eq(&self, rhs: &Self) -> bool { - self.name == rhs.name && self.span.ctxt() == rhs.span.ctxt() - } -} - -impl Hash for Ident { - fn hash(&self, state: &mut H) { - self.name.hash(state); - self.span.ctxt().hash(state); - } -} - -impl fmt::Debug for Ident { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}{:?}", self.name, self.span.ctxt()) - } -} - -impl fmt::Display for Ident { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.name, f) - } -} - -impl Encodable for Ident { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - if self.span.ctxt().modern() == SyntaxContext::empty() { - s.emit_str(&self.as_str()) - } else { // FIXME(jseyfried): intercrate hygiene - let mut string = "#".to_owned(); - string.push_str(&self.as_str()); - s.emit_str(&string) - } - } -} - -impl Decodable for Ident { - fn decode(d: &mut D) -> Result { - let string = d.read_str()?; - Ok(if !string.starts_with('#') { - Ident::from_str(&string) - } else { // FIXME(jseyfried): intercrate hygiene - Ident::from_str(&string[1..]).gensym() - }) - } -} - -/// A symbol is an interned or gensymed string. A gensym is a symbol that is -/// never equal to any other symbol. -/// -/// Conceptually, a gensym can be thought of as a normal symbol with an -/// invisible unique suffix. Gensyms are useful when creating new identifiers -/// that must not match any existing identifiers, e.g. during macro expansion -/// and syntax desugaring. Because gensyms should always be identifiers, all -/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the -/// future the gensym-ness may be moved from `Symbol` to hygiene data.) -/// -/// Examples: -/// ``` -/// assert_eq!(Ident::from_str("x"), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x")) -/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym()) -/// ``` -/// Internally, a symbol is implemented as an index, and all operations -/// (including hashing, equality, and ordering) operate on that index. The use -/// of `newtype_index!` means that `Option` only takes up 4 bytes, -/// because `newtype_index!` reserves the last 256 values for tagging purposes. -/// -/// Note that `Symbol` cannot directly be a `newtype_index!` because it -/// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Symbol(SymbolIndex); - -newtype_index! { - pub struct SymbolIndex { .. } -} - -impl Symbol { - const fn new(n: u32) -> Self { - Symbol(SymbolIndex::from_u32_const(n)) - } - - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - with_interner(|interner| interner.intern(string)) - } - - pub fn as_str(self) -> LocalInternedString { - with_interner(|interner| unsafe { - LocalInternedString { - string: std::mem::transmute::<&str, &str>(interner.get(self)) - } - }) - } - - pub fn as_interned_str(self) -> InternedString { - with_interner(|interner| InternedString { - symbol: interner.interned(self) - }) - } - - pub fn as_u32(self) -> u32 { - self.0.as_u32() - } -} - -impl fmt::Debug for Symbol { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let is_gensymed = with_interner(|interner| interner.is_gensymed(*self)); - if is_gensymed { - write!(f, "{}({:?})", self, self.0) - } else { - write!(f, "{}", self) - } - } -} - -impl fmt::Display for Symbol { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) - } -} - -impl Encodable for Symbol { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) - } -} - -impl Decodable for Symbol { - fn decode(d: &mut D) -> Result { - Ok(Symbol::intern(&d.read_str()?)) - } -} - -// The `&'static str`s in this type actually point into the arena. -// -// Note that normal symbols are indexed upward from 0, and gensyms are indexed -// downward from SymbolIndex::MAX_AS_U32. -#[derive(Default)] -pub struct Interner { - arena: DroplessArena, - names: FxHashMap<&'static str, Symbol>, - strings: Vec<&'static str>, - gensyms: Vec, -} - -impl Interner { - fn prefill(init: &[&'static str]) -> Self { - Interner { - strings: init.into(), - names: init.iter().copied().zip((0..).map(Symbol::new)).collect(), - ..Default::default() - } - } - - pub fn intern(&mut self, string: &str) -> Symbol { - if let Some(&name) = self.names.get(string) { - return name; - } - - let name = Symbol::new(self.strings.len() as u32); - - // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be - // UTF-8. - let string: &str = unsafe { - str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) - }; - // It is safe to extend the arena allocation to `'static` because we only access - // these while the arena is still alive. - let string: &'static str = unsafe { - &*(string as *const str) - }; - self.strings.push(string); - self.names.insert(string, name); - name - } - - fn interned(&self, symbol: Symbol) -> Symbol { - if (symbol.0.as_usize()) < self.strings.len() { - symbol - } else { - self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize] - } - } - - fn gensymed(&mut self, symbol: Symbol) -> Symbol { - self.gensyms.push(symbol); - Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1) - } - - fn is_gensymed(&mut self, symbol: Symbol) -> bool { - symbol.0.as_usize() >= self.strings.len() - } - - // Get the symbol as a string. `Symbol::as_str()` should be used in - // preference to this function. - pub fn get(&self, symbol: Symbol) -> &str { - match self.strings.get(symbol.0.as_usize()) { - Some(string) => string, - None => { - let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]; - self.strings[symbol.0.as_usize()] - } - } - } -} - -// This module has a very short name because it's used a lot. -pub mod kw { - use super::Symbol; - keywords!(); -} - -// This module has a very short name because it's used a lot. -pub mod sym { - use std::convert::TryInto; - use super::Symbol; - - symbols!(); - - // Get the symbol for an integer. The first few non-negative integers each - // have a static symbol and therefore are fast. - pub fn integer + Copy + ToString>(n: N) -> Symbol { - if let Result::Ok(idx) = n.try_into() { - if let Option::Some(&sym) = digits_array.get(idx) { - return sym; - } - } - Symbol::intern(&n.to_string()) - } -} - -impl Symbol { - fn is_used_keyword_2018(self) -> bool { - self == kw::Dyn - } - - fn is_unused_keyword_2018(self) -> bool { - self >= kw::Async && self <= kw::Try - } - - /// Used for sanity checking rustdoc keyword sections. - pub fn is_doc_keyword(self) -> bool { - self <= kw::Union - } - - /// A keyword or reserved identifier that can be used as a path segment. - pub fn is_path_segment_keyword(self) -> bool { - self == kw::Super || - self == kw::SelfLower || - self == kw::SelfUpper || - self == kw::Crate || - self == kw::PathRoot || - self == kw::DollarCrate - } - - /// This symbol can be a raw identifier. - pub fn can_be_raw(self) -> bool { - self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword() - } -} - -impl Ident { - // Returns `true` for reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. - pub fn is_special(self) -> bool { - self.name <= kw::Underscore - } - - /// Returns `true` if the token is a keyword used in the language. - pub fn is_used_keyword(self) -> bool { - // Note: `span.edition()` is relatively expensive, don't call it unless necessary. - self.name >= kw::As && self.name <= kw::While || - self.name.is_used_keyword_2018() && self.span.rust_2018() - } - - /// Returns `true` if the token is a keyword reserved for possible future use. - pub fn is_unused_keyword(self) -> bool { - // Note: `span.edition()` is relatively expensive, don't call it unless necessary. - self.name >= kw::Abstract && self.name <= kw::Yield || - self.name.is_unused_keyword_2018() && self.span.rust_2018() - } - - /// Returns `true` if the token is either a special identifier or a keyword. - pub fn is_reserved(self) -> bool { - self.is_special() || self.is_used_keyword() || self.is_unused_keyword() - } - - /// A keyword or reserved identifier that can be used as a path segment. - pub fn is_path_segment_keyword(self) -> bool { - self.name.is_path_segment_keyword() - } - - /// We see this identifier in a normal identifier position, like variable name or a type. - /// How was it written originally? Did it use the raw form? Let's try to guess. - pub fn is_raw_guess(self) -> bool { - self.name.can_be_raw() && self.is_reserved() - } -} - -// If an interner exists, return it. Otherwise, prepare a fresh one. -#[inline] -fn with_interner T>(f: F) -> T { - GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock())) -} - -/// An alternative to `Symbol` and `InternedString`, useful when the chars -/// within the symbol need to be accessed. It is best used for temporary -/// values. -/// -/// Because the interner outlives any thread which uses this type, we can -/// safely treat `string` which points to interner data, as an immortal string, -/// as long as this type never crosses between threads. -// -// FIXME: ensure that the interner outlives any thread which uses -// `LocalInternedString`, by creating a new thread right after constructing the -// interner. -#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] -pub struct LocalInternedString { - string: &'static str, -} - -impl LocalInternedString { - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - let string = with_interner(|interner| { - let symbol = interner.intern(string); - interner.strings[symbol.0.as_usize()] - }); - LocalInternedString { - string: unsafe { std::mem::transmute::<&str, &str>(string) } - } - } - - pub fn as_interned_str(self) -> InternedString { - InternedString { - symbol: Symbol::intern(self.string) - } - } - - #[inline] - pub fn get(&self) -> &str { - // This returns a valid string since we ensure that `self` outlives the interner - // by creating the interner on a thread which outlives threads which can access it. - // This type cannot move to a thread which outlives the interner since it does - // not implement Send. - self.string - } -} - -impl std::convert::AsRef for LocalInternedString -where - str: std::convert::AsRef -{ - #[inline] - fn as_ref(&self) -> &U { - self.string.as_ref() - } -} - -impl> std::cmp::PartialEq for LocalInternedString { - fn eq(&self, other: &T) -> bool { - self.string == other.deref() - } -} - -impl std::cmp::PartialEq for str { - fn eq(&self, other: &LocalInternedString) -> bool { - self == other.string - } -} - -impl<'a> std::cmp::PartialEq for &'a str { - fn eq(&self, other: &LocalInternedString) -> bool { - *self == other.string - } -} - -impl std::cmp::PartialEq for String { - fn eq(&self, other: &LocalInternedString) -> bool { - self == other.string - } -} - -impl<'a> std::cmp::PartialEq for &'a String { - fn eq(&self, other: &LocalInternedString) -> bool { - *self == other.string - } -} - -impl !Send for LocalInternedString {} -impl !Sync for LocalInternedString {} - -impl std::ops::Deref for LocalInternedString { - type Target = str; - #[inline] - fn deref(&self) -> &str { self.string } -} - -impl fmt::Debug for LocalInternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.string, f) - } -} - -impl fmt::Display for LocalInternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.string, f) - } -} - -impl Decodable for LocalInternedString { - fn decode(d: &mut D) -> Result { - Ok(LocalInternedString::intern(&d.read_str()?)) - } -} - -impl Encodable for LocalInternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self.string) - } -} - -/// An alternative to `Symbol` that is focused on string contents. It has two -/// main differences to `Symbol`. -/// -/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the -/// string chars rather than the symbol integer. This is useful when hash -/// stability is required across compile sessions, or a guaranteed sort -/// ordering is required. -/// -/// Second, gensym-ness is irrelevant. E.g.: -/// ``` -/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) -/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str()) -/// ``` -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct InternedString { - symbol: Symbol, -} - -impl InternedString { - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - InternedString { - symbol: Symbol::intern(string) - } - } - - pub fn with R, R>(self, f: F) -> R { - let str = with_interner(|interner| { - interner.get(self.symbol) as *const str - }); - // This is safe because the interner keeps string alive until it is dropped. - // We can access it because we know the interner is still alive since we use a - // scoped thread local to access it, and it was alive at the beginning of this scope - unsafe { f(&*str) } - } - - fn with2 R, R>(self, other: &InternedString, f: F) -> R { - let (self_str, other_str) = with_interner(|interner| { - (interner.get(self.symbol) as *const str, - interner.get(other.symbol) as *const str) - }); - // This is safe for the same reason that `with` is safe. - unsafe { f(&*self_str, &*other_str) } - } - - pub fn as_symbol(self) -> Symbol { - self.symbol - } - - pub fn as_str(self) -> LocalInternedString { - self.symbol.as_str() - } -} - -impl Hash for InternedString { - fn hash(&self, state: &mut H) { - self.with(|str| str.hash(state)) - } -} - -impl PartialOrd for InternedString { - fn partial_cmp(&self, other: &InternedString) -> Option { - if self.symbol == other.symbol { - return Some(Ordering::Equal); - } - self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str)) - } -} - -impl Ord for InternedString { - fn cmp(&self, other: &InternedString) -> Ordering { - if self.symbol == other.symbol { - return Ordering::Equal; - } - self.with2(other, |self_str, other_str| self_str.cmp(other_str)) - } -} - -impl fmt::Debug for InternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Debug::fmt(&str, f)) - } -} - -impl fmt::Display for InternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Display::fmt(&str, f)) - } -} - -impl Decodable for InternedString { - fn decode(d: &mut D) -> Result { - Ok(InternedString::intern(&d.read_str()?)) - } -} - -impl Encodable for InternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.with(|string| s.emit_str(string)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::Globals; - use crate::edition; - - #[test] - fn interner_tests() { - let mut i: Interner = Interner::default(); - // first one is zero: - assert_eq!(i.intern("dog"), Symbol::new(0)); - // re-use gets the same entry: - assert_eq!(i.intern("dog"), Symbol::new(0)); - // different string gets a different #: - assert_eq!(i.intern("cat"), Symbol::new(1)); - assert_eq!(i.intern("cat"), Symbol::new(1)); - // dog is still at zero - assert_eq!(i.intern("dog"), Symbol::new(0)); - let z = i.intern("zebra"); - assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32)); - // gensym of same string gets new number: - assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1)); - // gensym of *existing* string gets new number: - let d = i.intern("dog"); - assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2)); - } - - #[test] - fn without_first_quote_test() { - GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { - let i = Ident::from_str("'break"); - assert_eq!(i.without_first_quote().name, kw::Break); - }); - } -} diff --git a/gcc/rust/rustfrontend/backend.h b/gcc/rust/rustfrontend/backend.h deleted file mode 100644 index d69ad91..0000000 --- a/gcc/rust/rustfrontend/backend.h +++ /dev/null @@ -1,778 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "operator.h" - -// Pointers to these types are created by the backend, passed to the -// frontend, and passed back to the backend. The types must be -// defined by the backend using these names. - -// The backend representation of a type. -class Btype; - -// The backend represention of an expression. -class Bexpression; - -// The backend representation of a statement. -class Bstatement; - -// The backend representation of a function definition or declaration. -class Bfunction; - -// The backend representation of a block. -class Bblock; - -// The backend representation of a variable. -class Bvariable; - -// The backend representation of a label. -class Blabel; - - -// The backend interface. This is a pure abstract class that a -// specific backend will implement. - -class Backend -{ - public: - virtual ~Backend() { } - - // Name/type/location. Used for function parameters, struct fields, - // interface methods. - struct Btyped_identifier - { - std::string name; - Btype* btype; - Location location; - - Btyped_identifier() - : name(), btype(NULL), location(Linemap::unknown_location()) - { } - - Btyped_identifier(const std::string& a_name, Btype* a_btype, - Location a_location) - : name(a_name), btype(a_btype), location(a_location) - { } - }; - - // Types. - - // Produce an error type. Actually the backend could probably just - // crash if this is called. - virtual Btype* - error_type() = 0; - - // Get a void type. This is used in (at least) two ways: 1) as the - // return type of a function with no result parameters; 2) - // unsafe.Pointer is represented as *void. - virtual Btype* - void_type() = 0; - - // Get the unnamed boolean type. - virtual Btype* - bool_type() = 0; - - // Get an unnamed integer type with the given signedness and number - // of bits. - virtual Btype* - integer_type(bool is_unsigned, int bits) = 0; - - // Get an unnamed floating point type with the given number of bits - // (32 or 64). - virtual Btype* - float_type(int bits) = 0; - - // Get an unnamed complex type with the given number of bits (64 or 128). - virtual Btype* - complex_type(int bits) = 0; - - // Get a pointer type. - virtual Btype* - pointer_type(Btype* to_type) = 0; - - // Get a function type. The receiver, parameter, and results are - // generated from the types in the Function_type. The Function_type - // is provided so that the names are available. This should return - // not the type of a Go function (which is a pointer to a struct) - // but the type of a C function pointer (which will be used as the - // type of the first field of the struct). If there is more than - // one result, RESULT_STRUCT is a struct type to hold the results, - // and RESULTS may be ignored; if there are zero or one results, - // RESULT_STRUCT is NULL. - virtual Btype* - function_type(const Btyped_identifier& receiver, - const std::vector& parameters, - const std::vector& results, - Btype* result_struct, - Location location) = 0; - - // Get a struct type. - virtual Btype* - struct_type(const std::vector& fields) = 0; - - // Get an array type. - virtual Btype* - array_type(Btype* element_type, Bexpression* length) = 0; - - // Create a placeholder pointer type. This is used for a named - // pointer type, since in Go a pointer type may refer to itself. - // NAME is the name of the type, and the location is where the named - // type is defined. This function is also used for unnamed function - // types with multiple results, in which case the type has no name - // and NAME will be empty. FOR_FUNCTION is true if this is for a C - // pointer to function type. A Go func type is represented as a - // pointer to a struct, and the first field of the struct is a C - // pointer to function. The return value will later be passed as - // the first parameter to set_placeholder_pointer_type or - // set_placeholder_function_type. - virtual Btype* - placeholder_pointer_type(const std::string& name, Location, - bool for_function) = 0; - - // Fill in a placeholder pointer type as a pointer. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // point to the type that TO_TYPE points to (that is, PLACEHOLDER - // becomes the same type as TO_TYPE). Returns true on success, - // false on failure. - virtual bool - set_placeholder_pointer_type(Btype* placeholder, Btype* to_type) = 0; - - // Fill in a placeholder pointer type as a function. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // become a real Go function type (which corresponds to a C/C++ - // pointer to function type). FT will be something returned by the - // function_type method. Returns true on success, false on failure. - virtual bool - set_placeholder_function_type(Btype* placeholder, Btype* ft) = 0; - - // Create a placeholder struct type. This is used for a named - // struct type, as with placeholder_pointer_type. It is also used - // for interface types, in which case NAME will be the empty string. - virtual Btype* - placeholder_struct_type(const std::string& name, Location) = 0; - - // Fill in a placeholder struct type. This takes a type returned by - // placeholder_struct_type and arranges for it to become a real - // struct type. The parameter is as for struct_type. Returns true - // on success, false on failure. - virtual bool - set_placeholder_struct_type(Btype* placeholder, - const std::vector& fields) - = 0; - - // Create a placeholder array type. This is used for a named array - // type, as with placeholder_pointer_type, to handle cases like - // type A []*A. - virtual Btype* - placeholder_array_type(const std::string& name, Location) = 0; - - // Fill in a placeholder array type. This takes a type returned by - // placeholder_array_type and arranges for it to become a real array - // type. The parameters are as for array_type. Returns true on - // success, false on failure. - virtual bool - set_placeholder_array_type(Btype* placeholder, Btype* element_type, - Bexpression* length) = 0; - - // Return a named version of a type. The location is the location - // of the type definition. This will not be called for a type - // created via placeholder_pointer_type, placeholder_struct_type, or - // placeholder_array_type.. (It may be called for a pointer, - // struct, or array type in a case like "type P *byte; type Q P".) - virtual Btype* - named_type(const std::string& name, Btype*, Location) = 0; - - // Create a marker for a circular pointer type. Go pointer and - // function types can refer to themselves in ways that are not - // permitted in C/C++. When a circular type is found, this function - // is called for the circular reference. This permits the backend - // to decide how to handle such a type. PLACEHOLDER is the - // placeholder type which has already been created; if the backend - // is prepared to handle a circular pointer type, it may simply - // return PLACEHOLDER. FOR_FUNCTION is true if this is for a - // function type. - // - // For "type P *P" the sequence of calls will be - // bt1 = placeholder_pointer_type(); - // bt2 = circular_pointer_type(bt1, false); - // set_placeholder_pointer_type(bt1, bt2); - virtual Btype* - circular_pointer_type(Btype* placeholder, bool for_function) = 0; - - // Return whether the argument could be a special type created by - // circular_pointer_type. This is used to introduce explicit type - // conversions where needed. If circular_pointer_type returns its - // PLACEHOLDER parameter, this may safely always return false. - virtual bool - is_circular_pointer_type(Btype*) = 0; - - // Return the size of a type. - virtual int64_t - type_size(Btype*) = 0; - - // Return the alignment of a type. - virtual int64_t - type_alignment(Btype*) = 0; - - // Return the alignment of a struct field of this type. This is - // normally the same as type_alignment, but not always. - virtual int64_t - type_field_alignment(Btype*) = 0; - - // Return the offset of field INDEX in a struct type. INDEX is the - // entry in the FIELDS std::vector parameter of struct_type or - // set_placeholder_struct_type. - virtual int64_t - type_field_offset(Btype*, size_t index) = 0; - - // Expressions. - - // Return an expression for a zero value of the given type. This is - // used for cases such as local variable initialization and - // converting nil to other types. - virtual Bexpression* - zero_expression(Btype*) = 0; - - // Create an error expression. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bexpression* - error_expression() = 0; - - // Create a nil pointer expression. - virtual Bexpression* - nil_pointer_expression() = 0; - - // Create a reference to a variable. - virtual Bexpression* - var_expression(Bvariable* var, Location) = 0; - - // Create an expression that indirects through the pointer expression EXPR - // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer - // is known to point to a valid memory location. BTYPE is the expected type - // of the indirected EXPR. - virtual Bexpression* - indirect_expression(Btype* btype, Bexpression* expr, bool known_valid, - Location) = 0; - - // Return an expression that declares a constant named NAME with the - // constant value VAL in BTYPE. - virtual Bexpression* - named_constant_expression(Btype* btype, const std::string& name, - Bexpression* val, Location) = 0; - - // Return an expression for the multi-precision integer VAL in BTYPE. - virtual Bexpression* - integer_constant_expression(Btype* btype, mpz_t val) = 0; - - // Return an expression for the floating point value VAL in BTYPE. - virtual Bexpression* - float_constant_expression(Btype* btype, mpfr_t val) = 0; - - // Return an expression for the complex value VAL in BTYPE. - virtual Bexpression* - complex_constant_expression(Btype* btype, mpc_t val) = 0; - - // Return an expression for the string value VAL. - virtual Bexpression* - string_constant_expression(const std::string& val) = 0; - - // Return an expression for the boolean value VAL. - virtual Bexpression* - boolean_constant_expression(bool val) = 0; - - // Return an expression for the real part of BCOMPLEX. - virtual Bexpression* - real_part_expression(Bexpression* bcomplex, Location) = 0; - - // Return an expression for the imaginary part of BCOMPLEX. - virtual Bexpression* - imag_part_expression(Bexpression* bcomplex, Location) = 0; - - // Return an expression for the complex number (BREAL, BIMAG). - virtual Bexpression* - complex_expression(Bexpression* breal, Bexpression* bimag, Location) = 0; - - // Return an expression that converts EXPR to TYPE. - virtual Bexpression* - convert_expression(Btype* type, Bexpression* expr, Location) = 0; - - // Create an expression for the address of a function. This is used to - // get the address of the code for a function. - virtual Bexpression* - function_code_expression(Bfunction*, Location) = 0; - - // Create an expression that takes the address of an expression. - virtual Bexpression* - address_expression(Bexpression*, Location) = 0; - - // Return an expression for the field at INDEX in BSTRUCT. - virtual Bexpression* - struct_field_expression(Bexpression* bstruct, size_t index, Location) = 0; - - // Create an expression that executes BSTAT before BEXPR. - virtual Bexpression* - compound_expression(Bstatement* bstat, Bexpression* bexpr, Location) = 0; - - // Return an expression that executes THEN_EXPR if CONDITION is true, or - // ELSE_EXPR otherwise and returns the result as type BTYPE, within the - // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. - virtual Bexpression* - conditional_expression(Bfunction* function, Btype* btype, - Bexpression* condition, Bexpression* then_expr, - Bexpression* else_expr, Location) = 0; - - // Return an expression for the unary operation OP EXPR. - // Supported values of OP are (from operators.h): - // MINUS, NOT, XOR. - virtual Bexpression* - unary_expression(Operator op, Bexpression* expr, Location) = 0; - - // Return an expression for the binary operation LEFT OP RIGHT. - // Supported values of OP are (from operators.h): - // EQEQ, NOTEQ, LT, LE, GT, GE, PLUS, MINUS, OR, XOR, MULT, DIV, MOD, - // LSHIFT, RSHIFT, AND, NOT. - virtual Bexpression* - binary_expression(Operator op, Bexpression* left, Bexpression* right, - Location) = 0; - - // Return an expression that constructs BTYPE with VALS. BTYPE must be the - // backend representation a of struct. VALS must be in the same order as the - // corresponding fields in BTYPE. - virtual Bexpression* - constructor_expression(Btype* btype, const std::vector& vals, - Location) = 0; - - // Return an expression that constructs an array of BTYPE with INDEXES and - // VALS. INDEXES and VALS must have the same amount of elements. Each index - // in INDEXES must be in the same order as the corresponding value in VALS. - virtual Bexpression* - array_constructor_expression(Btype* btype, - const std::vector& indexes, - const std::vector& vals, - Location) = 0; - - // Return an expression for the address of BASE[INDEX]. - // BASE has a pointer type. This is used for slice indexing. - virtual Bexpression* - pointer_offset_expression(Bexpression* base, Bexpression* index, - Location) = 0; - - // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid - // fixed-length array, not a slice. - virtual Bexpression* - array_index_expression(Bexpression* array, Bexpression* index, Location) = 0; - - // Create an expression for a call to FN with ARGS, taking place within - // caller CALLER. - virtual Bexpression* - call_expression(Bfunction *caller, Bexpression* fn, - const std::vector& args, - Bexpression* static_chain, Location) = 0; - - // Statements. - - // Create an error statement. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bstatement* - error_statement() = 0; - - // Create an expression statement within the specified function. - virtual Bstatement* - expression_statement(Bfunction*, Bexpression*) = 0; - - // Create a variable initialization statement in the specified - // function. This initializes a local variable at the point in the - // program flow where it is declared. - virtual Bstatement* - init_statement(Bfunction*, Bvariable* var, Bexpression* init) = 0; - - // Create an assignment statement within the specified function. - virtual Bstatement* - assignment_statement(Bfunction*, Bexpression* lhs, Bexpression* rhs, - Location) = 0; - - // Create a return statement, passing the representation of the - // function and the list of values to return. - virtual Bstatement* - return_statement(Bfunction*, const std::vector&, - Location) = 0; - - // Create an if statement within a function. ELSE_BLOCK may be NULL. - virtual Bstatement* - if_statement(Bfunction*, Bexpression* condition, - Bblock* then_block, Bblock* else_block, - Location) = 0; - - // Create a switch statement where the case values are constants. - // CASES and STATEMENTS must have the same number of entries. If - // VALUE matches any of the list in CASES[i], which will all be - // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will - // either end with a goto statement or will fall through into - // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, - // which need not be last. FUNCTION is the current function. - virtual Bstatement* - switch_statement(Bfunction* function, Bexpression* value, - const std::vector >& cases, - const std::vector& statements, - Location) = 0; - - // Create a single statement from two statements. - virtual Bstatement* - compound_statement(Bstatement*, Bstatement*) = 0; - - // Create a single statement from a list of statements. - virtual Bstatement* - statement_list(const std::vector&) = 0; - - // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if - // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and - // if not NULL, it will always be executed. This is used for handling defers - // in Go functions. In C++, the resulting code is of this form: - // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } - virtual Bstatement* - exception_handler_statement(Bstatement* bstat, Bstatement* except_stmt, - Bstatement* finally_stmt, Location) = 0; - - // Blocks. - - // Create a block. The frontend will call this function when it - // starts converting a block within a function. FUNCTION is the - // current function. ENCLOSING is the enclosing block; it will be - // NULL for the top-level block in a function. VARS is the list of - // local variables defined within this block; each entry will be - // created by the local_variable function. START_LOCATION is the - // location of the start of the block, more or less the location of - // the initial curly brace. END_LOCATION is the location of the end - // of the block, more or less the location of the final curly brace. - // The statements will be added after the block is created. - virtual Bblock* - block(Bfunction* function, Bblock* enclosing, - const std::vector& vars, - Location start_location, Location end_location) = 0; - - // Add the statements to a block. The block is created first. Then - // the statements are created. Then the statements are added to the - // block. This will called exactly once per block. The vector may - // be empty if there are no statements. - virtual void - block_add_statements(Bblock*, const std::vector&) = 0; - - // Return the block as a statement. This is used to include a block - // in a list of statements. - virtual Bstatement* - block_statement(Bblock*) = 0; - - // Variables. - - // Create an error variable. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bvariable* - error_variable() = 0; - - // Create a global variable. NAME is the package-qualified name of - // the variable. ASM_NAME is the encoded identifier for the - // variable, incorporating the package, and made safe for the - // assembler. BTYPE is the type of the variable. IS_EXTERNAL is - // true if the variable is defined in some other package. IS_HIDDEN - // is true if the variable is not exported (name begins with a lower - // case letter). IN_UNIQUE_SECTION is true if the variable should - // be put into a unique section if possible; this is intended to - // permit the linker to garbage collect the variable if it is not - // referenced. LOCATION is where the variable was defined. - virtual Bvariable* - global_variable(const std::string& name, - const std::string& asm_name, - Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, - Location location) = 0; - - // A global variable will 1) be initialized to zero, or 2) be - // initialized to a constant value, or 3) be initialized in the init - // function. In case 2, the frontend will call - // global_variable_set_init to set the initial value. If this is - // not called, the backend should initialize a global variable to 0. - // The init function may then assign a value to it. - virtual void - global_variable_set_init(Bvariable*, Bexpression*) = 0; - - // Create a local variable. The frontend will create the local - // variables first, and then create the block which contains them. - // FUNCTION is the function in which the variable is defined. NAME - // is the name of the variable. TYPE is the type. DECL_VAR, if not - // null, gives the location at which the value of this variable may - // be found, typically used to create an inner-scope reference to an - // outer-scope variable, to extend the lifetime of the variable beyond - // the inner scope. IS_ADDRESS_TAKEN is true if the address of this - // variable is taken (this implies that the address does not escape - // the function, as otherwise the variable would be on the heap). - // LOCATION is where the variable is defined. For each local variable - // the frontend will call init_statement to set the initial value. - virtual Bvariable* - local_variable(Bfunction* function, const std::string& name, Btype* type, - Bvariable* decl_var, bool is_address_taken, Location location) = 0; - - // Create a function parameter. This is an incoming parameter, not - // a result parameter (result parameters are treated as local - // variables). The arguments are as for local_variable. - virtual Bvariable* - parameter_variable(Bfunction* function, const std::string& name, - Btype* type, bool is_address_taken, - Location location) = 0; - - // Create a static chain parameter. This is the closure parameter. - virtual Bvariable* - static_chain_variable(Bfunction* function, const std::string& name, - Btype* type, Location location) = 0; - - // Create a temporary variable. A temporary variable has no name, - // just a type. We pass in FUNCTION and BLOCK in case they are - // needed. If INIT is not NULL, the variable should be initialized - // to that value. Otherwise the initial value is irrelevant--the - // backend does not have to explicitly initialize it to zero. - // ADDRESS_IS_TAKEN is true if the programs needs to take the - // address of this temporary variable. LOCATION is the location of - // the statement or expression which requires creating the temporary - // variable, and may not be very useful. This function should - // return a variable which can be referenced later and should set - // *PSTATEMENT to a statement which initializes the variable. - virtual Bvariable* - temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression* init, - bool address_is_taken, Location location, - Bstatement** pstatement) = 0; - - // Create an implicit variable that is compiler-defined. This is - // used when generating GC data and roots, when storing the values - // of a slice constructor, and for the zero value of types. This returns a - // Bvariable because it corresponds to an initialized variable in C. - // - // NAME is the name to use for the initialized variable this will create. - // - // ASM_NAME is encoded assembler-friendly version of the name, or the - // empty string if no encoding is needed. - // - // TYPE is the type of the implicit variable. - // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_CONSTANT is true if the implicit variable should be treated like it is - // immutable. For slice initializers, if the values must be copied to the - // heap, the variable IS_CONSTANT. - // - // IS_COMMON is true if the implicit variable should - // be treated as a common variable (multiple definitions with - // different sizes permitted in different object files, all merged - // into the largest definition at link time); this will be true for - // the zero value. IS_HIDDEN and IS_COMMON will never both be true. - // - // If ALIGNMENT is not zero, it is the desired alignment of the variable. - virtual Bvariable* - implicit_variable(const std::string& name, const std::string& asm_name, - Btype* type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) = 0; - - - // Set the initial value of a variable created by implicit_variable. - // This must be called even if there is no initializer, i.e., INIT is NULL. - // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are - // the same ones passed to implicit_variable. INIT will be a composite - // literal of type TYPE. It will not contain any function calls or anything - // else that can not be put into a read-only data section. - // It may contain the address of variables created by implicit_variable. - // - // If IS_COMMON is true, INIT will be NULL, and the - // variable should be initialized to all zeros. - virtual void - implicit_variable_set_init(Bvariable*, const std::string& name, Btype* type, - bool is_hidden, bool is_constant, bool is_common, - Bexpression* init) = 0; - - // Create a reference to a named implicit variable defined in some - // other package. This will be a variable created by a call to - // implicit_variable with the same NAME, ASM_NAME and TYPE and with - // IS_COMMON passed as false. This corresponds to an extern global - // variable in C. - virtual Bvariable* - implicit_variable_reference(const std::string& name, - const std::string& asm_name, - Btype* type) = 0; - - // Create a named immutable initialized data structure. This is - // used for type descriptors, map descriptors, and function - // descriptors. This returns a Bvariable because it corresponds to - // an initialized const variable in C. - // - // NAME is the name to use for the initialized global variable which - // this call will create. - // - // ASM_NAME is the encoded, assembler-friendly version of NAME, or - // the empty string if no encoding is needed. - // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_COMMON is true if NAME may be defined by several packages, and - // the linker should merge all such definitions. If IS_COMMON is - // false, NAME should be defined in only one file. In general - // IS_COMMON will be true for the type descriptor of an unnamed type - // or a builtin type. IS_HIDDEN and IS_COMMON will never both be - // true. - // - // TYPE will be a struct type; the type of the returned expression - // must be a pointer to this struct type. - // - // We must create the named structure before we know its - // initializer, because the initializer may refer to its own - // address. After calling this the frontend will call - // immutable_struct_set_init. - virtual Bvariable* - immutable_struct(const std::string& name, - const std::string& asm_name, - bool is_hidden, bool is_common, - Btype* type, Location) = 0; - - // Set the initial value of a variable created by immutable_struct. - // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are - // the same ones passed to immutable_struct. INITIALIZER will be a - // composite literal of type TYPE. It will not contain any function - // calls or anything else that can not be put into a read-only data - // section. It may contain the address of variables created by - // immutable_struct. - virtual void - immutable_struct_set_init(Bvariable*, const std::string& name, - bool is_hidden, bool is_common, Btype* type, - Location, Bexpression* initializer) = 0; - - // Create a reference to a named immutable initialized data - // structure defined in some other package. This will be a - // structure created by a call to immutable_struct with the same - // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This - // corresponds to an extern const global variable in C. - virtual Bvariable* - immutable_struct_reference(const std::string& name, - const std::string& asm_name, - Btype* type, Location) = 0; - - // Labels. - - // Create a new label. NAME will be empty if this is a label - // created by the frontend for a loop construct. The location is - // where the label is defined. - virtual Blabel* - label(Bfunction*, const std::string& name, Location) = 0; - - // Create a statement which defines a label. This statement will be - // put into the codestream at the point where the label should be - // defined. - virtual Bstatement* - label_definition_statement(Blabel*) = 0; - - // Create a goto statement to a label. - virtual Bstatement* - goto_statement(Blabel*, Location) = 0; - - // Create an expression for the address of a label. This is used to - // get the return address of a deferred function which may call - // recover. - virtual Bexpression* - label_address(Blabel*, Location) = 0; - - // Functions. - - // Create an error function. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bfunction* - error_function() = 0; - - // Bit flags to pass to the function method. - - // Set if the function should be visible outside of the current - // compilation unit. - static const unsigned int function_is_visible = 1 << 0; - - // Set if this is a function declaration rather than a definition; - // the definition will be in another compilation unit. - static const unsigned int function_is_declaration = 1 << 1; - - // Set if the function can be inlined. This is normally set, but is - // false for functions that may not be inlined because they call - // recover and must be visible for correct panic recovery. - static const unsigned int function_is_inlinable = 1 << 2; - - // Set if the function may not split the stack. This is set for the - // implementation of recover itself, among other things. - static const unsigned int function_no_split_stack = 1 << 3; - - // Set if the function does not return. This is set for the - // implementation of panic. - static const unsigned int function_does_not_return = 1 << 4; - - // Set if the function should be put in a unique section if - // possible. This is used for field tracking. - static const unsigned int function_in_unique_section = 1 << 5; - - // Set if the function should be available for inlining in the - // backend, but should not be emitted as a standalone function. Any - // call to the function that is not inlined should be treated as a - // call to a function defined in a different compilation unit. This - // is like a C99 function marked inline but not extern. - static const unsigned int function_only_inline = 1 << 6; - - // Declare or define a function of FNTYPE. - // NAME is the Go name of the function. ASM_NAME, if not the empty - // string, is the name that should be used in the symbol table; this - // will be non-empty if a magic extern comment is used. FLAGS is - // bit flags described above. - virtual Bfunction* - function(Btype* fntype, const std::string& name, const std::string& asm_name, - unsigned int flags, Location) = 0; - - // Create a statement that runs all deferred calls for FUNCTION. This should - // be a statement that looks like this in C++: - // finish: - // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } - virtual Bstatement* - function_defer_statement(Bfunction* function, Bexpression* undefer, - Bexpression* check_defer, Location) = 0; - - // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. - // This will only be called for a function definition. Returns true on - // success, false on failure. - virtual bool - function_set_parameters(Bfunction* function, - const std::vector& param_vars) = 0; - - // Set the function body for FUNCTION using the code in CODE_STMT. Returns - // true on success, false on failure. - virtual bool - function_set_body(Bfunction* function, Bstatement* code_stmt) = 0; - - // Look up a named built-in function in the current backend implementation. - // Returns NULL if no built-in function by that name exists. - virtual Bfunction* - lookup_builtin(const std::string&) = 0; - - // Utility. - - // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, - // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. - virtual void - write_global_definitions(const std::vector& type_decls, - const std::vector& constant_decls, - const std::vector& function_decls, - const std::vector& variable_decls) = 0; - - // Write SIZE bytes of export data from BYTES to the proper - // section in the output object file. - virtual void - write_export_data(const char* bytes, unsigned int size) = 0; -}; diff --git a/gcc/rust/rustfrontend/main.cc b/gcc/rust/rustfrontend/main.cc deleted file mode 100644 index 00ef232..0000000 --- a/gcc/rust/rustfrontend/main.cc +++ /dev/null @@ -1,14 +0,0 @@ -// would maybe have to implement lang-hooks.h methods: -/* init_options: first call made to frontend before any options processing is done - handle_option: called to handle a single command-line option - post_options: called after all command-line processing is done. Could also determine name of - input file to parse here - init: called after post_options to initalize frontend - finish: called after all compilation is done. Can use to clean up front end. - parse_file: lang hook that does the parsing, semantic analysis, and code generation required - for input file, i.e. does the actual compilation work -*/ - - -// reference links: -// https://www.linuxjournal.com/article/7884 diff --git a/gcc/rust/rustfrontend/node.cc b/gcc/rust/rustfrontend/node.cc deleted file mode 100644 index 24393a5..0000000 --- a/gcc/rust/rustfrontend/node.cc +++ /dev/null @@ -1,862 +0,0 @@ -#include "rust-system.h" -#include "node.h" - - -static int const indent_step = 4; - -void print_indent(int depth); - -#define PUSHBACK_LEN 4 - -static char pushback[PUSHBACK_LEN]; -static int verbose; -struct node* nodes = NULL; -int n_nodes; - -void -parser_init(int v) -{ - verbose = v; - n_nodes = 0; - memset(pushback, '\0', PUSHBACK_LEN); -} - -// Note: this does nothing if the pushback queue is full. As long as -// there aren't more than PUSHBACK_LEN consecutive calls to push_back -// in an action, this shouldn't be a problem. -void push_back(char c) -{ - for (int i = 0; i < PUSHBACK_LEN; ++i) { - if (pushback[i] == '\0') { - pushback[i] = c; - break; - } - } -} - -Node -mk_node(ast_opcode_t op, int n, ...) -{ - unsigned sz = sizeof(struct node); - struct node* nd = (struct node *)xmalloc(sz); - nd->elems = (struct node **)xcalloc(n, sizeof(struct node*)); - - nd->prev = NULL; - nd->next = nodes; - if (nodes) { - nodes->prev = nd; - } - nodes = nd; - - nd->op = op; - nd->value = NULL; - nd->n_elems = n; - - va_list ap; - va_start(ap, n); - for (int i = 0; i < n; ++i) - { - struct node *nn = va_arg(ap, struct node *); - nd->elems[i] = nn; - } - va_end(ap); - - n_nodes++; - return nd; -} - -Node -mk_node_value(ast_opcode_t op, char* value, int n, ...) -{ - unsigned sz = sizeof(struct node); - struct node* nd = (struct node *)xmalloc(sz); - nd->elems = (struct node **)xcalloc(n, sizeof(struct node*)); - - nd->prev = NULL; - nd->next = nodes; - if (nodes) { - nodes->prev = nd; - } - nodes = nd; - - nd->op = op; - nd->value = value; - nd->n_elems = n; - - va_list ap; - va_start(ap, n); - for (int i = 0; i < n; ++i) - { - struct node *nn = va_arg(ap, struct node *); - nd->elems[i] = nn; - } - va_end(ap); - - n_nodes++; - return nd; -} - -Node -mk_atom(ast_opcode_t op, const char *value) -{ - return value == NULL ? - mk_empty_atom(op) : - mk_node_value(op, xstrdup(value), 0); -} - -Node -mk_empty_atom(ast_opcode_t op) -{ - return mk_node_value(op, NULL, 0); -} - -Node -mk_none() -{ - return mk_atom(NN_NONE, NULL); -} - -Node -ext_node(Node nd, int n, ...) -{ - int c = nd->n_elems + n; - unsigned sz = sizeof(struct node) + (c * sizeof(struct node *)); - - if (nd->next) { - nd->next->prev = nd->prev; - } - if (nd->prev) { - nd->prev->next = nd->next; - } - nd = (struct node*)xrealloc(nd, sz); - nd->prev = NULL; - nd->next = nodes; - nodes->prev = nd; - nodes = nd; - - va_list ap; - va_start(ap, n); - for (int i = 0; i < n; ++i) { - struct node* nn = va_arg(ap, struct node *); - nd->elems[nd->n_elems++] = nn; - } - va_end(ap); - - return nd; -} - - -void -print_indent(int depth) { - while (depth) { - if (depth-- % indent_step == 0) { - printf("|"); - } else { - printf(" "); - } - } -} - -void -print_node(Node n, int depth) -{ - print_indent(depth); - - if (n->n_elems == 0) { - printf("%s -> %s\n", NODE_TYPE_STR(n), NODE_TYPE_VALUE_STR(n)); - return; - } - - printf("(%s\n", NODE_TYPE_STR(n)); - for (int i = 0; i < n->n_elems; ++i) { - print_node(n->elems[i], depth + indent_step); - } - print_indent(depth); - printf(")\n"); -} - -const char* -get_ast_op_string(ast_opcode_t op) -{ - switch (op) { - case NN_ViewItemExternFn: - return "NN_ViewItemExternFn"; - case NN_TyParam: - return "NN_TyParam"; - case NN_DeclLocal: - return "NN_DeclLocal"; - case NN_DocComment: - return "NN_DocComment"; - case NN_WherePredicate: - return "NN_WherePredicate"; - case NN_ExprAddrOf: - return "NN_ExprAddrOf"; - case NN_TypeMethod: - return "NN_TypeMethod"; - case NN_crate: - return "NN_crate"; - case NN_DefaultFieldInit: - return "NN_DefaultFieldInit"; - case NN_ExprBinary: - return "NN_ExprBinary"; - case NN_ExprAssignBitAnd: - return "NN_ExprAssignBitAnd"; - case NN_TyFnDecl: - return "NN_TyFnDecl"; - case NN_Public: - return "NN_Public"; - case NN_Pats: - return "NN_Pats"; - case NN_ViewPathSimple: - return "NN_ViewPathSimple"; - case NN_TyParams: - return "NN_TyParams"; - case NN_ExprIf: - return "NN_ExprIf"; - case NN_Args: - return "NN_Args"; - case NN_MetaItems: - return "NN_MetaItems"; - case NN_AttrsAndVis: - return "NN_AttrsAndVis"; - case NN_LitInteger: - return "NN_LitInteger"; - case NN_ExprPath: - return "NN_ExprPath"; - case NN_ExprField: - return "NN_ExprField"; - case NN_TyDefault: - return "NN_TyDefault"; - case NN_ExprAssignAdd: - return "NN_ExprAssignAdd"; - case NN_ExprYield: - return "NN_ExprYield"; - case NN_ImplItems: - return "NN_ImplItems"; - case NN_TyRptr: - return "NN_TyRptr"; - case NN_TySum: - return "NN_TySum"; - case NN_ExprAssignDiv: - return "NN_ExprAssignDiv"; - case NN_PatTup: - return "NN_PatTup"; - case NN_ViewPath: - return "NN_ViewPath"; - case NN_ItemImplNeg: - return "NN_ItemImplNeg"; - case NN_ExprWhile: - return "NN_ExprWhile"; - case NN_WherePredicates: - return "NN_WherePredicates"; - case NN_FieldInits: - return "NN_FieldInits"; - case NN_PatQualifiedPath: - return "NN_PatQualifiedPath"; - case NN_ExprMatch: - return "NN_ExprMatch"; - case NN_Binding: - return "NN_Binding"; - case NN_ExprAssignBitOr: - return "NN_ExprAssignBitOr"; - case NN_ItemImpl: - return "NN_ItemImpl"; - case NN_ForeignItem: - return "NN_ForeignItem"; - case NN_Arg: - return "NN_Arg"; - case NN_Bindings: - return "NN_Bindings"; - case NN_PatWild: - return "NN_PatWild"; - case NN_ExprTypeAscr: - return "NN_ExprTypeAscr"; - case NN_ExprBreak: - return "NN_ExprBreak"; - case NN_ExprIfLet: - return "NN_ExprIfLet"; - case NN_Inherited: - return "NN_Inherited"; - case NN_TyPtr: - return "NN_TyPtr"; - case NN_Arms: - return "NN_Arms"; - case NN_LitByteStr: - return "NN_LitByteStr"; - case NN_ItemConst: - return "NN_ItemConst"; - case NN_ItemImplDefault: - return "NN_ItemImplDefault"; - case NN_VecRepeat: - return "NN_VecRepeat"; - case NN_TTTok: - return "NN_TTTok"; - case NN_RetTy: - return "NN_RetTy"; - case NN_TySumsAndBindings: - return "NN_TySumsAndBindings"; - case NN_MetaList: - return "NN_MetaList"; - case NN_ExprQualifiedPath: - return "NN_ExprQualifiedPath"; - case NN_ExprAssignBitXor: - return "NN_ExprAssignBitXor"; - case NN_Macro: - return "NN_Macro"; - case NN_Super: - return "NN_Super"; - case NN_ForeignFn: - return "NN_ForeignFn"; - case NN_SelfLower: - return "NN_SelfLower"; - case NN_ExprAssign: - return "NN_ExprAssign"; - case NN_OuterAttrs: - return "NN_OuterAttrs"; - case NN_ItemMacro: - return "NN_ItemMacro"; - case NN_ForeignItems: - return "NN_ForeignItems"; - case NN_Items: - return "NN_Items"; - case NN_TraitMacroItem: - return "NN_TraitMacroItem"; - case NN_ExprWhileLet: - return "NN_ExprWhileLet"; - case NN_BindByRef: - return "NN_BindByRef"; - case NN_ImplType: - return "NN_ImplType"; - case NN_ExprLoop: - return "NN_ExprLoop"; - case NN_SelfRegion: - return "NN_SelfRegion"; - case NN_TyTup: - return "NN_TyTup"; - case NN_PatUnit: - return "NN_PatUnit"; - case NN_ForInType: - return "NN_ForInType"; - case NN_FnDecl: - return "NN_FnDecl"; - case NN_PatUniq: - return "NN_PatUniq"; - case NN_UnsafeBlock: - return "NN_UnsafeBlock"; - case NN_TyQualifiedPath: - return "NN_TyQualifiedPath"; - case NN_TyBox: - return "NN_TyBox"; - case NN_PatEnum: - return "NN_PatEnum"; - case NN_TyClosure: - return "NN_TyClosure"; - case NN_ForSized: - return "NN_ForSized"; - case NN_ExprAssignSub: - return "NN_ExprAssignSub"; - case NN_GenericValues: - return "NN_GenericValues"; - case NN_TyPath: - return "NN_TyPath"; - case NN_PatIdent: - return "NN_PatIdent"; - case NN_ConstDefault: - return "NN_ConstDefault"; - case NN_WhereClause: - return "NN_WhereClause"; - case NN_MutImmutable: - return "NN_MutImmutable"; - case NN_TyMacro: - return "NN_TyMacro"; - case NN_ExprTupleIndex: - return "NN_ExprTupleIndex"; - case NN_ImplMacroItem: - return "NN_ImplMacroItem"; - case NN_ExprTry: - return "NN_ExprTry"; - case NN_ExprCast: - return "NN_ExprCast"; - case NN_Provided: - return "NN_Provided"; - case NN_PatRegion: - return "NN_PatRegion"; - case NN_ExprAssignShl: - return "NN_ExprAssignShl"; - case NN_static_lifetime: - return "NN_static_lifetime"; - case NN_MetaNameValue: - return "NN_MetaNameValue"; - case NN_ExprStruct: - return "NN_ExprStruct"; - case NN_ExprAssignShr: - return "NN_ExprAssignShr"; - case NN_FieldInit: - return "NN_FieldInit"; - case NN_Generics: - return "NN_Generics"; - case NN_ExprForLoop: - return "NN_ExprForLoop"; - case NN_Method: - return "NN_Method"; - case NN_TySums: - return "NN_TySums"; - case NN_ExprVec: - return "NN_ExprVec"; - case NN_LitChar: - return "NN_LitChar"; - case NN_PatFields: - return "NN_PatFields"; - case NN_PatMac: - return "NN_PatMac"; - case NN_InnerAttr: - return "NN_InnerAttr"; - case NN_ViewPathGlob: - return "NN_ViewPathGlob"; - case NN_ItemStatic: - return "NN_ItemStatic"; - case NN_PatRange: - return "NN_PatRange"; - case NN_LitBool: - return "NN_LitBool"; - case NN_IdentsOrSelf: - return "NN_IdentsOrSelf"; - case NN_ItemFn: - return "NN_ItemFn"; - case NN_ExprCall: - return "NN_ExprCall"; - case NN_Default: - return "NN_Default"; - case NN_trait: - return "NN_trait"; - case NN_Required: - return "NN_Required"; - case NN_TyInfer: - return "NN_TyInfer"; - case NN_ConstTraitItem: - return "NN_ConstTraitItem"; - case NN_SelfStatic: - return "NN_SelfStatic"; - case NN_ExprAssignRem: - return "NN_ExprAssignRem"; - case NN_PatLit: - return "NN_PatLit"; - case NN_PatField: - return "NN_PatField"; - case NN_TyNil: - return "NN_TyNil"; - case NN_EnumDef: - return "NN_EnumDef"; - case NN_TypeTraitItem: - return "NN_TypeTraitItem"; - case NN_PatVec: - return "NN_PatVec"; - case NN_ident: - return "NN_ident"; - case NN_MetaWord: - return "NN_MetaWord"; - case NN_Lifetimes: - return "NN_Lifetimes"; - case NN_LitStr: - return "NN_LitStr"; - case NN_SelfPath: - return "NN_SelfPath"; - case NN_bounds: - return "NN_bounds"; - case NN_EnumDefs: - return "NN_EnumDefs"; - case NN_ltbounds: - return "NN_ltbounds"; - case NN_ViewItemUse: - return "NN_ViewItemUse"; - case NN_ItemImplDefaultNeg: - return "NN_ItemImplDefaultNeg"; - case NN_PatVecElts: - return "NN_PatVecElts"; - case NN_TokenTrees: - return "NN_TokenTrees"; - case NN_semicolon: - return "NN_semicolon"; - case NN_ItemMod: - return "NN_ItemMod"; - case NN_ExprUnary: - return "NN_ExprUnary"; - case NN_ExprBlock: - return "NN_ExprBlock"; - case NN_ItemUnsafeFn: - return "NN_ItemUnsafeFn"; - case NN_EnumArgs: - return "NN_EnumArgs"; - case NN_ViewItemExternCrate: - return "NN_ViewItemExternCrate"; - case NN_lifetime: - return "NN_lifetime"; - case NN_StructFields: - return "NN_StructFields"; - case NN_ExprRet: - return "NN_ExprRet"; - case NN_ExprAssignMul: - return "NN_ExprAssignMul"; - case NN_ItemStruct: - return "NN_ItemStruct"; - case NN_LitFloat: - return "NN_LitFloat"; - case NN_TyTypeof: - return "NN_TyTypeof"; - case NN_exprs: - return "NN_exprs"; - case NN_InnerAttrs: - return "NN_InnerAttrs"; - case NN_PolyBound: - return "NN_PolyBound"; - case NN_TyVec: - return "NN_TyVec"; - case NN_ArmNonblock: - return "NN_ArmNonblock"; - case NN_ViewPathList: - return "NN_ViewPathList"; - case NN_TTDelim: - return "NN_TTDelim"; - case NN_ItemForeignMod: - return "NN_ItemForeignMod"; - case NN_PatTupElts: - return "NN_PatTupElts"; - case NN_ExprMac: - return "NN_ExprMac"; - case NN_ExprParen: - return "NN_ExprParen"; - case NN_StaticItem: - return "NN_StaticItem"; - case NN_ItemTrait: - return "NN_ItemTrait"; - case NN_ExprRange: - return "NN_ExprRange"; - case NN_ItemUnion: - return "NN_ItemUnion"; - case NN_ExprIndex: - return "NN_ExprIndex"; - case NN_ArmBlock: - return "NN_ArmBlock"; - case NN_DefaultUnsafe: - return "NN_DefaultUnsafe"; - case NN_PatStruct: - return "NN_PatStruct"; - case NN_MutMutable: - return "NN_MutMutable"; - case NN_ExprLit: - return "NN_ExprLit"; - case NN_TyFixedLengthVec: - return "NN_TyFixedLengthVec"; - case NN_ImplConst: - return "NN_ImplConst"; - case NN_InferrableParams: - return "NN_InferrableParams"; - case NN_Item: - return "NN_Item"; - case NN_TraitItems: - return "NN_TraitItems"; - case NN_MacroExpr: - return "NN_MacroExpr"; - case NN_LitByte: - return "NN_LitByte"; - case NN_InferrableParam: - return "NN_InferrableParam"; - case NN_BindByValue: - return "NN_BindByValue"; - case NN_StructField: - return "NN_StructField"; - case NN_Unsafe: - return "NN_Unsafe"; - case NN_ViewPathListEmpty: - return "NN_ViewPathListEmpty"; - case NN_ExprFnBlock: - return "NN_ExprFnBlock"; - case NN_ExprAgain: - return "NN_ExprAgain"; - case NN_components: - return "NN_components"; - case NN_ItemEnum: - return "NN_ItemEnum"; - case NN_ExprBox: - return "NN_ExprBox"; - case NN_ItemTy: - return "NN_ItemTy"; - case NN_NONE: - return "NN_NONE"; - case NN_SHL: - return "NN_SHL"; - case NN_SHR: - return "NN_SHR"; - case NN_LE: - return "NN_LE"; - case NN_EQEQ: - return "NN_EQEQ"; - case NN_NE: - return "NN_NE"; - case NN_GE: - return "NN_GE"; - case NN_ANDAND: - return "NN_ANDAND"; - case NN_OROR: - return "NN_OROR"; - case NN_LARROW: - return "NN_LARROW"; - case NN_SHLEQ: - return "NN_SHLEQ"; - case NN_SHREQ: - return "NN_SHREQ"; - case NN_MINUSEQ: - return "NN_MINUSEQ"; - case NN_ANDEQ: - return "NN_ANDEQ"; - case NN_OREQ: - return "NN_OREQ"; - case NN_PLUSEQ: - return "NN_PLUSEQ"; - case NN_STAREQ: - return "NN_STAREQ"; - case NN_SLASHEQ: - return "NN_SLASHEQ"; - case NN_CARETEQ: - return "NN_CARETEQ"; - case NN_PERCENTEQ: - return "NN_PERCENTEQ"; - case NN_DOTDOT: - return "NN_DOTDOT"; - case NN_DOTDOTDOT: - return "NN_DOTDOTDOT"; - case NN_MOD_SEP: - return "NN_MOD_SEP"; - case NN_RARROW: - return "NN_RARROW"; - case NN_FAT_ARROW: - return "NN_FAT_ARROW"; - case NN_LIT_BYTE: - return "NN_LIT_BYTE"; - case NN_LIT_CHAR: - return "NN_LIT_CHAR"; - case NN_LIT_INTEGER: - return "NN_LIT_INTEGER"; - case NN_LIT_FLOAT: - return "NN_LIT_FLOAT"; - case NN_LIT_STR: - return "NN_LIT_STR"; - case NN_LIT_STR_RAW: - return "NN_LIT_STR_RAW"; - case NN_LIT_BYTE_STR: - return "NN_LIT_BYTE_STR"; - case NN_LIT_BYTE_STR_RAW: - return "NN_LIT_BYTE_STR_RAW"; - case NN_IDENT: - return "NN_IDENT"; - case NN_UNDERSCORE: - return "NN_UNDERSCORE"; - case NN_LIFETIME: - return "NN_LIFETIME"; - case NN_SELF: - return "NN_SELF"; - case NN_STATIC: - return "NN_STATIC"; - case NN_ABSTRACT: - return "NN_ABSTRACT"; - case NN_ALIGNOF: - return "NN_ALIGNOF"; - case NN_AS: - return "NN_AS"; - case NN_BECOME: - return "NN_BECOME"; - case NN_BREAK: - return "NN_BREAK"; - case NN_CATCH: - return "NN_CATCH"; - case NN_CRATE: - return "NN_CRATE"; - case NN_DEFAULT: - return "NN_DEFAULT"; - case NN_DO: - return "NN_DO"; - case NN_ELSE: - return "NN_ELSE"; - case NN_ENUM: - return "NN_ENUM"; - case NN_EXTERN: - return "NN_EXTERN"; - case NN_XFALSE: - return "NN_XFALSE"; - case NN_FINAL: - return "NN_FINAL"; - case NN_FN: - return "NN_FN"; - case NN_FOR: - return "NN_FOR"; - case NN_IF: - return "NN_IF"; - case NN_IMPL: - return "NN_IMPL"; - case NN_IN: - return "NN_IN"; - case NN_LET: - return "NN_LET"; - case NN_LOOP: - return "NN_LOOP"; - case NN_MACRO: - return "NN_MACRO"; - case NN_MATCH: - return "NN_MATCH"; - case NN_MOD: - return "NN_MOD"; - case NN_MOVE: - return "NN_MOVE"; - case NN_MUT: - return "NN_MUT"; - case NN_OFFSETOF: - return "NN_OFFSETOF"; - case NN_OVERRIDE: - return "NN_OVERRIDE"; - case NN_PRIV: - return "NN_PRIV"; - case NN_PUB: - return "NN_PUB"; - case NN_PURE: - return "NN_PURE"; - case NN_REF: - return "NN_REF"; - case NN_RETURN: - return "NN_RETURN"; - case NN_STRUCT: - return "NN_STRUCT"; - case NN_SIZEOF: - return "NN_SIZEOF"; - case NN_SUPER: - return "NN_SUPER"; - case NN_XTRUE: - return "NN_XTRUE"; - case NN_TRAIT: - return "NN_TRAIT"; - case NN_TYPE: - return "NN_TYPE"; - case NN_UNION: - return "NN_UNION"; - case NN_UNSAFE: - return "NN_UNSAFE"; - case NN_UNSIZED: - return "NN_UNSIZED"; - case NN_USE: - return "NN_USE"; - case NN_VIRTUAL: - return "NN_VIRTUAL"; - case NN_WHILE: - return "NN_WHILE"; - case NN_YIELD: - return "NN_YIELD"; - case NN_CONTINUE: - return "NN_CONTINUE"; - case NN_PROC: - return "NN_PROC"; - case NN_BOX: - return "NN_BOX"; - case NN_CONST: - return "NN_CONST"; - case NN_WHERE: - return "NN_WHERE"; - case NN_TYPEOF: - return "NN_TYPEOF"; - case NN_INNER_DOC_COMMENT: - return "NN_INNER_DOC_COMMENT"; - case NN_OUTER_DOC_COMMENT: - return "NN_OUTER_DOC_COMMENT"; - case NN_SHEBANG: - return "NN_SHEBANG"; - case NN_STATIC_LIFETIME: - return "NN_STATIC_LIFETIME"; - case NN_SEMI_COLON: - return "NN_SEMI_COLON"; - case NN_COMMA: - return "NN_COMMA"; - case NN_SINGLE_DOT: - return "NN_SINGLE_DOT"; - case NN_AT: - return "NN_AT"; - case NN_HASH: - return "NN_HASH"; - case NN_TILDA: - return "NN_TILDA"; - case NN_COLON: - return "NN_COLON"; - case NN_DOLLAR: - return "NN_DOLLAR"; - case NN_EQUALS: - return "NN_EQUALS"; - case NN_QUESTION: - return "NN_QUESTION"; - case NN_EXCLAIM: - return "NN_EXCLAIM"; - case NN_LESS_THAN: - return "NN_LESS_THAN"; - case NN_GREATER_THAN: - return "NN_GREATER_THAN"; - case NN_MINUS: - return "NN_MINUS"; - case NN_AMPERSAND: - return "NN_AMPERSAND"; - case NN_PIPE: - return "NN_PIPE"; - case NN_PLUS: - return "NN_PLUS"; - case NN_MULT: - return "NN_MULT"; - case NN_DIVIDE: - return "NN_DIVIDE"; - case NN_HAT: - return "NN_HAT"; - case NN_PERCENTAGE: - return "NN_PERCENTAGE"; - case NN_GLOBAL: - return "NN_GLOBAL"; - case NN_stmts: - return "NN_stmts"; - case NN_BiOr: - return "NN_BiOr"; - case NN_BiAnd: - return "NN_BiAnd"; - case NN_BiEq: - return "NN_BiEq"; - case NN_BiNe: - return "NN_BiNe"; - case NN_BiLt: - return "NN_BiLt"; - case NN_BiGt: - return "NN_BiGt"; - case NN_BiLe: - return "NN_BiLe"; - case NN_BiGe: - return "NN_BiGe"; - case NN_BiBitOr: - return "NN_BiBitOr"; - case NN_BiBitXor: - return "NN_BiBitXor"; - case NN_BiBitAnd: - return "NN_BiBitAnd"; - case NN_BiShl: - return "NN_BiShl"; - case NN_BiShr: - return "NN_BiShr"; - case NN_BiAdd: - return "NN_BiAdd"; - case NN_BiSub: - return "NN_BiSub"; - case NN_BiMul: - return "NN_BiMul"; - case NN_BiDiv: - return "NN_BiDiv"; - case NN_BiRem: - return "NN_BiRem"; - case NN_UnNeg: - return "NN_UnNeg"; - case NN_UnNot: - return "NN_UnNot"; - case NN_UnDeref: - return "NN_UnDeref"; - } - return NULL; -} diff --git a/gcc/rust/rustfrontend/node.h b/gcc/rust/rustfrontend/node.h deleted file mode 100644 index 7d83c2d..0000000 --- a/gcc/rust/rustfrontend/node.h +++ /dev/null @@ -1,378 +0,0 @@ -#pragma once - -#include - -typedef enum { - NN_ViewItemExternFn, - NN_TyParam, - NN_DeclLocal, - NN_DocComment, - NN_WherePredicate, - NN_ExprAddrOf, - NN_TypeMethod, - NN_crate, - NN_DefaultFieldInit, - NN_ExprBinary, - NN_ExprAssignBitAnd, - NN_TyFnDecl, - NN_Public, - NN_Pats, - NN_ViewPathSimple, - NN_TyParams, - NN_ExprIf, - NN_Args, - NN_MetaItems, - NN_AttrsAndVis, - NN_LitInteger, - NN_ExprPath, - NN_ExprField, - NN_TyDefault, - NN_ExprAssignAdd, - NN_ExprYield, - NN_ImplItems, - NN_TyRptr, - NN_TySum, - NN_ExprAssignDiv, - NN_PatTup, - NN_ViewPath, - NN_ItemImplNeg, - NN_ExprWhile, - NN_WherePredicates, - NN_FieldInits, - NN_PatQualifiedPath, - NN_ExprMatch, - NN_Binding, - NN_ExprAssignBitOr, - NN_ItemImpl, - NN_ForeignItem, - NN_Arg, - NN_Bindings, - NN_PatWild, - NN_ExprTypeAscr, - NN_ExprBreak, - NN_ExprIfLet, - NN_Inherited, - NN_TyPtr, - NN_Arms, - NN_LitByteStr, - NN_ItemConst, - NN_ItemImplDefault, - NN_VecRepeat, - NN_TTTok, - NN_RetTy, - NN_TySumsAndBindings, - NN_MetaList, - NN_ExprQualifiedPath, - NN_ExprAssignBitXor, - NN_Macro, - NN_Super, - NN_ForeignFn, - NN_SelfLower, - NN_ExprAssign, - NN_OuterAttrs, - NN_ItemMacro, - NN_ForeignItems, - NN_Items, - NN_TraitMacroItem, - NN_ExprWhileLet, - NN_BindByRef, - NN_ImplType, - NN_ExprLoop, - NN_SelfRegion, - NN_TyTup, - NN_PatUnit, - NN_ForInType, - NN_FnDecl, - NN_PatUniq, - NN_UnsafeBlock, - NN_TyQualifiedPath, - NN_TyBox, - NN_PatEnum, - NN_TyClosure, - NN_ForSized, - NN_ExprAssignSub, - NN_GenericValues, - NN_TyPath, - NN_PatIdent, - NN_ConstDefault, - NN_WhereClause, - NN_MutImmutable, - NN_TyMacro, - NN_ExprTupleIndex, - NN_ImplMacroItem, - NN_ExprTry, - NN_ExprCast, - NN_Provided, - NN_PatRegion, - NN_ExprAssignShl, - NN_static_lifetime, - NN_MetaNameValue, - NN_ExprStruct, - NN_ExprAssignShr, - NN_FieldInit, - NN_Generics, - NN_ExprForLoop, - NN_Method, - NN_TySums, - NN_ExprVec, - NN_LitChar, - NN_PatFields, - NN_PatMac, - NN_InnerAttr, - NN_ViewPathGlob, - NN_ItemStatic, - NN_PatRange, - NN_LitBool, - NN_IdentsOrSelf, - NN_ItemFn, - NN_ExprCall, - NN_Default, - NN_trait, - NN_Required, - NN_TyInfer, - NN_ConstTraitItem, - NN_SelfStatic, - NN_ExprAssignRem, - NN_PatLit, - NN_PatField, - NN_TyNil, - NN_EnumDef, - NN_TypeTraitItem, - NN_PatVec, - NN_ident, - NN_MetaWord, - NN_Lifetimes, - NN_LitStr, - NN_SelfPath, - NN_bounds, - NN_EnumDefs, - NN_ltbounds, - NN_ViewItemUse, - NN_ItemImplDefaultNeg, - NN_PatVecElts, - NN_TokenTrees, - NN_semicolon, - NN_ItemMod, - NN_ExprUnary, - NN_ExprBlock, - NN_ItemUnsafeFn, - NN_EnumArgs, - NN_ViewItemExternCrate, - NN_lifetime, - NN_StructFields, - NN_ExprRet, - NN_ExprAssignMul, - NN_ItemStruct, - NN_LitFloat, - NN_TyTypeof, - NN_exprs, - NN_InnerAttrs, - NN_PolyBound, - NN_TyVec, - NN_ArmNonblock, - NN_ViewPathList, - NN_TTDelim, - NN_ItemForeignMod, - NN_PatTupElts, - NN_ExprMac, - NN_ExprParen, - NN_StaticItem, - NN_ItemTrait, - NN_ExprRange, - NN_ItemUnion, - NN_ExprIndex, - NN_ArmBlock, - NN_DefaultUnsafe, - NN_PatStruct, - NN_MutMutable, - NN_ExprLit, - NN_TyFixedLengthVec, - NN_ImplConst, - NN_InferrableParams, - NN_Item, - NN_TraitItems, - NN_MacroExpr, - NN_LitByte, - NN_InferrableParam, - NN_BindByValue, - NN_StructField, - NN_Unsafe, - NN_ViewPathListEmpty, - NN_ExprFnBlock, - NN_ExprAgain, - NN_components, - NN_ItemEnum, - NN_ExprBox, - NN_ItemTy, - NN_NONE, - NN_SHL, - NN_SHR, - NN_LE, - NN_EQEQ, - NN_NE, - NN_GE, - NN_ANDAND, - NN_OROR, - NN_LARROW, - NN_SHLEQ, - NN_SHREQ, - NN_MINUSEQ, - NN_ANDEQ, - NN_OREQ, - NN_PLUSEQ, - NN_STAREQ, - NN_SLASHEQ, - NN_CARETEQ, - NN_PERCENTEQ, - NN_DOTDOT, - NN_DOTDOTDOT, - NN_MOD_SEP, - NN_RARROW, - NN_FAT_ARROW, - NN_LIT_BYTE, - NN_LIT_CHAR, - NN_LIT_INTEGER, - NN_LIT_FLOAT, - NN_LIT_STR, - NN_LIT_STR_RAW, - NN_LIT_BYTE_STR, - NN_LIT_BYTE_STR_RAW, - NN_IDENT, - NN_UNDERSCORE, - NN_LIFETIME, - NN_SELF, - NN_STATIC, - NN_ABSTRACT, - NN_ALIGNOF, - NN_AS, - NN_BECOME, - NN_BREAK, - NN_CATCH, - NN_CRATE, - NN_DEFAULT, - NN_DO, - NN_ELSE, - NN_ENUM, - NN_EXTERN, - NN_XFALSE, - NN_FINAL, - NN_FN, - NN_FOR, - NN_IF, - NN_IMPL, - NN_IN, - NN_LET, - NN_LOOP, - NN_MACRO, - NN_MATCH, - NN_MOD, - NN_MOVE, - NN_MUT, - NN_OFFSETOF, - NN_OVERRIDE, - NN_PRIV, - NN_PUB, - NN_PURE, - NN_REF, - NN_RETURN, - NN_STRUCT, - NN_SIZEOF, - NN_SUPER, - NN_XTRUE, - NN_TRAIT, - NN_TYPE, - NN_UNION, - NN_UNSAFE, - NN_UNSIZED, - NN_USE, - NN_VIRTUAL, - NN_WHILE, - NN_YIELD, - NN_CONTINUE, - NN_PROC, - NN_BOX, - NN_CONST, - NN_WHERE, - NN_TYPEOF, - NN_INNER_DOC_COMMENT, - NN_OUTER_DOC_COMMENT, - NN_SHEBANG, - NN_STATIC_LIFETIME, - NN_SEMI_COLON, - NN_COMMA, - NN_SINGLE_DOT, - NN_AT, - NN_HASH, - NN_TILDA, - NN_COLON, - NN_DOLLAR, - NN_EQUALS, - NN_QUESTION, - NN_EXCLAIM, - NN_LESS_THAN, - NN_GREATER_THAN, - NN_MINUS, - NN_AMPERSAND, - NN_PIPE, - NN_PLUS, - NN_MULT, - NN_DIVIDE, - NN_HAT, - NN_PERCENTAGE, - NN_GLOBAL, - NN_stmts, - - NN_BiOr, - NN_BiAnd, - NN_BiEq, - NN_BiNe, - NN_BiLt, - NN_BiGt, - NN_BiLe, - NN_BiGe, - NN_BiBitOr, - NN_BiBitXor, - NN_BiBitAnd, - NN_BiShl, - NN_BiShr, - NN_BiAdd, - NN_BiSub, - NN_BiMul, - NN_BiDiv, - NN_BiRem, - NN_UnNeg, - NN_UnNot, - NN_UnDeref -} ast_opcode_t; - -typedef struct node { - ast_opcode_t op; - char* value; - - struct node* next; - struct node* prev; - - int n_elems; - struct node** elems; -} *Node; - -#define NODE_TYPE(x_) x_->op -#define NODE_TYPE_STR(x_) get_ast_op_string(x_->op) -#define NODE_TYPE_VALUE_STR(x_) (n->value == NULL ? "NULL" : n->value) -#define NODE_CHAIN(x_) (x_->next) -#define NODE_RCHAIN(x_) (x_->prev) - -extern Node mk_node(ast_opcode_t, int n, ...); -extern Node mk_node_value(ast_opcode_t, char*, int n, ...); -extern Node mk_atom(ast_opcode_t, const char *value); -extern Node mk_empty_atom(ast_opcode_t); -extern Node mk_none(); -extern Node ext_node(struct node *nd, int n, ...); -extern void print_node(Node n, int depth); -extern const char* get_ast_op_string(ast_opcode_t); - -extern void push_back(char); -extern void parser_init(int verbose); - -extern int n_nodes; -extern node* nodes; diff --git a/gcc/rust/rustfrontend/operator.h b/gcc/rust/rustfrontend/operator.h deleted file mode 100644 index 2ada147..0000000 --- a/gcc/rust/rustfrontend/operator.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -enum Operator -{ - OPERATOR_INVALID, - OPERATOR_OROR, // || - OPERATOR_ANDAND, // && - OPERATOR_EQEQ, // == - OPERATOR_NOTEQ, // != - OPERATOR_LT, // < - OPERATOR_LE, // <= - OPERATOR_GT, // > - OPERATOR_GE, // >= - OPERATOR_PLUS, // + - OPERATOR_MINUS, // - - OPERATOR_OR, // | - OPERATOR_XOR, // ^ - OPERATOR_MULT, // * - OPERATOR_DIV, // / - OPERATOR_MOD, // % - OPERATOR_LSHIFT, // << - OPERATOR_RSHIFT, // >> - OPERATOR_AND, // & - OPERATOR_NOT, // ! - OPERATOR_BITCLEAR, // &^ - OPERATOR_CHANOP, // <- - - OPERATOR_EQ, // = - OPERATOR_PLUSEQ, // += - OPERATOR_MINUSEQ, // -= - OPERATOR_OREQ, // |= - OPERATOR_XOREQ, // ^= - OPERATOR_MULTEQ, // *= - OPERATOR_DIVEQ, // /= - OPERATOR_MODEQ, // %= - OPERATOR_LSHIFTEQ, // <<= - OPERATOR_RSHIFTEQ, // >>= - OPERATOR_ANDEQ, // &= - OPERATOR_BITCLEAREQ, // &^= - OPERATOR_PLUSPLUS, // ++ - OPERATOR_MINUSMINUS, // -- - - OPERATOR_COLON, // : - OPERATOR_COLONEQ, // := - OPERATOR_SEMICOLON, // ; - OPERATOR_DOT, // . - OPERATOR_ELLIPSIS, // ... - OPERATOR_COMMA, // , - OPERATOR_LPAREN, // ( - OPERATOR_RPAREN, // ) - OPERATOR_LCURLY, // { - OPERATOR_RCURLY, // } - OPERATOR_LSQUARE, // [ - OPERATOR_RSQUARE // ] -}; diff --git a/gcc/rust/rustfrontend/rs-lexer.l b/gcc/rust/rustfrontend/rs-lexer.l deleted file mode 100644 index 76bbed3..0000000 --- a/gcc/rust/rustfrontend/rs-lexer.l +++ /dev/null @@ -1,350 +0,0 @@ -%{ -#include "rs-parser.h" - -static int num_hashes; -static int end_hashes; -static int saw_non_hash; -%} - -%option noyywrap -%option stack -%option yylineno - -%x str -%x rawstr -%x rawstr_esc_begin -%x rawstr_esc_body -%x rawstr_esc_end -%x byte -%x bytestr -%x rawbytestr -%x rawbytestr_nohash -%x pound -%x shebang_or_attr -%x ltorchar -%x linecomment -%x doc_line -%x blockcomment -%x doc_block -%x suffix - -ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]* - -%% - -{ident} { BEGIN(INITIAL); } -(.|\n) { yyless(0); BEGIN(INITIAL); } - -[ \n\t\r] { } - -\xef\xbb\xbf { - // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise - if (yyget_lineno() != 1) { - return -1; - } -} - -\/\/(\/|\!) { BEGIN(doc_line); yymore(); } -\n { BEGIN(INITIAL); - yyleng--; - yytext[yyleng] = 0; - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -[^\n]* { yymore(); } - -\/\/|\/\/\/\/ { BEGIN(linecomment); } -\n { BEGIN(INITIAL); } -[^\n]* { } - -\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } -\/\* { yy_push_state(doc_block); yymore(); } -\*\/ { - yy_pop_state(); - if (yy_top_state() == doc_block) { - yymore(); - } else { - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -} -(.|\n) { yymore(); } - -\/\* { yy_push_state(blockcomment); } -\/\* { yy_push_state(blockcomment); } -\*\/ { yy_pop_state(); } -(.|\n) { } - -_ { return UNDERSCORE; } -abstract { return ABSTRACT; } -alignof { return ALIGNOF; } -as { return AS; } -become { return BECOME; } -box { return BOX; } -break { return BREAK; } -catch { return CATCH; } -const { return CONST; } -continue { return CONTINUE; } -crate { return CRATE; } -default { return DEFAULT; } -do { return DO; } -else { return ELSE; } -enum { return ENUM; } -extern { return EXTERN; } -false { return XFALSE; } -final { return FINAL; } -fn { return FN; } -for { return FOR; } -if { return IF; } -impl { return IMPL; } -in { return IN; } -let { return LET; } -loop { return LOOP; } -macro { return MACRO; } -match { return MATCH; } -mod { return MOD; } -move { return MOVE; } -mut { return MUT; } -offsetof { return OFFSETOF; } -override { return OVERRIDE; } -priv { return PRIV; } -proc { return PROC; } -pure { return PURE; } -pub { return PUB; } -ref { return REF; } -return { return RETURN; } -self { return SELF; } -sizeof { return SIZEOF; } -static { return STATIC; } -struct { return STRUCT; } -super { return SUPER; } -trait { return TRAIT; } -true { return XTRUE; } -type { return TYPE; } -typeof { return TYPEOF; } -union { return UNION; } -unsafe { return UNSAFE; } -unsized { return UNSIZED; } -use { return USE; } -virtual { return VIRTUAL; } -where { return WHERE; } -while { return WHILE; } -yield { return YIELD; } - -{ident} { return IDENT; } - -0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } -0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } - -[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; } -[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; } - -; { return ';'; } -, { return ','; } -\.\.\. { return DOTDOTDOT; } -\.\. { return DOTDOT; } -\. { return '.'; } -\( { return '('; } -\) { return ')'; } -\{ { return '{'; } -\} { return '}'; } -\[ { return '['; } -\] { return ']'; } -@ { return '@'; } -# { BEGIN(pound); yymore(); } -\! { BEGIN(shebang_or_attr); yymore(); } -\[ { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; -} -[^\[\n]*\n { - // Since the \n was eaten as part of the token, yylineno will have - // been incremented to the value 2 if the shebang was on the first - // line. This yyless undoes that, setting yylineno back to 1. - yyless(yyleng - 1); - if (yyget_lineno() == 1) { - BEGIN(INITIAL); - return SHEBANG_LINE; - } else { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; - } -} -. { BEGIN(INITIAL); yyless(1); return '#'; } - -\~ { return '~'; } -:: { return MOD_SEP; } -: { return ':'; } -\$ { return '$'; } -\? { return '?'; } - -== { return EQEQ; } -=> { return FAT_ARROW; } -= { return '='; } -\!= { return NE; } -\! { return '!'; } -\<= { return LE; } -\<\< { return SHL; } -\<\<= { return SHLEQ; } -\< { return '<'; } -\>= { return GE; } -\>\> { return SHR; } -\>\>= { return SHREQ; } -\> { return '>'; } - -\x27 { BEGIN(ltorchar); yymore(); } -static { BEGIN(INITIAL); return STATIC_LIFETIME; } -{ident} { BEGIN(INITIAL); return LIFETIME; } -\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } -\\u\{([0-9a-fA-F]_*){1,6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } -.\x27 { BEGIN(suffix); return LIT_CHAR; } -[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } -<> { BEGIN(INITIAL); return -1; } - -b\x22 { BEGIN(bytestr); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR; } - -<> { return -1; } -\\[n\nrt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -br\x22 { BEGIN(rawbytestr_nohash); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -br/# { - BEGIN(rawbytestr); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} -# { - if (!saw_non_hash) { - num_hashes++; - } else if (end_hashes != 0) { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - } - yymore(); -} -\x22# { - end_hashes = 1; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - yymore(); -} -(.|\n) { - if (!saw_non_hash) { - saw_non_hash = 1; - } - if (end_hashes != 0) { - end_hashes = 0; - } - yymore(); -} -<> { return -1; } - -b\x27 { BEGIN(byte); yymore(); } -\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\u([0-9a-fA-F]_*){4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\U([0-9a-fA-F]_*){8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -.\x27 { BEGIN(INITIAL); return LIT_BYTE; } -<> { BEGIN(INITIAL); return -1; } - -r\x22 { BEGIN(rawstr); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -r/# { - BEGIN(rawstr_esc_begin); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - -# { - num_hashes++; - yymore(); -} -\x22 { - BEGIN(rawstr_esc_body); - yymore(); -} -(.|\n) { return -1; } - -\x22/# { - BEGIN(rawstr_esc_end); - yymore(); - } -(.|\n) { - yymore(); - } - -# { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_STR_RAW; - } - yymore(); - } -[^#] { - end_hashes = 0; - BEGIN(rawstr_esc_body); - yymore(); - } - -<> { return -1; } - -\x22 { BEGIN(str); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR; } - -<> { return -1; } -\\[n\nr\rt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -\<- { return LARROW; } --\> { return RARROW; } -- { return '-'; } --= { return MINUSEQ; } -&& { return ANDAND; } -& { return '&'; } -&= { return ANDEQ; } -\|\| { return OROR; } -\| { return '|'; } -\|= { return OREQ; } -\+ { return '+'; } -\+= { return PLUSEQ; } -\* { return '*'; } -\*= { return STAREQ; } -\/ { return '/'; } -\/= { return SLASHEQ; } -\^ { return '^'; } -\^= { return CARETEQ; } -% { return '%'; } -%= { return PERCENTEQ; } - -<> { return 0; } - -%% - diff --git a/gcc/rust/rustfrontend/rs-parser.y b/gcc/rust/rustfrontend/rs-parser.y deleted file mode 100644 index 17fff37..0000000 --- a/gcc/rust/rustfrontend/rs-parser.y +++ /dev/null @@ -1,1977 +0,0 @@ -%{ -#include "rust-system.h" -#include "node.h" - -#define YYERROR_VERBOSE -#define YYSTYPE Node - -extern int yylineno; -extern char *yytext; -extern int yylex (void); -extern void yyerror (const char *); -%} - -// borrowed/stolen from rust-lang repo since removed in PR: -// https://github.com/rust-lang/rust/pull/64896/commits/96c8049b201fa0b87b8074e139921fbc33a2db1d - -%debug - -%token SHL -%token SHR -%token LE -%token EQEQ -%token NE -%token GE -%token ANDAND -%token OROR -%token SHLEQ -%token SHREQ -%token MINUSEQ -%token ANDEQ -%token OREQ -%token PLUSEQ -%token STAREQ -%token SLASHEQ -%token CARETEQ -%token PERCENTEQ -%token DOTDOT -%token DOTDOTDOT -%token MOD_SEP -%token RARROW -%token LARROW -%token FAT_ARROW -%token LIT_BYTE -%token LIT_CHAR -%token LIT_INTEGER -%token LIT_FLOAT -%token LIT_STR -%token LIT_STR_RAW -%token LIT_BYTE_STR -%token LIT_BYTE_STR_RAW -%token IDENT -%token UNDERSCORE -%token LIFETIME - -// keywords -%token SELF -%token STATIC -%token ABSTRACT -%token ALIGNOF -%token AS -%token BECOME -%token BREAK -%token CATCH -%token CRATE -%token DO -%token ELSE -%token ENUM -%token EXTERN -%token XFALSE -%token FINAL -%token FN -%token FOR -%token IF -%token IMPL -%token IN -%token LET -%token LOOP -%token MACRO -%token MATCH -%token MOD -%token MOVE -%token MUT -%token OFFSETOF -%token OVERRIDE -%token PRIV -%token PUB -%token PURE -%token REF -%token RETURN -%token SIZEOF -%token STRUCT -%token SUPER -%token UNION -%token UNSIZED -%token XTRUE -%token TRAIT -%token TYPE -%token UNSAFE -%token VIRTUAL -%token YIELD -%token DEFAULT -%token USE -%token WHILE -%token CONTINUE -%token PROC -%token BOX -%token CONST -%token WHERE -%token TYPEOF -%token INNER_DOC_COMMENT -%token OUTER_DOC_COMMENT - -%token SHEBANG -%token SHEBANG_LINE -%token STATIC_LIFETIME - - /* - Quoting from the Bison manual: - "Finally, the resolution of conflicts works by comparing the precedence - of the rule being considered with that of the lookahead token. If the - token's precedence is higher, the choice is to shift. If the rule's - precedence is higher, the choice is to reduce. If they have equal - precedence, the choice is made based on the associativity of that - precedence level. The verbose output file made by ‘-v’ (see Invoking - Bison) says how each conflict was resolved" - */ - -// We expect no shift/reduce or reduce/reduce conflicts in this grammar; -// all potential ambiguities are scrutinized and eliminated manually. -%expect 0 - -// fake-precedence symbol to cause '|' bars in lambda context to parse -// at low precedence, permit things like |x| foo = bar, where '=' is -// otherwise lower-precedence than '|'. Also used for proc() to cause -// things like proc() a + b to parse as proc() { a + b }. -%precedence LAMBDA - -%precedence SELF - -// MUT should be lower precedence than IDENT so that in the pat rule, -// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]" -%precedence MUT - -// IDENT needs to be lower than '{' so that 'foo {' is shifted when -// trying to decide if we've got a struct-construction expr (esp. in -// contexts like 'if foo { .') -// -// IDENT also needs to be lower precedence than '<' so that '<' in -// 'foo:bar . <' is shifted (in a trait reference occurring in a -// bounds list), parsing as foo:(bar) rather than (foo:bar). -%precedence IDENT - // Put the weak keywords that can be used as idents here as well -%precedence CATCH -%precedence DEFAULT -%precedence UNION - -// A couple fake-precedence symbols to use in rules associated with + -// and < in trailing type contexts. These come up when you have a type -// in the RHS of operator-AS, such as "foo as bar". The "<" there -// has to be shifted so the parser keeps trying to parse a type, even -// though it might well consider reducing the type "bar" and then -// going on to "<" as a subsequent binop. The "+" case is with -// trailing type-bounds ("foo as bar:A+B"), for the same reason. -%precedence SHIFTPLUS -%precedence MOD_SEP -%precedence RARROW ':' -// In where clauses, "for" should have greater precedence when used as -// a higher ranked constraint than when used as the beginning of a -// for_in_type (which is a ty) -%precedence FORTYPE -%precedence FOR -// Binops & unops, and their precedences -%precedence '?' -%precedence BOX -%nonassoc DOTDOT -// RETURN needs to be lower-precedence than tokens that start -// prefix_exprs -%precedence RETURN YIELD -%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ -%right LARROW -%left OROR -%left ANDAND -%left EQEQ NE -%left '<' '>' LE GE -%left '|' -%left '^' -%left '&' -%left SHL SHR -%left '+' '-' -%precedence AS -%left '*' '/' '%' -%precedence '!' - -%precedence '{' '[' '(' '.' - -%precedence RANGE - -%start crate - -%% - -/////////////////////////////////////////////////////////////////////// -// Part 1: Items and attributes -//////////////////////////////////////////////////////////////////////// - -crate -: maybe_shebang inner_attrs maybe_mod_items { mk_node(NN_crate, 2, $2, $3); } -| maybe_shebang maybe_mod_items { mk_node(NN_crate, 1, $2); } -; - -maybe_shebang -: SHEBANG_LINE -| %empty -; - -maybe_inner_attrs -: inner_attrs -| %empty { $$ = mk_none(); } -; - -inner_attrs -: inner_attr { $$ = mk_node(NN_InnerAttrs, 1, $1); } -| inner_attrs inner_attr { $$ = ext_node($1, 1, $2); } -; - -inner_attr -: SHEBANG '[' meta_item ']' { $$ = mk_node(NN_InnerAttr, 1, $3); } -| INNER_DOC_COMMENT { $$ = mk_node(NN_InnerAttr, 1, mk_atom(NN_INNER_DOC_COMMENT, yytext)); } -; - -maybe_outer_attrs -: outer_attrs -| %empty { $$ = mk_none(); } -; - -outer_attrs -: outer_attr { $$ = mk_node(NN_OuterAttrs, 1, $1); } -| outer_attrs outer_attr { $$ = ext_node($1, 1, $2); } -; - -outer_attr -: '#' '[' meta_item ']' { $$ = $3; } -| OUTER_DOC_COMMENT { $$ = mk_atom(NN_OUTER_DOC_COMMENT, yytext); } -; - -meta_item -: ident { $$ = mk_node(NN_MetaWord, 1, $1); } -| ident '=' lit { $$ = mk_node(NN_MetaNameValue, 2, $1, $3); } -| ident '(' meta_seq ')' { $$ = mk_node(NN_MetaList, 2, $1, $3); } -| ident '(' meta_seq ',' ')' { $$ = mk_node(NN_MetaList, 2, $1, $3); } -; - -meta_seq -: %empty { $$ = mk_none(); } -| meta_item { $$ = mk_node(NN_MetaItems, 1, $1); } -| meta_seq ',' meta_item { $$ = ext_node($1, 1, $3); } -; - -maybe_mod_items -: mod_items -| %empty { $$ = mk_none(); } -; - -mod_items -: mod_item { $$ = mk_node(NN_Items, 1, $1); } -| mod_items mod_item { $$ = ext_node($1, 1, $2); } -; - -attrs_and_vis -: maybe_outer_attrs visibility { $$ = mk_node(NN_AttrsAndVis, 2, $1, $2); } -; - -mod_item -: attrs_and_vis item { $$ = mk_node(NN_Item, 2, $1, $2); } -; - -// items that can appear outside of a fn block -item -: stmt_item -| item_macro -; - -// items that can appear in "stmts" -stmt_item -: item_static -| item_const -| item_type -| block_item -| view_item -; - -item_static -: STATIC ident ':' ty '=' expr ';' { $$ = mk_node(NN_ItemStatic, 3, $2, $4, $6); } -| STATIC MUT ident ':' ty '=' expr ';' { $$ = mk_node(NN_ItemStatic, 3, $3, $5, $7); } -; - -item_const -: CONST ident ':' ty '=' expr ';' { $$ = mk_node(NN_ItemConst, 3, $2, $4, $6); } -; - -item_macro -: path_expr '!' maybe_ident parens_delimited_token_trees ';' { $$ = mk_node(NN_ItemMacro, 3, $1, $3, $4); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node(NN_ItemMacro, 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node(NN_ItemMacro, 3, $1, $3, $4); } -; - -view_item -: use_item -| extern_fn_item -| EXTERN CRATE ident ';' { $$ = mk_node(NN_ViewItemExternCrate, 1, $3); } -| EXTERN CRATE ident AS ident ';' { $$ = mk_node(NN_ViewItemExternCrate, 2, $3, $5); } -; - -extern_fn_item -: EXTERN maybe_abi item_fn { $$ = mk_node(NN_ViewItemExternFn, 2, $2, $3); } -; - -use_item -: USE view_path ';' { $$ = mk_node(NN_ViewItemUse, 1, $2); } -; - -view_path -: path_no_types_allowed { $$ = mk_node(NN_ViewPathSimple, 1, $1); } -| path_no_types_allowed MOD_SEP '{' '}' { $$ = mk_node(NN_ViewPathList, 2, $1, mk_empty_atom(NN_ViewPathListEmpty)); } -| MOD_SEP '{' '}' { $$ = mk_node(NN_ViewPathList, 1, mk_empty_atom(NN_ViewPathListEmpty)); } -| path_no_types_allowed MOD_SEP '{' idents_or_self '}' { $$ = mk_node(NN_ViewPathList, 2, $1, $4); } -| MOD_SEP '{' idents_or_self '}' { $$ = mk_node(NN_ViewPathList, 1, $3); } -| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node(NN_ViewPathList, 2, $1, $4); } -| MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node(NN_ViewPathList, 1, $3); } -| path_no_types_allowed MOD_SEP '*' { $$ = mk_node(NN_ViewPathGlob, 1, $1); } -| MOD_SEP '*' { $$ = mk_empty_atom(NN_ViewPathGlob); } -| '*' { $$ = mk_empty_atom(NN_ViewPathGlob); } -| '{' '}' { $$ = mk_empty_atom(NN_ViewPathListEmpty); } -| '{' idents_or_self '}' { $$ = mk_node(NN_ViewPathList, 1, $2); } -| '{' idents_or_self ',' '}' { $$ = mk_node(NN_ViewPathList, 1, $2); } -| path_no_types_allowed AS ident { $$ = mk_node(NN_ViewPathSimple, 2, $1, $3); } -; - -block_item -: item_fn -| item_unsafe_fn -| item_mod -| item_foreign_mod { $$ = mk_node(NN_ItemForeignMod, 1, $1); } -| item_struct -| item_enum -| item_union -| item_trait -| item_impl -; - -maybe_ty_ascription -: ':' ty_sum { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_init_expr -: '=' expr { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -// structs -item_struct -: STRUCT ident generic_params maybe_where_clause struct_decl_args -{ - $$ = mk_node(NN_ItemStruct, 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';' -{ - $$ = mk_node(NN_ItemStruct, 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params maybe_where_clause ';' -{ - $$ = mk_node(NN_ItemStruct, 3, $2, $3, $4); -} -; - -struct_decl_args -: '{' struct_decl_fields '}' { $$ = $2; } -| '{' struct_decl_fields ',' '}' { $$ = $2; } -; - -struct_tuple_args -: '(' struct_tuple_fields ')' { $$ = $2; } -| '(' struct_tuple_fields ',' ')' { $$ = $2; } -; - -struct_decl_fields -: struct_decl_field { $$ = mk_node(NN_StructFields, 1, $1); } -| struct_decl_fields ',' struct_decl_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_decl_field -: attrs_and_vis ident ':' ty_sum { $$ = mk_node(NN_StructField, 3, $1, $2, $4); } -; - -struct_tuple_fields -: struct_tuple_field { $$ = mk_node(NN_StructFields, 1, $1); } -| struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_tuple_field -: attrs_and_vis ty_sum { $$ = mk_node(NN_StructField, 2, $1, $2); } -; - -// enums -item_enum -: ENUM ident generic_params maybe_where_clause '{' enum_defs '}' { $$ = mk_node(NN_ItemEnum, 0); } -| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node(NN_ItemEnum, 0); } -; - -enum_defs -: enum_def { $$ = mk_node(NN_EnumDefs, 1, $1); } -| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -enum_def -: attrs_and_vis ident enum_args { $$ = mk_node(NN_EnumDef, 3, $1, $2, $3); } -; - -enum_args -: '{' struct_decl_fields '}' { $$ = mk_node(NN_EnumArgs, 1, $2); } -| '{' struct_decl_fields ',' '}' { $$ = mk_node(NN_EnumArgs, 1, $2); } -| '(' maybe_ty_sums ')' { $$ = mk_node(NN_EnumArgs, 1, $2); } -| '=' expr { $$ = mk_node(NN_EnumArgs, 1, $2); } -| %empty { $$ = mk_none(); } -; - -// unions -item_union -: UNION ident generic_params maybe_where_clause '{' struct_decl_fields '}' { $$ = mk_node(NN_ItemUnion, 0); } -| UNION ident generic_params maybe_where_clause '{' struct_decl_fields ',' '}' { $$ = mk_node(NN_ItemUnion, 0); } - -item_mod -: MOD ident ';' { $$ = mk_node(NN_ItemMod, 1, $2); } -| MOD ident '{' maybe_mod_items '}' { $$ = mk_node(NN_ItemMod, 2, $2, $4); } -| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node(NN_ItemMod, 3, $2, $4, $5); } -; - -item_foreign_mod -: EXTERN maybe_abi '{' maybe_foreign_items '}' { $$ = mk_node(NN_ItemForeignMod, 1, $4); } -| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node(NN_ItemForeignMod, 2, $4, $5); } -; - -maybe_abi -: str -| %empty { $$ = mk_none(); } -; - -maybe_foreign_items -: foreign_items -| %empty { $$ = mk_none(); } -; - -foreign_items -: foreign_item { $$ = mk_node(NN_ForeignItems, 1, $1); } -| foreign_items foreign_item { $$ = ext_node($1, 1, $2); } -; - -foreign_item -: attrs_and_vis STATIC item_foreign_static { $$ = mk_node(NN_ForeignItem, 2, $1, $3); } -| attrs_and_vis item_foreign_fn { $$ = mk_node(NN_ForeignItem, 2, $1, $2); } -| attrs_and_vis UNSAFE item_foreign_fn { $$ = mk_node(NN_ForeignItem, 2, $1, $3); } -; - -item_foreign_static -: maybe_mut ident ':' ty ';' { $$ = mk_node(NN_StaticItem, 3, $1, $2, $4); } -; - -item_foreign_fn -: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node(NN_ForeignFn, 4, $2, $3, $4, $5); } -; - -fn_decl_allow_variadic -: fn_params_allow_variadic ret_ty { $$ = mk_node(NN_FnDecl, 2, $1, $2); } -; - -fn_params_allow_variadic -: '(' ')' { $$ = mk_none(); } -| '(' params ')' { $$ = $2; } -| '(' params ',' ')' { $$ = $2; } -| '(' params ',' DOTDOTDOT ')' { $$ = $2; } -; - -visibility -: PUB { $$ = mk_empty_atom(NN_Public); } -| %empty { $$ = mk_empty_atom(NN_Inherited); } -; - -idents_or_self -: ident_or_self { $$ = mk_node(NN_IdentsOrSelf, 1, $1); } -| idents_or_self AS ident { $$ = mk_node(NN_IdentsOrSelf, 2, $1, $3); } -| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); } -; - -ident_or_self -: ident -| SELF { $$ = mk_empty_atom(NN_SELF); } -; - -item_type -: TYPE ident generic_params maybe_where_clause '=' ty_sum ';' { $$ = mk_node(NN_ItemTy, 4, $2, $3, $4, $6); } -; - -for_sized -: FOR '?' ident { $$ = mk_node(NN_ForSized, 1, $3); } -| FOR ident '?' { $$ = mk_node(NN_ForSized, 1, $2); } -| %empty { $$ = mk_none(); } -; - -item_trait -: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}' -{ - $$ = mk_node(NN_ItemTrait, 7, $1, $3, $4, $5, $6, $7, $9); -} -; - -maybe_trait_items -: trait_items -| %empty { $$ = mk_none(); } -; - -trait_items -: trait_item { $$ = mk_node(NN_TraitItems, 1, $1); } -| trait_items trait_item { $$ = ext_node($1, 1, $2); } -; - -trait_item -: trait_const -| trait_type -| trait_method -| maybe_outer_attrs item_macro { $$ = mk_node(NN_TraitMacroItem, 2, $1, $2); } -; - -trait_const -: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node(NN_ConstTraitItem, 4, $1, $3, $4, $5); } -; - -maybe_const_default -: '=' expr { $$ = mk_node(NN_ConstDefault, 1, $2); } -| %empty { $$ = mk_none(); } -; - -trait_type -: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node(NN_TypeTraitItem, 2, $1, $3); } -; - -maybe_unsafe -: UNSAFE { $$ = mk_empty_atom(NN_Unsafe); } -| %empty { $$ = mk_none(); } -; - -maybe_default_maybe_unsafe -: DEFAULT UNSAFE { $$ = mk_empty_atom(NN_DefaultUnsafe); } -| DEFAULT { $$ = mk_empty_atom(NN_Default); } -| UNSAFE { $$ = mk_empty_atom(NN_Unsafe); } -| %empty { $$ = mk_none(); } - -trait_method -: type_method { $$ = mk_node(NN_Required, 1, $1); } -| method { $$ = mk_node(NN_Provided, 1, $1); } -; - -type_method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node(NN_TypeMethod, 6, $1, $2, $4, $5, $6, $7); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node(NN_TypeMethod, 6, $1, $3, $5, $6, $7, $8); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node(NN_TypeMethod, 7, $1, $2, $4, $6, $7, $8, $9); -} -; - -method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 7, $1, $2, $4, $5, $6, $7, $8); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 7, $1, $3, $5, $6, $7, $8, $9); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -; - -impl_method -: attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 8, $1, $2, $3, $5, $6, $7, $8, $9); -} -| attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -| attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_Method, 9, $1, $2, $3, $5, $7, $8, $9, $10, $11); -} -; - -// There are two forms of impl: -// -// impl (<...>)? TY { ... } -// impl (<...>)? TRAIT for TY { ... } -// -// Unfortunately since TY can begin with '<' itself -- as part of a -// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL: -// should we reduce one of the early rules of TY (such as maybe_once) -// or shall we continue shifting into the generic_params list for the -// impl? -// -// The production parser disambiguates a different case here by -// permitting / requiring the user to provide parens around types when -// they are ambiguous with traits. We do the same here, regrettably, -// by splitting ty into ty and ty_prim. -item_impl -: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node(NN_ItemImpl, 6, $1, $3, $4, $5, $7, $8); -} -| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node(NN_ItemImpl, 6, $1, $3, 5, $6, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node(NN_ItemImpl, 6, $3, $4, $6, $7, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node(NN_ItemImplNeg, 7, $1, $3, $5, $7, $8, $10, $11); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node(NN_ItemImplDefault, 3, $1, $3, $4); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node(NN_ItemImplDefaultNeg, 3, $1, $3, $4); -} -; - -maybe_impl_items -: impl_items -| %empty { $$ = mk_none(); } -; - -impl_items -: impl_item { $$ = mk_node(NN_ImplItems, 1, $1); } -| impl_item impl_items { $$ = ext_node($1, 1, $2); } -; - -impl_item -: impl_method -| attrs_and_vis item_macro { $$ = mk_node(NN_ImplMacroItem, 2, $1, $2); } -| impl_const -| impl_type -; - -maybe_default -: DEFAULT { $$ = mk_empty_atom(NN_Default); } -| %empty { $$ = mk_none(); } -; - -impl_const -: attrs_and_vis maybe_default item_const { $$ = mk_node(NN_ImplConst, 3, $1, $2, $3); } -; - -impl_type -: attrs_and_vis maybe_default TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node(NN_ImplType, 5, $1, $2, $4, $5, $7); } -; - -item_fn -: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_ItemFn, 5, $2, $3, $4, $5, $6); -} -| CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_ItemFn, 5, $3, $4, $5, $6, $7); -} -; - -item_unsafe_fn -: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_ItemUnsafeFn, 5, $3, $4, $5, $6, $7); -} -| CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_ItemUnsafeFn, 5, $4, $5, $6, $7, $8); -} -| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node(NN_ItemUnsafeFn, 6, $3, $5, $6, $7, $8, $9); -} -; - -fn_decl -: fn_params ret_ty { $$ = mk_node(NN_FnDecl, 2, $1, $2); } -; - -fn_decl_with_self -: fn_params_with_self ret_ty { $$ = mk_node(NN_FnDecl, 2, $1, $2); } -; - -fn_decl_with_self_allow_anon_params -: fn_anon_params_with_self ret_ty { $$ = mk_node(NN_FnDecl, 2, $1, $2); } -; - -fn_params -: '(' maybe_params ')' { $$ = $2; } -; - -fn_anon_params -: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); } -| '(' ')' { $$ = mk_none(); } -; - -fn_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node(NN_SelfLower, 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node(NN_SelfRegion, 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node(NN_SelfRegion, 4, $3, $4, $6, $7); } -| '(' maybe_params ')' { $$ = mk_node(NN_SelfStatic, 1, $2); } -; - -fn_anon_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node(NN_SelfLower, 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node(NN_SelfRegion, 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node(NN_SelfRegion, 4, $3, $4, $6, $7); } -| '(' maybe_anon_params ')' { $$ = mk_node(NN_SelfStatic, 1, $2); } -; - -maybe_params -: params -| params ',' -| %empty { $$ = mk_none(); } -; - -params -: param { $$ = mk_node(NN_Args, 1, $1); } -| params ',' param { $$ = ext_node($1, 1, $3); } -; - -param -: pat ':' ty_sum { $$ = mk_node(NN_Arg, 2, $1, $3); } -; - -inferrable_params -: inferrable_param { $$ = mk_node(NN_InferrableParams, 1, $1); } -| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); } -; - -inferrable_param -: pat maybe_ty_ascription { $$ = mk_node(NN_InferrableParam, 2, $1, $2); } -; - -maybe_comma_params -: ',' { $$ = mk_none(); } -| ',' params { $$ = $2; } -| ',' params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_comma_anon_params -: ',' { $$ = mk_none(); } -| ',' anon_params { $$ = $2; } -| ',' anon_params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_anon_params -: anon_params -| anon_params ',' -| %empty { $$ = mk_none(); } -; - -anon_params -: anon_param { $$ = mk_node(NN_Args, 1, $1); } -| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); } -; - -// anon means it's allowed to be anonymous (type-only), but it can -// still have a name -anon_param -: named_arg ':' ty { $$ = mk_node(NN_Arg, 2, $1, $3); } -| ty -; - -anon_params_allow_variadic_tail -: ',' DOTDOTDOT { $$ = mk_none(); } -| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node(NN_Args, 2, $2, $3); } -| %empty { $$ = mk_none(); } -; - -named_arg -: ident -| UNDERSCORE { $$ = mk_empty_atom(NN_PatWild); } -| '&' ident { $$ = $2; } -| '&' UNDERSCORE { $$ = mk_empty_atom(NN_PatWild); } -| ANDAND ident { $$ = $2; } -| ANDAND UNDERSCORE { $$ = mk_empty_atom(NN_PatWild); } -| MUT ident { $$ = $2; } -; - -ret_ty -: RARROW '!' { $$ = mk_none(); } -| RARROW ty { $$ = mk_node(NN_RetTy, 1, $2); } -| %prec IDENT %empty { $$ = mk_none(); } -; - -generic_params -: '<' '>' { $$ = mk_node(NN_Generics, 2, mk_none(), mk_none()); } -| '<' lifetimes '>' { $$ = mk_node(NN_Generics, 2, $2, mk_none()); } -| '<' lifetimes ',' '>' { $$ = mk_node(NN_Generics, 2, $2, mk_none()); } -| '<' lifetimes SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, $2, mk_none()); } -| '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, $2, mk_none()); } -| '<' lifetimes ',' ty_params '>' { $$ = mk_node(NN_Generics, 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node(NN_Generics, 2, $2, $4); } -| '<' lifetimes ',' ty_params SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, $2, $4); } -| '<' ty_params '>' { $$ = mk_node(NN_Generics, 2, mk_none(), $2); } -| '<' ty_params ',' '>' { $$ = mk_node(NN_Generics, 2, mk_none(), $2); } -| '<' ty_params SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, mk_none(), $2); } -| '<' ty_params ',' SHR { push_back('>'); $$ = mk_node(NN_Generics, 2, mk_none(), $2); } -| %empty { $$ = mk_none(); } -; - -maybe_where_clause -: %empty { $$ = mk_none(); } -| where_clause -; - -where_clause -: WHERE where_predicates { $$ = mk_node(NN_WhereClause, 1, $2); } -| WHERE where_predicates ',' { $$ = mk_node(NN_WhereClause, 1, $2); } -; - -where_predicates -: where_predicate { $$ = mk_node(NN_WherePredicates, 1, $1); } -| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); } -; - -where_predicate -: maybe_for_lifetimes lifetime ':' bounds { $$ = mk_node(NN_WherePredicate, 3, $1, $2, $4); } -| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node(NN_WherePredicate, 3, $1, $2, $4); } -; - -maybe_for_lifetimes -: FOR '<' lifetimes '>' { $$ = mk_none(); } -| %prec FORTYPE %empty { $$ = mk_none(); } - -ty_params -: ty_param { $$ = mk_node(NN_TyParams, 1, $1); } -| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); } -; - -// A path with no type parameters; e.g. `foo::bar::Baz` -// -// These show up in 'use' view-items, because these are processed -// without respect to types. -path_no_types_allowed -: ident { $$ = mk_node(NN_ViewPath, 1, $1); } -| MOD_SEP ident { $$ = mk_node(NN_ViewPath, 1, $2); } -| SELF { $$ = mk_node(NN_ViewPath, 1, mk_empty_atom(NN_SELF)); } -| MOD_SEP SELF { $$ = mk_node(NN_ViewPath, 1, mk_empty_atom(NN_SELF)); } -| SUPER { $$ = mk_node(NN_ViewPath, 1, mk_empty_atom(NN_SUPER)); } -| MOD_SEP SUPER { $$ = mk_node(NN_ViewPath, 1, mk_empty_atom(NN_SUPER)); } -| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); } -; - -// A path with a lifetime and type parameters, with no double colons -// before the type parameters; e.g. `foo::bar<'a>::Baz` -// -// These show up in "trait references", the components of -// type-parameter bounds lists, as well as in the prefix of the -// path_generic_args_and_bounds rule, which is the full form of a -// named typed expression. -// -// They do not have (nor need) an extra '::' before '<' because -// unlike in expr context, there are no "less-than" type exprs to -// be ambiguous with. -path_generic_args_without_colons -: %prec IDENT - ident { $$ = mk_node(NN_components, 1, $1); } -| %prec IDENT - ident generic_args { $$ = mk_node(NN_components, 2, $1, $2); } -| %prec IDENT - ident '(' maybe_ty_sums ')' ret_ty { $$ = mk_node(NN_components, 2, $1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident generic_args { $$ = ext_node($1, 2, $3, $4); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); } -; - -generic_args -: '<' generic_values '>' { $$ = $2; } -| '<' generic_values SHR { push_back('>'); $$ = $2; } -| '<' generic_values GE { push_back('='); $$ = $2; } -| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -// If generic_args starts with "<<", the first arg must be a -// TyQualifiedPath because that's the only type that can start with a -// '<'. This rule parses that as the first ty_sum and then continues -// with the rest of generic_values. -| SHL ty_qualified_path_and_generic_values '>' { $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHR { push_back('>'); $$ = $2; } -| SHL ty_qualified_path_and_generic_values GE { push_back('='); $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -; - -generic_values -: maybe_ty_sums_and_or_bindings { $$ = mk_node(NN_GenericValues, 1, $1); } -; - -maybe_ty_sums_and_or_bindings -: ty_sums -| ty_sums ',' -| ty_sums ',' bindings { $$ = mk_node(NN_TySumsAndBindings, 2, $1, $3); } -| bindings -| bindings ',' -| %empty { $$ = mk_none(); } -; - -maybe_bindings -: ',' bindings { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 2: Patterns -//////////////////////////////////////////////////////////////////////// - -pat -: UNDERSCORE { $$ = mk_empty_atom(NN_PatWild); } -| '&' pat { $$ = mk_node(NN_PatRegion, 1, $2); } -| '&' MUT pat { $$ = mk_node(NN_PatRegion, 1, $3); } -| ANDAND pat { $$ = mk_node(NN_PatRegion, 1, mk_node(NN_PatRegion, 1, $2)); } -| '(' ')' { $$ = mk_empty_atom(NN_PatUnit); } -| '(' pat_tup ')' { $$ = mk_node(NN_PatTup, 1, $2); } -| '[' pat_vec ']' { $$ = mk_node(NN_PatVec, 1, $2); } -| lit_or_path -| lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node(NN_PatRange, 2, $1, $3); } -| path_expr '{' pat_struct '}' { $$ = mk_node(NN_PatStruct, 2, $1, $3); } -| path_expr '(' ')' { $$ = mk_node(NN_PatEnum, 2, $1, mk_none()); } -| path_expr '(' pat_tup ')' { $$ = mk_node(NN_PatEnum, 2, $1, $3); } -| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node(NN_PatMac, 3, $1, $3, $4); } -| binding_mode ident { $$ = mk_node(NN_PatIdent, 2, $1, $2); } -| ident '@' pat { $$ = mk_node(NN_PatIdent, 3, mk_node(NN_BindByValue, 1, mk_empty_atom(NN_MutImmutable)), $1, $3); } -| binding_mode ident '@' pat { $$ = mk_node(NN_PatIdent, 3, $1, $2, $4); } -| BOX pat { $$ = mk_node(NN_PatUniq, 1, $2); } -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node(NN_PatQualifiedPath, 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node(NN_PatQualifiedPath, 3, mk_node(NN_PatQualifiedPath, 3, $2, $3, $6), $7, $10); -} -; - -pats_or -: pat { $$ = mk_node(NN_Pats, 1, $1); } -| pats_or '|' pat { $$ = ext_node($1, 1, $3); } -; - -binding_mode -: REF { $$ = mk_node(NN_BindByRef, 1, mk_empty_atom(NN_MutImmutable)); } -| REF MUT { $$ = mk_node(NN_BindByRef, 1, mk_empty_atom(NN_MutMutable)); } -| MUT { $$ = mk_node(NN_BindByValue, 1, mk_empty_atom(NN_MutMutable)); } -; - -lit_or_path -: path_expr { $$ = mk_node(NN_PatLit, 1, $1); } -| lit { $$ = mk_node(NN_PatLit, 1, $1); } -| '-' lit { $$ = mk_node(NN_PatLit, 1, $2); } -; - -pat_field -: ident { $$ = mk_node(NN_PatField, 1, $1); } -| binding_mode ident { $$ = mk_node(NN_PatField, 2, $1, $2); } -| BOX ident { $$ = mk_node(NN_PatField, 2, mk_empty_atom(NN_BOX), $2); } -| BOX binding_mode ident { $$ = mk_node(NN_PatField, 3, mk_empty_atom(NN_BOX), $2, $3); } -| ident ':' pat { $$ = mk_node(NN_PatField, 2, $1, $3); } -| binding_mode ident ':' pat { $$ = mk_node(NN_PatField, 3, $1, $2, $4); } -| LIT_INTEGER ':' pat { $$ = mk_node(NN_PatField, 2, mk_atom(NN_LitInteger, yytext), $3); } -; - -pat_fields -: pat_field { $$ = mk_node(NN_PatFields, 1, $1); } -| pat_fields ',' pat_field { $$ = ext_node($1, 1, $3); } -; - -pat_struct -: pat_fields { $$ = mk_node(NN_PatStruct, 2, $1, mk_atom(NN_LitBool, "false")); } -| pat_fields ',' { $$ = mk_node(NN_PatStruct, 2, $1, mk_atom(NN_LitBool, "false")); } -| pat_fields ',' DOTDOT { $$ = mk_node(NN_PatStruct, 2, $1, mk_atom(NN_LitBool, "true")); } -| DOTDOT { $$ = mk_node(NN_PatStruct, 1, mk_atom(NN_LitBool, "true")); } -| %empty { $$ = mk_node(NN_PatStruct, 1, mk_none()); } -; - -pat_tup -: pat_tup_elts { $$ = mk_node(NN_PatTup, 2, $1, mk_none()); } -| pat_tup_elts ',' { $$ = mk_node(NN_PatTup, 2, $1, mk_none()); } -| pat_tup_elts DOTDOT { $$ = mk_node(NN_PatTup, 2, $1, mk_none()); } -| pat_tup_elts ',' DOTDOT { $$ = mk_node(NN_PatTup, 2, $1, mk_none()); } -| pat_tup_elts DOTDOT ',' pat_tup_elts { $$ = mk_node(NN_PatTup, 2, $1, $4); } -| pat_tup_elts DOTDOT ',' pat_tup_elts ',' { $$ = mk_node(NN_PatTup, 2, $1, $4); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts { $$ = mk_node(NN_PatTup, 2, $1, $5); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts ',' { $$ = mk_node(NN_PatTup, 2, $1, $5); } -| DOTDOT ',' pat_tup_elts { $$ = mk_node(NN_PatTup, 2, mk_none(), $3); } -| DOTDOT ',' pat_tup_elts ',' { $$ = mk_node(NN_PatTup, 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node(NN_PatTup, 2, mk_none(), mk_none()); } -; - -pat_tup_elts -: pat { $$ = mk_node(NN_PatTupElts, 1, $1); } -| pat_tup_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -pat_vec -: pat_vec_elts { $$ = mk_node(NN_PatVec, 2, $1, mk_none()); } -| pat_vec_elts ',' { $$ = mk_node(NN_PatVec, 2, $1, mk_none()); } -| pat_vec_elts DOTDOT { $$ = mk_node(NN_PatVec, 2, $1, mk_none()); } -| pat_vec_elts ',' DOTDOT { $$ = mk_node(NN_PatVec, 2, $1, mk_none()); } -| pat_vec_elts DOTDOT ',' pat_vec_elts { $$ = mk_node(NN_PatVec, 2, $1, $4); } -| pat_vec_elts DOTDOT ',' pat_vec_elts ',' { $$ = mk_node(NN_PatVec, 2, $1, $4); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts { $$ = mk_node(NN_PatVec, 2, $1, $5); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ',' { $$ = mk_node(NN_PatVec, 2, $1, $5); } -| DOTDOT ',' pat_vec_elts { $$ = mk_node(NN_PatVec, 2, mk_none(), $3); } -| DOTDOT ',' pat_vec_elts ',' { $$ = mk_node(NN_PatVec, 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node(NN_PatVec, 2, mk_none(), mk_none()); } -| %empty { $$ = mk_node(NN_PatVec, 2, mk_none(), mk_none()); } -; - -pat_vec_elts -: pat { $$ = mk_node(NN_PatVecElts, 1, $1); } -| pat_vec_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 3: Types -//////////////////////////////////////////////////////////////////////// - -ty -: ty_prim -| ty_closure -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node(NN_TyQualifiedPath, 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node(NN_TyQualifiedPath, 3, mk_node(NN_TyQualifiedPath, 3, $2, $3, $6), $7, $10); } -| '(' ty_sums ')' { $$ = mk_node(NN_TyTup, 1, $2); } -| '(' ty_sums ',' ')' { $$ = mk_node(NN_TyTup, 1, $2); } -| '(' ')' { $$ = mk_empty_atom(NN_TyNil); } -; - -ty_prim -: %prec IDENT path_generic_args_without_colons { $$ = mk_node(NN_TyPath, 2, mk_node(NN_GLOBAL, 1, mk_atom(NN_LitBool, "false")), $1); } -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node(NN_TyPath, 2, mk_node(NN_GLOBAL, 1, mk_atom(NN_LitBool, "true")), $2); } -| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node(NN_TyPath, 2, mk_node(NN_SELF, 1, mk_atom(NN_LitBool, "true")), $3); } -| %prec IDENT path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node(NN_TyMacro, 3, $1, $3, $4); } -| %prec IDENT MOD_SEP path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node(NN_TyMacro, 3, $2, $4, $5); } -| BOX ty { $$ = mk_node(NN_TyBox, 1, $2); } -| '*' maybe_mut_or_const ty { $$ = mk_node(NN_TyPtr, 2, $2, $3); } -| '&' ty { $$ = mk_node(NN_TyRptr, 2, mk_empty_atom(NN_MutImmutable), $2); } -| '&' MUT ty { $$ = mk_node(NN_TyRptr, 2, mk_empty_atom(NN_MutMutable), $3); } -| ANDAND ty { $$ = mk_node(NN_TyRptr, 1, mk_node(NN_TyRptr, 2, mk_empty_atom(NN_MutImmutable), $2)); } -| ANDAND MUT ty { $$ = mk_node(NN_TyRptr, 1, mk_node(NN_TyRptr, 2, mk_empty_atom(NN_MutMutable), $3)); } -| '&' lifetime maybe_mut ty { $$ = mk_node(NN_TyRptr, 3, $2, $3, $4); } -| ANDAND lifetime maybe_mut ty { $$ = mk_node(NN_TyRptr, 1, mk_node(NN_TyRptr, 3, $2, $3, $4)); } -| '[' ty ']' { $$ = mk_node(NN_TyVec, 1, $2); } -| '[' ty ',' DOTDOT expr ']' { $$ = mk_node(NN_TyFixedLengthVec, 2, $2, $5); } -| '[' ty ';' expr ']' { $$ = mk_node(NN_TyFixedLengthVec, 2, $2, $4); } -| TYPEOF '(' expr ')' { $$ = mk_node(NN_TyTypeof, 1, $3); } -| UNDERSCORE { $$ = mk_empty_atom(NN_TyInfer); } -| ty_bare_fn -| for_in_type -; - -ty_bare_fn -: FN ty_fn_decl { $$ = $2; } -| UNSAFE FN ty_fn_decl { $$ = $3; } -| EXTERN maybe_abi FN ty_fn_decl { $$ = $4; } -| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; } -; - -ty_fn_decl -: generic_params fn_anon_params ret_ty { $$ = mk_node(NN_TyFnDecl, 3, $1, $2, $3); } -; - -ty_closure -: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node(NN_TyClosure, 3, $3, $5, $6); } -| '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node(NN_TyClosure, 3, $2, $4, $5); } -| UNSAFE OROR maybe_bounds ret_ty { $$ = mk_node(NN_TyClosure, 2, $3, $4); } -| OROR maybe_bounds ret_ty { $$ = mk_node(NN_TyClosure, 2, $2, $3); } -; - -for_in_type -: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node(NN_ForInType, 2, $3, $5); } -; - -for_in_type_suffix -: ty_bare_fn -| trait_ref -| ty_closure -; - -maybe_mut -: MUT { $$ = mk_empty_atom(NN_MutMutable); } -| %prec MUT %empty { $$ = mk_empty_atom(NN_MutImmutable); } -; - -maybe_mut_or_const -: MUT { $$ = mk_empty_atom(NN_MutMutable); } -| CONST { $$ = mk_empty_atom(NN_MutImmutable); } -| %empty { $$ = mk_empty_atom(NN_MutImmutable); } -; - -ty_qualified_path_and_generic_values -: ty_qualified_path maybe_bindings -{ - $$ = mk_node(NN_GenericValues, 3, mk_none(), mk_node(NN_TySums, 1, mk_node(NN_TySum, 1, $1)), $2); -} -| ty_qualified_path ',' ty_sums maybe_bindings -{ - $$ = mk_node(NN_GenericValues, 3, mk_none(), mk_node(NN_TySums, 2, $1, $3), $4); -} -; - -ty_qualified_path -: ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node(NN_TyQualifiedPath, 3, $1, $3, $6); } -| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node(NN_TyQualifiedPath, 3, $1, $3, $6); } -; - -maybe_ty_sums -: ty_sums -| ty_sums ',' -| %empty { $$ = mk_none(); } -; - -ty_sums -: ty_sum { $$ = mk_node(NN_TySums, 1, $1); } -| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); } -; - -ty_sum -: ty_sum_elt { $$ = mk_node(NN_TySum, 1, $1); } -| ty_sum '+' ty_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_sum_elt -: ty -| lifetime -; - -ty_prim_sum -: ty_prim_sum_elt { $$ = mk_node(NN_TySum, 1, $1); } -| ty_prim_sum '+' ty_prim_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_prim_sum_elt -: ty_prim -| lifetime -; - -maybe_ty_param_bounds -: ':' ty_param_bounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ty_param_bounds -: boundseq -| %empty { $$ = mk_none(); } -; - -boundseq -: polybound -| boundseq '+' polybound { $$ = ext_node($1, 1, $3); } -; - -polybound -: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node(NN_PolyBound, 2, $3, $5); } -| bound -| '?' FOR '<' maybe_lifetimes '>' bound { $$ = mk_node(NN_PolyBound, 2, $4, $6); } -| '?' bound { $$ = $2; } -; - -bindings -: binding { $$ = mk_node(NN_Binding, 1, $1); } -| bindings ',' binding { $$ = ext_node($1, 1, $3); } -; - -binding -: ident '=' ty { mk_node(NN_Binding, 2, $1, $3); } -; - -ty_param -: ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node(NN_TyParam, 3, $1, $2, $3); } -| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node(NN_TyParam, 4, $1, $3, $4, $5); } -; - -maybe_bounds -: %prec SHIFTPLUS - ':' bounds { $$ = $2; } -| %prec SHIFTPLUS %empty { $$ = mk_none(); } -; - -bounds -: bound { $$ = mk_node(NN_bounds, 1, $1); } -| bounds '+' bound { $$ = ext_node($1, 1, $3); } -; - -bound -: lifetime -| trait_ref -; - -maybe_ltbounds -: %prec SHIFTPLUS - ':' ltbounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ltbounds -: lifetime { $$ = mk_node(NN_ltbounds, 1, $1); } -| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); } -; - -maybe_ty_default -: '=' ty_sum { $$ = mk_node(NN_TyDefault, 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_lifetimes -: lifetimes -| lifetimes ',' -| %empty { $$ = mk_none(); } -; - -lifetimes -: lifetime_and_bounds { $$ = mk_node(NN_Lifetimes, 1, $1); } -| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); } -; - -lifetime_and_bounds -: LIFETIME maybe_ltbounds { $$ = mk_node(NN_lifetime, 2, mk_atom(NN_lifetime, yytext), $2); } -| STATIC_LIFETIME { $$ = mk_empty_atom(NN_static_lifetime); } -; - -lifetime -: LIFETIME { $$ = mk_atom(NN_lifetime, yytext); } -| STATIC_LIFETIME { $$ = mk_empty_atom(NN_static_lifetime); } -; - -trait_ref -: %prec IDENT path_generic_args_without_colons -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; } -; - -//////////////////////////////////////////////////////////////////////// -// Part 4: Blocks, statements, and expressions -//////////////////////////////////////////////////////////////////////// - -inner_attrs_and_block -: '{' maybe_inner_attrs maybe_stmts '}' { $$ = mk_node(NN_ExprBlock, 2, $2, $3); } -; - -block -: '{' maybe_stmts '}' { $$ = mk_node(NN_ExprBlock, 1, $2); } -; - -maybe_stmts -: stmts -| stmts nonblock_expr { $$ = ext_node($1, 1, $2); } -| nonblock_expr -| %empty { $$ = mk_none(); } -; - -// There are two sub-grammars within a "stmts: exprs" derivation -// depending on whether each stmt-expr is a block-expr form; this is to -// handle the "semicolon rule" for stmt sequencing that permits -// writing -// -// if foo { bar } 10 -// -// as a sequence of two stmts (one if-expr stmt, one lit-10-expr -// stmt). Unfortunately by permitting juxtaposition of exprs in -// sequence like that, the non-block expr grammar has to have a -// second limited sub-grammar that excludes the prefix exprs that -// are ambiguous with binops. That is to say: -// -// {10} - 1 -// -// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that -// is to say, two statements rather than one, at least according to -// the mainline rust parser. -// -// So we wind up with a 3-way split in exprs that occur in stmt lists: -// block, nonblock-prefix, and nonblock-nonprefix. -// -// In non-stmts contexts, expr can relax this trichotomy. - -stmts -: stmt { $$ = mk_node(NN_stmts, 1, $1); } -| stmts stmt { $$ = ext_node($1, 1, $2); } -; - -stmt -: maybe_outer_attrs let { $$ = $2; } -| stmt_item -| PUB stmt_item { $$ = $2; } -| outer_attrs stmt_item { $$ = $2; } -| outer_attrs PUB stmt_item { $$ = $3; } -| full_block_expr -| maybe_outer_attrs block { $$ = $2; } -| nonblock_expr ';' -| outer_attrs nonblock_expr ';' { $$ = $2; } -| ';' { $$ = mk_none(); } -; - -maybe_exprs -: exprs -| exprs ',' -| %empty { $$ = mk_none(); } -; - -maybe_expr -: expr -| %empty { $$ = mk_none(); } -; - -exprs -: expr { $$ = mk_node(NN_exprs, 1, $1); } -| exprs ',' expr { $$ = ext_node($1, 1, $3); } -; - -path_expr -: path_generic_args_with_colons -| MOD_SEP path_generic_args_with_colons { $$ = $2; } -| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node(NN_SelfPath, 1, $3); } -; - -// A path with a lifetime and type parameters with double colons before -// the type parameters; e.g. `foo::bar::<'a>::Baz::` -// -// These show up in expr context, in order to disambiguate from "less-than" -// expressions. -path_generic_args_with_colons -: ident { $$ = mk_node(NN_components, 1, $1); } -| SUPER { $$ = mk_empty_atom(NN_Super); } -| path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| path_generic_args_with_colons MOD_SEP SUPER { $$ = ext_node($1, 1, mk_empty_atom(NN_Super)); } -| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); } -; - -// the braces-delimited macro is a block_expr so it doesn't appear here -macro_expr -: path_expr '!' maybe_ident parens_delimited_token_trees { $$ = mk_node(NN_MacroExpr, 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node(NN_MacroExpr, 3, $1, $3, $4); } -; - -nonblock_expr -: lit { $$ = mk_node(NN_ExprLit, 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node(NN_ExprPath, 1, $1); } -| SELF { $$ = mk_node(NN_ExprPath, 1, mk_empty_atom(NN_SELF)); } -| macro_expr { $$ = mk_node(NN_ExprMac, 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node(NN_ExprStruct, 2, $1, $3); } -| nonblock_expr '?' { $$ = mk_node(NN_ExprTry, 1, $1); } -| nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node(NN_ExprField, 2, $1, $3); } -| nonblock_expr '.' LIT_INTEGER { $$ = mk_node(NN_ExprTupleIndex, 1, $1); } -| nonblock_expr '[' maybe_expr ']' { $$ = mk_node(NN_ExprIndex, 2, $1, $3); } -| nonblock_expr '(' maybe_exprs ')' { $$ = mk_node(NN_ExprCall, 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node(NN_ExprVec, 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node(NN_ExprParen, 1, $2); } -| CONTINUE { $$ = mk_node(NN_ExprAgain, 0); } -| CONTINUE lifetime { $$ = mk_node(NN_ExprAgain, 1, $2); } -| RETURN { $$ = mk_node(NN_ExprRet, 0); } -| RETURN expr { $$ = mk_node(NN_ExprRet, 1, $2); } -| BREAK { $$ = mk_node(NN_ExprBreak, 0); } -| BREAK lifetime { $$ = mk_node(NN_ExprBreak, 1, $2); } -| YIELD { $$ = mk_node(NN_ExprYield, 0); } -| YIELD expr { $$ = mk_node(NN_ExprYield, 1, $2); } -| nonblock_expr '=' expr { $$ = mk_node(NN_ExprAssign, 2, $1, $3); } -| nonblock_expr SHLEQ expr { $$ = mk_node(NN_ExprAssignShl, 2, $1, $3); } -| nonblock_expr SHREQ expr { $$ = mk_node(NN_ExprAssignShr, 2, $1, $3); } -| nonblock_expr MINUSEQ expr { $$ = mk_node(NN_ExprAssignSub, 2, $1, $3); } -| nonblock_expr ANDEQ expr { $$ = mk_node(NN_ExprAssignBitAnd, 2, $1, $3); } -| nonblock_expr OREQ expr { $$ = mk_node(NN_ExprAssignBitOr, 2, $1, $3); } -| nonblock_expr PLUSEQ expr { $$ = mk_node(NN_ExprAssignAdd, 2, $1, $3); } -| nonblock_expr STAREQ expr { $$ = mk_node(NN_ExprAssignMul, 2, $1, $3); } -| nonblock_expr SLASHEQ expr { $$ = mk_node(NN_ExprAssignDiv, 2, $1, $3); } -| nonblock_expr CARETEQ expr { $$ = mk_node(NN_ExprAssignBitXor, 2, $1, $3); } -| nonblock_expr PERCENTEQ expr { $$ = mk_node(NN_ExprAssignRem, 2, $1, $3); } -| nonblock_expr OROR expr { $$ = mk_node(NN_BiOr, 2,$1, $3); } -| nonblock_expr ANDAND expr { $$ = mk_node(NN_BiAnd, 2,$1, $3); } -| nonblock_expr EQEQ expr { $$ = mk_node(NN_BiEq, 2,$1, $3); } -| nonblock_expr NE expr { $$ = mk_node(NN_BiNe, 2,$1, $3); } -| nonblock_expr '<' expr { $$ = mk_node(NN_BiLt, 2,$1, $3); } -| nonblock_expr '>' expr { $$ = mk_node(NN_BiGt, 2,$1, $3); } -| nonblock_expr LE expr { $$ = mk_node(NN_BiLe, 2,$1, $3); } -| nonblock_expr GE expr { $$ = mk_node(NN_BiGe, 2,$1, $3); } -| nonblock_expr '|' expr { $$ = mk_node(NN_BiBitOr, 2,$1, $3); } -| nonblock_expr '^' expr { $$ = mk_node(NN_BiBitXor, 2,$1, $3); } -| nonblock_expr '&' expr { $$ = mk_node(NN_BiBitAnd, 2,$1, $3); } -| nonblock_expr SHL expr { $$ = mk_node(NN_BiShl, 2,$1, $3); } -| nonblock_expr SHR expr { $$ = mk_node(NN_BiShr, 2,$1, $3); } -| nonblock_expr '+' expr { $$ = mk_node(NN_BiAdd, 2,$1, $3); } -| nonblock_expr '-' expr { $$ = mk_node(NN_BiSub, 2,$1, $3); } -| nonblock_expr '*' expr { $$ = mk_node(NN_BiMul, 2,$1, $3); } -| nonblock_expr '/' expr { $$ = mk_node(NN_BiDiv, 2,$1, $3); } -| nonblock_expr '%' expr { $$ = mk_node(NN_BiRem, 2,$1, $3); } -| nonblock_expr DOTDOT { $$ = mk_node(NN_ExprRange, 2, $1, mk_none()); } -| nonblock_expr DOTDOT expr { $$ = mk_node(NN_ExprRange, 2, $1, $3); } -| DOTDOT expr { $$ = mk_node(NN_ExprRange, 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node(NN_ExprRange, 2, mk_none(), mk_none()); } -| nonblock_expr AS ty { $$ = mk_node(NN_ExprCast, 2, $1, $3); } -| nonblock_expr ':' ty { $$ = mk_node(NN_ExprTypeAscr, 2, $1, $3); } -| BOX expr { $$ = mk_node(NN_ExprBox, 1, $2); } -| expr_qualified_path -| nonblock_prefix_expr -; - -expr -: lit { $$ = mk_node(NN_ExprLit, 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node(NN_ExprPath, 1, $1); } -| SELF { $$ = mk_node(NN_ExprPath, 1, mk_empty_atom(NN_SELF)); } -| macro_expr { $$ = mk_node(NN_ExprMac, 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node(NN_ExprStruct, 2, $1, $3); } -| expr '?' { $$ = mk_node(NN_ExprTry, 1, $1); } -| expr '.' path_generic_args_with_colons { $$ = mk_node(NN_ExprField, 2, $1, $3); } -| expr '.' LIT_INTEGER { $$ = mk_node(NN_ExprTupleIndex, 1, $1); } -| expr '[' maybe_expr ']' { $$ = mk_node(NN_ExprIndex, 2, $1, $3); } -| expr '(' maybe_exprs ')' { $$ = mk_node(NN_ExprCall, 2, $1, $3); } -| '(' maybe_exprs ')' { $$ = mk_node(NN_ExprParen, 1, $2); } -| '[' vec_expr ']' { $$ = mk_node(NN_ExprVec, 1, $2); } -| CONTINUE { $$ = mk_node(NN_ExprAgain, 0); } -| CONTINUE ident { $$ = mk_node(NN_ExprAgain, 1, $2); } -| RETURN { $$ = mk_node(NN_ExprRet, 0); } -| RETURN expr { $$ = mk_node(NN_ExprRet, 1, $2); } -| BREAK { $$ = mk_node(NN_ExprBreak, 0); } -| BREAK ident { $$ = mk_node(NN_ExprBreak, 1, $2); } -| YIELD { $$ = mk_node(NN_ExprYield, 0); } -| YIELD expr { $$ = mk_node(NN_ExprYield, 1, $2); } -| expr '=' expr { $$ = mk_node(NN_ExprAssign, 2, $1, $3); } -| expr SHLEQ expr { $$ = mk_node(NN_ExprAssignShl, 2, $1, $3); } -| expr SHREQ expr { $$ = mk_node(NN_ExprAssignShr, 2, $1, $3); } -| expr MINUSEQ expr { $$ = mk_node(NN_ExprAssignSub, 2, $1, $3); } -| expr ANDEQ expr { $$ = mk_node(NN_ExprAssignBitAnd, 2, $1, $3); } -| expr OREQ expr { $$ = mk_node(NN_ExprAssignBitOr, 2, $1, $3); } -| expr PLUSEQ expr { $$ = mk_node(NN_ExprAssignAdd, 2, $1, $3); } -| expr STAREQ expr { $$ = mk_node(NN_ExprAssignMul, 2, $1, $3); } -| expr SLASHEQ expr { $$ = mk_node(NN_ExprAssignDiv, 2, $1, $3); } -| expr CARETEQ expr { $$ = mk_node(NN_ExprAssignBitXor, 2, $1, $3); } -| expr PERCENTEQ expr { $$ = mk_node(NN_ExprAssignRem, 2, $1, $3); } -| expr OROR expr { $$ = mk_node(NN_BiOr, 2,$1, $3); } -| expr ANDAND expr { $$ = mk_node(NN_BiAnd, 2,$1, $3); } -| expr EQEQ expr { $$ = mk_node(NN_BiEq, 2,$1, $3); } -| expr NE expr { $$ = mk_node(NN_BiNe, 2,$1, $3); } -| expr '<' expr { $$ = mk_node(NN_BiLt, 2,$1, $3); } -| expr '>' expr { $$ = mk_node(NN_BiGt, 2,$1, $3); } -| expr LE expr { $$ = mk_node(NN_BiLe, 2,$1, $3); } -| expr GE expr { $$ = mk_node(NN_BiGe, 2,$1, $3); } -| expr '|' expr { $$ = mk_node(NN_BiBitOr, 2,$1, $3); } -| expr '^' expr { $$ = mk_node(NN_BiBitXor, 2,$1, $3); } -| expr '&' expr { $$ = mk_node(NN_BiBitAnd, 2,$1, $3); } -| expr SHL expr { $$ = mk_node(NN_BiShl, 2,$1, $3); } -| expr SHR expr { $$ = mk_node(NN_BiShr, 2,$1, $3); } -| expr '+' expr { $$ = mk_node(NN_BiAdd, 2,$1, $3); } -| expr '-' expr { $$ = mk_node(NN_BiSub, 2,$1, $3); } -| expr '*' expr { $$ = mk_node(NN_BiMul, 2,$1, $3); } -| expr '/' expr { $$ = mk_node(NN_BiDiv, 2,$1, $3); } -| expr '%' expr { $$ = mk_node(NN_BiRem, 2,$1, $3); } -| expr DOTDOT { $$ = mk_node(NN_ExprRange, 2, $1, mk_none()); } -| expr DOTDOT expr { $$ = mk_node(NN_ExprRange, 2, $1, $3); } -| DOTDOT expr { $$ = mk_node(NN_ExprRange, 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node(NN_ExprRange, 2, mk_none(), mk_none()); } -| expr AS ty { $$ = mk_node(NN_ExprCast, 2, $1, $3); } -| expr ':' ty { $$ = mk_node(NN_ExprTypeAscr, 2, $1, $3); } -| BOX expr { $$ = mk_node(NN_ExprBox, 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr -; - -expr_nostruct -: lit { $$ = mk_node(NN_ExprLit, 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node(NN_ExprPath, 1, $1); } -| SELF { $$ = mk_node(NN_ExprPath, 1, mk_empty_atom(NN_SELF)); } -| macro_expr { $$ = mk_node(NN_ExprMac, 1, $1); } -| expr_nostruct '?' { $$ = mk_node(NN_ExprTry, 1, $1); } -| expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node(NN_ExprField, 2, $1, $3); } -| expr_nostruct '.' LIT_INTEGER { $$ = mk_node(NN_ExprTupleIndex, 1, $1); } -| expr_nostruct '[' maybe_expr ']' { $$ = mk_node(NN_ExprIndex, 2, $1, $3); } -| expr_nostruct '(' maybe_exprs ')' { $$ = mk_node(NN_ExprCall, 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node(NN_ExprVec, 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node(NN_ExprParen, 1, $2); } -| CONTINUE { $$ = mk_node(NN_ExprAgain, 0); } -| CONTINUE ident { $$ = mk_node(NN_ExprAgain, 1, $2); } -| RETURN { $$ = mk_node(NN_ExprRet, 0); } -| RETURN expr { $$ = mk_node(NN_ExprRet, 1, $2); } -| BREAK { $$ = mk_node(NN_ExprBreak, 0); } -| BREAK ident { $$ = mk_node(NN_ExprBreak, 1, $2); } -| YIELD { $$ = mk_node(NN_ExprYield, 0); } -| YIELD expr { $$ = mk_node(NN_ExprYield, 1, $2); } -| expr_nostruct '=' expr_nostruct { $$ = mk_node(NN_ExprAssign, 2, $1, $3); } -| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node(NN_ExprAssignShl, 2, $1, $3); } -| expr_nostruct SHREQ expr_nostruct { $$ = mk_node(NN_ExprAssignShr, 2, $1, $3); } -| expr_nostruct MINUSEQ expr_nostruct { $$ = mk_node(NN_ExprAssignSub, 2, $1, $3); } -| expr_nostruct ANDEQ expr_nostruct { $$ = mk_node(NN_ExprAssignBitAnd, 2, $1, $3); } -| expr_nostruct OREQ expr_nostruct { $$ = mk_node(NN_ExprAssignBitOr, 2, $1, $3); } -| expr_nostruct PLUSEQ expr_nostruct { $$ = mk_node(NN_ExprAssignAdd, 2, $1, $3); } -| expr_nostruct STAREQ expr_nostruct { $$ = mk_node(NN_ExprAssignMul, 2, $1, $3); } -| expr_nostruct SLASHEQ expr_nostruct { $$ = mk_node(NN_ExprAssignDiv, 2, $1, $3); } -| expr_nostruct CARETEQ expr_nostruct { $$ = mk_node(NN_ExprAssignBitXor, 2, $1, $3); } -| expr_nostruct PERCENTEQ expr_nostruct { $$ = mk_node(NN_ExprAssignRem, 2, $1, $3); } -| expr_nostruct OROR expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiOr), $1, $3); } -| expr_nostruct ANDAND expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiAnd), $1, $3); } -| expr_nostruct EQEQ expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiEq), $1, $3); } -| expr_nostruct NE expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiNe), $1, $3); } -| expr_nostruct '<' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiLt), $1, $3); } -| expr_nostruct '>' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiGt), $1, $3); } -| expr_nostruct LE expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiLe), $1, $3); } -| expr_nostruct GE expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiGe), $1, $3); } -| expr_nostruct '|' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiBitOr), $1, $3); } -| expr_nostruct '^' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiBitXor), $1, $3); } -| expr_nostruct '&' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiBitAnd), $1, $3); } -| expr_nostruct SHL expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiShl), $1, $3); } -| expr_nostruct SHR expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiShr), $1, $3); } -| expr_nostruct '+' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiAdd), $1, $3); } -| expr_nostruct '-' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiSub), $1, $3); } -| expr_nostruct '*' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiMul), $1, $3); } -| expr_nostruct '/' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiDiv), $1, $3); } -| expr_nostruct '%' expr_nostruct { $$ = mk_node(NN_ExprBinary, 3, mk_empty_atom(NN_BiRem), $1, $3); } -| expr_nostruct DOTDOT %prec RANGE { $$ = mk_node(NN_ExprRange, 2, $1, mk_none()); } -| expr_nostruct DOTDOT expr_nostruct { $$ = mk_node(NN_ExprRange, 2, $1, $3); } -| DOTDOT expr_nostruct { $$ = mk_node(NN_ExprRange, 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node(NN_ExprRange, 2, mk_none(), mk_none()); } -| expr_nostruct AS ty { $$ = mk_node(NN_ExprCast, 2, $1, $3); } -| expr_nostruct ':' ty { $$ = mk_node(NN_ExprTypeAscr, 2, $1, $3); } -| BOX expr { $$ = mk_node(NN_ExprBox, 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr_nostruct -; - -nonblock_prefix_expr_nostruct -: '-' expr_nostruct { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnNeg), $2); } -| '!' expr_nostruct { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnNot), $2); } -| '*' expr_nostruct { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnDeref), $2); } -| '&' maybe_mut expr_nostruct { $$ = mk_node(NN_ExprAddrOf, 2, $2, $3); } -| ANDAND maybe_mut expr_nostruct { $$ = mk_node(NN_ExprAddrOf, 1, mk_node(NN_ExprAddrOf, 2, $2, $3)); } -| lambda_expr_nostruct -| MOVE lambda_expr_nostruct { $$ = $2; } -; - -nonblock_prefix_expr -: '-' expr { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnNeg), $2); } -| '!' expr { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnNot), $2); } -| '*' expr { $$ = mk_node(NN_ExprUnary, 2, mk_empty_atom(NN_UnDeref), $2); } -| '&' maybe_mut expr { $$ = mk_node(NN_ExprAddrOf, 2, $2, $3); } -| ANDAND maybe_mut expr { $$ = mk_node(NN_ExprAddrOf, 1, mk_node(NN_ExprAddrOf, 2, $2, $3)); } -| lambda_expr -| MOVE lambda_expr { $$ = $2; } -; - -expr_qualified_path -: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params -{ - $$ = mk_node(NN_ExprQualifiedPath, 4, $2, $3, $6, $7); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node(NN_ExprQualifiedPath, 3, mk_node(NN_ExprQualifiedPath, 3, $2, $3, $6), $7, $10); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node(NN_ExprQualifiedPath, 3, mk_node(NN_ExprQualifiedPath, 4, $2, $3, $6, $7), $8, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node(NN_ExprQualifiedPath, 4, mk_node(NN_ExprQualifiedPath, 3, $2, $3, $6), $7, $10, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node(NN_ExprQualifiedPath, 4, mk_node(NN_ExprQualifiedPath, 4, $2, $3, $6, $7), $8, $11, $12); -} - -maybe_qpath_params -: MOD_SEP generic_args { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_as_trait_ref -: AS trait_ref { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -lambda_expr -: %prec LAMBDA - OROR ret_ty expr { $$ = mk_node(NN_ExprFnBlock, 3, mk_none(), $2, $3); } -| %prec LAMBDA - '|' '|' ret_ty expr { $$ = mk_node(NN_ExprFnBlock, 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' ret_ty expr { $$ = mk_node(NN_ExprFnBlock, 3, $2, $4, $5); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node(NN_ExprFnBlock, 3, $2, mk_none(), $4); } -; - -lambda_expr_no_first_bar -: %prec LAMBDA - '|' ret_ty expr { $$ = mk_node(NN_ExprFnBlock, 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr { $$ = mk_node(NN_ExprFnBlock, 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node(NN_ExprFnBlock, 3, $1, mk_none(), $3); } -; - -lambda_expr_nostruct -: %prec LAMBDA - OROR expr_nostruct { $$ = mk_node(NN_ExprFnBlock, 2, mk_none(), $2); } -| %prec LAMBDA - '|' '|' ret_ty expr_nostruct { $$ = mk_node(NN_ExprFnBlock, 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' expr_nostruct { $$ = mk_node(NN_ExprFnBlock, 2, $2, $4); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node(NN_ExprFnBlock, 3, $2, mk_none(), $4); } -; - -lambda_expr_nostruct_no_first_bar -: %prec LAMBDA - '|' ret_ty expr_nostruct { $$ = mk_node(NN_ExprFnBlock, 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr_nostruct { $$ = mk_node(NN_ExprFnBlock, 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node(NN_ExprFnBlock, 3, $1, mk_none(), $3); } -; - -vec_expr -: maybe_exprs -| exprs ';' expr { $$ = mk_node(NN_VecRepeat, 2, $1, $3); } -; - -struct_expr_fields -: field_inits -| field_inits ',' -| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_field_inits -: field_inits -| field_inits ',' -| %empty { $$ = mk_none(); } -; - -field_inits -: field_init { $$ = mk_node(NN_FieldInits, 1, $1); } -| field_inits ',' field_init { $$ = ext_node($1, 1, $3); } -; - -field_init -: ident { $$ = mk_node(NN_FieldInit, 1, $1); } -| ident ':' expr { $$ = mk_node(NN_FieldInit, 2, $1, $3); } -| LIT_INTEGER ':' expr { $$ = mk_node(NN_FieldInit, 2, mk_atom(NN_LitInteger, yytext), $3); } -; - -default_field_init -: DOTDOT expr { $$ = mk_node(NN_DefaultFieldInit, 1, $2); } -; - -block_expr -: expr_match -| expr_if -| expr_if_let -| expr_while -| expr_while_let -| expr_loop -| expr_for -| UNSAFE block { $$ = mk_node(NN_UnsafeBlock, 1, $2); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node(NN_Macro, 3, $1, $3, $4); } -; - -full_block_expr -: block_expr -| block_expr_dot -; - -block_expr_dot -: block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node(NN_ExprField, 2, $1, $3); } -| block_expr_dot '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node(NN_ExprField, 2, $1, $3); } -| block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node(NN_ExprIndex, 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node(NN_ExprIndex, 3, $1, $3, $5); } -| block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node(NN_ExprCall, 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node(NN_ExprCall, 3, $1, $3, $5); } -| block_expr '.' LIT_INTEGER { $$ = mk_node(NN_ExprTupleIndex, 1, $1); } -| block_expr_dot '.' LIT_INTEGER { $$ = mk_node(NN_ExprTupleIndex, 1, $1); } -; - -expr_match -: MATCH expr_nostruct '{' '}' { $$ = mk_node(NN_ExprMatch, 1, $2); } -| MATCH expr_nostruct '{' match_clauses '}' { $$ = mk_node(NN_ExprMatch, 2, $2, $4); } -| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node(NN_ExprMatch, 2, $2, ext_node($4, 1, $5)); } -| MATCH expr_nostruct '{' nonblock_match_clause '}' { $$ = mk_node(NN_ExprMatch, 2, $2, mk_node(NN_Arms, 1, $4)); } -; - -match_clauses -: match_clause { $$ = mk_node(NN_Arms, 1, $1); } -| match_clauses match_clause { $$ = ext_node($1, 1, $2); } -; - -match_clause -: nonblock_match_clause ',' -| block_match_clause -| block_match_clause ',' -; - -nonblock_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node(NN_ArmNonblock, 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot { $$ = mk_node(NN_ArmNonblock, 4, $1, $2, $3, $5); } -; - -block_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node(NN_ArmBlock, 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr { $$ = mk_node(NN_ArmBlock, 4, $1, $2, $3, $5); } -; - -maybe_guard -: IF expr_nostruct { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -expr_if -: IF expr_nostruct block { $$ = mk_node(NN_ExprIf, 2, $2, $3); } -| IF expr_nostruct block ELSE block_or_if { $$ = mk_node(NN_ExprIf, 3, $2, $3, $5); } -; - -expr_if_let -: IF LET pat '=' expr_nostruct block { $$ = mk_node(NN_ExprIfLet, 3, $3, $5, $6); } -| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node(NN_ExprIfLet, 4, $3, $5, $6, $8); } -; - -block_or_if -: block -| expr_if -| expr_if_let -; - -expr_while -: maybe_label WHILE expr_nostruct block { $$ = mk_node(NN_ExprWhile, 3, $1, $3, $4); } -; - -expr_while_let -: maybe_label WHILE LET pat '=' expr_nostruct block { $$ = mk_node(NN_ExprWhileLet, 4, $1, $4, $6, $7); } -; - -expr_loop -: maybe_label LOOP block { $$ = mk_node(NN_ExprLoop, 2, $1, $3); } -; - -expr_for -: maybe_label FOR pat IN expr_nostruct block { $$ = mk_node(NN_ExprForLoop, 4, $1, $3, $5, $6); } -; - -maybe_label -: lifetime ':' -| %empty { $$ = mk_none(); } -; - -let -: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node(NN_DeclLocal, 3, $2, $3, $4); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 5: Macros and misc. rules -//////////////////////////////////////////////////////////////////////// - -lit -: LIT_BYTE { $$ = mk_atom(NN_LitByte, yytext); } -| LIT_CHAR { $$ = mk_atom(NN_LitChar, yytext); } -| LIT_INTEGER { $$ = mk_atom(NN_LitInteger, yytext); } -| LIT_FLOAT { $$ = mk_atom(NN_LitFloat, yytext); } -| XTRUE { $$ = mk_atom(NN_LitBool, yytext); } -| XFALSE { $$ = mk_atom(NN_LitBool, yytext); } -| str -; - -str -: LIT_STR { $$ = mk_atom(NN_LIT_STR, yytext); } -| LIT_STR_RAW { $$ = mk_atom(NN_LIT_STR_RAW, yytext); } -| LIT_BYTE_STR { $$ = mk_atom(NN_LIT_BYTE_STR, yytext); } -| LIT_BYTE_STR_RAW { $$ = mk_atom(NN_LIT_BYTE_STR_RAW, yytext); } -; - -maybe_ident -: %empty { $$ = mk_none(); } -| ident -; - -ident -: IDENT { $$ = mk_node(NN_ident, 1, mk_atom(NN_IDENT, yytext)); } -// Weak keywords that can be used as identifiers -| CATCH { $$ = mk_node(NN_ident, 1, mk_atom(NN_CATCH, yytext)); } -| DEFAULT { $$ = mk_node(NN_ident, 1, mk_atom(NN_DEFAULT, yytext)); } -| UNION { $$ = mk_node(NN_ident, 1, mk_atom(NN_UNION, yytext)); } -; - -unpaired_token -: SHL { $$ = mk_empty_atom(NN_SHL); } -| SHR { $$ = mk_empty_atom(NN_SHR); } -| LE { $$ = mk_empty_atom(NN_LE); } -| EQEQ { $$ = mk_empty_atom(NN_EQEQ); } -| NE { $$ = mk_empty_atom(NN_NE); } -| GE { $$ = mk_empty_atom(NN_GE); } -| ANDAND { $$ = mk_empty_atom(NN_ANDAND); } -| OROR { $$ = mk_empty_atom(NN_OROR); } -| LARROW { $$ = mk_empty_atom(NN_LARROW); } -| SHLEQ { $$ = mk_empty_atom(NN_SHLEQ); } -| SHREQ { $$ = mk_empty_atom(NN_SHREQ); } -| MINUSEQ { $$ = mk_empty_atom(NN_MINUSEQ); } -| ANDEQ { $$ = mk_empty_atom(NN_ANDEQ); } -| OREQ { $$ = mk_empty_atom(NN_OREQ); } -| PLUSEQ { $$ = mk_empty_atom(NN_PLUSEQ); } -| STAREQ { $$ = mk_empty_atom(NN_STAREQ); } -| SLASHEQ { $$ = mk_empty_atom(NN_SLASHEQ); } -| CARETEQ { $$ = mk_empty_atom(NN_CARETEQ); } -| PERCENTEQ { $$ = mk_empty_atom(NN_PERCENTEQ); } -| DOTDOT { $$ = mk_empty_atom(NN_DOTDOT); } -| DOTDOTDOT { $$ = mk_empty_atom(NN_DOTDOTDOT); } -| MOD_SEP { $$ = mk_empty_atom(NN_MOD_SEP); } -| RARROW { $$ = mk_empty_atom(NN_RARROW); } -| FAT_ARROW { $$ = mk_empty_atom(NN_FAT_ARROW); } -| LIT_BYTE { $$ = mk_atom(NN_LIT_BYTE, yytext); } -| LIT_CHAR { $$ = mk_atom(NN_LIT_CHAR, yytext); } -| LIT_INTEGER { $$ = mk_atom(NN_LIT_INTEGER, yytext); } -| LIT_FLOAT { $$ = mk_atom(NN_LIT_FLOAT, yytext); } -| LIT_STR { $$ = mk_atom(NN_LIT_STR, yytext); } -| LIT_STR_RAW { $$ = mk_atom(NN_LIT_STR_RAW, yytext); } -| LIT_BYTE_STR { $$ = mk_atom(NN_LIT_BYTE_STR, yytext); } -| LIT_BYTE_STR_RAW { $$ = mk_atom(NN_LIT_BYTE_STR_RAW, yytext); } -| IDENT { $$ = mk_atom(NN_IDENT, yytext); } -| UNDERSCORE { $$ = mk_empty_atom(NN_UNDERSCORE); } -| LIFETIME { $$ = mk_empty_atom(NN_LIFETIME); } -| SELF { $$ = mk_empty_atom(NN_SELF); } -| STATIC { $$ = mk_empty_atom(NN_STATIC); } -| ABSTRACT { $$ = mk_empty_atom(NN_ABSTRACT); } -| ALIGNOF { $$ = mk_empty_atom(NN_ALIGNOF); } -| AS { $$ = mk_empty_atom(NN_AS); } -| BECOME { $$ = mk_empty_atom(NN_BECOME); } -| BREAK { $$ = mk_empty_atom(NN_BREAK); } -| CATCH { $$ = mk_empty_atom(NN_CATCH); } -| CRATE { $$ = mk_empty_atom(NN_CRATE); } -| DEFAULT { $$ = mk_empty_atom(NN_DEFAULT); } -| DO { $$ = mk_empty_atom(NN_DO); } -| ELSE { $$ = mk_empty_atom(NN_ELSE); } -| ENUM { $$ = mk_empty_atom(NN_ENUM); } -| EXTERN { $$ = mk_empty_atom(NN_EXTERN); } -| XFALSE { $$ = mk_empty_atom(NN_XFALSE); } -| FINAL { $$ = mk_empty_atom(NN_FINAL); } -| FN { $$ = mk_empty_atom(NN_FN); } -| FOR { $$ = mk_empty_atom(NN_FOR); } -| IF { $$ = mk_empty_atom(NN_IF); } -| IMPL { $$ = mk_empty_atom(NN_IMPL); } -| IN { $$ = mk_empty_atom(NN_IN); } -| LET { $$ = mk_empty_atom(NN_LET); } -| LOOP { $$ = mk_empty_atom(NN_LOOP); } -| MACRO { $$ = mk_empty_atom(NN_MACRO); } -| MATCH { $$ = mk_empty_atom(NN_MATCH); } -| MOD { $$ = mk_empty_atom(NN_MOD); } -| MOVE { $$ = mk_empty_atom(NN_MOVE); } -| MUT { $$ = mk_empty_atom(NN_MUT); } -| OFFSETOF { $$ = mk_empty_atom(NN_OFFSETOF); } -| OVERRIDE { $$ = mk_empty_atom(NN_OVERRIDE); } -| PRIV { $$ = mk_empty_atom(NN_PRIV); } -| PUB { $$ = mk_empty_atom(NN_PUB); } -| PURE { $$ = mk_empty_atom(NN_PURE); } -| REF { $$ = mk_empty_atom(NN_REF); } -| RETURN { $$ = mk_empty_atom(NN_RETURN); } -| STRUCT { $$ = mk_empty_atom(NN_STRUCT); } -| SIZEOF { $$ = mk_empty_atom(NN_SIZEOF); } -| SUPER { $$ = mk_empty_atom(NN_SUPER); } -| XTRUE { $$ = mk_empty_atom(NN_XTRUE); } -| TRAIT { $$ = mk_empty_atom(NN_TRAIT); } -| TYPE { $$ = mk_empty_atom(NN_TYPE); } -| UNION { $$ = mk_empty_atom(NN_UNION); } -| UNSAFE { $$ = mk_empty_atom(NN_UNSAFE); } -| UNSIZED { $$ = mk_empty_atom(NN_UNSIZED); } -| USE { $$ = mk_empty_atom(NN_USE); } -| VIRTUAL { $$ = mk_empty_atom(NN_VIRTUAL); } -| WHILE { $$ = mk_empty_atom(NN_WHILE); } -| YIELD { $$ = mk_empty_atom(NN_YIELD); } -| CONTINUE { $$ = mk_empty_atom(NN_CONTINUE); } -| PROC { $$ = mk_empty_atom(NN_PROC); } -| BOX { $$ = mk_empty_atom(NN_BOX); } -| CONST { $$ = mk_empty_atom(NN_CONST); } -| WHERE { $$ = mk_empty_atom(NN_WHERE); } -| TYPEOF { $$ = mk_empty_atom(NN_TYPEOF); } -| INNER_DOC_COMMENT { $$ = mk_empty_atom(NN_INNER_DOC_COMMENT); } -| OUTER_DOC_COMMENT { $$ = mk_empty_atom(NN_OUTER_DOC_COMMENT); } -| SHEBANG { $$ = mk_empty_atom(NN_SHEBANG); } -| STATIC_LIFETIME { $$ = mk_empty_atom(NN_STATIC_LIFETIME); } -| ';' { $$ = mk_empty_atom(NN_SEMI_COLON); } -| ',' { $$ = mk_empty_atom(NN_COMMA); } -| '.' { $$ = mk_empty_atom(NN_SINGLE_DOT); } -| '@' { $$ = mk_empty_atom(NN_AT); } -| '#' { $$ = mk_empty_atom(NN_HASH); } -| '~' { $$ = mk_empty_atom(NN_TILDA); } -| ':' { $$ = mk_empty_atom(NN_COLON); } -| '$' { $$ = mk_empty_atom(NN_DOLLAR); } -| '=' { $$ = mk_empty_atom(NN_EQUALS); } -| '?' { $$ = mk_empty_atom(NN_QUESTION); } -| '!' { $$ = mk_empty_atom(NN_EXCLAIM); } -| '<' { $$ = mk_empty_atom(NN_LESS_THAN); } -| '>' { $$ = mk_empty_atom(NN_GREATER_THAN); } -| '-' { $$ = mk_empty_atom(NN_MINUS); } -| '&' { $$ = mk_empty_atom(NN_AMPERSAND); } -| '|' { $$ = mk_empty_atom(NN_PIPE); } -| '+' { $$ = mk_empty_atom(NN_PLUS); } -| '*' { $$ = mk_empty_atom(NN_MULT); } -| '/' { $$ = mk_empty_atom(NN_DIVIDE); } -| '^' { $$ = mk_empty_atom(NN_HAT); } -| '%' { $$ = mk_empty_atom(NN_PERCENTAGE); } -; - -token_trees -: %empty { $$ = mk_node(NN_TokenTrees, 0); } -| token_trees token_tree { $$ = ext_node($1, 1, $2); } -; - -token_tree -: delimited_token_trees -| unpaired_token { $$ = mk_node(NN_TTTok, 1, $1); } -; - -delimited_token_trees -: parens_delimited_token_trees -| braces_delimited_token_trees -| brackets_delimited_token_trees -; - -parens_delimited_token_trees -: '(' token_trees ')' -{ - $$ = mk_node(NN_TTDelim, 1, $2); -} -; - -braces_delimited_token_trees -: '{' token_trees '}' -{ - $$ = mk_node(NN_TTDelim, 1, $2); -} -; - -brackets_delimited_token_trees -: '[' token_trees ']' -{ - $$ = mk_node(NN_TTDelim, 1, $2); -} -; - -%% - -void yyerror (const char* msg) -{ - fatal_error (UNKNOWN_LOCATION, "%s at line %i\n", msg, yylineno); -} diff --git a/gcc/rust/rustfrontend/rustly.cc b/gcc/rust/rustfrontend/rustly.cc deleted file mode 100644 index eb14194..0000000 --- a/gcc/rust/rustfrontend/rustly.cc +++ /dev/null @@ -1,83 +0,0 @@ -#include "rustly.h" -#include "node.h" - -extern FILE* yyin; -static Rustly* rustly; - - -Rustly::Rustly (bool only_check_syntax, Linemap* linemap) - : mSyntaxOnly(only_check_syntax), - mLinemap(linemap) -{ - -} - -Rustly::~Rustly () -{ - -} - -void Rustly::parse_input_files (size_t n, const char** in) -{ - int verbose = 1; - parser_init(verbose); - - int ret = 0; - - size_t i; - for (i = 0; i < n; ++i) - { - yyin = fopen(in[i], "rb"); - if (yyin == NULL) { - fatal_error(UNKNOWN_LOCATION, "FAILED TO OPEN %s", in[i]); - return; - } - - ret = yyparse(); - } - - - printf("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes); - if (nodes) { - print_node(nodes, 0); - } - - // FIXME double-free exists here - // struct node *tmp; - // while (nodes) { - // tmp = nodes; - // nodes = tmp->next; - // if (tmp->own_string) { - // free((void*)tmp->name); - // } - // free(tmp); - // } - - if (mSyntaxOnly) - return; - - - // do type inferance - - // convert to GENERIC tree's -} - - -void Rustly::do_compile() -{ - // TODO -} - -// C INTERFACE THIS NEEDS CLEANUP AT SOMEPOINT - -void -rust_create_rustly(bool only_check_syntax, Linemap* linemap) -{ - rustly = new Rustly(only_check_syntax, linemap); -} - -void -rust_parse_input_files (const char** in, unsigned int n) -{ - rustly->parse_input_files(n, in); -} diff --git a/gcc/rust/rustfrontend/rustly.h b/gcc/rust/rustfrontend/rustly.h deleted file mode 100644 index db7455f..0000000 --- a/gcc/rust/rustfrontend/rustly.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "rust-linemap.h" -#include "rust-system.h" -#include "rust-c.h" - -#include "rs-parser.h" -#include "node.h" - -class Rustly -{ -public: - Rustly(bool only_check_syntax, Linemap* mLinemap); - - ~Rustly(); - - void parse_input_files (size_t n, const char** in); - - void do_compile(); - -private: - bool mSyntaxOnly; - Linemap* mLinemap; -}; - - diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc index 101237d..8a765da 100644 --- a/gcc/rust/rustspec.cc +++ b/gcc/rust/rustspec.cc @@ -1,4 +1,4 @@ -/* gospec.c -- Specific flags and argument handling of the gcc Go front end. +/* rustspec.c -- Specific flags and argument handling of the gcc Go front end. Copyright (C) 2009-2019 Free Software Foundation, Inc. This file is part of GCC. @@ -24,15 +24,15 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" /* This bit is set if we saw a `-xfoo' language specification. */ -#define LANGSPEC (1<<1) +#define LANGSPEC (1 << 1) /* This bit is set if they did `-lm' or `-lmath'. */ -#define MATHLIB (1<<2) +#define MATHLIB (1 << 2) /* This bit is set if they did `-lpthread'. */ -#define THREADLIB (1<<3) +#define THREADLIB (1 << 3) /* This bit is set if they did `-lc'. */ -#define WITHLIBC (1<<4) +#define WITHLIBC (1 << 4) /* Skip this option. */ -#define SKIPOPT (1<<5) +#define SKIPOPT (1 << 5) #ifndef MATH_LIBRARY #define MATH_LIBRARY "m" @@ -44,10 +44,6 @@ along with GCC; see the file COPYING3. If not see #define THREAD_LIBRARY "pthread" #define THREAD_LIBRARY_PROFILE THREAD_LIBRARY -<<<<<<< HEAD -// Refers to compiler driver: handles calling the compiler (i.e. options, libraries to use) -======= ->>>>>>> c611d209696bd5983b4b777be0beea80351dee46 void lang_specific_driver (struct cl_decoded_option **in_decoded_options, unsigned int *in_decoded_options_count, @@ -125,7 +121,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, #endif /* The first input file with an extension of .go. */ - const char *first_go_file = NULL; + const char *first_go_file = NULL; argc = *in_decoded_options_count; decoded_options = *in_decoded_options; @@ -238,8 +234,8 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, } } - /* There's no point adding -shared-libgcc if we don't have a shared - libgcc. */ + /* There's no point adding -shared-libgcc if we don't have a shared + libgcc. */ #ifndef ENABLE_SHARED_LIBGCC shared_libgcc = 0; #endif @@ -330,12 +326,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, else out[baselen + 1] = 'o'; out[baselen + 2] = '\0'; - generate_option (OPT_o, out, 1, CL_DRIVER, - &new_decoded_options[j]); + generate_option (OPT_o, out, 1, CL_DRIVER, &new_decoded_options[j]); } else - generate_option (OPT_o, "a.out", 1, CL_DRIVER, - &new_decoded_options[j]); + generate_option (OPT_o, "a.out", 1, CL_DRIVER, &new_decoded_options[j]); j++; } @@ -356,10 +350,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, } #endif - // generate_option (OPT_l, saw_profile_flag ? LIBGO_PROFILE : LIBGO, 1, - // CL_DRIVER, &new_decoded_options[j]); - // added_libraries++; - // j++; + // generate_option (OPT_l, saw_profile_flag ? LIBGO_PROFILE : LIBGO, 1, + // CL_DRIVER, &new_decoded_options[j]); + // added_libraries++; + // j++; #ifdef HAVE_LD_STATIC_DYNAMIC if (library > 1 && !static_link) @@ -381,9 +375,8 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, else if (library > 0 && need_thread) { generate_option (OPT_l, - (saw_profile_flag - ? THREAD_LIBRARY_PROFILE - : THREAD_LIBRARY), + (saw_profile_flag ? THREAD_LIBRARY_PROFILE + : THREAD_LIBRARY), 1, CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; @@ -433,10 +426,11 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, } /* Called before linking. Returns 0 on success and -1 on failure. */ -int lang_specific_pre_link (void) /* Not used for Go. */ +int +lang_specific_pre_link (void) /* Not used for Go. */ { return 0; } /* Number of extra output files that lang_specific_pre_link may generate. */ -int lang_specific_extra_outfiles = 0; /* Not used for Go. */ +int lang_specific_extra_outfiles = 0; /* Not used for Go. */ diff --git a/gcc/rust/test/rustc_bison_test/lex.yy.c b/gcc/rust/test/rustc_bison_test/lex.yy.c deleted file mode 100644 index d0b6693..0000000 --- a/gcc/rust/test/rustc_bison_test/lex.yy.c +++ /dev/null @@ -1,3389 +0,0 @@ -// include tokens.h generated by bison for shared token access -#include "token.h" - -#line 2 "lex.yy.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 4 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#ifndef SIZE_MAX -#define SIZE_MAX (~(size_t)0) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* begin standard C++ headers. */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an - * integer in range [0..255] for use as an array index. - */ -#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -extern int yyleng; - -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE yylex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - #define YY_LINENO_REWIND_TO(dst) \ - do {\ - const char *p;\ - for ( p = yy_cp-1; p >= (dst); --p)\ - if ( *p == '\n' )\ - --yylineno;\ - }while(0) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = NULL; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart ( FILE *input_file ); -void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); -void yy_delete_buffer ( YY_BUFFER_STATE b ); -void yy_flush_buffer ( YY_BUFFER_STATE b ); -void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); -void yypop_buffer_state ( void ); - -static void yyensure_buffer_stack ( void ); -static void yy_load_buffer_state ( void ); -static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); -#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); -YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); - -void *yyalloc ( yy_size_t ); -void *yyrealloc ( void *, yy_size_t ); -void yyfree ( void * ); - -#define yy_new_buffer yy_create_buffer -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ -typedef flex_uint8_t YY_CHAR; - -FILE *yyin = NULL, *yyout = NULL; - -typedef int yy_state_type; - -extern int yylineno; -int yylineno = 1; - -extern char *yytext; -#ifdef yytext_ptr -#undef yytext_ptr -#endif -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state ( void ); -static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); -static int yy_get_next_buffer ( void ); -static void yynoreturn yy_fatal_error ( const char* msg ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - (yytext_ptr) -= (yy_more_len); \ - yyleng = (int) (yy_cp - (yytext_ptr)); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 183 -#define YY_END_OF_BUFFER 184 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static const flex_int16_t yy_accept[502] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 10, 10, 7, 7, - 0, 0, 0, 0, 0, 0, 184, 183, 3, 108, - 156, 94, 102, 181, 168, 117, 87, 88, 175, 173, - 83, 165, 86, 177, 78, 78, 101, 82, 112, 106, - 116, 103, 93, 74, 91, 92, 179, 19, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 89, 171, 90, 99, - 74, 162, 157, 162, 147, 146, 151, 150, 149, 153, - - 153, 155, 154, 183, 183, 131, 126, 131, 138, 138, - 136, 134, 133, 98, 95, 183, 97, 96, 183, 119, - 183, 119, 119, 10, 9, 7, 6, 18, 18, 18, - 14, 14, 14, 2, 1, 107, 182, 167, 169, 176, - 174, 166, 164, 85, 15, 8, 178, 80, 78, 0, - 0, 0, 0, 100, 163, 110, 109, 104, 105, 113, - 114, 74, 180, 74, 74, 22, 125, 139, 74, 74, - 74, 74, 74, 74, 74, 31, 74, 74, 74, 74, - 74, 37, 74, 39, 74, 41, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 145, 148, 74, 74, 74, - - 74, 74, 74, 74, 74, 74, 74, 74, 74, 172, - 170, 74, 161, 158, 158, 161, 161, 152, 144, 0, - 144, 0, 0, 0, 130, 127, 130, 130, 137, 0, - 97, 123, 119, 0, 123, 0, 0, 119, 119, 10, - 7, 17, 16, 13, 12, 1, 84, 0, 5, 5, - 79, 80, 79, 0, 81, 77, 76, 75, 111, 115, - 74, 74, 74, 24, 132, 135, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 38, 74, 42, 74, - 74, 74, 46, 74, 48, 74, 74, 74, 74, 54, - 74, 55, 74, 74, 74, 74, 74, 74, 74, 74, - - 74, 74, 74, 69, 74, 74, 74, 74, 4, 0, - 0, 140, 0, 0, 0, 0, 0, 120, 0, 0, - 119, 124, 119, 11, 8, 0, 0, 80, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 32, 33, 74, - 74, 74, 40, 43, 74, 74, 47, 74, 74, 51, - 52, 53, 74, 57, 74, 74, 74, 74, 74, 63, - 64, 74, 74, 74, 74, 74, 74, 74, 0, 159, - 0, 0, 0, 0, 0, 0, 128, 0, 0, 119, - 119, 74, 74, 74, 25, 26, 27, 74, 29, 74, - 74, 35, 36, 44, 45, 74, 74, 74, 74, 74, - - 74, 61, 62, 74, 66, 74, 74, 74, 71, 72, - 73, 0, 0, 160, 0, 0, 0, 0, 141, 0, - 0, 129, 0, 0, 0, 121, 119, 74, 74, 23, - 74, 74, 34, 74, 74, 56, 58, 59, 60, 65, - 67, 74, 74, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 122, 118, 74, 21, 74, 30, 74, - 74, 68, 70, 0, 0, 0, 0, 142, 0, 0, - 0, 0, 0, 20, 28, 49, 50, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, - - 0 - } ; - -static const YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 22, 22, 22, 22, 22, 23, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 31, 31, 31, 32, 31, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 34, 33, 33, 33, 33, 33, - 35, 36, 37, 38, 39, 1, 40, 41, 42, 43, - - 44, 45, 46, 47, 48, 33, 49, 50, 51, 52, - 53, 54, 33, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 1, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 69, 68, 68, 68, - 70, 68, 68, 68, 68, 68, 68, 68, 68, 68, - - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 71, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68 - } ; - -static const YY_CHAR yy_meta[72] = - { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 4, 1, 1, 1, 5, 1, 6, - 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, - 6, 6, 7, 7, 8, 1, 1, 1, 9, 6, - 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 1, 1, 10, 1, 11, 11, 11, - 11 - } ; - -static const flex_int16_t yy_base[566] = - { 0, - 0, 0, 66, 67, 1090, 1089, 68, 70, 1088, 1087, - 1085, 1084, 75, 76, 74, 77, 75, 78, 1084, 1083, - 83, 84, 87, 88, 123, 0, 1085, 1084, 1083, 1082, - 78, 79, 80, 81, 194, 0, 1084, 1097, 1097, 1056, - 1097, 1097, 1097, 1055, 91, 1097, 1097, 1097, 1054, 1053, - 1097, 77, 1061, 252, 262, 254, 1054, 1097, 89, 80, - 92, 1097, 1097, 0, 1097, 1097, 1050, 0, 240, 267, - 247, 244, 255, 273, 267, 251, 56, 265, 212, 285, - 283, 273, 65, 1028, 1028, 1026, 1097, 272, 1097, 1097, - 1004, 1097, 1097, 339, 1097, 1097, 1097, 1097, 1097, 1097, - - 1065, 1097, 1097, 1060, 327, 1097, 1097, 351, 1097, 1063, - 1097, 1097, 1097, 1097, 1097, 1066, 1097, 1097, 1057, 1056, - 363, 257, 297, 0, 1097, 0, 1097, 1097, 1047, 1051, - 1097, 1045, 1049, 1097, 0, 1097, 1097, 1097, 1097, 1097, - 1097, 1097, 1097, 1044, 325, 327, 1097, 405, 411, 425, - 331, 356, 0, 1097, 1097, 1034, 1097, 1097, 1097, 1097, - 1033, 0, 1097, 1003, 1010, 0, 1097, 1097, 1015, 995, - 342, 998, 1002, 1013, 1007, 0, 995, 992, 992, 998, - 995, 0, 991, 0, 991, 0, 987, 990, 316, 301, - 985, 996, 996, 345, 349, 1097, 1097, 335, 989, 975, - - 361, 983, 349, 982, 261, 991, 979, 366, 989, 1097, - 1097, 962, 1097, 1097, 1097, 967, 0, 1097, 1097, 1019, - 1018, 0, 0, 0, 1097, 1097, 964, 0, 1097, 1024, - 1097, 1097, 1015, 1014, 1013, 959, 0, 411, 391, 0, - 0, 1097, 1097, 1097, 1097, 0, 1097, 0, 1097, 1003, - 1097, 445, 458, 449, 470, 415, 465, 0, 1097, 1097, - 964, 974, 966, 0, 1097, 1097, 978, 975, 299, 959, - 975, 970, 962, 968, 955, 970, 0, 959, 0, 954, - 952, 964, 0, 961, 0, 948, 948, 943, 959, 0, - 956, 0, 941, 953, 953, 939, 937, 950, 945, 948, - - 947, 936, 324, 0, 931, 929, 933, 929, 0, 0, - 0, 1097, 939, 936, 0, 0, 0, 1097, 0, 0, - 400, 1097, 430, 1097, 1097, 490, 494, 498, 919, 918, - 918, 916, 917, 903, 911, 912, 897, 0, 0, 896, - 906, 896, 0, 0, 892, 894, 0, 896, 882, 0, - 0, 0, 881, 0, 879, 883, 885, 871, 865, 0, - 868, 866, 872, 851, 855, 865, 864, 861, 417, 1097, - 864, 860, 859, 856, 883, 437, 1097, 456, 880, 483, - 879, 846, 832, 838, 0, 0, 0, 829, 0, 828, - 825, 0, 0, 0, 0, 811, 815, 810, 814, 812, - - 795, 0, 0, 795, 0, 785, 782, 784, 0, 0, - 0, 457, 469, 1097, 782, 781, 776, 745, 1097, 485, - 486, 1097, 487, 488, 771, 1097, 517, 571, 567, 0, - 552, 552, 0, 551, 560, 0, 0, 0, 0, 0, - 0, 559, 551, 491, 495, 561, 560, 342, 559, 497, - 499, 500, 501, 1097, 586, 539, 0, 551, 0, 549, - 549, 0, 0, 502, 503, 553, 551, 1097, 419, 504, - 505, 506, 507, 0, 0, 0, 0, 508, 509, 549, - 493, 510, 511, 516, 517, 519, 521, 467, 443, 523, - 525, 539, 540, 541, 463, 424, 542, 545, 1097, 575, - - 1097, 614, 625, 636, 647, 658, 669, 680, 691, 702, - 713, 724, 735, 746, 757, 768, 774, 785, 796, 807, - 816, 827, 838, 844, 851, 855, 447, 446, 433, 432, - 417, 413, 864, 411, 407, 870, 874, 399, 330, 328, - 283, 263, 878, 883, 887, 891, 896, 901, 906, 910, - 914, 919, 924, 929, 933, 938, 943, 948, 952, 957, - 962, 967, 971, 976, 981 - } ; - -static const flex_int16_t yy_def[566] = - { 0, - 501, 1, 502, 502, 503, 503, 504, 504, 505, 505, - 506, 506, 507, 507, 508, 508, 509, 509, 510, 510, - 511, 511, 512, 512, 501, 25, 513, 513, 514, 514, - 515, 515, 516, 516, 501, 35, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 517, 501, 501, 501, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 501, 501, 501, 501, - 517, 501, 501, 518, 501, 501, 501, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 519, 501, 501, - 501, 501, 501, 501, 501, 520, 501, 501, 501, 521, - 501, 521, 521, 522, 501, 523, 501, 501, 501, 501, - 501, 501, 501, 501, 524, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 525, 501, 501, - 501, 501, 526, 501, 501, 501, 501, 501, 501, 501, - 501, 517, 501, 517, 517, 517, 501, 501, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 501, 501, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 501, - 501, 517, 501, 501, 501, 501, 527, 501, 501, 501, - 501, 528, 529, 530, 501, 501, 501, 531, 501, 520, - 501, 501, 521, 501, 501, 501, 532, 521, 521, 522, - 523, 501, 501, 501, 501, 524, 501, 533, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 526, 501, 501, - 517, 517, 517, 517, 501, 501, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 534, - 535, 501, 536, 537, 538, 539, 540, 501, 541, 542, - 521, 501, 521, 501, 501, 501, 501, 501, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 543, 501, - 544, 536, 545, 537, 501, 546, 501, 547, 501, 521, - 521, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 548, 543, 501, 549, 544, 550, 545, 501, 551, - 546, 501, 552, 547, 501, 501, 521, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 553, 548, 554, 549, 501, 550, 555, - 551, 556, 552, 501, 521, 517, 517, 517, 517, 517, - 517, 517, 517, 557, 553, 558, 554, 501, 501, 559, - 555, 560, 556, 517, 517, 517, 517, 561, 557, 562, - 558, 563, 559, 564, 560, 501, 561, 565, 562, 501, - 563, 501, 564, 501, 501, 565, 501, 501, 501, 501, - - 0, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501 - } ; - -static const flex_int16_t yy_nxt[1169] = - { 0, - 38, 39, 39, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 56, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 64, 64, 64, 65, 38, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 64, 64, 75, 64, 76, - 77, 64, 78, 79, 80, 81, 82, 83, 84, 85, - 64, 86, 64, 87, 88, 89, 90, 64, 64, 64, - 91, 93, 93, 98, 99, 98, 99, 38, 38, 107, - 110, 111, 107, 110, 111, 38, 38, 115, 115, 117, - 117, 129, 129, 132, 132, 189, 130, 130, 133, 133, - - 138, 94, 94, 142, 143, 155, 158, 159, 190, 108, - 105, 105, 108, 191, 156, 157, 205, 139, 160, 161, - 206, 118, 118, 119, 119, 38, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 120, 120, 120, 120, 119, 121, 119, - 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 122, 120, - 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, - 123, 123, 123, 123, 134, 134, 134, 134, 134, 134, - - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 135, 135, 135, 135, 134, 134, - 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, - 134, 135, 135, 135, 135, 145, 194, 232, 379, 195, - 146, 148, 167, 149, 149, 149, 149, 168, 147, 148, - 164, 149, 149, 149, 149, 150, 172, 175, 378, 165, - 196, 197, 149, 150, 187, 166, 176, 150, 210, 173, - - 149, 174, 151, 188, 177, 150, 178, 232, 302, 192, - 169, 184, 180, 238, 152, 179, 303, 185, 186, 170, - 181, 171, 153, 193, 182, 183, 199, 203, 198, 248, - 200, 249, 220, 377, 204, 376, 211, 221, 248, 201, - 202, 214, 215, 283, 214, 250, 220, 265, 266, 214, - 256, 256, 468, 226, 334, 335, 226, 281, 214, 284, - 222, 226, 220, 363, 239, 239, 239, 239, 234, 256, - 226, 364, 282, 235, 214, 257, 257, 257, 220, 292, - 469, 220, 234, 220, 223, 267, 226, 224, 299, 290, - 214, 293, 288, 214, 257, 214, 216, 289, 234, 217, - - 296, 322, 226, 291, 375, 226, 300, 226, 227, 306, - 501, 228, 370, 307, 234, 297, 369, 234, 320, 234, - 236, 501, 317, 237, 252, 252, 252, 252, 148, 468, - 149, 149, 149, 149, 256, 256, 253, 315, 314, 254, - 322, 254, 150, 252, 255, 255, 255, 255, 253, 149, - 321, 313, 311, 256, 150, 413, 380, 469, 323, 323, - 323, 323, 496, 255, 252, 252, 252, 252, 255, 255, - 255, 255, 327, 499, 327, 421, 326, 328, 328, 328, - 328, 489, 414, 252, 257, 257, 257, 255, 326, 255, - 255, 255, 255, 501, 424, 445, 328, 381, 381, 381, - - 381, 500, 422, 257, 327, 496, 327, 413, 255, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 425, 414, 451, 421, 453, 424, 501, 328, 465, - 427, 481, 328, 445, 414, 471, 328, 451, 473, 453, - 479, 465, 483, 471, 485, 473, 487, 479, 491, 483, - 422, 422, 425, 425, 493, 485, 414, 494, 455, 487, - 414, 497, 422, 491, 422, 425, 425, 414, 414, 422, - 422, 425, 425, 414, 414, 422, 422, 498, 493, 494, - 497, 425, 425, 498, 414, 499, 414, 489, 422, 467, - 422, 481, 477, 476, 475, 474, 501, 449, 447, 467, - - 463, 462, 461, 460, 425, 425, 414, 422, 459, 458, - 425, 457, 456, 500, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 100, 100, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 109, 109, 109, 109, 109, 109, 109, 109, 109, - - 109, 109, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 116, 116, 116, 116, 116, 116, - 116, 116, 116, 116, 116, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 162, - 162, 454, 162, 418, 162, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 225, 225, 225, 225, - - 225, 225, 225, 225, 225, 225, 225, 230, 230, 230, - 230, 230, 230, 230, 449, 230, 230, 230, 233, 416, - 447, 233, 233, 443, 233, 442, 233, 240, 441, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 241, 440, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 246, - 246, 439, 246, 438, 246, 251, 251, 251, 437, 251, - 258, 436, 435, 258, 324, 324, 324, 434, 324, 324, - 324, 324, 324, 324, 324, 371, 433, 432, 371, 373, - 431, 430, 373, 412, 429, 428, 412, 412, 415, 322, - 426, 415, 417, 419, 374, 417, 420, 418, 372, 420, - - 420, 423, 416, 411, 423, 423, 444, 410, 409, 444, - 444, 446, 408, 407, 446, 448, 406, 405, 448, 450, - 404, 403, 450, 450, 452, 402, 401, 452, 452, 464, - 400, 399, 464, 464, 466, 398, 397, 466, 470, 396, - 395, 470, 470, 472, 394, 393, 472, 472, 478, 392, - 391, 478, 478, 480, 390, 389, 480, 482, 388, 387, - 482, 482, 484, 386, 385, 484, 484, 486, 384, 383, - 486, 486, 488, 382, 374, 488, 490, 372, 368, 490, - 490, 492, 367, 366, 492, 492, 495, 365, 362, 495, - 361, 360, 359, 358, 357, 356, 355, 354, 353, 352, - - 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, - 341, 340, 339, 338, 337, 336, 333, 332, 331, 330, - 329, 325, 319, 318, 318, 501, 231, 316, 312, 312, - 310, 309, 308, 305, 304, 301, 298, 295, 294, 287, - 286, 285, 280, 279, 278, 277, 276, 275, 274, 273, - 272, 271, 270, 269, 268, 264, 263, 262, 261, 260, - 259, 247, 245, 244, 243, 242, 232, 232, 231, 229, - 219, 218, 212, 209, 208, 207, 163, 154, 144, 141, - 140, 137, 136, 501, 127, 127, 125, 125, 113, 113, - 103, 103, 101, 101, 96, 96, 37, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501 - } ; - -static const flex_int16_t yy_chk[1169] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 4, 7, 7, 8, 8, 13, 14, 15, - 17, 17, 16, 18, 18, 21, 22, 21, 22, 23, - 24, 31, 32, 33, 34, 77, 31, 32, 33, 34, - - 45, 3, 4, 52, 52, 59, 60, 60, 77, 15, - 13, 14, 16, 77, 59, 59, 83, 45, 61, 61, - 83, 23, 24, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 35, 35, 35, 35, 35, 35, - - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 54, 79, 122, 542, 79, - 54, 56, 70, 56, 56, 56, 56, 70, 54, 55, - 69, 55, 55, 55, 55, 56, 71, 72, 541, 69, - 80, 80, 56, 55, 76, 69, 72, 56, 88, 71, - - 55, 71, 55, 76, 73, 55, 73, 123, 205, 78, - 70, 75, 74, 122, 55, 73, 205, 75, 75, 70, - 74, 70, 55, 78, 74, 74, 81, 82, 80, 145, - 81, 146, 105, 540, 82, 539, 88, 105, 145, 81, - 81, 94, 94, 190, 94, 146, 105, 171, 171, 94, - 151, 151, 448, 108, 269, 269, 108, 189, 94, 190, - 105, 108, 105, 303, 123, 123, 123, 123, 121, 151, - 108, 303, 189, 121, 94, 152, 152, 152, 105, 198, - 448, 105, 121, 105, 105, 171, 108, 105, 203, 195, - 94, 198, 194, 94, 152, 94, 94, 194, 121, 94, - - 201, 239, 108, 195, 538, 108, 203, 108, 108, 208, - 321, 108, 535, 208, 121, 201, 534, 121, 532, 121, - 121, 238, 531, 121, 148, 148, 148, 148, 149, 469, - 149, 149, 149, 149, 256, 256, 148, 530, 529, 150, - 323, 150, 149, 148, 150, 150, 150, 150, 148, 149, - 238, 528, 527, 256, 149, 369, 321, 469, 239, 239, - 239, 239, 496, 150, 252, 252, 252, 252, 254, 254, - 254, 254, 253, 495, 253, 376, 252, 253, 253, 253, - 253, 489, 369, 252, 257, 257, 257, 254, 252, 255, - 255, 255, 255, 380, 378, 412, 253, 323, 323, 323, - - 323, 495, 376, 257, 326, 488, 326, 413, 255, 326, - 326, 326, 326, 327, 327, 327, 327, 328, 328, 328, - 328, 378, 412, 420, 421, 423, 424, 427, 326, 444, - 380, 481, 327, 445, 413, 450, 328, 451, 452, 453, - 464, 465, 470, 471, 472, 473, 478, 479, 482, 483, - 420, 421, 423, 424, 484, 485, 444, 486, 427, 487, - 445, 490, 450, 491, 451, 452, 453, 464, 465, 470, - 471, 472, 473, 478, 479, 482, 483, 492, 493, 494, - 497, 484, 485, 498, 486, 500, 487, 480, 490, 467, - 491, 466, 461, 460, 458, 456, 455, 449, 447, 446, - - 443, 442, 435, 434, 492, 493, 494, 497, 432, 431, - 498, 429, 428, 500, 502, 502, 502, 502, 502, 502, - 502, 502, 502, 502, 502, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 504, 504, 504, 504, - 504, 504, 504, 504, 504, 504, 504, 505, 505, 505, - 505, 505, 505, 505, 505, 505, 505, 505, 506, 506, - 506, 506, 506, 506, 506, 506, 506, 506, 506, 507, - 507, 507, 507, 507, 507, 507, 507, 507, 507, 507, - 508, 508, 508, 508, 508, 508, 508, 508, 508, 508, - 508, 509, 509, 509, 509, 509, 509, 509, 509, 509, - - 509, 509, 510, 510, 510, 510, 510, 510, 510, 510, - 510, 510, 510, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 512, 512, 512, 512, 512, 512, - 512, 512, 512, 512, 512, 513, 513, 513, 513, 513, - 513, 513, 513, 513, 513, 513, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 516, 516, - 516, 516, 516, 516, 516, 516, 516, 516, 516, 517, - 517, 425, 517, 418, 517, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 518, 519, 519, 519, 519, - - 519, 519, 519, 519, 519, 519, 519, 520, 520, 520, - 520, 520, 520, 520, 417, 520, 520, 520, 521, 416, - 415, 521, 521, 408, 521, 407, 521, 522, 406, 522, - 522, 522, 522, 522, 522, 522, 522, 522, 523, 404, - 523, 523, 523, 523, 523, 523, 523, 523, 523, 524, - 524, 401, 524, 400, 524, 525, 525, 525, 399, 525, - 526, 398, 397, 526, 533, 533, 533, 396, 533, 533, - 533, 533, 533, 533, 533, 536, 391, 390, 536, 537, - 388, 384, 537, 543, 383, 382, 543, 543, 544, 381, - 379, 544, 545, 375, 374, 545, 546, 373, 372, 546, - - 546, 547, 371, 368, 547, 547, 548, 367, 366, 548, - 548, 549, 365, 364, 549, 550, 363, 362, 550, 551, - 361, 359, 551, 551, 552, 358, 357, 552, 552, 553, - 356, 355, 553, 553, 554, 353, 349, 554, 555, 348, - 346, 555, 555, 556, 345, 342, 556, 556, 557, 341, - 340, 557, 557, 558, 337, 336, 558, 559, 335, 334, - 559, 559, 560, 333, 332, 560, 560, 561, 331, 330, - 561, 561, 562, 329, 314, 562, 563, 313, 308, 563, - 563, 564, 307, 306, 564, 564, 565, 305, 302, 565, - 301, 300, 299, 298, 297, 296, 295, 294, 293, 291, - - 289, 288, 287, 286, 284, 282, 281, 280, 278, 276, - 275, 274, 273, 272, 271, 270, 268, 267, 263, 262, - 261, 250, 236, 235, 234, 233, 230, 227, 221, 220, - 216, 212, 209, 207, 206, 204, 202, 200, 199, 193, - 192, 191, 188, 187, 185, 183, 181, 180, 179, 178, - 177, 175, 174, 173, 172, 170, 169, 165, 164, 161, - 156, 144, 133, 132, 130, 129, 120, 119, 116, 110, - 104, 101, 91, 86, 85, 84, 67, 57, 53, 50, - 49, 44, 40, 37, 30, 29, 28, 27, 20, 19, - 12, 11, 10, 9, 6, 5, 501, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501 - } ; - -/* Table of booleans, true if rule could match eol. */ -static const flex_int32_t yy_rule_can_match_eol[184] = - { 0, -0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, }; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -extern int yy_flex_debug; -int yy_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -static int yy_more_flag = 0; -static int yy_more_len = 0; -#define yymore() ((yy_more_flag) = 1) -#define YY_MORE_ADJ (yy_more_len) -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "lexer.l" -#line 2 "lexer.l" -#include -#include - -static int num_hashes; -static int end_hashes; -static int saw_non_hash; - -#line 922 "lex.yy.c" - -#line 924 "lex.yy.c" - -#define INITIAL 0 -#define str 1 -#define rawstr 2 -#define rawstr_esc_begin 3 -#define rawstr_esc_body 4 -#define rawstr_esc_end 5 -#define byte 6 -#define bytestr 7 -#define rawbytestr 8 -#define rawbytestr_nohash 9 -#define pound 10 -#define shebang_or_attr 11 -#define ltorchar 12 -#define linecomment 13 -#define doc_line 14 -#define blockcomment 15 -#define doc_block 16 -#define suffix 17 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals ( void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int yylex_destroy ( void ); - -int yyget_debug ( void ); - -void yyset_debug ( int debug_flag ); - -YY_EXTRA_TYPE yyget_extra ( void ); - -void yyset_extra ( YY_EXTRA_TYPE user_defined ); - -FILE *yyget_in ( void ); - -void yyset_in ( FILE * _in_str ); - -FILE *yyget_out ( void ); - -void yyset_out ( FILE * _out_str ); - - int yyget_leng ( void ); - -char *yyget_text ( void ); - -int yyget_lineno ( void ); - -void yyset_lineno ( int _line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap ( void ); -#else -extern int yywrap ( void ); -#endif -#endif - -#ifndef YY_NO_UNPUT - - static void yyunput ( int c, char *buf_ptr ); - -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char * ); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput ( void ); -#else -static int input ( void ); -#endif - -#endif - - static int yy_start_stack_ptr = 0; - static int yy_start_stack_depth = 0; - static int *yy_start_stack = NULL; - - static void yy_push_state ( int _new_state ); - - static void yy_pop_state ( void ); - - static int yy_top_state ( void ); - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - int n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (void); - -#define YY_DECL int yylex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_load_buffer_state( ); - } - - { -#line 34 "lexer.l" - - -#line 1171 "lex.yy.c" - - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - (yy_more_len) = 0; - if ( (yy_more_flag) ) - { - (yy_more_len) = (int) ((yy_c_buf_p) - (yytext_ptr)); - (yy_more_flag) = 0; - } - yy_cp = (yy_c_buf_p); - - /* Support of yytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 1097 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - int yyl; - for ( yyl = (yy_more_len); yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - yylineno++; -; - } - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 36 "lexer.l" -{ BEGIN(INITIAL); } - YY_BREAK -case 2: -/* rule 2 can match eol */ -YY_RULE_SETUP -#line 37 "lexer.l" -{ yyless(0); BEGIN(INITIAL); } - YY_BREAK -case 3: -/* rule 3 can match eol */ -YY_RULE_SETUP -#line 39 "lexer.l" -{ } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 41 "lexer.l" -{ - // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise - if (yyget_lineno() != 1) { - return -1; - } -} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 48 "lexer.l" -{ BEGIN(doc_line); yymore(); } - YY_BREAK -case 6: -/* rule 6 can match eol */ -YY_RULE_SETUP -#line 49 "lexer.l" -{ BEGIN(INITIAL); - yyleng--; - yytext[yyleng] = 0; - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 54 "lexer.l" -{ yymore(); } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 56 "lexer.l" -{ BEGIN(linecomment); } - YY_BREAK -case 9: -/* rule 9 can match eol */ -YY_RULE_SETUP -#line 57 "lexer.l" -{ BEGIN(INITIAL); } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 58 "lexer.l" -{ } - YY_BREAK -case 11: -/* rule 11 can match eol */ -YY_RULE_SETUP -#line 60 "lexer.l" -{ yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 61 "lexer.l" -{ yy_push_state(doc_block); yymore(); } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 62 "lexer.l" -{ - yy_pop_state(); - if (yy_top_state() == doc_block) { - yymore(); - } else { - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -} - YY_BREAK -case 14: -/* rule 14 can match eol */ -YY_RULE_SETUP -#line 70 "lexer.l" -{ yymore(); } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 72 "lexer.l" -{ yy_push_state(blockcomment); } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 73 "lexer.l" -{ yy_push_state(blockcomment); } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 74 "lexer.l" -{ yy_pop_state(); } - YY_BREAK -case 18: -/* rule 18 can match eol */ -YY_RULE_SETUP -#line 75 "lexer.l" -{ } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 77 "lexer.l" -{ return UNDERSCORE; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 78 "lexer.l" -{ return ABSTRACT; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 79 "lexer.l" -{ return ALIGNOF; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 80 "lexer.l" -{ return AS; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 81 "lexer.l" -{ return BECOME; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 82 "lexer.l" -{ return BOX; } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 83 "lexer.l" -{ return BREAK; } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 84 "lexer.l" -{ return CATCH; } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 85 "lexer.l" -{ return CONST; } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 86 "lexer.l" -{ return CONTINUE; } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 87 "lexer.l" -{ return CRATE; } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 88 "lexer.l" -{ return DEFAULT; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 89 "lexer.l" -{ return DO; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 90 "lexer.l" -{ return ELSE; } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 91 "lexer.l" -{ return ENUM; } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 92 "lexer.l" -{ return EXTERN; } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 93 "lexer.l" -{ return FALSE; } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 94 "lexer.l" -{ return FINAL; } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 95 "lexer.l" -{ return FN; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 96 "lexer.l" -{ return FOR; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 97 "lexer.l" -{ return IF; } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 98 "lexer.l" -{ return IMPL; } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 99 "lexer.l" -{ return IN; } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 100 "lexer.l" -{ return LET; } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 101 "lexer.l" -{ return LOOP; } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 102 "lexer.l" -{ return MACRO; } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 103 "lexer.l" -{ return MATCH; } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 104 "lexer.l" -{ return MOD; } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 105 "lexer.l" -{ return MOVE; } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 106 "lexer.l" -{ return MUT; } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 107 "lexer.l" -{ return OFFSETOF; } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 108 "lexer.l" -{ return OVERRIDE; } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 109 "lexer.l" -{ return PRIV; } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 110 "lexer.l" -{ return PROC; } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 111 "lexer.l" -{ return PURE; } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 112 "lexer.l" -{ return PUB; } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 113 "lexer.l" -{ return REF; } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 114 "lexer.l" -{ return RETURN; } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 115 "lexer.l" -{ return SELF; } - YY_BREAK -case 58: -YY_RULE_SETUP -#line 116 "lexer.l" -{ return SIZEOF; } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 117 "lexer.l" -{ return STATIC; } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 118 "lexer.l" -{ return STRUCT; } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 119 "lexer.l" -{ return SUPER; } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 120 "lexer.l" -{ return TRAIT; } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 121 "lexer.l" -{ return TRUE; } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 122 "lexer.l" -{ return TYPE; } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 123 "lexer.l" -{ return TYPEOF; } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 124 "lexer.l" -{ return UNION; } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 125 "lexer.l" -{ return UNSAFE; } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 126 "lexer.l" -{ return UNSIZED; } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 127 "lexer.l" -{ return USE; } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 128 "lexer.l" -{ return VIRTUAL; } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 129 "lexer.l" -{ return WHERE; } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 130 "lexer.l" -{ return WHILE; } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 131 "lexer.l" -{ return YIELD; } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 133 "lexer.l" -{ return IDENT; } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 135 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 136 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 137 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 138 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 139 "lexer.l" -{ yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 141 "lexer.l" -{ BEGIN(suffix); return LIT_FLOAT; } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 142 "lexer.l" -{ BEGIN(suffix); return LIT_FLOAT; } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 144 "lexer.l" -{ return ';'; } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 145 "lexer.l" -{ return ','; } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 146 "lexer.l" -{ return DOTDOTDOT; } - YY_BREAK -case 85: -YY_RULE_SETUP -#line 147 "lexer.l" -{ return DOTDOT; } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 148 "lexer.l" -{ return '.'; } - YY_BREAK -case 87: -YY_RULE_SETUP -#line 149 "lexer.l" -{ return '('; } - YY_BREAK -case 88: -YY_RULE_SETUP -#line 150 "lexer.l" -{ return ')'; } - YY_BREAK -case 89: -YY_RULE_SETUP -#line 151 "lexer.l" -{ return '{'; } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 152 "lexer.l" -{ return '}'; } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 153 "lexer.l" -{ return '['; } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 154 "lexer.l" -{ return ']'; } - YY_BREAK -case 93: -YY_RULE_SETUP -#line 155 "lexer.l" -{ return '@'; } - YY_BREAK -case 94: -YY_RULE_SETUP -#line 156 "lexer.l" -{ BEGIN(pound); yymore(); } - YY_BREAK -case 95: -YY_RULE_SETUP -#line 157 "lexer.l" -{ BEGIN(shebang_or_attr); yymore(); } - YY_BREAK -case 96: -YY_RULE_SETUP -#line 158 "lexer.l" -{ - BEGIN(INITIAL); - yyless(2); - return SHEBANG; -} - YY_BREAK -case 97: -/* rule 97 can match eol */ -YY_RULE_SETUP -#line 163 "lexer.l" -{ - // Since the \n was eaten as part of the token, yylineno will have - // been incremented to the value 2 if the shebang was on the first - // line. This yyless undoes that, setting yylineno back to 1. - yyless(yyleng - 1); - if (yyget_lineno() == 1) { - BEGIN(INITIAL); - return SHEBANG_LINE; - } else { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; - } -} - YY_BREAK -case 98: -YY_RULE_SETUP -#line 177 "lexer.l" -{ BEGIN(INITIAL); yyless(1); return '#'; } - YY_BREAK -case 99: -YY_RULE_SETUP -#line 179 "lexer.l" -{ return '~'; } - YY_BREAK -case 100: -YY_RULE_SETUP -#line 180 "lexer.l" -{ return MOD_SEP; } - YY_BREAK -case 101: -YY_RULE_SETUP -#line 181 "lexer.l" -{ return ':'; } - YY_BREAK -case 102: -YY_RULE_SETUP -#line 182 "lexer.l" -{ return '$'; } - YY_BREAK -case 103: -YY_RULE_SETUP -#line 183 "lexer.l" -{ return '?'; } - YY_BREAK -case 104: -YY_RULE_SETUP -#line 185 "lexer.l" -{ return EQEQ; } - YY_BREAK -case 105: -YY_RULE_SETUP -#line 186 "lexer.l" -{ return FAT_ARROW; } - YY_BREAK -case 106: -YY_RULE_SETUP -#line 187 "lexer.l" -{ return '='; } - YY_BREAK -case 107: -YY_RULE_SETUP -#line 188 "lexer.l" -{ return NE; } - YY_BREAK -case 108: -YY_RULE_SETUP -#line 189 "lexer.l" -{ return '!'; } - YY_BREAK -case 109: -YY_RULE_SETUP -#line 190 "lexer.l" -{ return LE; } - YY_BREAK -case 110: -YY_RULE_SETUP -#line 191 "lexer.l" -{ return SHL; } - YY_BREAK -case 111: -YY_RULE_SETUP -#line 192 "lexer.l" -{ return SHLEQ; } - YY_BREAK -case 112: -YY_RULE_SETUP -#line 193 "lexer.l" -{ return '<'; } - YY_BREAK -case 113: -YY_RULE_SETUP -#line 194 "lexer.l" -{ return GE; } - YY_BREAK -case 114: -YY_RULE_SETUP -#line 195 "lexer.l" -{ return SHR; } - YY_BREAK -case 115: -YY_RULE_SETUP -#line 196 "lexer.l" -{ return SHREQ; } - YY_BREAK -case 116: -YY_RULE_SETUP -#line 197 "lexer.l" -{ return '>'; } - YY_BREAK -case 117: -YY_RULE_SETUP -#line 199 "lexer.l" -{ BEGIN(ltorchar); yymore(); } - YY_BREAK -case 118: -YY_RULE_SETUP -#line 200 "lexer.l" -{ BEGIN(INITIAL); return STATIC_LIFETIME; } - YY_BREAK -case 119: -YY_RULE_SETUP -#line 201 "lexer.l" -{ BEGIN(INITIAL); return LIFETIME; } - YY_BREAK -case 120: -YY_RULE_SETUP -#line 202 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 121: -YY_RULE_SETUP -#line 203 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 122: -YY_RULE_SETUP -#line 204 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 123: -YY_RULE_SETUP -#line 205 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 124: -YY_RULE_SETUP -#line 206 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case YY_STATE_EOF(ltorchar): -#line 207 "lexer.l" -{ BEGIN(INITIAL); return -1; } - YY_BREAK -case 125: -YY_RULE_SETUP -#line 209 "lexer.l" -{ BEGIN(bytestr); yymore(); } - YY_BREAK -case 126: -YY_RULE_SETUP -#line 210 "lexer.l" -{ BEGIN(suffix); return LIT_BYTE_STR; } - YY_BREAK -case YY_STATE_EOF(bytestr): -#line 212 "lexer.l" -{ return -1; } - YY_BREAK -case 127: -/* rule 127 can match eol */ -YY_RULE_SETUP -#line 213 "lexer.l" -{ yymore(); } - YY_BREAK -case 128: -YY_RULE_SETUP -#line 214 "lexer.l" -{ yymore(); } - YY_BREAK -case 129: -YY_RULE_SETUP -#line 215 "lexer.l" -{ yymore(); } - YY_BREAK -case 130: -YY_RULE_SETUP -#line 216 "lexer.l" -{ return -1; } - YY_BREAK -case 131: -/* rule 131 can match eol */ -YY_RULE_SETUP -#line 217 "lexer.l" -{ yymore(); } - YY_BREAK -case 132: -YY_RULE_SETUP -#line 219 "lexer.l" -{ BEGIN(rawbytestr_nohash); yymore(); } - YY_BREAK -case 133: -YY_RULE_SETUP -#line 220 "lexer.l" -{ BEGIN(suffix); return LIT_BYTE_STR_RAW; } - YY_BREAK -case 134: -/* rule 134 can match eol */ -YY_RULE_SETUP -#line 221 "lexer.l" -{ yymore(); } - YY_BREAK -case YY_STATE_EOF(rawbytestr_nohash): -#line 222 "lexer.l" -{ return -1; } - YY_BREAK -case 135: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 2; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 224 "lexer.l" -{ - BEGIN(rawbytestr); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - YY_BREAK -case 136: -YY_RULE_SETUP -#line 231 "lexer.l" -{ - if (!saw_non_hash) { - num_hashes++; - } else if (end_hashes != 0) { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - } - yymore(); -} - YY_BREAK -case 137: -YY_RULE_SETUP -#line 243 "lexer.l" -{ - end_hashes = 1; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - yymore(); -} - YY_BREAK -case 138: -/* rule 138 can match eol */ -YY_RULE_SETUP -#line 251 "lexer.l" -{ - if (!saw_non_hash) { - saw_non_hash = 1; - } - if (end_hashes != 0) { - end_hashes = 0; - } - yymore(); -} - YY_BREAK -case YY_STATE_EOF(rawbytestr): -#line 260 "lexer.l" -{ return -1; } - YY_BREAK -case 139: -YY_RULE_SETUP -#line 262 "lexer.l" -{ BEGIN(byte); yymore(); } - YY_BREAK -case 140: -YY_RULE_SETUP -#line 263 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 141: -YY_RULE_SETUP -#line 264 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 142: -YY_RULE_SETUP -#line 265 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 143: -YY_RULE_SETUP -#line 266 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 144: -YY_RULE_SETUP -#line 267 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case YY_STATE_EOF(byte): -#line 268 "lexer.l" -{ BEGIN(INITIAL); return -1; } - YY_BREAK -case 145: -YY_RULE_SETUP -#line 270 "lexer.l" -{ BEGIN(rawstr); yymore(); } - YY_BREAK -case 146: -YY_RULE_SETUP -#line 271 "lexer.l" -{ BEGIN(suffix); return LIT_STR_RAW; } - YY_BREAK -case 147: -/* rule 147 can match eol */ -YY_RULE_SETUP -#line 272 "lexer.l" -{ yymore(); } - YY_BREAK -case YY_STATE_EOF(rawstr): -#line 273 "lexer.l" -{ return -1; } - YY_BREAK -case 148: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 275 "lexer.l" -{ - BEGIN(rawstr_esc_begin); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - YY_BREAK -case 149: -YY_RULE_SETUP -#line 283 "lexer.l" -{ - num_hashes++; - yymore(); -} - YY_BREAK -case 150: -YY_RULE_SETUP -#line 287 "lexer.l" -{ - BEGIN(rawstr_esc_body); - yymore(); -} - YY_BREAK -case 151: -/* rule 151 can match eol */ -YY_RULE_SETUP -#line 291 "lexer.l" -{ return -1; } - YY_BREAK -case 152: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 293 "lexer.l" -{ - BEGIN(rawstr_esc_end); - yymore(); - } - YY_BREAK -case 153: -/* rule 153 can match eol */ -YY_RULE_SETUP -#line 297 "lexer.l" -{ - yymore(); - } - YY_BREAK -case 154: -YY_RULE_SETUP -#line 301 "lexer.l" -{ - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_STR_RAW; - } - yymore(); - } - YY_BREAK -case 155: -/* rule 155 can match eol */ -YY_RULE_SETUP -#line 309 "lexer.l" -{ - end_hashes = 0; - BEGIN(rawstr_esc_body); - yymore(); - } - YY_BREAK -case YY_STATE_EOF(rawstr_esc_begin): -case YY_STATE_EOF(rawstr_esc_body): -case YY_STATE_EOF(rawstr_esc_end): -#line 315 "lexer.l" -{ return -1; } - YY_BREAK -case 156: -YY_RULE_SETUP -#line 317 "lexer.l" -{ BEGIN(str); yymore(); } - YY_BREAK -case 157: -YY_RULE_SETUP -#line 318 "lexer.l" -{ BEGIN(suffix); return LIT_STR; } - YY_BREAK -case YY_STATE_EOF(str): -#line 320 "lexer.l" -{ return -1; } - YY_BREAK -case 158: -/* rule 158 can match eol */ -YY_RULE_SETUP -#line 321 "lexer.l" -{ yymore(); } - YY_BREAK -case 159: -YY_RULE_SETUP -#line 322 "lexer.l" -{ yymore(); } - YY_BREAK -case 160: -YY_RULE_SETUP -#line 323 "lexer.l" -{ yymore(); } - YY_BREAK -case 161: -YY_RULE_SETUP -#line 324 "lexer.l" -{ return -1; } - YY_BREAK -case 162: -/* rule 162 can match eol */ -YY_RULE_SETUP -#line 325 "lexer.l" -{ yymore(); } - YY_BREAK -case 163: -YY_RULE_SETUP -#line 327 "lexer.l" -{ return LARROW; } - YY_BREAK -case 164: -YY_RULE_SETUP -#line 328 "lexer.l" -{ return RARROW; } - YY_BREAK -case 165: -YY_RULE_SETUP -#line 329 "lexer.l" -{ return '-'; } - YY_BREAK -case 166: -YY_RULE_SETUP -#line 330 "lexer.l" -{ return MINUSEQ; } - YY_BREAK -case 167: -YY_RULE_SETUP -#line 331 "lexer.l" -{ return ANDAND; } - YY_BREAK -case 168: -YY_RULE_SETUP -#line 332 "lexer.l" -{ return '&'; } - YY_BREAK -case 169: -YY_RULE_SETUP -#line 333 "lexer.l" -{ return ANDEQ; } - YY_BREAK -case 170: -YY_RULE_SETUP -#line 334 "lexer.l" -{ return OROR; } - YY_BREAK -case 171: -YY_RULE_SETUP -#line 335 "lexer.l" -{ return '|'; } - YY_BREAK -case 172: -YY_RULE_SETUP -#line 336 "lexer.l" -{ return OREQ; } - YY_BREAK -case 173: -YY_RULE_SETUP -#line 337 "lexer.l" -{ return '+'; } - YY_BREAK -case 174: -YY_RULE_SETUP -#line 338 "lexer.l" -{ return PLUSEQ; } - YY_BREAK -case 175: -YY_RULE_SETUP -#line 339 "lexer.l" -{ return '*'; } - YY_BREAK -case 176: -YY_RULE_SETUP -#line 340 "lexer.l" -{ return STAREQ; } - YY_BREAK -case 177: -YY_RULE_SETUP -#line 341 "lexer.l" -{ return '/'; } - YY_BREAK -case 178: -YY_RULE_SETUP -#line 342 "lexer.l" -{ return SLASHEQ; } - YY_BREAK -case 179: -YY_RULE_SETUP -#line 343 "lexer.l" -{ return '^'; } - YY_BREAK -case 180: -YY_RULE_SETUP -#line 344 "lexer.l" -{ return CARETEQ; } - YY_BREAK -case 181: -YY_RULE_SETUP -#line 345 "lexer.l" -{ return '%'; } - YY_BREAK -case 182: -YY_RULE_SETUP -#line 346 "lexer.l" -{ return PERCENTEQ; } - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(pound): -case YY_STATE_EOF(shebang_or_attr): -case YY_STATE_EOF(linecomment): -case YY_STATE_EOF(doc_line): -case YY_STATE_EOF(blockcomment): -case YY_STATE_EOF(doc_block): -case YY_STATE_EOF(suffix): -#line 348 "lexer.l" -{ return 0; } - YY_BREAK -case 183: -YY_RULE_SETUP -#line 350 "lexer.l" -ECHO; - YY_BREAK -#line 2324 "lex.yy.c" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( yywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of yylex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = (yytext_ptr); - int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yyrealloc( (void *) b->yy_ch_buf, - (yy_size_t) (b->yy_buf_size + 2) ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( - (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - /* "- 2" to take care of EOB's */ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - yy_state_type yy_current_state; - char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - int yy_is_jam; - char *yy_cp = (yy_c_buf_p); - - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 501); - - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_UNPUT - - static void yyunput (int c, char * yy_bp ) -{ - char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up yytext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - int number_to_move = (yy_n_chars) + 2; - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - if ( c == '\n' ){ - --yylineno; - } - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap( ) ) - return 0; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - if ( c == '\n' ) - - yylineno++; -; - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_init_buffer( YY_CURRENT_BUFFER, input_file ); - yy_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void yy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yy_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yyfree( (void *) b->yy_ch_buf ); - - yyfree( (void *) b ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void yyensure_buffer_stack (void) -{ - yy_size_t num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return NULL; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (const char * yystr ) -{ - - return yy_scan_bytes( yystr, (int) strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) (_yybytes_len + 2); - buf = (char *) yyalloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - - static void yy_push_state (int _new_state ) -{ - if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) - { - yy_size_t new_size; - - (yy_start_stack_depth) += YY_START_STACK_INCR; - new_size = (yy_size_t) (yy_start_stack_depth) * sizeof( int ); - - if ( ! (yy_start_stack) ) - (yy_start_stack) = (int *) yyalloc( new_size ); - - else - (yy_start_stack) = (int *) yyrealloc( - (void *) (yy_start_stack), new_size ); - - if ( ! (yy_start_stack) ) - YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); - } - - (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; - - BEGIN(_new_state); -} - - static void yy_pop_state (void) -{ - if ( --(yy_start_stack_ptr) < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); -} - - static int yy_top_state (void) -{ - return (yy_start_stack)[(yy_start_stack_ptr) - 1]; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yynoreturn yy_fatal_error (const char* msg ) -{ - fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int yyget_lineno (void) -{ - - return yylineno; -} - -/** Get the input stream. - * - */ -FILE *yyget_in (void) -{ - return yyin; -} - -/** Get the output stream. - * - */ -FILE *yyget_out (void) -{ - return yyout; -} - -/** Get the length of the current token. - * - */ -int yyget_leng (void) -{ - return yyleng; -} - -/** Get the current token. - * - */ - -char *yyget_text (void) -{ - return yytext; -} - -/** Set the current line number. - * @param _line_number line number - * - */ -void yyset_lineno (int _line_number ) -{ - - yylineno = _line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param _in_str A readable stream. - * - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * _in_str ) -{ - yyin = _in_str ; -} - -void yyset_out (FILE * _out_str ) -{ - yyout = _out_str ; -} - -int yyget_debug (void) -{ - return yy_flex_debug; -} - -void yyset_debug (int _bdebug ) -{ - yy_flex_debug = _bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. - */ - - /* We do not touch yylineno unless the option is enabled. */ - yylineno = 1; - - (yy_buffer_stack) = NULL; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = NULL; - (yy_init) = 0; - (yy_start) = 0; - - (yy_start_stack_ptr) = 0; - (yy_start_stack_depth) = 0; - (yy_start_stack) = NULL; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = NULL; - yyout = NULL; -#endif - - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} - -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer( YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(); - } - - /* Destroy the stack itself. */ - yyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Destroy the start condition stack. */ - yyfree( (yy_start_stack) ); - (yy_start_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, const char * s2, int n ) -{ - - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (const char * s ) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *yyalloc (yy_size_t size ) -{ - return malloc(size); -} - -void *yyrealloc (void * ptr, yy_size_t size ) -{ - - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return realloc(ptr, size); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 350 "lexer.l" - - diff --git a/gcc/rust/test/rustc_bison_test/lex.yy.cc b/gcc/rust/test/rustc_bison_test/lex.yy.cc deleted file mode 100644 index 934c28e..0000000 --- a/gcc/rust/test/rustc_bison_test/lex.yy.cc +++ /dev/null @@ -1,3151 +0,0 @@ - -#line 2 "lex.yy.cc" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 4 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - - /* The c++ scanner is a mess. The FlexLexer.h header file relies on the - * following macro. This is required in order to pass the c++-multiple-scanners - * test in the regression suite. We get reports that it breaks inheritance. - * We will address this in a future release of flex, or omit the C++ scanner - * altogether. - */ - #define yyFlexLexer yyFlexLexer - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#ifndef SIZE_MAX -#define SIZE_MAX (~(size_t)0) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* begin standard C++ headers. */ -#include -#include -#include -#include -#include -/* end standard C++ headers. */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an - * integer in range [0..255] for use as an array index. - */ -#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -extern int yyleng; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE yylex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - #define YY_LINENO_REWIND_TO(dst) \ - do {\ - const char *p;\ - for ( p = yy_cp-1; p >= (dst); --p)\ - if ( *p == '\n' )\ - --yylineno;\ - }while(0) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - - std::streambuf* yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -void *yyalloc ( yy_size_t ); -void *yyrealloc ( void *, yy_size_t ); -void yyfree ( void * ); - -#define yy_new_buffer yy_create_buffer -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ -typedef flex_uint8_t YY_CHAR; - -#define yytext_ptr yytext -#define YY_INTERACTIVE - -#include - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - (yytext_ptr) -= (yy_more_len); \ - yyleng = (int) (yy_cp - (yytext_ptr)); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 183 -#define YY_END_OF_BUFFER 184 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static const flex_int16_t yy_accept[502] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 10, 10, 7, 7, - 0, 0, 0, 0, 0, 0, 184, 183, 3, 108, - 156, 94, 102, 181, 168, 117, 87, 88, 175, 173, - 83, 165, 86, 177, 78, 78, 101, 82, 112, 106, - 116, 103, 93, 74, 91, 92, 179, 19, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 89, 171, 90, 99, - 74, 162, 157, 162, 147, 146, 151, 150, 149, 153, - - 153, 155, 154, 183, 183, 131, 126, 131, 138, 138, - 136, 134, 133, 98, 95, 183, 97, 96, 183, 119, - 183, 119, 119, 10, 9, 7, 6, 18, 18, 18, - 14, 14, 14, 2, 1, 107, 182, 167, 169, 176, - 174, 166, 164, 85, 15, 8, 178, 80, 78, 0, - 0, 0, 0, 100, 163, 110, 109, 104, 105, 113, - 114, 74, 180, 74, 74, 22, 125, 139, 74, 74, - 74, 74, 74, 74, 74, 31, 74, 74, 74, 74, - 74, 37, 74, 39, 74, 41, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 145, 148, 74, 74, 74, - - 74, 74, 74, 74, 74, 74, 74, 74, 74, 172, - 170, 74, 161, 158, 158, 161, 161, 152, 144, 0, - 144, 0, 0, 0, 130, 127, 130, 130, 137, 0, - 97, 123, 119, 0, 123, 0, 0, 119, 119, 10, - 7, 17, 16, 13, 12, 1, 84, 0, 5, 5, - 79, 80, 79, 0, 81, 77, 76, 75, 111, 115, - 74, 74, 74, 24, 132, 135, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 38, 74, 42, 74, - 74, 74, 46, 74, 48, 74, 74, 74, 74, 54, - 74, 55, 74, 74, 74, 74, 74, 74, 74, 74, - - 74, 74, 74, 69, 74, 74, 74, 74, 4, 0, - 0, 140, 0, 0, 0, 0, 0, 120, 0, 0, - 119, 124, 119, 11, 8, 0, 0, 80, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 32, 33, 74, - 74, 74, 40, 43, 74, 74, 47, 74, 74, 51, - 52, 53, 74, 57, 74, 74, 74, 74, 74, 63, - 64, 74, 74, 74, 74, 74, 74, 74, 0, 159, - 0, 0, 0, 0, 0, 0, 128, 0, 0, 119, - 119, 74, 74, 74, 25, 26, 27, 74, 29, 74, - 74, 35, 36, 44, 45, 74, 74, 74, 74, 74, - - 74, 61, 62, 74, 66, 74, 74, 74, 71, 72, - 73, 0, 0, 160, 0, 0, 0, 0, 141, 0, - 0, 129, 0, 0, 0, 121, 119, 74, 74, 23, - 74, 74, 34, 74, 74, 56, 58, 59, 60, 65, - 67, 74, 74, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 122, 118, 74, 21, 74, 30, 74, - 74, 68, 70, 0, 0, 0, 0, 142, 0, 0, - 0, 0, 0, 20, 28, 49, 50, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, - - 0 - } ; - -static const YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 22, 22, 22, 22, 22, 23, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 31, 31, 31, 32, 31, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 34, 33, 33, 33, 33, 33, - 35, 36, 37, 38, 39, 1, 40, 41, 42, 43, - - 44, 45, 46, 47, 48, 33, 49, 50, 51, 52, - 53, 54, 33, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 1, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 69, 68, 68, 68, - 70, 68, 68, 68, 68, 68, 68, 68, 68, 68, - - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 71, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68 - } ; - -static const YY_CHAR yy_meta[72] = - { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 4, 1, 1, 1, 5, 1, 6, - 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, - 6, 6, 7, 7, 8, 1, 1, 1, 9, 6, - 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 1, 1, 10, 1, 11, 11, 11, - 11 - } ; - -static const flex_int16_t yy_base[566] = - { 0, - 0, 0, 66, 67, 1090, 1089, 68, 70, 1088, 1087, - 1085, 1084, 75, 76, 74, 77, 75, 78, 1084, 1083, - 83, 84, 87, 88, 123, 0, 1085, 1084, 1083, 1082, - 78, 79, 80, 81, 194, 0, 1084, 1097, 1097, 1056, - 1097, 1097, 1097, 1055, 91, 1097, 1097, 1097, 1054, 1053, - 1097, 77, 1061, 252, 262, 254, 1054, 1097, 89, 80, - 92, 1097, 1097, 0, 1097, 1097, 1050, 0, 240, 267, - 247, 244, 255, 273, 267, 251, 56, 265, 212, 285, - 283, 273, 65, 1028, 1028, 1026, 1097, 272, 1097, 1097, - 1004, 1097, 1097, 339, 1097, 1097, 1097, 1097, 1097, 1097, - - 1065, 1097, 1097, 1060, 327, 1097, 1097, 351, 1097, 1063, - 1097, 1097, 1097, 1097, 1097, 1066, 1097, 1097, 1057, 1056, - 363, 257, 297, 0, 1097, 0, 1097, 1097, 1047, 1051, - 1097, 1045, 1049, 1097, 0, 1097, 1097, 1097, 1097, 1097, - 1097, 1097, 1097, 1044, 325, 327, 1097, 405, 411, 425, - 331, 356, 0, 1097, 1097, 1034, 1097, 1097, 1097, 1097, - 1033, 0, 1097, 1003, 1010, 0, 1097, 1097, 1015, 995, - 342, 998, 1002, 1013, 1007, 0, 995, 992, 992, 998, - 995, 0, 991, 0, 991, 0, 987, 990, 316, 301, - 985, 996, 996, 345, 349, 1097, 1097, 335, 989, 975, - - 361, 983, 349, 982, 261, 991, 979, 366, 989, 1097, - 1097, 962, 1097, 1097, 1097, 967, 0, 1097, 1097, 1019, - 1018, 0, 0, 0, 1097, 1097, 964, 0, 1097, 1024, - 1097, 1097, 1015, 1014, 1013, 959, 0, 411, 391, 0, - 0, 1097, 1097, 1097, 1097, 0, 1097, 0, 1097, 1003, - 1097, 445, 458, 449, 470, 415, 465, 0, 1097, 1097, - 964, 974, 966, 0, 1097, 1097, 978, 975, 299, 959, - 975, 970, 962, 968, 955, 970, 0, 959, 0, 954, - 952, 964, 0, 961, 0, 948, 948, 943, 959, 0, - 956, 0, 941, 953, 953, 939, 937, 950, 945, 948, - - 947, 936, 324, 0, 931, 929, 933, 929, 0, 0, - 0, 1097, 939, 936, 0, 0, 0, 1097, 0, 0, - 400, 1097, 430, 1097, 1097, 490, 494, 498, 919, 918, - 918, 916, 917, 903, 911, 912, 897, 0, 0, 896, - 906, 896, 0, 0, 892, 894, 0, 896, 882, 0, - 0, 0, 881, 0, 879, 883, 885, 871, 865, 0, - 868, 866, 872, 851, 855, 865, 864, 861, 417, 1097, - 864, 860, 859, 856, 883, 437, 1097, 456, 880, 483, - 879, 846, 832, 838, 0, 0, 0, 829, 0, 828, - 825, 0, 0, 0, 0, 811, 815, 810, 814, 812, - - 795, 0, 0, 795, 0, 785, 782, 784, 0, 0, - 0, 457, 469, 1097, 782, 781, 776, 745, 1097, 485, - 486, 1097, 487, 488, 771, 1097, 517, 571, 567, 0, - 552, 552, 0, 551, 560, 0, 0, 0, 0, 0, - 0, 559, 551, 491, 495, 561, 560, 342, 559, 497, - 499, 500, 501, 1097, 586, 539, 0, 551, 0, 549, - 549, 0, 0, 502, 503, 553, 551, 1097, 419, 504, - 505, 506, 507, 0, 0, 0, 0, 508, 509, 549, - 493, 510, 511, 516, 517, 519, 521, 467, 443, 523, - 525, 539, 540, 541, 463, 424, 542, 545, 1097, 575, - - 1097, 614, 625, 636, 647, 658, 669, 680, 691, 702, - 713, 724, 735, 746, 757, 768, 774, 785, 796, 807, - 816, 827, 838, 844, 851, 855, 447, 446, 433, 432, - 417, 413, 864, 411, 407, 870, 874, 399, 330, 328, - 283, 263, 878, 883, 887, 891, 896, 901, 906, 910, - 914, 919, 924, 929, 933, 938, 943, 948, 952, 957, - 962, 967, 971, 976, 981 - } ; - -static const flex_int16_t yy_def[566] = - { 0, - 501, 1, 502, 502, 503, 503, 504, 504, 505, 505, - 506, 506, 507, 507, 508, 508, 509, 509, 510, 510, - 511, 511, 512, 512, 501, 25, 513, 513, 514, 514, - 515, 515, 516, 516, 501, 35, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 517, 501, 501, 501, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 501, 501, 501, 501, - 517, 501, 501, 518, 501, 501, 501, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 519, 501, 501, - 501, 501, 501, 501, 501, 520, 501, 501, 501, 521, - 501, 521, 521, 522, 501, 523, 501, 501, 501, 501, - 501, 501, 501, 501, 524, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 525, 501, 501, - 501, 501, 526, 501, 501, 501, 501, 501, 501, 501, - 501, 517, 501, 517, 517, 517, 501, 501, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 501, 501, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 501, - 501, 517, 501, 501, 501, 501, 527, 501, 501, 501, - 501, 528, 529, 530, 501, 501, 501, 531, 501, 520, - 501, 501, 521, 501, 501, 501, 532, 521, 521, 522, - 523, 501, 501, 501, 501, 524, 501, 533, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 526, 501, 501, - 517, 517, 517, 517, 501, 501, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 534, - 535, 501, 536, 537, 538, 539, 540, 501, 541, 542, - 521, 501, 521, 501, 501, 501, 501, 501, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 543, 501, - 544, 536, 545, 537, 501, 546, 501, 547, 501, 521, - 521, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 548, 543, 501, 549, 544, 550, 545, 501, 551, - 546, 501, 552, 547, 501, 501, 521, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 553, 548, 554, 549, 501, 550, 555, - 551, 556, 552, 501, 521, 517, 517, 517, 517, 517, - 517, 517, 517, 557, 553, 558, 554, 501, 501, 559, - 555, 560, 556, 517, 517, 517, 517, 561, 557, 562, - 558, 563, 559, 564, 560, 501, 561, 565, 562, 501, - 563, 501, 564, 501, 501, 565, 501, 501, 501, 501, - - 0, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501 - } ; - -static const flex_int16_t yy_nxt[1169] = - { 0, - 38, 39, 39, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 56, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 64, 64, 64, 65, 38, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 64, 64, 75, 64, 76, - 77, 64, 78, 79, 80, 81, 82, 83, 84, 85, - 64, 86, 64, 87, 88, 89, 90, 64, 64, 64, - 91, 93, 93, 98, 99, 98, 99, 38, 38, 107, - 110, 111, 107, 110, 111, 38, 38, 115, 115, 117, - 117, 129, 129, 132, 132, 189, 130, 130, 133, 133, - - 138, 94, 94, 142, 143, 155, 158, 159, 190, 108, - 105, 105, 108, 191, 156, 157, 205, 139, 160, 161, - 206, 118, 118, 119, 119, 38, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 120, 120, 120, 120, 119, 121, 119, - 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 122, 120, - 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, - 123, 123, 123, 123, 134, 134, 134, 134, 134, 134, - - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 135, 135, 135, 135, 134, 134, - 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, - 134, 135, 135, 135, 135, 145, 194, 232, 379, 195, - 146, 148, 167, 149, 149, 149, 149, 168, 147, 148, - 164, 149, 149, 149, 149, 150, 172, 175, 378, 165, - 196, 197, 149, 150, 187, 166, 176, 150, 210, 173, - - 149, 174, 151, 188, 177, 150, 178, 232, 302, 192, - 169, 184, 180, 238, 152, 179, 303, 185, 186, 170, - 181, 171, 153, 193, 182, 183, 199, 203, 198, 248, - 200, 249, 220, 377, 204, 376, 211, 221, 248, 201, - 202, 214, 215, 283, 214, 250, 220, 265, 266, 214, - 256, 256, 468, 226, 334, 335, 226, 281, 214, 284, - 222, 226, 220, 363, 239, 239, 239, 239, 234, 256, - 226, 364, 282, 235, 214, 257, 257, 257, 220, 292, - 469, 220, 234, 220, 223, 267, 226, 224, 299, 290, - 214, 293, 288, 214, 257, 214, 216, 289, 234, 217, - - 296, 322, 226, 291, 375, 226, 300, 226, 227, 306, - 501, 228, 370, 307, 234, 297, 369, 234, 320, 234, - 236, 501, 317, 237, 252, 252, 252, 252, 148, 468, - 149, 149, 149, 149, 256, 256, 253, 315, 314, 254, - 322, 254, 150, 252, 255, 255, 255, 255, 253, 149, - 321, 313, 311, 256, 150, 413, 380, 469, 323, 323, - 323, 323, 496, 255, 252, 252, 252, 252, 255, 255, - 255, 255, 327, 499, 327, 421, 326, 328, 328, 328, - 328, 489, 414, 252, 257, 257, 257, 255, 326, 255, - 255, 255, 255, 501, 424, 445, 328, 381, 381, 381, - - 381, 500, 422, 257, 327, 496, 327, 413, 255, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 425, 414, 451, 421, 453, 424, 501, 328, 465, - 427, 481, 328, 445, 414, 471, 328, 451, 473, 453, - 479, 465, 483, 471, 485, 473, 487, 479, 491, 483, - 422, 422, 425, 425, 493, 485, 414, 494, 455, 487, - 414, 497, 422, 491, 422, 425, 425, 414, 414, 422, - 422, 425, 425, 414, 414, 422, 422, 498, 493, 494, - 497, 425, 425, 498, 414, 499, 414, 489, 422, 467, - 422, 481, 477, 476, 475, 474, 501, 449, 447, 467, - - 463, 462, 461, 460, 425, 425, 414, 422, 459, 458, - 425, 457, 456, 500, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 100, 100, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 109, 109, 109, 109, 109, 109, 109, 109, 109, - - 109, 109, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 116, 116, 116, 116, 116, 116, - 116, 116, 116, 116, 116, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 162, - 162, 454, 162, 418, 162, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 225, 225, 225, 225, - - 225, 225, 225, 225, 225, 225, 225, 230, 230, 230, - 230, 230, 230, 230, 449, 230, 230, 230, 233, 416, - 447, 233, 233, 443, 233, 442, 233, 240, 441, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 241, 440, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 246, - 246, 439, 246, 438, 246, 251, 251, 251, 437, 251, - 258, 436, 435, 258, 324, 324, 324, 434, 324, 324, - 324, 324, 324, 324, 324, 371, 433, 432, 371, 373, - 431, 430, 373, 412, 429, 428, 412, 412, 415, 322, - 426, 415, 417, 419, 374, 417, 420, 418, 372, 420, - - 420, 423, 416, 411, 423, 423, 444, 410, 409, 444, - 444, 446, 408, 407, 446, 448, 406, 405, 448, 450, - 404, 403, 450, 450, 452, 402, 401, 452, 452, 464, - 400, 399, 464, 464, 466, 398, 397, 466, 470, 396, - 395, 470, 470, 472, 394, 393, 472, 472, 478, 392, - 391, 478, 478, 480, 390, 389, 480, 482, 388, 387, - 482, 482, 484, 386, 385, 484, 484, 486, 384, 383, - 486, 486, 488, 382, 374, 488, 490, 372, 368, 490, - 490, 492, 367, 366, 492, 492, 495, 365, 362, 495, - 361, 360, 359, 358, 357, 356, 355, 354, 353, 352, - - 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, - 341, 340, 339, 338, 337, 336, 333, 332, 331, 330, - 329, 325, 319, 318, 318, 501, 231, 316, 312, 312, - 310, 309, 308, 305, 304, 301, 298, 295, 294, 287, - 286, 285, 280, 279, 278, 277, 276, 275, 274, 273, - 272, 271, 270, 269, 268, 264, 263, 262, 261, 260, - 259, 247, 245, 244, 243, 242, 232, 232, 231, 229, - 219, 218, 212, 209, 208, 207, 163, 154, 144, 141, - 140, 137, 136, 501, 127, 127, 125, 125, 113, 113, - 103, 103, 101, 101, 96, 96, 37, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501 - } ; - -static const flex_int16_t yy_chk[1169] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 4, 7, 7, 8, 8, 13, 14, 15, - 17, 17, 16, 18, 18, 21, 22, 21, 22, 23, - 24, 31, 32, 33, 34, 77, 31, 32, 33, 34, - - 45, 3, 4, 52, 52, 59, 60, 60, 77, 15, - 13, 14, 16, 77, 59, 59, 83, 45, 61, 61, - 83, 23, 24, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 35, 35, 35, 35, 35, 35, - - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 54, 79, 122, 542, 79, - 54, 56, 70, 56, 56, 56, 56, 70, 54, 55, - 69, 55, 55, 55, 55, 56, 71, 72, 541, 69, - 80, 80, 56, 55, 76, 69, 72, 56, 88, 71, - - 55, 71, 55, 76, 73, 55, 73, 123, 205, 78, - 70, 75, 74, 122, 55, 73, 205, 75, 75, 70, - 74, 70, 55, 78, 74, 74, 81, 82, 80, 145, - 81, 146, 105, 540, 82, 539, 88, 105, 145, 81, - 81, 94, 94, 190, 94, 146, 105, 171, 171, 94, - 151, 151, 448, 108, 269, 269, 108, 189, 94, 190, - 105, 108, 105, 303, 123, 123, 123, 123, 121, 151, - 108, 303, 189, 121, 94, 152, 152, 152, 105, 198, - 448, 105, 121, 105, 105, 171, 108, 105, 203, 195, - 94, 198, 194, 94, 152, 94, 94, 194, 121, 94, - - 201, 239, 108, 195, 538, 108, 203, 108, 108, 208, - 321, 108, 535, 208, 121, 201, 534, 121, 532, 121, - 121, 238, 531, 121, 148, 148, 148, 148, 149, 469, - 149, 149, 149, 149, 256, 256, 148, 530, 529, 150, - 323, 150, 149, 148, 150, 150, 150, 150, 148, 149, - 238, 528, 527, 256, 149, 369, 321, 469, 239, 239, - 239, 239, 496, 150, 252, 252, 252, 252, 254, 254, - 254, 254, 253, 495, 253, 376, 252, 253, 253, 253, - 253, 489, 369, 252, 257, 257, 257, 254, 252, 255, - 255, 255, 255, 380, 378, 412, 253, 323, 323, 323, - - 323, 495, 376, 257, 326, 488, 326, 413, 255, 326, - 326, 326, 326, 327, 327, 327, 327, 328, 328, 328, - 328, 378, 412, 420, 421, 423, 424, 427, 326, 444, - 380, 481, 327, 445, 413, 450, 328, 451, 452, 453, - 464, 465, 470, 471, 472, 473, 478, 479, 482, 483, - 420, 421, 423, 424, 484, 485, 444, 486, 427, 487, - 445, 490, 450, 491, 451, 452, 453, 464, 465, 470, - 471, 472, 473, 478, 479, 482, 483, 492, 493, 494, - 497, 484, 485, 498, 486, 500, 487, 480, 490, 467, - 491, 466, 461, 460, 458, 456, 455, 449, 447, 446, - - 443, 442, 435, 434, 492, 493, 494, 497, 432, 431, - 498, 429, 428, 500, 502, 502, 502, 502, 502, 502, - 502, 502, 502, 502, 502, 503, 503, 503, 503, 503, - 503, 503, 503, 503, 503, 503, 504, 504, 504, 504, - 504, 504, 504, 504, 504, 504, 504, 505, 505, 505, - 505, 505, 505, 505, 505, 505, 505, 505, 506, 506, - 506, 506, 506, 506, 506, 506, 506, 506, 506, 507, - 507, 507, 507, 507, 507, 507, 507, 507, 507, 507, - 508, 508, 508, 508, 508, 508, 508, 508, 508, 508, - 508, 509, 509, 509, 509, 509, 509, 509, 509, 509, - - 509, 509, 510, 510, 510, 510, 510, 510, 510, 510, - 510, 510, 510, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 512, 512, 512, 512, 512, 512, - 512, 512, 512, 512, 512, 513, 513, 513, 513, 513, - 513, 513, 513, 513, 513, 513, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 516, 516, - 516, 516, 516, 516, 516, 516, 516, 516, 516, 517, - 517, 425, 517, 418, 517, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 518, 519, 519, 519, 519, - - 519, 519, 519, 519, 519, 519, 519, 520, 520, 520, - 520, 520, 520, 520, 417, 520, 520, 520, 521, 416, - 415, 521, 521, 408, 521, 407, 521, 522, 406, 522, - 522, 522, 522, 522, 522, 522, 522, 522, 523, 404, - 523, 523, 523, 523, 523, 523, 523, 523, 523, 524, - 524, 401, 524, 400, 524, 525, 525, 525, 399, 525, - 526, 398, 397, 526, 533, 533, 533, 396, 533, 533, - 533, 533, 533, 533, 533, 536, 391, 390, 536, 537, - 388, 384, 537, 543, 383, 382, 543, 543, 544, 381, - 379, 544, 545, 375, 374, 545, 546, 373, 372, 546, - - 546, 547, 371, 368, 547, 547, 548, 367, 366, 548, - 548, 549, 365, 364, 549, 550, 363, 362, 550, 551, - 361, 359, 551, 551, 552, 358, 357, 552, 552, 553, - 356, 355, 553, 553, 554, 353, 349, 554, 555, 348, - 346, 555, 555, 556, 345, 342, 556, 556, 557, 341, - 340, 557, 557, 558, 337, 336, 558, 559, 335, 334, - 559, 559, 560, 333, 332, 560, 560, 561, 331, 330, - 561, 561, 562, 329, 314, 562, 563, 313, 308, 563, - 563, 564, 307, 306, 564, 564, 565, 305, 302, 565, - 301, 300, 299, 298, 297, 296, 295, 294, 293, 291, - - 289, 288, 287, 286, 284, 282, 281, 280, 278, 276, - 275, 274, 273, 272, 271, 270, 268, 267, 263, 262, - 261, 250, 236, 235, 234, 233, 230, 227, 221, 220, - 216, 212, 209, 207, 206, 204, 202, 200, 199, 193, - 192, 191, 188, 187, 185, 183, 181, 180, 179, 178, - 177, 175, 174, 173, 172, 170, 169, 165, 164, 161, - 156, 144, 133, 132, 130, 129, 120, 119, 116, 110, - 104, 101, 91, 86, 85, 84, 67, 57, 53, 50, - 49, 44, 40, 37, 30, 29, 28, 27, 20, 19, - 12, 11, 10, 9, 6, 5, 501, 501, 501, 501, - - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501 - } ; - -/* Table of booleans, true if rule could match eol. */ -static const flex_int32_t yy_rule_can_match_eol[184] = - { 0, -0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, }; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() ((yy_more_flag) = 1) -#define YY_MORE_ADJ (yy_more_len) -#define YY_RESTORE_YY_MORE_OFFSET -#line 1 "lexer.l" -#line 2 "lexer.l" -#include -#include - -static int num_hashes; -static int end_hashes; -static int saw_non_hash; - -#line 872 "lex.yy.cc" - -#line 874 "lex.yy.cc" - -#define INITIAL 0 -#define str 1 -#define rawstr 2 -#define rawstr_esc_begin 3 -#define rawstr_esc_body 4 -#define rawstr_esc_end 5 -#define byte 6 -#define bytestr 7 -#define rawbytestr 8 -#define rawbytestr_nohash 9 -#define pound 10 -#define shebang_or_attr 11 -#define ltorchar 12 -#define linecomment 13 -#define doc_line 14 -#define blockcomment 15 -#define doc_block 16 -#define suffix 17 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char * ); -#endif - -#ifndef YY_NO_INPUT - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -#define ECHO LexerOutput( yytext, yyleng ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ -\ - if ( (int)(result = LexerInput( (char *) buf, max_size )) < 0 ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) LexerError( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 -#define YY_DECL int yyFlexLexer::yylex() -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! yyin ) - yyin.rdbuf(std::cin.rdbuf()); - - if ( ! yyout ) - yyout.rdbuf(std::cout.rdbuf()); - - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_load_buffer_state( ); - } - - { -#line 34 "lexer.l" - - -#line 1026 "lex.yy.cc" - - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - (yy_more_len) = 0; - if ( (yy_more_flag) ) - { - (yy_more_len) = (int) ((yy_c_buf_p) - (yytext_ptr)); - (yy_more_flag) = 0; - } - yy_cp = (yy_c_buf_p); - - /* Support of yytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 1097 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - int yyl; - for ( yyl = (yy_more_len); yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - yylineno++; -; - } - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 36 "lexer.l" -{ BEGIN(INITIAL); } - YY_BREAK -case 2: -/* rule 2 can match eol */ -YY_RULE_SETUP -#line 37 "lexer.l" -{ yyless(0); BEGIN(INITIAL); } - YY_BREAK -case 3: -/* rule 3 can match eol */ -YY_RULE_SETUP -#line 39 "lexer.l" -{ } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 41 "lexer.l" -{ - // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise - if (yyget_lineno() != 1) { - return -1; - } -} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 48 "lexer.l" -{ BEGIN(doc_line); yymore(); } - YY_BREAK -case 6: -/* rule 6 can match eol */ -YY_RULE_SETUP -#line 49 "lexer.l" -{ BEGIN(INITIAL); - yyleng--; - yytext[yyleng] = 0; - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 54 "lexer.l" -{ yymore(); } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 56 "lexer.l" -{ BEGIN(linecomment); } - YY_BREAK -case 9: -/* rule 9 can match eol */ -YY_RULE_SETUP -#line 57 "lexer.l" -{ BEGIN(INITIAL); } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 58 "lexer.l" -{ } - YY_BREAK -case 11: -/* rule 11 can match eol */ -YY_RULE_SETUP -#line 60 "lexer.l" -{ yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 61 "lexer.l" -{ yy_push_state(doc_block); yymore(); } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 62 "lexer.l" -{ - yy_pop_state(); - if (yy_top_state() == doc_block) { - yymore(); - } else { - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -} - YY_BREAK -case 14: -/* rule 14 can match eol */ -YY_RULE_SETUP -#line 70 "lexer.l" -{ yymore(); } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 72 "lexer.l" -{ yy_push_state(blockcomment); } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 73 "lexer.l" -{ yy_push_state(blockcomment); } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 74 "lexer.l" -{ yy_pop_state(); } - YY_BREAK -case 18: -/* rule 18 can match eol */ -YY_RULE_SETUP -#line 75 "lexer.l" -{ } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 77 "lexer.l" -{ return UNDERSCORE; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 78 "lexer.l" -{ return ABSTRACT; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 79 "lexer.l" -{ return ALIGNOF; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 80 "lexer.l" -{ return AS; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 81 "lexer.l" -{ return BECOME; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 82 "lexer.l" -{ return BOX; } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 83 "lexer.l" -{ return BREAK; } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 84 "lexer.l" -{ return CATCH; } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 85 "lexer.l" -{ return CONST; } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 86 "lexer.l" -{ return CONTINUE; } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 87 "lexer.l" -{ return CRATE; } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 88 "lexer.l" -{ return DEFAULT; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 89 "lexer.l" -{ return DO; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 90 "lexer.l" -{ return ELSE; } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 91 "lexer.l" -{ return ENUM; } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 92 "lexer.l" -{ return EXTERN; } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 93 "lexer.l" -{ return FALSE; } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 94 "lexer.l" -{ return FINAL; } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 95 "lexer.l" -{ return FN; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 96 "lexer.l" -{ return FOR; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 97 "lexer.l" -{ return IF; } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 98 "lexer.l" -{ return IMPL; } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 99 "lexer.l" -{ return IN; } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 100 "lexer.l" -{ return LET; } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 101 "lexer.l" -{ return LOOP; } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 102 "lexer.l" -{ return MACRO; } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 103 "lexer.l" -{ return MATCH; } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 104 "lexer.l" -{ return MOD; } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 105 "lexer.l" -{ return MOVE; } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 106 "lexer.l" -{ return MUT; } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 107 "lexer.l" -{ return OFFSETOF; } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 108 "lexer.l" -{ return OVERRIDE; } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 109 "lexer.l" -{ return PRIV; } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 110 "lexer.l" -{ return PROC; } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 111 "lexer.l" -{ return PURE; } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 112 "lexer.l" -{ return PUB; } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 113 "lexer.l" -{ return REF; } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 114 "lexer.l" -{ return RETURN; } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 115 "lexer.l" -{ return SELF; } - YY_BREAK -case 58: -YY_RULE_SETUP -#line 116 "lexer.l" -{ return SIZEOF; } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 117 "lexer.l" -{ return STATIC; } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 118 "lexer.l" -{ return STRUCT; } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 119 "lexer.l" -{ return SUPER; } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 120 "lexer.l" -{ return TRAIT; } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 121 "lexer.l" -{ return TRUE; } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 122 "lexer.l" -{ return TYPE; } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 123 "lexer.l" -{ return TYPEOF; } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 124 "lexer.l" -{ return UNION; } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 125 "lexer.l" -{ return UNSAFE; } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 126 "lexer.l" -{ return UNSIZED; } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 127 "lexer.l" -{ return USE; } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 128 "lexer.l" -{ return VIRTUAL; } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 129 "lexer.l" -{ return WHERE; } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 130 "lexer.l" -{ return WHILE; } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 131 "lexer.l" -{ return YIELD; } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 133 "lexer.l" -{ return IDENT; } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 135 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 136 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 137 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 138 "lexer.l" -{ BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 139 "lexer.l" -{ yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 141 "lexer.l" -{ BEGIN(suffix); return LIT_FLOAT; } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 142 "lexer.l" -{ BEGIN(suffix); return LIT_FLOAT; } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 144 "lexer.l" -{ return ';'; } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 145 "lexer.l" -{ return ','; } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 146 "lexer.l" -{ return DOTDOTDOT; } - YY_BREAK -case 85: -YY_RULE_SETUP -#line 147 "lexer.l" -{ return DOTDOT; } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 148 "lexer.l" -{ return '.'; } - YY_BREAK -case 87: -YY_RULE_SETUP -#line 149 "lexer.l" -{ return '('; } - YY_BREAK -case 88: -YY_RULE_SETUP -#line 150 "lexer.l" -{ return ')'; } - YY_BREAK -case 89: -YY_RULE_SETUP -#line 151 "lexer.l" -{ return '{'; } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 152 "lexer.l" -{ return '}'; } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 153 "lexer.l" -{ return '['; } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 154 "lexer.l" -{ return ']'; } - YY_BREAK -case 93: -YY_RULE_SETUP -#line 155 "lexer.l" -{ return '@'; } - YY_BREAK -case 94: -YY_RULE_SETUP -#line 156 "lexer.l" -{ BEGIN(pound); yymore(); } - YY_BREAK -case 95: -YY_RULE_SETUP -#line 157 "lexer.l" -{ BEGIN(shebang_or_attr); yymore(); } - YY_BREAK -case 96: -YY_RULE_SETUP -#line 158 "lexer.l" -{ - BEGIN(INITIAL); - yyless(2); - return SHEBANG; -} - YY_BREAK -case 97: -/* rule 97 can match eol */ -YY_RULE_SETUP -#line 163 "lexer.l" -{ - // Since the \n was eaten as part of the token, yylineno will have - // been incremented to the value 2 if the shebang was on the first - // line. This yyless undoes that, setting yylineno back to 1. - yyless(yyleng - 1); - if (yyget_lineno() == 1) { - BEGIN(INITIAL); - return SHEBANG_LINE; - } else { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; - } -} - YY_BREAK -case 98: -YY_RULE_SETUP -#line 177 "lexer.l" -{ BEGIN(INITIAL); yyless(1); return '#'; } - YY_BREAK -case 99: -YY_RULE_SETUP -#line 179 "lexer.l" -{ return '~'; } - YY_BREAK -case 100: -YY_RULE_SETUP -#line 180 "lexer.l" -{ return MOD_SEP; } - YY_BREAK -case 101: -YY_RULE_SETUP -#line 181 "lexer.l" -{ return ':'; } - YY_BREAK -case 102: -YY_RULE_SETUP -#line 182 "lexer.l" -{ return '$'; } - YY_BREAK -case 103: -YY_RULE_SETUP -#line 183 "lexer.l" -{ return '?'; } - YY_BREAK -case 104: -YY_RULE_SETUP -#line 185 "lexer.l" -{ return EQEQ; } - YY_BREAK -case 105: -YY_RULE_SETUP -#line 186 "lexer.l" -{ return FAT_ARROW; } - YY_BREAK -case 106: -YY_RULE_SETUP -#line 187 "lexer.l" -{ return '='; } - YY_BREAK -case 107: -YY_RULE_SETUP -#line 188 "lexer.l" -{ return NE; } - YY_BREAK -case 108: -YY_RULE_SETUP -#line 189 "lexer.l" -{ return '!'; } - YY_BREAK -case 109: -YY_RULE_SETUP -#line 190 "lexer.l" -{ return LE; } - YY_BREAK -case 110: -YY_RULE_SETUP -#line 191 "lexer.l" -{ return SHL; } - YY_BREAK -case 111: -YY_RULE_SETUP -#line 192 "lexer.l" -{ return SHLEQ; } - YY_BREAK -case 112: -YY_RULE_SETUP -#line 193 "lexer.l" -{ return '<'; } - YY_BREAK -case 113: -YY_RULE_SETUP -#line 194 "lexer.l" -{ return GE; } - YY_BREAK -case 114: -YY_RULE_SETUP -#line 195 "lexer.l" -{ return SHR; } - YY_BREAK -case 115: -YY_RULE_SETUP -#line 196 "lexer.l" -{ return SHREQ; } - YY_BREAK -case 116: -YY_RULE_SETUP -#line 197 "lexer.l" -{ return '>'; } - YY_BREAK -case 117: -YY_RULE_SETUP -#line 199 "lexer.l" -{ BEGIN(ltorchar); yymore(); } - YY_BREAK -case 118: -YY_RULE_SETUP -#line 200 "lexer.l" -{ BEGIN(INITIAL); return STATIC_LIFETIME; } - YY_BREAK -case 119: -YY_RULE_SETUP -#line 201 "lexer.l" -{ BEGIN(INITIAL); return LIFETIME; } - YY_BREAK -case 120: -YY_RULE_SETUP -#line 202 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 121: -YY_RULE_SETUP -#line 203 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 122: -YY_RULE_SETUP -#line 204 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 123: -YY_RULE_SETUP -#line 205 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case 124: -YY_RULE_SETUP -#line 206 "lexer.l" -{ BEGIN(suffix); return LIT_CHAR; } - YY_BREAK -case YY_STATE_EOF(ltorchar): -#line 207 "lexer.l" -{ BEGIN(INITIAL); return -1; } - YY_BREAK -case 125: -YY_RULE_SETUP -#line 209 "lexer.l" -{ BEGIN(bytestr); yymore(); } - YY_BREAK -case 126: -YY_RULE_SETUP -#line 210 "lexer.l" -{ BEGIN(suffix); return LIT_BYTE_STR; } - YY_BREAK -case YY_STATE_EOF(bytestr): -#line 212 "lexer.l" -{ return -1; } - YY_BREAK -case 127: -/* rule 127 can match eol */ -YY_RULE_SETUP -#line 213 "lexer.l" -{ yymore(); } - YY_BREAK -case 128: -YY_RULE_SETUP -#line 214 "lexer.l" -{ yymore(); } - YY_BREAK -case 129: -YY_RULE_SETUP -#line 215 "lexer.l" -{ yymore(); } - YY_BREAK -case 130: -YY_RULE_SETUP -#line 216 "lexer.l" -{ return -1; } - YY_BREAK -case 131: -/* rule 131 can match eol */ -YY_RULE_SETUP -#line 217 "lexer.l" -{ yymore(); } - YY_BREAK -case 132: -YY_RULE_SETUP -#line 219 "lexer.l" -{ BEGIN(rawbytestr_nohash); yymore(); } - YY_BREAK -case 133: -YY_RULE_SETUP -#line 220 "lexer.l" -{ BEGIN(suffix); return LIT_BYTE_STR_RAW; } - YY_BREAK -case 134: -/* rule 134 can match eol */ -YY_RULE_SETUP -#line 221 "lexer.l" -{ yymore(); } - YY_BREAK -case YY_STATE_EOF(rawbytestr_nohash): -#line 222 "lexer.l" -{ return -1; } - YY_BREAK -case 135: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 2; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 224 "lexer.l" -{ - BEGIN(rawbytestr); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - YY_BREAK -case 136: -YY_RULE_SETUP -#line 231 "lexer.l" -{ - if (!saw_non_hash) { - num_hashes++; - } else if (end_hashes != 0) { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - } - yymore(); -} - YY_BREAK -case 137: -YY_RULE_SETUP -#line 243 "lexer.l" -{ - end_hashes = 1; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - yymore(); -} - YY_BREAK -case 138: -/* rule 138 can match eol */ -YY_RULE_SETUP -#line 251 "lexer.l" -{ - if (!saw_non_hash) { - saw_non_hash = 1; - } - if (end_hashes != 0) { - end_hashes = 0; - } - yymore(); -} - YY_BREAK -case YY_STATE_EOF(rawbytestr): -#line 260 "lexer.l" -{ return -1; } - YY_BREAK -case 139: -YY_RULE_SETUP -#line 262 "lexer.l" -{ BEGIN(byte); yymore(); } - YY_BREAK -case 140: -YY_RULE_SETUP -#line 263 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 141: -YY_RULE_SETUP -#line 264 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 142: -YY_RULE_SETUP -#line 265 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 143: -YY_RULE_SETUP -#line 266 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case 144: -YY_RULE_SETUP -#line 267 "lexer.l" -{ BEGIN(INITIAL); return LIT_BYTE; } - YY_BREAK -case YY_STATE_EOF(byte): -#line 268 "lexer.l" -{ BEGIN(INITIAL); return -1; } - YY_BREAK -case 145: -YY_RULE_SETUP -#line 270 "lexer.l" -{ BEGIN(rawstr); yymore(); } - YY_BREAK -case 146: -YY_RULE_SETUP -#line 271 "lexer.l" -{ BEGIN(suffix); return LIT_STR_RAW; } - YY_BREAK -case 147: -/* rule 147 can match eol */ -YY_RULE_SETUP -#line 272 "lexer.l" -{ yymore(); } - YY_BREAK -case YY_STATE_EOF(rawstr): -#line 273 "lexer.l" -{ return -1; } - YY_BREAK -case 148: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 275 "lexer.l" -{ - BEGIN(rawstr_esc_begin); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - YY_BREAK -case 149: -YY_RULE_SETUP -#line 283 "lexer.l" -{ - num_hashes++; - yymore(); -} - YY_BREAK -case 150: -YY_RULE_SETUP -#line 287 "lexer.l" -{ - BEGIN(rawstr_esc_body); - yymore(); -} - YY_BREAK -case 151: -/* rule 151 can match eol */ -YY_RULE_SETUP -#line 291 "lexer.l" -{ return -1; } - YY_BREAK -case 152: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp = yy_bp + 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ -YY_RULE_SETUP -#line 293 "lexer.l" -{ - BEGIN(rawstr_esc_end); - yymore(); - } - YY_BREAK -case 153: -/* rule 153 can match eol */ -YY_RULE_SETUP -#line 297 "lexer.l" -{ - yymore(); - } - YY_BREAK -case 154: -YY_RULE_SETUP -#line 301 "lexer.l" -{ - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_STR_RAW; - } - yymore(); - } - YY_BREAK -case 155: -/* rule 155 can match eol */ -YY_RULE_SETUP -#line 309 "lexer.l" -{ - end_hashes = 0; - BEGIN(rawstr_esc_body); - yymore(); - } - YY_BREAK -case YY_STATE_EOF(rawstr_esc_begin): -case YY_STATE_EOF(rawstr_esc_body): -case YY_STATE_EOF(rawstr_esc_end): -#line 315 "lexer.l" -{ return -1; } - YY_BREAK -case 156: -YY_RULE_SETUP -#line 317 "lexer.l" -{ BEGIN(str); yymore(); } - YY_BREAK -case 157: -YY_RULE_SETUP -#line 318 "lexer.l" -{ BEGIN(suffix); return LIT_STR; } - YY_BREAK -case YY_STATE_EOF(str): -#line 320 "lexer.l" -{ return -1; } - YY_BREAK -case 158: -/* rule 158 can match eol */ -YY_RULE_SETUP -#line 321 "lexer.l" -{ yymore(); } - YY_BREAK -case 159: -YY_RULE_SETUP -#line 322 "lexer.l" -{ yymore(); } - YY_BREAK -case 160: -YY_RULE_SETUP -#line 323 "lexer.l" -{ yymore(); } - YY_BREAK -case 161: -YY_RULE_SETUP -#line 324 "lexer.l" -{ return -1; } - YY_BREAK -case 162: -/* rule 162 can match eol */ -YY_RULE_SETUP -#line 325 "lexer.l" -{ yymore(); } - YY_BREAK -case 163: -YY_RULE_SETUP -#line 327 "lexer.l" -{ return LARROW; } - YY_BREAK -case 164: -YY_RULE_SETUP -#line 328 "lexer.l" -{ return RARROW; } - YY_BREAK -case 165: -YY_RULE_SETUP -#line 329 "lexer.l" -{ return '-'; } - YY_BREAK -case 166: -YY_RULE_SETUP -#line 330 "lexer.l" -{ return MINUSEQ; } - YY_BREAK -case 167: -YY_RULE_SETUP -#line 331 "lexer.l" -{ return ANDAND; } - YY_BREAK -case 168: -YY_RULE_SETUP -#line 332 "lexer.l" -{ return '&'; } - YY_BREAK -case 169: -YY_RULE_SETUP -#line 333 "lexer.l" -{ return ANDEQ; } - YY_BREAK -case 170: -YY_RULE_SETUP -#line 334 "lexer.l" -{ return OROR; } - YY_BREAK -case 171: -YY_RULE_SETUP -#line 335 "lexer.l" -{ return '|'; } - YY_BREAK -case 172: -YY_RULE_SETUP -#line 336 "lexer.l" -{ return OREQ; } - YY_BREAK -case 173: -YY_RULE_SETUP -#line 337 "lexer.l" -{ return '+'; } - YY_BREAK -case 174: -YY_RULE_SETUP -#line 338 "lexer.l" -{ return PLUSEQ; } - YY_BREAK -case 175: -YY_RULE_SETUP -#line 339 "lexer.l" -{ return '*'; } - YY_BREAK -case 176: -YY_RULE_SETUP -#line 340 "lexer.l" -{ return STAREQ; } - YY_BREAK -case 177: -YY_RULE_SETUP -#line 341 "lexer.l" -{ return '/'; } - YY_BREAK -case 178: -YY_RULE_SETUP -#line 342 "lexer.l" -{ return SLASHEQ; } - YY_BREAK -case 179: -YY_RULE_SETUP -#line 343 "lexer.l" -{ return '^'; } - YY_BREAK -case 180: -YY_RULE_SETUP -#line 344 "lexer.l" -{ return CARETEQ; } - YY_BREAK -case 181: -YY_RULE_SETUP -#line 345 "lexer.l" -{ return '%'; } - YY_BREAK -case 182: -YY_RULE_SETUP -#line 346 "lexer.l" -{ return PERCENTEQ; } - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(pound): -case YY_STATE_EOF(shebang_or_attr): -case YY_STATE_EOF(linecomment): -case YY_STATE_EOF(doc_line): -case YY_STATE_EOF(blockcomment): -case YY_STATE_EOF(doc_block): -case YY_STATE_EOF(suffix): -#line 348 "lexer.l" -{ return 0; } - YY_BREAK -case 183: -YY_RULE_SETUP -#line 350 "lexer.l" -ECHO; - YY_BREAK -#line 2179 "lex.yy.cc" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin.rdbuf(); - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( yywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of yylex */ - -/* The contents of this function are C++ specific, so the () macro is not used. - * This constructor simply maintains backward compatibility. - * DEPRECATED - */ -yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ): - yyin(arg_yyin ? arg_yyin->rdbuf() : std::cin.rdbuf()), - yyout(arg_yyout ? arg_yyout->rdbuf() : std::cout.rdbuf()) -{ - ctor_common(); -} - -/* The contents of this function are C++ specific, so the () macro is not used. - */ -yyFlexLexer::yyFlexLexer( std::istream& arg_yyin, std::ostream& arg_yyout ): - yyin(arg_yyin.rdbuf()), - yyout(arg_yyout.rdbuf()) -{ - ctor_common(); -} - -/* The contents of this function are C++ specific, so the () macro is not used. - */ -void yyFlexLexer::ctor_common() -{ - yy_c_buf_p = 0; - yy_init = 0; - yy_start = 0; - yy_flex_debug = 0; - yylineno = 1; // this will only get updated if %option yylineno - - yy_did_buffer_switch_on_eof = 0; - - yy_looking_for_trail_begin = 0; - yy_more_flag = 0; - yy_more_len = 0; - yy_more_offset = yy_prev_more_offset = 0; - - yy_start_stack_ptr = yy_start_stack_depth = 0; - yy_start_stack = NULL; - - yy_buffer_stack = NULL; - yy_buffer_stack_top = 0; - yy_buffer_stack_max = 0; - - yy_state_buf = 0; - -} - -/* The contents of this function are C++ specific, so the () macro is not used. - */ -yyFlexLexer::~yyFlexLexer() -{ - delete [] yy_state_buf; - yyfree( yy_start_stack ); - yy_delete_buffer( YY_CURRENT_BUFFER ); - yyfree( yy_buffer_stack ); -} - -/* The contents of this function are C++ specific, so the () macro is not used. - */ -void yyFlexLexer::switch_streams( std::istream& new_in, std::ostream& new_out ) -{ - // was if( new_in ) - yy_delete_buffer( YY_CURRENT_BUFFER ); - yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); - - // was if( new_out ) - yyout.rdbuf(new_out.rdbuf()); -} - -/* The contents of this function are C++ specific, so the () macro is not used. - */ -void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out ) -{ - if( ! new_in ) { - new_in = &yyin; - } - - if ( ! new_out ) { - new_out = &yyout; - } - - switch_streams(*new_in, *new_out); -} - -#ifdef YY_INTERACTIVE -int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) -#else -int yyFlexLexer::LexerInput( char* buf, int max_size ) -#endif -{ - if ( yyin.eof() || yyin.fail() ) - return 0; - -#ifdef YY_INTERACTIVE - yyin.get( buf[0] ); - - if ( yyin.eof() ) - return 0; - - if ( yyin.bad() ) - return -1; - - return 1; - -#else - (void) yyin.read( buf, max_size ); - - if ( yyin.bad() ) - return -1; - else - return yyin.gcount(); -#endif -} - -void yyFlexLexer::LexerOutput( const char* buf, int size ) -{ - (void) yyout.write( buf, size ); -} - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -int yyFlexLexer::yy_get_next_buffer() -{ - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = (yytext_ptr); - int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yyrealloc( (void *) b->yy_ch_buf, - (yy_size_t) (b->yy_buf_size + 2) ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( - (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - /* "- 2" to take care of EOB's */ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - yy_state_type yyFlexLexer::yy_get_previous_state() -{ - yy_state_type yy_current_state; - char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) -{ - int yy_is_jam; - char *yy_cp = (yy_c_buf_p); - - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 502 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 501); - - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_UNPUT - void yyFlexLexer::yyunput( int c, char* yy_bp) -{ - char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up yytext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - int number_to_move = (yy_n_chars) + 2; - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - if ( c == '\n' ){ - --yylineno; - } - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} -#endif - - int yyFlexLexer::yyinput() -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap( ) ) - return 0; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - if ( c == '\n' ) - - yylineno++; -; - - return c; -} - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyFlexLexer::yyrestart( std::istream& input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_init_buffer( YY_CURRENT_BUFFER, input_file ); - yy_load_buffer_state( ); -} - -/** Delegate to the new version that takes an istream reference. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ -void yyFlexLexer::yyrestart( std::istream* input_file ) -{ - if( ! input_file ) { - input_file = &yyin; - } - yyrestart( *input_file ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - - void yyFlexLexer::yy_load_buffer_state() -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin.rdbuf(YY_CURRENT_BUFFER_LVALUE->yy_input_file); - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream& file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; -} - -/** Delegate creation of buffers to the new version that takes an istream reference. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size ) -{ - return yy_create_buffer( *file, size ); -} - -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yyfree( (void *) b->yy_ch_buf ); - - yyfree( (void *) b ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream& file ) - -{ - int oerrno = errno; - - yy_flush_buffer( b ); - - b->yy_input_file = file.rdbuf(); - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yyFlexLexer::yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -void yyFlexLexer::yyensure_buffer_stack(void) -{ - yy_size_t num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - - void yyFlexLexer::yy_push_state( int _new_state ) -{ - if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) - { - yy_size_t new_size; - - (yy_start_stack_depth) += YY_START_STACK_INCR; - new_size = (yy_size_t) (yy_start_stack_depth) * sizeof( int ); - - if ( ! (yy_start_stack) ) - (yy_start_stack) = (int *) yyalloc( new_size ); - - else - (yy_start_stack) = (int *) yyrealloc( - (void *) (yy_start_stack), new_size ); - - if ( ! (yy_start_stack) ) - YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); - } - - (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; - - BEGIN(_new_state); -} - - void yyFlexLexer::yy_pop_state() -{ - if ( --(yy_start_stack_ptr) < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); -} - - int yyFlexLexer::yy_top_state() -{ - return (yy_start_stack)[(yy_start_stack_ptr) - 1]; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -void yyFlexLexer::LexerError( const char* msg ) -{ - std::cerr << msg << std::endl; - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, const char * s2, int n ) -{ - - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (const char * s ) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *yyalloc (yy_size_t size ) -{ - return malloc(size); -} - -void *yyrealloc (void * ptr, yy_size_t size ) -{ - - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return realloc(ptr, size); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 350 "lexer.l" - - diff --git a/gcc/rust/test/rustc_bison_test/lexer.l b/gcc/rust/test/rustc_bison_test/lexer.l deleted file mode 100644 index 1feb781..0000000 --- a/gcc/rust/test/rustc_bison_test/lexer.l +++ /dev/null @@ -1,350 +0,0 @@ -%{ -#include -#include - -static int num_hashes; -static int end_hashes; -static int saw_non_hash; - -%} - -%option stack -%option yylineno - -%x str -%x rawstr -%x rawstr_esc_begin -%x rawstr_esc_body -%x rawstr_esc_end -%x byte -%x bytestr -%x rawbytestr -%x rawbytestr_nohash -%x pound -%x shebang_or_attr -%x ltorchar -%x linecomment -%x doc_line -%x blockcomment -%x doc_block -%x suffix - -ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]* - -%% - -{ident} { BEGIN(INITIAL); } -(.|\n) { yyless(0); BEGIN(INITIAL); } - -[ \n\t\r] { } - -\xef\xbb\xbf { - // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise - if (yyget_lineno() != 1) { - return -1; - } -} - -\/\/(\/|\!) { BEGIN(doc_line); yymore(); } -\n { BEGIN(INITIAL); - yyleng--; - yytext[yyleng] = 0; - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -[^\n]* { yymore(); } - -\/\/|\/\/\/\/ { BEGIN(linecomment); } -\n { BEGIN(INITIAL); } -[^\n]* { } - -\/\*(\*|\!)[^*] { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); } -\/\* { yy_push_state(doc_block); yymore(); } -\*\/ { - yy_pop_state(); - if (yy_top_state() == doc_block) { - yymore(); - } else { - return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT); - } -} -(.|\n) { yymore(); } - -\/\* { yy_push_state(blockcomment); } -\/\* { yy_push_state(blockcomment); } -\*\/ { yy_pop_state(); } -(.|\n) { } - -_ { return UNDERSCORE; } -abstract { return ABSTRACT; } -alignof { return ALIGNOF; } -as { return AS; } -become { return BECOME; } -box { return BOX; } -break { return BREAK; } -catch { return CATCH; } -const { return CONST; } -continue { return CONTINUE; } -crate { return CRATE; } -default { return DEFAULT; } -do { return DO; } -else { return ELSE; } -enum { return ENUM; } -extern { return EXTERN; } -false { return FALSE; } -final { return FINAL; } -fn { return FN; } -for { return FOR; } -if { return IF; } -impl { return IMPL; } -in { return IN; } -let { return LET; } -loop { return LOOP; } -macro { return MACRO; } -match { return MATCH; } -mod { return MOD; } -move { return MOVE; } -mut { return MUT; } -offsetof { return OFFSETOF; } -override { return OVERRIDE; } -priv { return PRIV; } -proc { return PROC; } -pure { return PURE; } -pub { return PUB; } -ref { return REF; } -return { return RETURN; } -self { return SELF; } -sizeof { return SIZEOF; } -static { return STATIC; } -struct { return STRUCT; } -super { return SUPER; } -trait { return TRAIT; } -true { return TRUE; } -type { return TYPE; } -typeof { return TYPEOF; } -union { return UNION; } -unsafe { return UNSAFE; } -unsized { return UNSIZED; } -use { return USE; } -virtual { return VIRTUAL; } -where { return WHERE; } -while { return WHILE; } -yield { return YIELD; } - -{ident} { return IDENT; } - -0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } -0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } -[0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } - -[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)? { BEGIN(suffix); return LIT_FLOAT; } -[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+ { BEGIN(suffix); return LIT_FLOAT; } - -; { return ';'; } -, { return ','; } -\.\.\. { return DOTDOTDOT; } -\.\. { return DOTDOT; } -\. { return '.'; } -\( { return '('; } -\) { return ')'; } -\{ { return '{'; } -\} { return '}'; } -\[ { return '['; } -\] { return ']'; } -@ { return '@'; } -# { BEGIN(pound); yymore(); } -\! { BEGIN(shebang_or_attr); yymore(); } -\[ { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; -} -[^\[\n]*\n { - // Since the \n was eaten as part of the token, yylineno will have - // been incremented to the value 2 if the shebang was on the first - // line. This yyless undoes that, setting yylineno back to 1. - yyless(yyleng - 1); - if (yyget_lineno() == 1) { - BEGIN(INITIAL); - return SHEBANG_LINE; - } else { - BEGIN(INITIAL); - yyless(2); - return SHEBANG; - } -} -. { BEGIN(INITIAL); yyless(1); return '#'; } - -\~ { return '~'; } -:: { return MOD_SEP; } -: { return ':'; } -\$ { return '$'; } -\? { return '?'; } - -== { return EQEQ; } -=> { return FAT_ARROW; } -= { return '='; } -\!= { return NE; } -\! { return '!'; } -\<= { return LE; } -\<\< { return SHL; } -\<\<= { return SHLEQ; } -\< { return '<'; } -\>= { return GE; } -\>\> { return SHR; } -\>\>= { return SHREQ; } -\> { return '>'; } - -\x27 { BEGIN(ltorchar); yymore(); } -static { BEGIN(INITIAL); return STATIC_LIFETIME; } -{ident} { BEGIN(INITIAL); return LIFETIME; } -\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } -\\u\{([0-9a-fA-F]_*){1,6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } -.\x27 { BEGIN(suffix); return LIT_CHAR; } -[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } -<> { BEGIN(INITIAL); return -1; } - -b\x22 { BEGIN(bytestr); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR; } - -<> { return -1; } -\\[n\nrt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -br\x22 { BEGIN(rawbytestr_nohash); yymore(); } -\x22 { BEGIN(suffix); return LIT_BYTE_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -br/# { - BEGIN(rawbytestr); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} -# { - if (!saw_non_hash) { - num_hashes++; - } else if (end_hashes != 0) { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - } - yymore(); -} -\x22# { - end_hashes = 1; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_BYTE_STR_RAW; - } - yymore(); -} -(.|\n) { - if (!saw_non_hash) { - saw_non_hash = 1; - } - if (end_hashes != 0) { - end_hashes = 0; - } - yymore(); -} -<> { return -1; } - -b\x27 { BEGIN(byte); yymore(); } -\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\u([0-9a-fA-F]_*){4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\U([0-9a-fA-F]_*){8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -.\x27 { BEGIN(INITIAL); return LIT_BYTE; } -<> { BEGIN(INITIAL); return -1; } - -r\x22 { BEGIN(rawstr); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR_RAW; } -(.|\n) { yymore(); } -<> { return -1; } - -r/# { - BEGIN(rawstr_esc_begin); - yymore(); - num_hashes = 0; - saw_non_hash = 0; - end_hashes = 0; -} - -# { - num_hashes++; - yymore(); -} -\x22 { - BEGIN(rawstr_esc_body); - yymore(); -} -(.|\n) { return -1; } - -\x22/# { - BEGIN(rawstr_esc_end); - yymore(); - } -(.|\n) { - yymore(); - } - -# { - end_hashes++; - if (end_hashes == num_hashes) { - BEGIN(INITIAL); - return LIT_STR_RAW; - } - yymore(); - } -[^#] { - end_hashes = 0; - BEGIN(rawstr_esc_body); - yymore(); - } - -<> { return -1; } - -\x22 { BEGIN(str); yymore(); } -\x22 { BEGIN(suffix); return LIT_STR; } - -<> { return -1; } -\\[n\nr\rt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } - -\<- { return LARROW; } --\> { return RARROW; } -- { return '-'; } --= { return MINUSEQ; } -&& { return ANDAND; } -& { return '&'; } -&= { return ANDEQ; } -\|\| { return OROR; } -\| { return '|'; } -\|= { return OREQ; } -\+ { return '+'; } -\+= { return PLUSEQ; } -\* { return '*'; } -\*= { return STAREQ; } -\/ { return '/'; } -\/= { return SLASHEQ; } -\^ { return '^'; } -\^= { return CARETEQ; } -% { return '%'; } -%= { return PERCENTEQ; } - -<> { return 0; } - -%% diff --git a/gcc/rust/test/rustc_bison_test/parser-interface.c b/gcc/rust/test/rustc_bison_test/parser-interface.c deleted file mode 100644 index a0cab12..0000000 --- a/gcc/rust/test/rustc_bison_test/parser-interface.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include - -extern int yylex(); -extern int yyparse(); - -#define PUSHBACK_LEN 4 - -static char pushback[PUSHBACK_LEN]; -static int verbose; - -void print(const char* format, ...) { - va_list args; - va_start(args, format); - if (verbose) { - vprintf(format, args); - } - va_end(args); -} - -// If there is a non-null char at the head of the pushback queue, -// dequeue it and shift the rest of the queue forwards. Otherwise, -// return the token from calling yylex. -int rslex() { - if (pushback[0] == '\0') { - return yylex(); - } else { - char c = pushback[0]; - memmove(pushback, pushback + 1, PUSHBACK_LEN - 1); - pushback[PUSHBACK_LEN - 1] = '\0'; - return c; - } -} - -// Note: this does nothing if the pushback queue is full. As long as -// there aren't more than PUSHBACK_LEN consecutive calls to push_back -// in an action, this shouldn't be a problem. -void push_back(char c) { - for (int i = 0; i < PUSHBACK_LEN; ++i) { - if (pushback[i] == '\0') { - pushback[i] = c; - break; - } - } -} - -extern int rsdebug; - -struct node { - struct node* next; - struct node* prev; - int own_string; - char const* name; - int n_elems; - struct node* elems[]; -}; - -struct node* nodes = NULL; -int n_nodes; - -struct node* mk_node(char const* name, int n, ...) { - va_list ap; - int i = 0; - unsigned sz = sizeof(struct node) + (n * sizeof(struct node*)); - struct node *nn, *nd = (struct node*)malloc(sz); - - print("# New %d-ary node: %s = %p\n", n, name, nd); - - nd->own_string = 0; - nd->prev = NULL; - nd->next = nodes; - - if (nodes) { - nodes->prev = nd; - } - - nodes = nd; - - nd->name = name; - nd->n_elems = n; - - va_start(ap, n); - - while (i < n) { - nn = va_arg(ap, struct node*); - print("# arg[%d]: %p\n", i, nn); - print("# (%s ...)\n", nn->name); - nd->elems[i++] = nn; - } - - va_end(ap); - n_nodes++; - return nd; -} - -struct node* mk_atom(char* name) { - struct node* nd = mk_node((char const*)strdup(name), 0); - nd->own_string = 1; - return nd; -} - -struct node* mk_none() { - return mk_atom(""); -} - -struct node* ext_node(struct node* nd, int n, ...) { - va_list ap; - int i = 0, c = nd->n_elems + n; - unsigned sz = sizeof(struct node) + (c * sizeof(struct node*)); - struct node* nn; - - print("# Extending %d-ary node by %d nodes: %s = %p", - nd->n_elems, - c, - nd->name, - nd); - - if (nd->next) { - nd->next->prev = nd->prev; - } - if (nd->prev) { - nd->prev->next = nd->next; - } - nd = realloc(nd, sz); - nd->prev = NULL; - nd->next = nodes; - nodes->prev = nd; - nodes = nd; - - print(" ==> %p\n", nd); - - va_start(ap, n); - while (i < n) { - nn = va_arg(ap, struct node*); - print("# arg[%d]: %p\n", i, nn); - print("# (%s ...)\n", nn->name); - nd->elems[nd->n_elems++] = nn; - ++i; - } - va_end(ap); - return nd; -} - -int const indent_step = 4; - -void print_indent(int depth) { - while (depth) { - if (depth-- % indent_step == 0) { - print("|"); - } else { - print(" "); - } - } -} - -void print_node(struct node* n, int depth) { - int i = 0; - print_indent(depth); - if (n->n_elems == 0) { - print("%s\n", n->name); - } else { - print("(%s\n", n->name); - for (i = 0; i < n->n_elems; ++i) { - print_node(n->elems[i], depth + indent_step); - } - print_indent(depth); - print(")\n"); - } -} - -int main(int argc, char** argv) { - if (argc == 2 && strcmp(argv[1], "-v") == 0) { - verbose = 1; - } else { - verbose = 0; - } - int ret = 0; - struct node* tmp; - memset(pushback, '\0', PUSHBACK_LEN); - ret = rsparse(); - print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes); - if (nodes) { - print_node(nodes, 0); - } - while (nodes) { - tmp = nodes; - nodes = tmp->next; - if (tmp->own_string) { - free((void*)tmp->name); - } - free(tmp); - } - return ret; -} - -void rserror(char const* s) { - fprintf(stderr, "%s\n", s); -} \ No newline at end of file diff --git a/gcc/rust/test/rustc_bison_test/parser-lalr.y b/gcc/rust/test/rustc_bison_test/parser-lalr.y deleted file mode 100644 index 5585c95..0000000 --- a/gcc/rust/test/rustc_bison_test/parser-lalr.y +++ /dev/null @@ -1,1982 +0,0 @@ -%{ -#define YYERROR_VERBOSE -#define YYSTYPE struct node * -struct node; -extern int yylex(); -extern void yyerror(char const *s); -extern struct node *mk_node(char const *name, int n, ...); -extern struct node *mk_atom(char *text); -extern struct node *mk_none(); -extern struct node *ext_node(struct node *nd, int n, ...); -extern void push_back(char c); -extern char *yytext; -%} -%debug - -%token SHL -%token SHR -%token LE -%token EQEQ -%token NE -%token GE -%token ANDAND -%token OROR -%token SHLEQ -%token SHREQ -%token MINUSEQ -%token ANDEQ -%token OREQ -%token PLUSEQ -%token STAREQ -%token SLASHEQ -%token CARETEQ -%token PERCENTEQ -%token DOTDOT -%token DOTDOTDOT -%token MOD_SEP -%token RARROW -%token LARROW -%token FAT_ARROW -%token LIT_BYTE -%token LIT_CHAR -%token LIT_INTEGER -%token LIT_FLOAT -%token LIT_STR -%token LIT_STR_RAW -%token LIT_BYTE_STR -%token LIT_BYTE_STR_RAW -%token IDENT -%token UNDERSCORE -%token LIFETIME - -// keywords -%token SELF -%token STATIC -%token ABSTRACT -%token ALIGNOF -%token AS -%token BECOME -%token BREAK -%token CATCH -%token CRATE -%token DO -%token ELSE -%token ENUM -%token EXTERN -%token FALSE -%token FINAL -%token FN -%token FOR -%token IF -%token IMPL -%token IN -%token LET -%token LOOP -%token MACRO -%token MATCH -%token MOD -%token MOVE -%token MUT -%token OFFSETOF -%token OVERRIDE -%token PRIV -%token PUB -%token PURE -%token REF -%token RETURN -%token SIZEOF -%token STRUCT -%token SUPER -%token UNION -%token UNSIZED -%token TRUE -%token TRAIT -%token TYPE -%token UNSAFE -%token VIRTUAL -%token YIELD -%token DEFAULT -%token USE -%token WHILE -%token CONTINUE -%token PROC -%token BOX -%token CONST -%token WHERE -%token TYPEOF -%token INNER_DOC_COMMENT -%token OUTER_DOC_COMMENT - -%token SHEBANG -%token SHEBANG_LINE -%token STATIC_LIFETIME - - /* - Quoting from the Bison manual: - - "Finally, the resolution of conflicts works by comparing the precedence - of the rule being considered with that of the lookahead token. If the - token's precedence is higher, the choice is to shift. If the rule's - precedence is higher, the choice is to reduce. If they have equal - precedence, the choice is made based on the associativity of that - precedence level. The verbose output file made by ‘-v’ (see Invoking - Bison) says how each conflict was resolved" - */ - -// We expect no shift/reduce or reduce/reduce conflicts in this grammar; -// all potential ambiguities are scrutinized and eliminated manually. -%expect 0 - -// fake-precedence symbol to cause '|' bars in lambda context to parse -// at low precedence, permit things like |x| foo = bar, where '=' is -// otherwise lower-precedence than '|'. Also used for proc() to cause -// things like proc() a + b to parse as proc() { a + b }. -%precedence LAMBDA - -%precedence SELF - -// MUT should be lower precedence than IDENT so that in the pat rule, -// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]" -%precedence MUT - -// IDENT needs to be lower than '{' so that 'foo {' is shifted when -// trying to decide if we've got a struct-construction expr (esp. in -// contexts like 'if foo { .') -// -// IDENT also needs to be lower precedence than '<' so that '<' in -// 'foo:bar . <' is shifted (in a trait reference occurring in a -// bounds list), parsing as foo:(bar) rather than (foo:bar). -%precedence IDENT - // Put the weak keywords that can be used as idents here as well -%precedence CATCH -%precedence DEFAULT -%precedence UNION - -// A couple fake-precedence symbols to use in rules associated with + -// and < in trailing type contexts. These come up when you have a type -// in the RHS of operator-AS, such as "foo as bar". The "<" there -// has to be shifted so the parser keeps trying to parse a type, even -// though it might well consider reducing the type "bar" and then -// going on to "<" as a subsequent binop. The "+" case is with -// trailing type-bounds ("foo as bar:A+B"), for the same reason. -%precedence SHIFTPLUS - -%precedence MOD_SEP -%precedence RARROW ':' - -// In where clauses, "for" should have greater precedence when used as -// a higher ranked constraint than when used as the beginning of a -// for_in_type (which is a ty) -%precedence FORTYPE -%precedence FOR - -// Binops & unops, and their precedences -%precedence '?' -%precedence BOX -%nonassoc DOTDOT - -// RETURN needs to be lower-precedence than tokens that start -// prefix_exprs -%precedence RETURN YIELD - -%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ -%right LARROW -%left OROR -%left ANDAND -%left EQEQ NE -%left '<' '>' LE GE -%left '|' -%left '^' -%left '&' -%left SHL SHR -%left '+' '-' -%precedence AS -%left '*' '/' '%' -%precedence '!' - -%precedence '{' '[' '(' '.' - -%precedence RANGE - -%start crate - -%% - -//////////////////////////////////////////////////////////////////////// -// Part 1: Items and attributes -//////////////////////////////////////////////////////////////////////// - -crate -: maybe_shebang inner_attrs maybe_mod_items { mk_node("crate", 2, $2, $3); } -| maybe_shebang maybe_mod_items { mk_node("crate", 1, $2); } -; - -maybe_shebang -: SHEBANG_LINE -| %empty -; - -maybe_inner_attrs -: inner_attrs -| %empty { $$ = mk_none(); } -; - -inner_attrs -: inner_attr { $$ = mk_node("InnerAttrs", 1, $1); } -| inner_attrs inner_attr { $$ = ext_node($1, 1, $2); } -; - -inner_attr -: SHEBANG '[' meta_item ']' { $$ = mk_node("InnerAttr", 1, $3); } -| INNER_DOC_COMMENT { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); } -; - -maybe_outer_attrs -: outer_attrs -| %empty { $$ = mk_none(); } -; - -outer_attrs -: outer_attr { $$ = mk_node("OuterAttrs", 1, $1); } -| outer_attrs outer_attr { $$ = ext_node($1, 1, $2); } -; - -outer_attr -: '#' '[' meta_item ']' { $$ = $3; } -| OUTER_DOC_COMMENT { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); } -; - -meta_item -: ident { $$ = mk_node("MetaWord", 1, $1); } -| ident '=' lit { $$ = mk_node("MetaNameValue", 2, $1, $3); } -| ident '(' meta_seq ')' { $$ = mk_node("MetaList", 2, $1, $3); } -| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); } -; - -meta_seq -: %empty { $$ = mk_none(); } -| meta_item { $$ = mk_node("MetaItems", 1, $1); } -| meta_seq ',' meta_item { $$ = ext_node($1, 1, $3); } -; - -maybe_mod_items -: mod_items -| %empty { $$ = mk_none(); } -; - -mod_items -: mod_item { $$ = mk_node("Items", 1, $1); } -| mod_items mod_item { $$ = ext_node($1, 1, $2); } -; - -attrs_and_vis -: maybe_outer_attrs visibility { $$ = mk_node("AttrsAndVis", 2, $1, $2); } -; - -mod_item -: attrs_and_vis item { $$ = mk_node("Item", 2, $1, $2); } -; - -// items that can appear outside of a fn block -item -: stmt_item -| item_macro -; - -// items that can appear in "stmts" -stmt_item -: item_static -| item_const -| item_type -| block_item -| view_item -; - -item_static -: STATIC ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $2, $4, $6); } -| STATIC MUT ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $3, $5, $7); } -; - -item_const -: CONST ident ':' ty '=' expr ';' { $$ = mk_node("ItemConst", 3, $2, $4, $6); } -; - -item_macro -: path_expr '!' maybe_ident parens_delimited_token_trees ';' { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node("ItemMacro", 3, $1, $3, $4); } -; - -view_item -: use_item -| extern_fn_item -| EXTERN CRATE ident ';' { $$ = mk_node("ViewItemExternCrate", 1, $3); } -| EXTERN CRATE ident AS ident ';' { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); } -; - -extern_fn_item -: EXTERN maybe_abi item_fn { $$ = mk_node("ViewItemExternFn", 2, $2, $3); } -; - -use_item -: USE view_path ';' { $$ = mk_node("ViewItemUse", 1, $2); } -; - -view_path -: path_no_types_allowed { $$ = mk_node("ViewPathSimple", 1, $1); } -| path_no_types_allowed MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); } -| MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); } -| path_no_types_allowed MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } -| MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $3); } -| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } -| MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); } -| path_no_types_allowed MOD_SEP '*' { $$ = mk_node("ViewPathGlob", 1, $1); } -| MOD_SEP '*' { $$ = mk_atom("ViewPathGlob"); } -| '*' { $$ = mk_atom("ViewPathGlob"); } -| '{' '}' { $$ = mk_atom("ViewPathListEmpty"); } -| '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $2); } -| '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); } -| path_no_types_allowed AS ident { $$ = mk_node("ViewPathSimple", 2, $1, $3); } -; - -block_item -: item_fn -| item_unsafe_fn -| item_mod -| item_foreign_mod { $$ = mk_node("ItemForeignMod", 1, $1); } -| item_struct -| item_enum -| item_union -| item_trait -| item_impl -; - -maybe_ty_ascription -: ':' ty_sum { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_init_expr -: '=' expr { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -// structs -item_struct -: STRUCT ident generic_params maybe_where_clause struct_decl_args -{ - $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';' -{ - $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5); -} -| STRUCT ident generic_params maybe_where_clause ';' -{ - $$ = mk_node("ItemStruct", 3, $2, $3, $4); -} -; - -struct_decl_args -: '{' struct_decl_fields '}' { $$ = $2; } -| '{' struct_decl_fields ',' '}' { $$ = $2; } -; - -struct_tuple_args -: '(' struct_tuple_fields ')' { $$ = $2; } -| '(' struct_tuple_fields ',' ')' { $$ = $2; } -; - -struct_decl_fields -: struct_decl_field { $$ = mk_node("StructFields", 1, $1); } -| struct_decl_fields ',' struct_decl_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_decl_field -: attrs_and_vis ident ':' ty_sum { $$ = mk_node("StructField", 3, $1, $2, $4); } -; - -struct_tuple_fields -: struct_tuple_field { $$ = mk_node("StructFields", 1, $1); } -| struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -struct_tuple_field -: attrs_and_vis ty_sum { $$ = mk_node("StructField", 2, $1, $2); } -; - -// enums -item_enum -: ENUM ident generic_params maybe_where_clause '{' enum_defs '}' { $$ = mk_node("ItemEnum", 0); } -| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); } -; - -enum_defs -: enum_def { $$ = mk_node("EnumDefs", 1, $1); } -| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); } -| %empty { $$ = mk_none(); } -; - -enum_def -: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); } -; - -enum_args -: '{' struct_decl_fields '}' { $$ = mk_node("EnumArgs", 1, $2); } -| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); } -| '(' maybe_ty_sums ')' { $$ = mk_node("EnumArgs", 1, $2); } -| '=' expr { $$ = mk_node("EnumArgs", 1, $2); } -| %empty { $$ = mk_none(); } -; - -// unions -item_union -: UNION ident generic_params maybe_where_clause '{' struct_decl_fields '}' { $$ = mk_node("ItemUnion", 0); } -| UNION ident generic_params maybe_where_clause '{' struct_decl_fields ',' '}' { $$ = mk_node("ItemUnion", 0); } - -item_mod -: MOD ident ';' { $$ = mk_node("ItemMod", 1, $2); } -| MOD ident '{' maybe_mod_items '}' { $$ = mk_node("ItemMod", 2, $2, $4); } -| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); } -; - -item_foreign_mod -: EXTERN maybe_abi '{' maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 1, $4); } -| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); } -; - -maybe_abi -: str -| %empty { $$ = mk_none(); } -; - -maybe_foreign_items -: foreign_items -| %empty { $$ = mk_none(); } -; - -foreign_items -: foreign_item { $$ = mk_node("ForeignItems", 1, $1); } -| foreign_items foreign_item { $$ = ext_node($1, 1, $2); } -; - -foreign_item -: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); } -| attrs_and_vis item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $2); } -| attrs_and_vis UNSAFE item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $3); } -; - -item_foreign_static -: maybe_mut ident ':' ty ';' { $$ = mk_node("StaticItem", 3, $1, $2, $4); } -; - -item_foreign_fn -: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); } -; - -fn_decl_allow_variadic -: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_params_allow_variadic -: '(' ')' { $$ = mk_none(); } -| '(' params ')' { $$ = $2; } -| '(' params ',' ')' { $$ = $2; } -| '(' params ',' DOTDOTDOT ')' { $$ = $2; } -; - -visibility -: PUB { $$ = mk_atom("Public"); } -| %empty { $$ = mk_atom("Inherited"); } -; - -idents_or_self -: ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); } -| idents_or_self AS ident { $$ = mk_node("IdentsOrSelf", 2, $1, $3); } -| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); } -; - -ident_or_self -: ident -| SELF { $$ = mk_atom(yytext); } -; - -item_type -: TYPE ident generic_params maybe_where_clause '=' ty_sum ';' { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); } -; - -for_sized -: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); } -| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); } -| %empty { $$ = mk_none(); } -; - -item_trait -: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}' -{ - $$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9); -} -; - -maybe_trait_items -: trait_items -| %empty { $$ = mk_none(); } -; - -trait_items -: trait_item { $$ = mk_node("TraitItems", 1, $1); } -| trait_items trait_item { $$ = ext_node($1, 1, $2); } -; - -trait_item -: trait_const -| trait_type -| trait_method -| maybe_outer_attrs item_macro { $$ = mk_node("TraitMacroItem", 2, $1, $2); } -; - -trait_const -: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 4, $1, $3, $4, $5); } -; - -maybe_const_default -: '=' expr { $$ = mk_node("ConstDefault", 1, $2); } -| %empty { $$ = mk_none(); } -; - -trait_type -: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); } -; - -maybe_unsafe -: UNSAFE { $$ = mk_atom("Unsafe"); } -| %empty { $$ = mk_none(); } -; - -maybe_default_maybe_unsafe -: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); } -| DEFAULT { $$ = mk_atom("Default"); } -| UNSAFE { $$ = mk_atom("Unsafe"); } -| %empty { $$ = mk_none(); } - -trait_method -: type_method { $$ = mk_node("Required", 1, $1); } -| method { $$ = mk_node("Provided", 1, $1); } -; - -type_method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 6, $1, $3, $5, $6, $7, $8); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' -{ - $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9); -} -; - -method -: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8); -} -| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 7, $1, $3, $5, $6, $7, $8, $9); -} -| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -; - -impl_method -: attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $3, $5, $6, $7, $8, $9); -} -| attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); -} -| attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("Method", 9, $1, $2, $3, $5, $7, $8, $9, $10, $11); -} -; - -// There are two forms of impl: -// -// impl (<...>)? TY { ... } -// impl (<...>)? TRAIT for TY { ... } -// -// Unfortunately since TY can begin with '<' itself -- as part of a -// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL: -// should we reduce one of the early rules of TY (such as maybe_once) -// or shall we continue shifting into the generic_params list for the -// impl? -// -// The production parser disambiguates a different case here by -// permitting / requiring the user to provide parens around types when -// they are ambiguous with traits. We do the same here, regrettably, -// by splitting ty into ty and ty_prim. -item_impl -: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8); -} -| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}' -{ - $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11); -} -| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node("ItemImplDefault", 3, $1, $3, $4); -} -| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}' -{ - $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4); -} -; - -maybe_impl_items -: impl_items -| %empty { $$ = mk_none(); } -; - -impl_items -: impl_item { $$ = mk_node("ImplItems", 1, $1); } -| impl_item impl_items { $$ = ext_node($1, 1, $2); } -; - -impl_item -: impl_method -| attrs_and_vis item_macro { $$ = mk_node("ImplMacroItem", 2, $1, $2); } -| impl_const -| impl_type -; - -maybe_default -: DEFAULT { $$ = mk_atom("Default"); } -| %empty { $$ = mk_none(); } -; - -impl_const -: attrs_and_vis maybe_default item_const { $$ = mk_node("ImplConst", 3, $1, $2, $3); } -; - -impl_type -: attrs_and_vis maybe_default TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 5, $1, $2, $4, $5, $7); } -; - -item_fn -: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6); -} -| CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemFn", 5, $3, $4, $5, $6, $7); -} -; - -item_unsafe_fn -: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7); -} -| CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 5, $4, $5, $6, $7, $8); -} -| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block -{ - $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9); -} -; - -fn_decl -: fn_params ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_decl_with_self -: fn_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_decl_with_self_allow_anon_params -: fn_anon_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); } -; - -fn_params -: '(' maybe_params ')' { $$ = $2; } -; - -fn_anon_params -: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); } -| '(' ')' { $$ = mk_none(); } -; - -fn_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } -| '(' maybe_params ')' { $$ = mk_node("SelfStatic", 1, $2); } -; - -fn_anon_params_with_self -: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfLower", 3, $2, $4, $5); } -| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); } -| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); } -| '(' maybe_anon_params ')' { $$ = mk_node("SelfStatic", 1, $2); } -; - -maybe_params -: params -| params ',' -| %empty { $$ = mk_none(); } -; - -params -: param { $$ = mk_node("Args", 1, $1); } -| params ',' param { $$ = ext_node($1, 1, $3); } -; - -param -: pat ':' ty_sum { $$ = mk_node("Arg", 2, $1, $3); } -; - -inferrable_params -: inferrable_param { $$ = mk_node("InferrableParams", 1, $1); } -| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); } -; - -inferrable_param -: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); } -; - -maybe_comma_params -: ',' { $$ = mk_none(); } -| ',' params { $$ = $2; } -| ',' params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_comma_anon_params -: ',' { $$ = mk_none(); } -| ',' anon_params { $$ = $2; } -| ',' anon_params ',' { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_anon_params -: anon_params -| anon_params ',' -| %empty { $$ = mk_none(); } -; - -anon_params -: anon_param { $$ = mk_node("Args", 1, $1); } -| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); } -; - -// anon means it's allowed to be anonymous (type-only), but it can -// still have a name -anon_param -: named_arg ':' ty { $$ = mk_node("Arg", 2, $1, $3); } -| ty -; - -anon_params_allow_variadic_tail -: ',' DOTDOTDOT { $$ = mk_none(); } -| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); } -| %empty { $$ = mk_none(); } -; - -named_arg -: ident -| UNDERSCORE { $$ = mk_atom("PatWild"); } -| '&' ident { $$ = $2; } -| '&' UNDERSCORE { $$ = mk_atom("PatWild"); } -| ANDAND ident { $$ = $2; } -| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); } -| MUT ident { $$ = $2; } -; - -ret_ty -: RARROW '!' { $$ = mk_none(); } -| RARROW ty { $$ = mk_node("ret-ty", 1, $2); } -| %prec IDENT %empty { $$ = mk_none(); } -; - -generic_params -: '<' '>' { $$ = mk_node("Generics", 2, mk_none(), mk_none()); } -| '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } -| '<' lifetimes ',' ty_params '>' { $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } -| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); } -| '<' ty_params '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params ',' '>' { $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } -| '<' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); } -| %empty { $$ = mk_none(); } -; - -maybe_where_clause -: %empty { $$ = mk_none(); } -| where_clause -; - -where_clause -: WHERE where_predicates { $$ = mk_node("WhereClause", 1, $2); } -| WHERE where_predicates ',' { $$ = mk_node("WhereClause", 1, $2); } -; - -where_predicates -: where_predicate { $$ = mk_node("WherePredicates", 1, $1); } -| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); } -; - -where_predicate -: maybe_for_lifetimes lifetime ':' bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } -| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); } -; - -maybe_for_lifetimes -: FOR '<' lifetimes '>' { $$ = mk_none(); } -| %prec FORTYPE %empty { $$ = mk_none(); } - -ty_params -: ty_param { $$ = mk_node("TyParams", 1, $1); } -| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); } -; - -// A path with no type parameters; e.g. `foo::bar::Baz` -// -// These show up in 'use' view-items, because these are processed -// without respect to types. -path_no_types_allowed -: ident { $$ = mk_node("ViewPath", 1, $1); } -| MOD_SEP ident { $$ = mk_node("ViewPath", 1, $2); } -| SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } -| MOD_SEP SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } -| SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } -| MOD_SEP SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } -| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); } -; - -// A path with a lifetime and type parameters, with no double colons -// before the type parameters; e.g. `foo::bar<'a>::Baz` -// -// These show up in "trait references", the components of -// type-parameter bounds lists, as well as in the prefix of the -// path_generic_args_and_bounds rule, which is the full form of a -// named typed expression. -// -// They do not have (nor need) an extra '::' before '<' because -// unlike in expr context, there are no "less-than" type exprs to -// be ambiguous with. -path_generic_args_without_colons -: %prec IDENT - ident { $$ = mk_node("components", 1, $1); } -| %prec IDENT - ident generic_args { $$ = mk_node("components", 2, $1, $2); } -| %prec IDENT - ident '(' maybe_ty_sums ')' ret_ty { $$ = mk_node("components", 2, $1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident generic_args { $$ = ext_node($1, 2, $3, $4); } -| %prec IDENT - path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); } -; - -generic_args -: '<' generic_values '>' { $$ = $2; } -| '<' generic_values SHR { push_back('>'); $$ = $2; } -| '<' generic_values GE { push_back('='); $$ = $2; } -| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -// If generic_args starts with "<<", the first arg must be a -// TyQualifiedPath because that's the only type that can start with a -// '<'. This rule parses that as the first ty_sum and then continues -// with the rest of generic_values. -| SHL ty_qualified_path_and_generic_values '>' { $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHR { push_back('>'); $$ = $2; } -| SHL ty_qualified_path_and_generic_values GE { push_back('='); $$ = $2; } -| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; } -; - -generic_values -: maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 1, $1); } -; - -maybe_ty_sums_and_or_bindings -: ty_sums -| ty_sums ',' -| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); } -| bindings -| bindings ',' -| %empty { $$ = mk_none(); } -; - -maybe_bindings -: ',' bindings { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 2: Patterns -//////////////////////////////////////////////////////////////////////// - -pat -: UNDERSCORE { $$ = mk_atom("PatWild"); } -| '&' pat { $$ = mk_node("PatRegion", 1, $2); } -| '&' MUT pat { $$ = mk_node("PatRegion", 1, $3); } -| ANDAND pat { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); } -| '(' ')' { $$ = mk_atom("PatUnit"); } -| '(' pat_tup ')' { $$ = mk_node("PatTup", 1, $2); } -| '[' pat_vec ']' { $$ = mk_node("PatVec", 1, $2); } -| lit_or_path -| lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node("PatRange", 2, $1, $3); } -| path_expr '{' pat_struct '}' { $$ = mk_node("PatStruct", 2, $1, $3); } -| path_expr '(' ')' { $$ = mk_node("PatEnum", 2, $1, mk_none()); } -| path_expr '(' pat_tup ')' { $$ = mk_node("PatEnum", 2, $1, $3); } -| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); } -| binding_mode ident { $$ = mk_node("PatIdent", 2, $1, $2); } -| ident '@' pat { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); } -| binding_mode ident '@' pat { $$ = mk_node("PatIdent", 3, $1, $2, $4); } -| BOX pat { $$ = mk_node("PatUniq", 1, $2); } -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("PatQualifiedPath", 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, $2, $3, $6), $7, $10); -} -; - -pats_or -: pat { $$ = mk_node("Pats", 1, $1); } -| pats_or '|' pat { $$ = ext_node($1, 1, $3); } -; - -binding_mode -: REF { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); } -| REF MUT { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); } -| MUT { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); } -; - -lit_or_path -: path_expr { $$ = mk_node("PatLit", 1, $1); } -| lit { $$ = mk_node("PatLit", 1, $1); } -| '-' lit { $$ = mk_node("PatLit", 1, $2); } -; - -pat_field -: ident { $$ = mk_node("PatField", 1, $1); } -| binding_mode ident { $$ = mk_node("PatField", 2, $1, $2); } -| BOX ident { $$ = mk_node("PatField", 2, mk_atom("box"), $2); } -| BOX binding_mode ident { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); } -| ident ':' pat { $$ = mk_node("PatField", 2, $1, $3); } -| binding_mode ident ':' pat { $$ = mk_node("PatField", 3, $1, $2, $4); } -| LIT_INTEGER ':' pat { $$ = mk_node("PatField", 2, mk_atom(yytext), $3); } -; - -pat_fields -: pat_field { $$ = mk_node("PatFields", 1, $1); } -| pat_fields ',' pat_field { $$ = ext_node($1, 1, $3); } -; - -pat_struct -: pat_fields { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } -| pat_fields ',' { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } -| pat_fields ',' DOTDOT { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); } -| DOTDOT { $$ = mk_node("PatStruct", 1, mk_atom("true")); } -| %empty { $$ = mk_node("PatStruct", 1, mk_none()); } -; - -pat_tup -: pat_tup_elts { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts ',' DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } -| pat_tup_elts DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $4); } -| pat_tup_elts DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $4); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $5); } -| pat_tup_elts ',' DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $5); } -| DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, mk_none(), $3); } -| DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node("PatTup", 2, mk_none(), mk_none()); } -; - -pat_tup_elts -: pat { $$ = mk_node("PatTupElts", 1, $1); } -| pat_tup_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -pat_vec -: pat_vec_elts { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts ',' DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); } -| pat_vec_elts DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $4); } -| pat_vec_elts DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $4); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $5); } -| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $5); } -| DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, mk_none(), $3); } -| DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, mk_none(), $3); } -| DOTDOT { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } -| %empty { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); } -; - -pat_vec_elts -: pat { $$ = mk_node("PatVecElts", 1, $1); } -| pat_vec_elts ',' pat { $$ = ext_node($1, 1, $3); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 3: Types -//////////////////////////////////////////////////////////////////////// - -ty -: ty_prim -| ty_closure -| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $2, $3, $6); } -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $3, $6), $7, $10); } -| '(' ty_sums ')' { $$ = mk_node("TyTup", 1, $2); } -| '(' ty_sums ',' ')' { $$ = mk_node("TyTup", 1, $2); } -| '(' ')' { $$ = mk_atom("TyNil"); } -; - -ty_prim -: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); } -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); } -| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); } -| %prec IDENT path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $1, $3, $4); } -| %prec IDENT MOD_SEP path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $2, $4, $5); } -| BOX ty { $$ = mk_node("TyBox", 1, $2); } -| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); } -| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); } -| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); } -| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); } -| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); } -| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); } -| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); } -| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); } -| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); } -| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); } -| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); } -| UNDERSCORE { $$ = mk_atom("TyInfer"); } -| ty_bare_fn -| for_in_type -; - -ty_bare_fn -: FN ty_fn_decl { $$ = $2; } -| UNSAFE FN ty_fn_decl { $$ = $3; } -| EXTERN maybe_abi FN ty_fn_decl { $$ = $4; } -| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; } -; - -ty_fn_decl -: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); } -; - -ty_closure -: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); } -| '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); } -| UNSAFE OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $3, $4); } -| OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $2, $3); } -; - -for_in_type -: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); } -; - -for_in_type_suffix -: ty_bare_fn -| trait_ref -| ty_closure -; - -maybe_mut -: MUT { $$ = mk_atom("MutMutable"); } -| %prec MUT %empty { $$ = mk_atom("MutImmutable"); } -; - -maybe_mut_or_const -: MUT { $$ = mk_atom("MutMutable"); } -| CONST { $$ = mk_atom("MutImmutable"); } -| %empty { $$ = mk_atom("MutImmutable"); } -; - -ty_qualified_path_and_generic_values -: ty_qualified_path maybe_bindings -{ - $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2); -} -| ty_qualified_path ',' ty_sums maybe_bindings -{ - $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, $1, $3), $4); -} -; - -ty_qualified_path -: ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } -| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); } -; - -maybe_ty_sums -: ty_sums -| ty_sums ',' -| %empty { $$ = mk_none(); } -; - -ty_sums -: ty_sum { $$ = mk_node("TySums", 1, $1); } -| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); } -; - -ty_sum -: ty_sum_elt { $$ = mk_node("TySum", 1, $1); } -| ty_sum '+' ty_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_sum_elt -: ty -| lifetime -; - -ty_prim_sum -: ty_prim_sum_elt { $$ = mk_node("TySum", 1, $1); } -| ty_prim_sum '+' ty_prim_sum_elt { $$ = ext_node($1, 1, $3); } -; - -ty_prim_sum_elt -: ty_prim -| lifetime -; - -maybe_ty_param_bounds -: ':' ty_param_bounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ty_param_bounds -: boundseq -| %empty { $$ = mk_none(); } -; - -boundseq -: polybound -| boundseq '+' polybound { $$ = ext_node($1, 1, $3); } -; - -polybound -: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); } -| bound -| '?' FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $4, $6); } -| '?' bound { $$ = $2; } -; - -bindings -: binding { $$ = mk_node("Bindings", 1, $1); } -| bindings ',' binding { $$ = ext_node($1, 1, $3); } -; - -binding -: ident '=' ty { mk_node("Binding", 2, $1, $3); } -; - -ty_param -: ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 3, $1, $2, $3); } -| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); } -; - -maybe_bounds -: %prec SHIFTPLUS - ':' bounds { $$ = $2; } -| %prec SHIFTPLUS %empty { $$ = mk_none(); } -; - -bounds -: bound { $$ = mk_node("bounds", 1, $1); } -| bounds '+' bound { $$ = ext_node($1, 1, $3); } -; - -bound -: lifetime -| trait_ref -; - -maybe_ltbounds -: %prec SHIFTPLUS - ':' ltbounds { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -ltbounds -: lifetime { $$ = mk_node("ltbounds", 1, $1); } -| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); } -; - -maybe_ty_default -: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_lifetimes -: lifetimes -| lifetimes ',' -| %empty { $$ = mk_none(); } -; - -lifetimes -: lifetime_and_bounds { $$ = mk_node("Lifetimes", 1, $1); } -| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); } -; - -lifetime_and_bounds -: LIFETIME maybe_ltbounds { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); } -| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } -; - -lifetime -: LIFETIME { $$ = mk_node("lifetime", 1, mk_atom(yytext)); } -| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); } -; - -trait_ref -: %prec IDENT path_generic_args_without_colons -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; } -; - -//////////////////////////////////////////////////////////////////////// -// Part 4: Blocks, statements, and expressions -//////////////////////////////////////////////////////////////////////// - -inner_attrs_and_block -: '{' maybe_inner_attrs maybe_stmts '}' { $$ = mk_node("ExprBlock", 2, $2, $3); } -; - -block -: '{' maybe_stmts '}' { $$ = mk_node("ExprBlock", 1, $2); } -; - -maybe_stmts -: stmts -| stmts nonblock_expr { $$ = ext_node($1, 1, $2); } -| nonblock_expr -| %empty { $$ = mk_none(); } -; - -// There are two sub-grammars within a "stmts: exprs" derivation -// depending on whether each stmt-expr is a block-expr form; this is to -// handle the "semicolon rule" for stmt sequencing that permits -// writing -// -// if foo { bar } 10 -// -// as a sequence of two stmts (one if-expr stmt, one lit-10-expr -// stmt). Unfortunately by permitting juxtaposition of exprs in -// sequence like that, the non-block expr grammar has to have a -// second limited sub-grammar that excludes the prefix exprs that -// are ambiguous with binops. That is to say: -// -// {10} - 1 -// -// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that -// is to say, two statements rather than one, at least according to -// the mainline rust parser. -// -// So we wind up with a 3-way split in exprs that occur in stmt lists: -// block, nonblock-prefix, and nonblock-nonprefix. -// -// In non-stmts contexts, expr can relax this trichotomy. - -stmts -: stmt { $$ = mk_node("stmts", 1, $1); } -| stmts stmt { $$ = ext_node($1, 1, $2); } -; - -stmt -: maybe_outer_attrs let { $$ = $2; } -| stmt_item -| PUB stmt_item { $$ = $2; } -| outer_attrs stmt_item { $$ = $2; } -| outer_attrs PUB stmt_item { $$ = $3; } -| full_block_expr -| maybe_outer_attrs block { $$ = $2; } -| nonblock_expr ';' -| outer_attrs nonblock_expr ';' { $$ = $2; } -| ';' { $$ = mk_none(); } -; - -maybe_exprs -: exprs -| exprs ',' -| %empty { $$ = mk_none(); } -; - -maybe_expr -: expr -| %empty { $$ = mk_none(); } -; - -exprs -: expr { $$ = mk_node("exprs", 1, $1); } -| exprs ',' expr { $$ = ext_node($1, 1, $3); } -; - -path_expr -: path_generic_args_with_colons -| MOD_SEP path_generic_args_with_colons { $$ = $2; } -| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); } -; - -// A path with a lifetime and type parameters with double colons before -// the type parameters; e.g. `foo::bar::<'a>::Baz::` -// -// These show up in expr context, in order to disambiguate from "less-than" -// expressions. -path_generic_args_with_colons -: ident { $$ = mk_node("components", 1, $1); } -| SUPER { $$ = mk_atom("Super"); } -| path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } -| path_generic_args_with_colons MOD_SEP SUPER { $$ = ext_node($1, 1, mk_atom("Super")); } -| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); } -; - -// the braces-delimited macro is a block_expr so it doesn't appear here -macro_expr -: path_expr '!' maybe_ident parens_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } -| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); } -; - -nonblock_expr -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } -| nonblock_expr '?' { $$ = mk_node("ExprTry", 1, $1); } -| nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| nonblock_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| nonblock_expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| nonblock_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE lifetime { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } -| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| nonblock_expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| nonblock_expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| nonblock_expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| nonblock_expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| nonblock_expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| nonblock_expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| nonblock_expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| nonblock_expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| nonblock_expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| nonblock_expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| nonblock_expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| nonblock_expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| nonblock_expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| nonblock_expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| nonblock_expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| nonblock_expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| nonblock_expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| nonblock_expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| nonblock_expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| nonblock_expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| nonblock_expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| nonblock_expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| nonblock_expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| nonblock_expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| nonblock_expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| nonblock_expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| nonblock_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| nonblock_expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| nonblock_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| nonblock_expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| nonblock_prefix_expr -; - -expr -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } -| expr '?' { $$ = mk_node("ExprTry", 1, $1); } -| expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } -| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr -; - -expr_nostruct -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| expr_nostruct '?' { $$ = mk_node("ExprTry", 1, $1); } -| expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| expr_nostruct '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| expr_nostruct '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| expr_nostruct '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } -| YIELD { $$ = mk_node("ExprYield", 0); } -| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); } -| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| expr_nostruct MINUSEQ expr_nostruct { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| expr_nostruct ANDEQ expr_nostruct { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| expr_nostruct OREQ expr_nostruct { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| expr_nostruct PLUSEQ expr_nostruct { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| expr_nostruct STAREQ expr_nostruct { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| expr_nostruct SLASHEQ expr_nostruct { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| expr_nostruct CARETEQ expr_nostruct { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| expr_nostruct PERCENTEQ expr_nostruct { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| expr_nostruct OROR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| expr_nostruct ANDAND expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| expr_nostruct EQEQ expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| expr_nostruct NE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| expr_nostruct '<' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| expr_nostruct '>' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| expr_nostruct LE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| expr_nostruct GE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| expr_nostruct '|' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| expr_nostruct '^' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| expr_nostruct '&' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| expr_nostruct SHL expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| expr_nostruct SHR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| expr_nostruct '+' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| expr_nostruct '-' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| expr_nostruct '*' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| expr_nostruct '/' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| expr_nostruct '%' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| expr_nostruct DOTDOT %prec RANGE { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| expr_nostruct DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| expr_nostruct AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| expr_nostruct ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } -| BOX expr { $$ = mk_node("ExprBox", 1, $2); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr_nostruct -; - -nonblock_prefix_expr_nostruct -: '-' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } -| '!' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } -| '*' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } -| '&' maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 2, $2, $3); } -| ANDAND maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } -| lambda_expr_nostruct -| MOVE lambda_expr_nostruct { $$ = $2; } -; - -nonblock_prefix_expr -: '-' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); } -| '!' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); } -| '*' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); } -| '&' maybe_mut expr { $$ = mk_node("ExprAddrOf", 2, $2, $3); } -| ANDAND maybe_mut expr { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } -| lambda_expr -| MOVE lambda_expr { $$ = $2; } -; - -expr_qualified_path -: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params -{ - $$ = mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident -{ - $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10, $11); -} -| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args -{ - $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11, $12); -} - -maybe_qpath_params -: MOD_SEP generic_args { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -maybe_as_trait_ref -: AS trait_ref { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -lambda_expr -: %prec LAMBDA - OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - '|' '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } -; - -lambda_expr_no_first_bar -: %prec LAMBDA - '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } -; - -lambda_expr_nostruct -: %prec LAMBDA - OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); } -| %prec LAMBDA - '|' '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } -| %prec LAMBDA - '|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); } -| %prec LAMBDA - '|' inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } -; - -lambda_expr_nostruct_no_first_bar -: %prec LAMBDA - '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } -| %prec LAMBDA - inferrable_params '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } -| %prec LAMBDA - inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } -; - -vec_expr -: maybe_exprs -| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); } -; - -struct_expr_fields -: field_inits -| field_inits ',' -| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); } -| %empty { $$ = mk_none(); } -; - -maybe_field_inits -: field_inits -| field_inits ',' -| %empty { $$ = mk_none(); } -; - -field_inits -: field_init { $$ = mk_node("FieldInits", 1, $1); } -| field_inits ',' field_init { $$ = ext_node($1, 1, $3); } -; - -field_init -: ident { $$ = mk_node("FieldInit", 1, $1); } -| ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); } -| LIT_INTEGER ':' expr { $$ = mk_node("FieldInit", 2, mk_atom(yytext), $3); } -; - -default_field_init -: DOTDOT expr { $$ = mk_node("DefaultFieldInit", 1, $2); } -; - -block_expr -: expr_match -| expr_if -| expr_if_let -| expr_while -| expr_while_let -| expr_loop -| expr_for -| UNSAFE block { $$ = mk_node("UnsafeBlock", 1, $2); } -| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); } -; - -full_block_expr -: block_expr -| block_expr_dot -; - -block_expr_dot -: block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } -| block_expr_dot '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } -| block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } -| block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } -| block_expr_dot '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } -| block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| block_expr_dot '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -; - -expr_match -: MATCH expr_nostruct '{' '}' { $$ = mk_node("ExprMatch", 1, $2); } -| MATCH expr_nostruct '{' match_clauses '}' { $$ = mk_node("ExprMatch", 2, $2, $4); } -| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); } -| MATCH expr_nostruct '{' nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); } -; - -match_clauses -: match_clause { $$ = mk_node("Arms", 1, $1); } -| match_clauses match_clause { $$ = ext_node($1, 1, $2); } -; - -match_clause -: nonblock_match_clause ',' -| block_match_clause -| block_match_clause ',' -; - -nonblock_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } -; - -block_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } -; - -maybe_guard -: IF expr_nostruct { $$ = $2; } -| %empty { $$ = mk_none(); } -; - -expr_if -: IF expr_nostruct block { $$ = mk_node("ExprIf", 2, $2, $3); } -| IF expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIf", 3, $2, $3, $5); } -; - -expr_if_let -: IF LET pat '=' expr_nostruct block { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); } -| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); } -; - -block_or_if -: block -| expr_if -| expr_if_let -; - -expr_while -: maybe_label WHILE expr_nostruct block { $$ = mk_node("ExprWhile", 3, $1, $3, $4); } -; - -expr_while_let -: maybe_label WHILE LET pat '=' expr_nostruct block { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); } -; - -expr_loop -: maybe_label LOOP block { $$ = mk_node("ExprLoop", 2, $1, $3); } -; - -expr_for -: maybe_label FOR pat IN expr_nostruct block { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); } -; - -maybe_label -: lifetime ':' -| %empty { $$ = mk_none(); } -; - -let -: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); } -; - -//////////////////////////////////////////////////////////////////////// -// Part 5: Macros and misc. rules -//////////////////////////////////////////////////////////////////////// - -lit -: LIT_BYTE { $$ = mk_node("LitByte", 1, mk_atom(yytext)); } -| LIT_CHAR { $$ = mk_node("LitChar", 1, mk_atom(yytext)); } -| LIT_INTEGER { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); } -| LIT_FLOAT { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); } -| TRUE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } -| FALSE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); } -| str -; - -str -: LIT_STR { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); } -| LIT_STR_RAW { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); } -| LIT_BYTE_STR { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); } -| LIT_BYTE_STR_RAW { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); } -; - -maybe_ident -: %empty { $$ = mk_none(); } -| ident -; - -ident -: IDENT { $$ = mk_node("ident", 1, mk_atom(yytext)); } -// Weak keywords that can be used as identifiers -| CATCH { $$ = mk_node("ident", 1, mk_atom(yytext)); } -| DEFAULT { $$ = mk_node("ident", 1, mk_atom(yytext)); } -| UNION { $$ = mk_node("ident", 1, mk_atom(yytext)); } -; - -unpaired_token -: SHL { $$ = mk_atom(yytext); } -| SHR { $$ = mk_atom(yytext); } -| LE { $$ = mk_atom(yytext); } -| EQEQ { $$ = mk_atom(yytext); } -| NE { $$ = mk_atom(yytext); } -| GE { $$ = mk_atom(yytext); } -| ANDAND { $$ = mk_atom(yytext); } -| OROR { $$ = mk_atom(yytext); } -| LARROW { $$ = mk_atom(yytext); } -| SHLEQ { $$ = mk_atom(yytext); } -| SHREQ { $$ = mk_atom(yytext); } -| MINUSEQ { $$ = mk_atom(yytext); } -| ANDEQ { $$ = mk_atom(yytext); } -| OREQ { $$ = mk_atom(yytext); } -| PLUSEQ { $$ = mk_atom(yytext); } -| STAREQ { $$ = mk_atom(yytext); } -| SLASHEQ { $$ = mk_atom(yytext); } -| CARETEQ { $$ = mk_atom(yytext); } -| PERCENTEQ { $$ = mk_atom(yytext); } -| DOTDOT { $$ = mk_atom(yytext); } -| DOTDOTDOT { $$ = mk_atom(yytext); } -| MOD_SEP { $$ = mk_atom(yytext); } -| RARROW { $$ = mk_atom(yytext); } -| FAT_ARROW { $$ = mk_atom(yytext); } -| LIT_BYTE { $$ = mk_atom(yytext); } -| LIT_CHAR { $$ = mk_atom(yytext); } -| LIT_INTEGER { $$ = mk_atom(yytext); } -| LIT_FLOAT { $$ = mk_atom(yytext); } -| LIT_STR { $$ = mk_atom(yytext); } -| LIT_STR_RAW { $$ = mk_atom(yytext); } -| LIT_BYTE_STR { $$ = mk_atom(yytext); } -| LIT_BYTE_STR_RAW { $$ = mk_atom(yytext); } -| IDENT { $$ = mk_atom(yytext); } -| UNDERSCORE { $$ = mk_atom(yytext); } -| LIFETIME { $$ = mk_atom(yytext); } -| SELF { $$ = mk_atom(yytext); } -| STATIC { $$ = mk_atom(yytext); } -| ABSTRACT { $$ = mk_atom(yytext); } -| ALIGNOF { $$ = mk_atom(yytext); } -| AS { $$ = mk_atom(yytext); } -| BECOME { $$ = mk_atom(yytext); } -| BREAK { $$ = mk_atom(yytext); } -| CATCH { $$ = mk_atom(yytext); } -| CRATE { $$ = mk_atom(yytext); } -| DEFAULT { $$ = mk_atom(yytext); } -| DO { $$ = mk_atom(yytext); } -| ELSE { $$ = mk_atom(yytext); } -| ENUM { $$ = mk_atom(yytext); } -| EXTERN { $$ = mk_atom(yytext); } -| FALSE { $$ = mk_atom(yytext); } -| FINAL { $$ = mk_atom(yytext); } -| FN { $$ = mk_atom(yytext); } -| FOR { $$ = mk_atom(yytext); } -| IF { $$ = mk_atom(yytext); } -| IMPL { $$ = mk_atom(yytext); } -| IN { $$ = mk_atom(yytext); } -| LET { $$ = mk_atom(yytext); } -| LOOP { $$ = mk_atom(yytext); } -| MACRO { $$ = mk_atom(yytext); } -| MATCH { $$ = mk_atom(yytext); } -| MOD { $$ = mk_atom(yytext); } -| MOVE { $$ = mk_atom(yytext); } -| MUT { $$ = mk_atom(yytext); } -| OFFSETOF { $$ = mk_atom(yytext); } -| OVERRIDE { $$ = mk_atom(yytext); } -| PRIV { $$ = mk_atom(yytext); } -| PUB { $$ = mk_atom(yytext); } -| PURE { $$ = mk_atom(yytext); } -| REF { $$ = mk_atom(yytext); } -| RETURN { $$ = mk_atom(yytext); } -| STRUCT { $$ = mk_atom(yytext); } -| SIZEOF { $$ = mk_atom(yytext); } -| SUPER { $$ = mk_atom(yytext); } -| TRUE { $$ = mk_atom(yytext); } -| TRAIT { $$ = mk_atom(yytext); } -| TYPE { $$ = mk_atom(yytext); } -| UNION { $$ = mk_atom(yytext); } -| UNSAFE { $$ = mk_atom(yytext); } -| UNSIZED { $$ = mk_atom(yytext); } -| USE { $$ = mk_atom(yytext); } -| VIRTUAL { $$ = mk_atom(yytext); } -| WHILE { $$ = mk_atom(yytext); } -| YIELD { $$ = mk_atom(yytext); } -| CONTINUE { $$ = mk_atom(yytext); } -| PROC { $$ = mk_atom(yytext); } -| BOX { $$ = mk_atom(yytext); } -| CONST { $$ = mk_atom(yytext); } -| WHERE { $$ = mk_atom(yytext); } -| TYPEOF { $$ = mk_atom(yytext); } -| INNER_DOC_COMMENT { $$ = mk_atom(yytext); } -| OUTER_DOC_COMMENT { $$ = mk_atom(yytext); } -| SHEBANG { $$ = mk_atom(yytext); } -| STATIC_LIFETIME { $$ = mk_atom(yytext); } -| ';' { $$ = mk_atom(yytext); } -| ',' { $$ = mk_atom(yytext); } -| '.' { $$ = mk_atom(yytext); } -| '@' { $$ = mk_atom(yytext); } -| '#' { $$ = mk_atom(yytext); } -| '~' { $$ = mk_atom(yytext); } -| ':' { $$ = mk_atom(yytext); } -| '$' { $$ = mk_atom(yytext); } -| '=' { $$ = mk_atom(yytext); } -| '?' { $$ = mk_atom(yytext); } -| '!' { $$ = mk_atom(yytext); } -| '<' { $$ = mk_atom(yytext); } -| '>' { $$ = mk_atom(yytext); } -| '-' { $$ = mk_atom(yytext); } -| '&' { $$ = mk_atom(yytext); } -| '|' { $$ = mk_atom(yytext); } -| '+' { $$ = mk_atom(yytext); } -| '*' { $$ = mk_atom(yytext); } -| '/' { $$ = mk_atom(yytext); } -| '^' { $$ = mk_atom(yytext); } -| '%' { $$ = mk_atom(yytext); } -; - -token_trees -: %empty { $$ = mk_node("TokenTrees", 0); } -| token_trees token_tree { $$ = ext_node($1, 1, $2); } -; - -token_tree -: delimited_token_trees -| unpaired_token { $$ = mk_node("TTTok", 1, $1); } -; - -delimited_token_trees -: parens_delimited_token_trees -| braces_delimited_token_trees -| brackets_delimited_token_trees -; - -parens_delimited_token_trees -: '(' token_trees ')' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("(")), - $2, - mk_node("TTTok", 1, mk_atom(")"))); -} -; - -braces_delimited_token_trees -: '{' token_trees '}' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("{")), - $2, - mk_node("TTTok", 1, mk_atom("}"))); -} -; - -brackets_delimited_token_trees -: '[' token_trees ']' -{ - $$ = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("[")), - $2, - mk_node("TTTok", 1, mk_atom("]"))); -} -; diff --git a/gcc/rust/test/rustc_bison_test/parser.tab.c b/gcc/rust/test/rustc_bison_test/parser.tab.c deleted file mode 100644 index 795ff6a..0000000 --- a/gcc/rust/test/rustc_bison_test/parser.tab.c +++ /dev/null @@ -1,9173 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.4.1. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Undocumented macros, especially those whose name start with YY_, - are private implementation details. Do not rely on them. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.4.1" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* First part of user prologue. */ -#line 1 "parser-lalr.y" - -#define YYERROR_VERBOSE -struct node; -#define YYSTYPE struct node* -extern int yylex(); -extern void yyerror(char const *s); -extern struct node *mk_node(char const *name, int n, ...); -extern struct node *mk_atom(char *text); -extern struct node *mk_none(); -extern struct node *ext_node(struct node *nd, int n, ...); -extern void push_back(char c); -extern char *yytext; - -#line 84 "parser.tab.c" - -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Use api.header.include to #include this header - instead of duplicating it here. */ -#ifndef YY_YY_TOKEN_H_INCLUDED -# define YY_YY_TOKEN_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - SHL = 258, - SHR = 259, - LE = 260, - EQEQ = 261, - NE = 262, - GE = 263, - ANDAND = 264, - OROR = 265, - SHLEQ = 266, - SHREQ = 267, - MINUSEQ = 268, - ANDEQ = 269, - OREQ = 270, - PLUSEQ = 271, - STAREQ = 272, - SLASHEQ = 273, - CARETEQ = 274, - PERCENTEQ = 275, - DOTDOT = 276, - DOTDOTDOT = 277, - MOD_SEP = 278, - RARROW = 279, - LARROW = 280, - FAT_ARROW = 281, - LIT_BYTE = 282, - LIT_CHAR = 283, - LIT_INTEGER = 284, - LIT_FLOAT = 285, - LIT_STR = 286, - LIT_STR_RAW = 287, - LIT_BYTE_STR = 288, - LIT_BYTE_STR_RAW = 289, - IDENT = 290, - UNDERSCORE = 291, - LIFETIME = 292, - SELF = 293, - STATIC = 294, - ABSTRACT = 295, - ALIGNOF = 296, - AS = 297, - BECOME = 298, - BREAK = 299, - CATCH = 300, - CRATE = 301, - DO = 302, - ELSE = 303, - ENUM = 304, - EXTERN = 305, - FALSE = 306, - FINAL = 307, - FN = 308, - FOR = 309, - IF = 310, - IMPL = 311, - IN = 312, - LET = 313, - LOOP = 314, - MACRO = 315, - MATCH = 316, - MOD = 317, - MOVE = 318, - MUT = 319, - OFFSETOF = 320, - OVERRIDE = 321, - PRIV = 322, - PUB = 323, - PURE = 324, - REF = 325, - RETURN = 326, - SIZEOF = 327, - STRUCT = 328, - SUPER = 329, - UNION = 330, - UNSIZED = 331, - TRUE = 332, - TRAIT = 333, - TYPE = 334, - UNSAFE = 335, - VIRTUAL = 336, - YIELD = 337, - DEFAULT = 338, - USE = 339, - WHILE = 340, - CONTINUE = 341, - PROC = 342, - BOX = 343, - CONST = 344, - WHERE = 345, - TYPEOF = 346, - INNER_DOC_COMMENT = 347, - OUTER_DOC_COMMENT = 348, - SHEBANG = 349, - SHEBANG_LINE = 350, - STATIC_LIFETIME = 351, - LAMBDA = 352, - SHIFTPLUS = 353, - FORTYPE = 354, - RANGE = 355 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE yylval; - -int yyparse (void); - -#endif /* !YY_YY_TOKEN_H_INCLUDED */ - - - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) -# else -# define YY_ATTRIBUTE(Spec) /* empty */ -# endif -#endif - -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 4 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 9250 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 128 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 213 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 917 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 1646 - -#define YYUNDEFTOK 2 -#define YYMAXUTOK 355 - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 113, 2, 120, 127, 112, 107, 2, - 116, 121, 110, 108, 122, 109, 117, 111, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 99, 123, - 103, 102, 104, 101, 125, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 115, 2, 119, 106, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 114, 105, 124, 126, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 100, 118 -}; - -#if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 210, 210, 211, 215, 216, 220, 221, 225, 226, - 230, 231, 235, 236, 240, 241, 245, 246, 250, 251, - 252, 253, 257, 258, 259, 263, 264, 268, 269, 273, - 277, 282, 283, 288, 289, 290, 291, 292, 296, 297, - 301, 305, 306, 307, 311, 312, 313, 314, 318, 322, - 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 337, 338, 339, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 355, 356, 360, 361, 366, 370, 374, - 381, 382, 386, 387, 391, 392, 393, 397, 401, 402, - 403, 407, 412, 413, 417, 418, 419, 423, 427, 428, - 429, 430, 431, 436, 437, 440, 441, 442, 446, 447, - 451, 452, 456, 457, 461, 462, 466, 467, 468, 472, - 476, 480, 484, 485, 486, 487, 491, 492, 496, 497, - 498, 502, 503, 507, 511, 512, 513, 517, 524, 525, - 529, 530, 534, 535, 536, 537, 541, 545, 546, 550, - 554, 555, 559, 560, 561, 562, 565, 566, 570, 574, - 578, 585, 589, 593, 600, 604, 608, 630, 634, 638, - 642, 646, 650, 657, 658, 662, 663, 667, 668, 669, - 670, 674, 675, 679, 683, 687, 691, 698, 702, 706, - 713, 717, 721, 725, 729, 730, 734, 735, 736, 737, - 741, 742, 743, 744, 748, 749, 750, 754, 755, 759, - 763, 764, 768, 772, 773, 774, 775, 779, 780, 781, - 782, 786, 787, 788, 792, 793, 799, 800, 804, 805, - 806, 810, 811, 812, 813, 814, 815, 816, 820, 821, - 822, 826, 827, 828, 829, 830, 831, 832, 833, 834, - 835, 836, 837, 838, 839, 843, 844, 848, 849, 853, - 854, 858, 859, 863, 864, 867, 868, 876, 877, 878, - 879, 880, 881, 882, 897, 899, 901, 903, 905, 907, - 912, 913, 914, 915, 920, 921, 922, 923, 927, 931, - 932, 933, 934, 935, 936, 940, 941, 949, 950, 951, - 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, - 962, 963, 964, 965, 966, 967, 974, 975, 979, 980, - 981, 985, 986, 987, 991, 992, 993, 994, 995, 996, - 997, 1001, 1002, 1006, 1007, 1008, 1009, 1010, 1014, 1015, - 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1028, - 1029, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, - 1042, 1043, 1044, 1048, 1049, 1057, 1058, 1059, 1060, 1061, - 1062, 1063, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, - 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, - 1085, 1086, 1090, 1091, 1092, 1093, 1097, 1101, 1102, 1103, - 1104, 1108, 1112, 1113, 1114, 1118, 1119, 1123, 1124, 1125, - 1129, 1133, 1140, 1141, 1145, 1146, 1147, 1151, 1152, 1156, - 1157, 1161, 1162, 1166, 1167, 1171, 1172, 1176, 1177, 1181, - 1182, 1186, 1187, 1191, 1192, 1193, 1194, 1198, 1199, 1203, - 1207, 1208, 1212, 1214, 1218, 1219, 1223, 1224, 1228, 1230, - 1234, 1235, 1239, 1240, 1244, 1245, 1246, 1250, 1251, 1255, - 1256, 1260, 1261, 1265, 1266, 1274, 1278, 1282, 1283, 1284, - 1285, 1313, 1314, 1318, 1319, 1320, 1321, 1322, 1323, 1324, - 1325, 1326, 1327, 1331, 1332, 1333, 1337, 1338, 1342, 1343, - 1347, 1348, 1349, 1358, 1359, 1360, 1361, 1362, 1367, 1368, - 1372, 1373, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, - 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, - 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, - 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, - 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, - 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1434, 1435, - 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, - 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, - 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, - 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, - 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, - 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1498, 1499, - 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, - 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, - 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, - 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, - 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, - 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1561, 1562, 1563, - 1564, 1565, 1566, 1567, 1571, 1572, 1573, 1574, 1575, 1576, - 1577, 1581, 1585, 1589, 1593, 1597, 1603, 1604, 1608, 1609, - 1613, 1615, 1617, 1619, 1624, 1626, 1628, 1633, 1635, 1637, - 1639, 1644, 1646, 1648, 1653, 1654, 1658, 1659, 1660, 1661, - 1665, 1666, 1667, 1671, 1672, 1676, 1677, 1678, 1682, 1686, - 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1698, 1699, - 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1714, 1715, - 1716, 1717, 1721, 1722, 1726, 1727, 1728, 1732, 1733, 1737, - 1738, 1742, 1743, 1747, 1748, 1752, 1753, 1757, 1758, 1759, - 1763, 1767, 1771, 1775, 1779, 1780, 1784, 1792, 1793, 1794, - 1795, 1796, 1797, 1798, 1802, 1803, 1804, 1805, 1809, 1810, - 1814, 1816, 1817, 1818, 1822, 1823, 1824, 1825, 1826, 1827, - 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, - 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, - 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, - 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, - 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, - 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, - 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, - 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, - 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, - 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, - 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1939, 1940, - 1944, 1945, 1949, 1950, 1951, 1955, 1965, 1975 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || 0 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "SHL", "SHR", "LE", "EQEQ", "NE", "GE", - "ANDAND", "OROR", "SHLEQ", "SHREQ", "MINUSEQ", "ANDEQ", "OREQ", "PLUSEQ", - "STAREQ", "SLASHEQ", "CARETEQ", "PERCENTEQ", "DOTDOT", "DOTDOTDOT", - "MOD_SEP", "RARROW", "LARROW", "FAT_ARROW", "LIT_BYTE", "LIT_CHAR", - "LIT_INTEGER", "LIT_FLOAT", "LIT_STR", "LIT_STR_RAW", "LIT_BYTE_STR", - "LIT_BYTE_STR_RAW", "IDENT", "UNDERSCORE", "LIFETIME", "SELF", "STATIC", - "ABSTRACT", "ALIGNOF", "AS", "BECOME", "BREAK", "CATCH", "CRATE", "DO", - "ELSE", "ENUM", "EXTERN", "FALSE", "FINAL", "FN", "FOR", "IF", "IMPL", - "IN", "LET", "LOOP", "MACRO", "MATCH", "MOD", "MOVE", "MUT", "OFFSETOF", - "OVERRIDE", "PRIV", "PUB", "PURE", "REF", "RETURN", "SIZEOF", "STRUCT", - "SUPER", "UNION", "UNSIZED", "TRUE", "TRAIT", "TYPE", "UNSAFE", - "VIRTUAL", "YIELD", "DEFAULT", "USE", "WHILE", "CONTINUE", "PROC", "BOX", - "CONST", "WHERE", "TYPEOF", "INNER_DOC_COMMENT", "OUTER_DOC_COMMENT", - "SHEBANG", "SHEBANG_LINE", "STATIC_LIFETIME", "LAMBDA", "SHIFTPLUS", - "':'", "FORTYPE", "'?'", "'='", "'<'", "'>'", "'|'", "'^'", "'&'", "'+'", - "'-'", "'*'", "'/'", "'%'", "'!'", "'{'", "'['", "'('", "'.'", "RANGE", - "']'", "'#'", "')'", "','", "';'", "'}'", "'@'", "'~'", "'$'", "$accept", - "crate", "maybe_shebang", "maybe_inner_attrs", "inner_attrs", - "inner_attr", "maybe_outer_attrs", "outer_attrs", "outer_attr", - "meta_item", "meta_seq", "maybe_mod_items", "mod_items", "attrs_and_vis", - "mod_item", "item", "stmt_item", "item_static", "item_const", - "item_macro", "view_item", "extern_fn_item", "use_item", "view_path", - "block_item", "maybe_ty_ascription", "maybe_init_expr", "item_struct", - "struct_decl_args", "struct_tuple_args", "struct_decl_fields", - "struct_decl_field", "struct_tuple_fields", "struct_tuple_field", - "item_enum", "enum_defs", "enum_def", "enum_args", "item_union", - "item_mod", "item_foreign_mod", "maybe_abi", "maybe_foreign_items", - "foreign_items", "foreign_item", "item_foreign_static", - "item_foreign_fn", "fn_decl_allow_variadic", "fn_params_allow_variadic", - "visibility", "idents_or_self", "ident_or_self", "item_type", - "for_sized", "item_trait", "maybe_trait_items", "trait_items", - "trait_item", "trait_const", "maybe_const_default", "trait_type", - "maybe_unsafe", "maybe_default_maybe_unsafe", "trait_method", - "type_method", "method", "impl_method", "item_impl", "maybe_impl_items", - "impl_items", "impl_item", "maybe_default", "impl_const", "impl_type", - "item_fn", "item_unsafe_fn", "fn_decl", "fn_decl_with_self", - "fn_decl_with_self_allow_anon_params", "fn_params", "fn_anon_params", - "fn_params_with_self", "fn_anon_params_with_self", "maybe_params", - "params", "param", "inferrable_params", "inferrable_param", - "maybe_comma_params", "maybe_comma_anon_params", "maybe_anon_params", - "anon_params", "anon_param", "anon_params_allow_variadic_tail", - "named_arg", "ret_ty", "generic_params", "maybe_where_clause", - "where_clause", "where_predicates", "where_predicate", - "maybe_for_lifetimes", "ty_params", "path_no_types_allowed", - "path_generic_args_without_colons", "generic_args", "generic_values", - "maybe_ty_sums_and_or_bindings", "maybe_bindings", "pat", "pats_or", - "binding_mode", "lit_or_path", "pat_field", "pat_fields", "pat_struct", - "pat_tup", "pat_tup_elts", "pat_vec", "pat_vec_elts", "ty", "ty_prim", - "ty_bare_fn", "ty_fn_decl", "ty_closure", "for_in_type", - "for_in_type_suffix", "maybe_mut", "maybe_mut_or_const", - "ty_qualified_path_and_generic_values", "ty_qualified_path", - "maybe_ty_sums", "ty_sums", "ty_sum", "ty_sum_elt", "ty_prim_sum", - "ty_prim_sum_elt", "maybe_ty_param_bounds", "ty_param_bounds", - "boundseq", "polybound", "bindings", "binding", "ty_param", - "maybe_bounds", "bounds", "bound", "maybe_ltbounds", "ltbounds", - "maybe_ty_default", "maybe_lifetimes", "lifetimes", - "lifetime_and_bounds", "lifetime", "trait_ref", "inner_attrs_and_block", - "block", "maybe_stmts", "stmts", "stmt", "maybe_exprs", "maybe_expr", - "exprs", "path_expr", "path_generic_args_with_colons", "macro_expr", - "nonblock_expr", "expr", "expr_nostruct", - "nonblock_prefix_expr_nostruct", "nonblock_prefix_expr", - "expr_qualified_path", "maybe_qpath_params", "maybe_as_trait_ref", - "lambda_expr", "lambda_expr_no_first_bar", "lambda_expr_nostruct", - "lambda_expr_nostruct_no_first_bar", "vec_expr", "struct_expr_fields", - "maybe_field_inits", "field_inits", "field_init", "default_field_init", - "block_expr", "full_block_expr", "block_expr_dot", "expr_match", - "match_clauses", "match_clause", "nonblock_match_clause", - "block_match_clause", "maybe_guard", "expr_if", "expr_if_let", - "block_or_if", "expr_while", "expr_while_let", "expr_loop", "expr_for", - "maybe_label", "let", "lit", "str", "maybe_ident", "ident", - "unpaired_token", "token_trees", "token_tree", "delimited_token_trees", - "parens_delimited_token_trees", "braces_delimited_token_trees", - "brackets_delimited_token_trees", YY_NULLPTR -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 58, - 354, 63, 61, 60, 62, 124, 94, 38, 43, 45, - 42, 47, 37, 33, 123, 91, 40, 46, 355, 93, - 35, 41, 44, 59, 125, 64, 126, 36 -}; -# endif - -#define YYPACT_NINF -1336 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-1336))) - -#define YYTABLE_NINF -793 - -#define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-793))) - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 21, -1336, 177, 111, -1336, -1336, -1336, 182, 193, 111, - -1336, 254, 26, -1336, -1336, 92, 2942, -1336, 1211, 1211, - -1336, -1336, -1336, -1336, -1336, -1336, 856, -1336, 326, 1089, - -1336, 1211, 990, 1211, 1211, 1211, -1336, 1211, 1211, 765, - 361, 630, 766, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, 354, - 413, -1336, -1336, -1336, 352, 456, -1336, -1336, -1336, 380, - 47, 431, 456, 856, 1211, 419, 465, -1336, -1336, -1336, - -1336, 1211, 231, -1336, 465, 305, 465, 465, 465, 773, - 1211, -1336, 839, -1336, -1336, -1336, 446, 502, 94, -1336, - 1211, 537, 540, 1211, 465, 1211, 264, -1336, 2008, 1211, - -1336, 456, 565, 8929, 960, 546, 59, 601, 30, -1336, - 551, 33, -1336, 24, 546, 546, 643, 465, -1336, -1336, - -1336, 603, -1336, -1336, -1336, 237, -1336, -1336, -1336, 635, - 1211, 465, 1211, 8929, 465, 1701, 569, -1336, 8634, -1336, - 8634, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, 220, 8929, 8634, 8250, 608, 1211, -1336, 694, - 773, 465, 620, 125, 8929, 612, 8634, 8811, 8314, 49, - 8929, 1822, 174, 634, -1336, -1336, -1336, -1336, 105, 685, - -1336, -1336, 84, -1336, 89, -1336, 397, 734, 682, -1336, - 1211, -1336, 30, 444, 690, 288, -1336, 7986, 546, 800, - 33, 713, 494, 546, 457, 728, 743, 1211, 551, -1336, - 318, 1211, 703, -1336, -1336, 757, -1336, -1336, 551, 465, - 770, 829, 1211, -1336, 395, -1336, 574, 8929, 281, -1336, - 25, -1336, -1336, 849, -1336, -1336, -1336, 792, -1336, 809, - -1336, 258, 821, 52, -1336, -1336, 286, -1336, 824, 787, - 830, -1336, 142, -1336, 392, 833, 58, 8929, -1336, 890, - 576, 800, 253, 1211, 902, 842, -1336, 83, 608, 773, - 465, 8811, -1336, 7142, 58, 8378, 858, 1211, 8442, 252, - -1336, 901, -1336, 134, 8929, -1336, 890, -1336, -1336, 8929, - 918, -1336, 303, 1211, 1211, 7142, 8634, -1336, 255, -1336, - -1336, -1336, 309, -1336, -1336, 360, 1107, 1211, 897, 903, - 885, -1336, 8634, 358, 895, 889, 890, 1211, 972, -1336, - -1336, -1336, 8634, 7986, -1336, -1336, 962, 7986, 8634, 8049, - 2008, 7455, 599, 906, 909, -1336, 929, 1211, 1011, 542, - -1336, 914, 930, 450, -1336, 922, -1336, 8634, 625, -1336, - 925, 469, -1336, -1336, 469, 8634, 465, 546, 788, -1336, - -1336, -1336, -1336, -1336, 368, 546, 551, 7142, 697, 950, - 289, 1211, 1028, 999, 936, 2536, 944, 8506, 4582, 4759, - 5033, -1336, -1336, -1336, -1336, -1336, -1336, 8634, -1336, 574, - 8634, -1336, -1336, -1336, -1336, 8634, 1211, 8929, -1336, -1336, - 7142, 574, 955, -1336, -1336, 8929, 952, -1336, -1336, -1336, - -1336, 1211, 1028, 465, 5458, 800, 957, 945, 800, 1018, - -1336, 311, 8634, 890, 800, 6602, 326, 1211, 6926, 7250, - 79, 6818, 959, 6818, 1211, 7142, 8634, 7518, 890, 7142, - 7142, 7142, 4886, 5665, 5370, 977, -1336, 490, -1336, 4180, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, 102, -1336, 974, 984, 136, -1336, 992, 148, 608, - 8811, 8929, -1336, 8929, -1336, -1336, 1071, 7142, -1336, 3193, - 126, 569, 2414, 985, 986, 1001, -1336, -1336, -1336, -1336, - -1336, -1336, 98, -1336, 1004, 1610, -1336, 1003, -1336, -1336, - 950, 8634, -1336, 83, 409, 1013, 1024, 1211, 422, -1336, - -1336, -1336, -1336, 1211, 465, -1336, 58, -1336, -1336, -1336, - 58, 7986, -1336, -1336, 1006, -1336, 1008, 74, 1007, -1336, - -1336, 1016, 97, -1336, 7986, 8634, 1000, 3625, 1211, 1891, - 2170, 7986, 553, -1336, -1336, -1336, -1336, 787, -1336, 185, - -1336, 1211, 555, -1336, 579, 394, 551, 930, -1336, 835, - -1336, 930, 546, 2653, 1211, 1037, 546, 1028, 8570, 546, - -1336, 553, 1026, 295, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, -1336, -1336, -1336, -1336, 1019, 1021, 1042, - -1336, 787, 1021, -1336, 1046, -1336, 3337, -1336, 1126, -1336, - 576, 569, -1336, -1336, 1032, -1336, 1615, 83, -1336, 465, - 608, 58, 7142, 7142, 6262, -1336, 890, 7250, 6710, 326, - 1211, 7986, 93, 6818, 6818, 1211, 7142, 7581, 890, 7250, - 7250, 7250, 5665, 5370, -1336, 1044, -1336, 5961, -1336, -1336, - -1336, -1336, -1336, 6032, -1336, 6421, -1336, 6421, -1336, 6306, - 58, 800, 149, -1336, 1051, 7142, 1005, 645, 645, 6602, - 326, 255, 1972, 6818, 498, 6818, 255, 7142, 5665, 5370, - -1336, 41, 5557, -1336, 1038, 5154, -1336, 755, -1336, 3523, - -1336, -1336, 1050, -1336, 1052, -1336, -1336, 706, 6076, 1054, - 1053, 1041, -1336, 1211, 742, 7142, 7142, 7142, 7142, 7142, - 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, - 7142, 7142, 7142, 6602, 8929, 8929, -1336, 7142, 7142, 7142, - 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 5773, 5370, - 1130, -1336, 7986, 959, 7034, 1148, 800, -1336, -1336, -1336, - 7142, 5890, -1336, 8634, -1336, -1336, -1336, 800, 8634, 255, - -1336, -1336, 351, 83, 1073, -1336, 1107, 897, 787, 317, - -1336, 1107, 576, 834, 381, -1336, 1078, 1062, 1085, 1090, - -1336, 7986, -1336, 1058, 7644, 7986, -1336, 1084, 7707, -1336, - 787, 7986, -1336, -1336, 569, -1336, 1096, 841, 1211, -1336, - 1087, 1083, 1101, -1336, 1093, -1336, 4886, 553, -1336, -1336, - 1112, 423, -1336, 619, -1336, -1336, 546, -1336, -1336, -1336, - 930, -1336, -1336, -1336, 1108, 1110, 295, 1111, 689, 1102, - 1113, 8634, -1336, 1211, 1206, -1336, 1211, -1336, -1336, 8693, - 1109, -1336, -1336, -1336, -1336, -1336, 800, 1147, 2001, 6076, - 7250, 6147, 6377, -1336, 1151, -1336, 6421, 6421, -1336, 6306, - 800, 155, 7250, 1160, 772, 772, 1138, 1139, 7250, 7250, - 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, - 7250, 7250, 7250, 7250, 7250, 7250, 9137, 8929, 8929, -1336, - 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, 7250, - 7250, 5773, 5370, 1213, 1214, 710, 1155, 7142, 7770, 800, - 7986, 8634, -1336, 978, 6262, -1336, 1211, 1181, -1336, 6421, - 6421, -1336, 6306, 1146, 1145, 7986, -1336, -1336, 1972, -1336, - 794, 4015, -1336, -1336, 3523, 742, 7142, 7142, 7142, 7142, - 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, - 7142, 7142, 7142, 7142, 6602, 8929, 8929, -1336, 7142, 7142, - 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 7142, 5773, - 5370, 1494, -1336, 1568, 1667, 5262, 7142, -1336, -1336, 569, - 1174, 1156, 1258, 121, -1336, 1182, 900, 900, 1260, 749, - 749, 1260, 2001, 1212, 6421, 6421, 6421, 6421, 6421, 6421, - 6421, 6421, 6421, 6421, 6262, -1336, -1336, 6421, 1260, 1260, - 467, 658, 978, 1005, 1005, 645, 645, 645, 1164, 6076, - 1163, -1336, 456, 1228, -1336, 7986, 5961, 1211, -1336, 5909, - -1336, 1168, -1336, -1336, -1336, -1336, 1186, 83, -1336, -1336, - -1336, 83, -1336, 952, 7142, 469, 8634, -1336, -1336, -1336, - 8929, 2826, 546, 800, 1268, 1270, 1173, 7986, 1175, -1336, - 1176, 7986, 1178, -1336, -1336, -1336, 7986, 1211, -1336, 1205, - 1912, -1336, 7986, -1336, 1183, 8634, -1336, -1336, -1336, 930, - -1336, 715, 1184, 1195, 553, 1027, -1336, 1187, -1336, 723, - -1336, -1336, -1336, 553, 1211, 1289, -1336, 1032, -1336, -1336, - 1287, 2633, 7250, 7250, 7833, 7250, 1076, -1336, -1336, 988, - 988, 1322, 1128, 1128, 1322, 2633, 2263, 6492, 6492, 6492, - 6492, 6492, 6492, 6492, 6492, 6492, 6492, 6377, -1336, -1336, - 6492, 1322, 1322, 582, 1572, 1076, 1160, 1160, 772, 772, - 772, 1193, 1218, -1336, 456, 238, -1336, 7986, 774, -1336, - 602, 1219, 1310, 6076, 800, 158, -1336, 7142, -1336, 787, - -1336, -1336, 1051, -1336, 1211, -1336, 1220, 900, 900, 1260, - 749, 749, 1260, 2001, 1212, 6421, 6421, 6421, 6421, 6421, - 6421, 6421, 6421, 6421, 6421, 6262, -1336, -1336, 6421, 1260, - 1260, 467, 658, 978, 1005, 1005, 645, 645, 645, 1223, - 1224, -1336, 456, -1336, 284, -1336, 291, 6076, 6076, -1336, - -1336, -1336, 7142, -1336, 7142, -1336, 1474, 7142, -1336, -1336, - 7250, 1244, -1336, -1336, -1336, 800, 576, 1245, 6076, 659, - 1227, 1229, -1336, 799, 1230, -1336, 1211, 1211, 7986, 1232, - 7986, 7986, 1234, 7986, -1336, -1336, 7986, -1336, -1336, -1336, - -1336, 787, -1336, 1375, 1226, 803, -1336, -1336, -1336, -1336, - -1336, -1336, -1336, 553, 689, 260, -1336, 447, -1336, -1336, - 689, 1243, 1253, -1336, 1211, 5961, 6147, 800, 160, -1336, - 6147, -1336, -1336, -1336, -1336, -1336, -1336, -1336, 66, -1336, - -1336, 726, -1336, -1336, -1336, 1211, 7142, 7770, 800, 6076, - 1256, 810, -1336, -1336, -1336, 5773, 5370, 5773, 5370, 6076, - 6076, -1336, 6076, 5961, 7250, -1336, -1336, 576, 813, -1336, - -1336, -1336, -1336, 4297, -1336, 1289, -1336, 7986, 1237, 7986, - 1239, -1336, 1211, -1336, 636, -1336, 489, -1336, -1336, 689, - 1238, 1211, 636, -1336, 511, 1249, 1107, 1351, 269, 1330, - 7250, 7833, 800, 7250, 7986, 1353, -1336, 1357, 6076, -1336, - 7142, 7142, 1259, 1262, 1264, 1267, 1269, -1336, 5961, -1336, - -1336, 1271, -1336, 1284, 7986, 7986, 1266, 1341, 1051, 773, - 1211, 1272, -1336, 465, 1342, 773, 1211, -1336, -1336, 1211, - 1289, 1293, 238, 6147, -1336, 7250, 6147, -1336, 7358, 166, - -1336, 6076, 6076, -1336, -1336, -1336, -1336, -1336, -1336, -1336, - 1376, -1336, 1211, 1298, 1348, 465, -1336, 1300, 1211, 1350, - 465, -1336, 1303, 1381, -1336, 6147, -1336, 6191, 1050, 1052, - -1336, 1211, 465, 7142, 1286, 1211, 1296, 8634, 465, 1211, - 1299, 1391, 1211, -1336, 1296, 6076, -1336, 465, 8870, 546, - 800, 399, 1299, 465, 8112, 546, 800, 1211, 166, 546, - 1296, 1211, 8752, 1297, 1302, 1384, 482, -1336, -1336, 546, - 1299, 1387, 7896, 1305, 1397, 930, -1336, 166, -1336, 484, - 546, 9047, 1398, 890, -1336, 8811, 1051, -1336, -1336, 930, - 546, 8175, 1402, 890, -1336, 1051, -1336, -1336, -1336, -1336, - 487, 1051, 8988, 1319, -1336, 930, 1051, 1404, 1321, -1336, - -1336, 1319, 272, 8811, 1325, -1336, 1321, 1051, 7986, 1331, - 1336, 1319, 1329, -1336, 1340, 1321, 1344, -1336, -1336, 1352, - 8811, -1336, 1359, 7986, -1336, -1336 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint16 yydefact[] = -{ - 5, 4, 0, 13, 1, 11, 17, 0, 0, 13, - 8, 127, 12, 14, 3, 13, 151, 27, 0, 0, - 9, 2, 126, 29, 15, 28, 0, 790, 0, 0, - 791, 0, 111, 0, 0, 0, 494, 793, 0, 150, - 792, 0, 0, 30, 31, 33, 34, 32, 37, 45, - 44, 36, 68, 69, 70, 66, 67, 35, 71, 0, - 0, 72, 64, 65, 0, 490, 493, 793, 792, 0, - 18, 0, 491, 0, 0, 0, 254, 784, 785, 786, - 787, 0, 0, 110, 254, 0, 254, 254, 254, 111, - 0, 152, 0, 269, 271, 59, 0, 0, 50, 267, - 0, 0, 0, 0, 254, 788, 0, 10, 0, 22, - 16, 492, 0, 0, 0, 255, 0, 0, 13, 48, - 0, 13, 105, 255, 255, 255, 0, 254, 270, 272, - 58, 0, 268, 132, 60, 0, 128, 131, 49, 0, - 0, 254, 0, 0, 254, 0, 0, 789, 0, 496, - 294, 497, 495, 777, 778, 779, 780, 782, 781, 19, - 783, 23, 0, 0, 0, 0, 443, 0, 389, 0, - 111, 254, 0, 0, 0, 0, 0, 0, 0, 409, - 0, 0, 372, 0, 365, 390, 366, 391, 274, 449, - 460, 241, 0, 265, 0, 457, 428, 264, 0, 256, - 0, 46, 13, 0, 0, 13, 114, 206, 255, 240, - 13, 0, 13, 255, 0, 0, 0, 0, 0, 52, - 0, 0, 0, 61, 57, 0, 273, 63, 0, 254, - 0, 136, 0, 461, 0, 462, 0, 0, 372, 425, - 255, 423, 426, 0, 908, 908, 908, 0, 42, 0, - 421, 0, 296, 0, 419, 422, 0, 288, 289, 417, - 292, 437, 274, 20, 0, 0, 699, 0, 381, 406, - 0, 240, 373, 0, 0, 0, 392, 456, 443, 111, - 254, 0, 377, 775, 699, 0, 389, 0, 0, 0, - 224, 0, 227, 274, 0, 379, 406, 407, 408, 0, - 0, 371, 0, 0, 788, 775, 416, 275, 0, 459, - 252, 250, 0, 244, 242, 0, 430, 0, 453, 0, - 257, 259, 0, 13, 0, 0, 406, 0, 0, 117, - 108, 115, 0, 0, 297, 320, 318, 0, 0, 0, - 0, 362, 0, 0, 204, 207, 0, 0, 304, 321, - 322, 493, 0, 0, 190, 0, 106, 0, 0, 88, - 0, 13, 79, 77, 13, 0, 254, 255, 0, 54, - 129, 62, 130, 51, 0, 255, 0, 775, 0, 428, - 373, 0, 463, 0, 0, 0, 0, 0, 0, 0, - 0, 41, 43, 285, 286, 287, 284, 0, 410, 0, - 0, 281, 282, 283, 280, 290, 293, 0, 21, 24, - 775, 0, 0, 382, 405, 0, 442, 444, 446, 447, - 400, 788, 374, 254, 0, 240, 0, 454, 240, 0, - 393, 0, 0, 406, 240, 610, 560, 574, 775, 775, - 0, 572, 0, 576, 570, 775, 0, 0, 406, 775, - 775, 775, 775, 775, 775, 0, 616, 559, 561, 0, - 617, 614, 689, 615, 729, 730, 731, 732, 733, 734, - 735, 0, 558, 0, 389, 274, 237, 389, 274, 443, - 0, 0, 380, 0, 378, 385, 0, 775, 369, 0, - 277, 0, 0, 0, 414, 448, 450, 253, 251, 266, - 245, 243, 0, 458, 0, 0, 427, 429, 431, 434, - 428, 0, 440, 0, 264, 0, 0, 0, 0, 94, - 47, 109, 116, 0, 254, 118, 699, 300, 319, 313, - 699, 0, 298, 323, 361, 363, 0, 351, 348, 301, - 349, 0, 338, 193, 205, 0, 310, 0, 788, 337, - 0, 0, 7, 185, 238, 239, 107, 91, 82, 13, - 78, 0, 0, 84, 0, 0, 0, 0, 56, 0, - 53, 0, 255, 0, 0, 0, 255, 464, 0, 255, - 424, 7, 0, 255, 794, 795, 796, 797, 798, 799, - 800, 801, 803, 804, 805, 806, 807, 808, 809, 810, - 811, 812, 813, 814, 815, 816, 802, 817, 818, 819, - 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, - 830, 831, 832, 833, 834, 835, 836, 837, 839, 840, - 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, - 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, - 861, 862, 863, 865, 864, 866, 870, 872, 867, 868, - 869, 871, 874, 876, 838, 873, 875, 877, 878, 879, - 880, 881, 882, 883, 884, 885, 886, 893, 896, 895, - 898, 899, 902, 906, 901, 903, 900, 904, 905, 907, - 897, 889, 891, 888, 887, 916, 890, 892, 894, 911, - 909, 910, 912, 913, 914, 917, 915, 296, 295, 0, - 420, 418, 291, 438, 0, 439, 0, 698, 0, 384, - 0, 0, 394, 195, 230, 396, 0, 455, 399, 254, - 443, 699, 775, 775, 609, 575, 406, 775, 669, 620, - 633, 0, 0, 631, 635, 629, 775, 0, 406, 775, - 775, 775, 775, 775, 675, 619, 621, 0, 676, 673, - 682, 674, 618, 0, 690, 573, 736, 577, 571, 613, - 699, 240, 0, 210, 74, 775, 684, 686, 685, 552, - 502, 516, 151, 514, 150, 518, 512, 775, 775, 775, - 482, 0, 12, 474, 0, 775, 471, 501, 503, 469, - 557, 556, 738, 478, 739, 500, 714, 483, 488, 0, - 0, 483, 774, 788, 719, 775, 775, 775, 775, 775, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 775, 775, 607, 0, 0, 563, 775, 775, 775, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 0, 388, 0, 0, 775, 0, 240, 225, 226, 383, - 775, 0, 370, 416, 278, 375, 38, 240, 415, 0, - 248, 246, 0, 456, 0, 436, 0, 453, 452, 0, - 260, 430, 0, 102, 13, 92, 0, 0, 0, 0, - 299, 0, 303, 353, 352, 0, 302, 340, 339, 208, - 209, 0, 305, 321, 0, 336, 0, 0, 0, 331, - 333, 0, 324, 307, 0, 311, 775, 6, 83, 89, - 0, 13, 80, 13, 103, 133, 255, 187, 55, 186, - 0, 40, 134, 135, 0, 0, 255, 0, 13, 0, - 0, 0, 411, 0, 0, 39, 0, 445, 376, 0, - 0, 402, 404, 401, 403, 395, 240, 0, 688, 700, - 775, 707, 668, 634, 0, 683, 632, 636, 630, 672, - 240, 0, 775, 677, 679, 678, 0, 0, 775, 775, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 775, 775, 775, 775, 775, 666, 0, 0, 622, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 775, 775, 0, 763, 13, 0, 775, 0, 240, - 0, 0, 212, 687, 551, 517, 0, 153, 475, 515, - 519, 513, 555, 0, 0, 0, 479, 473, 151, 476, - 501, 0, 466, 472, 468, 719, 775, 775, 775, 775, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 775, 775, 775, 549, 0, 0, 505, 775, 775, - 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 0, 480, 0, 0, 775, 775, 569, 568, 0, - 0, 0, 0, 716, 723, 725, 600, 601, 595, 591, - 592, 596, 590, 589, 579, 580, 581, 582, 583, 584, - 585, 586, 587, 588, 608, 611, 612, 578, 593, 594, - 597, 598, 599, 602, 603, 604, 605, 606, 0, 486, - 0, 565, 564, 0, 772, 0, 0, 0, 398, 0, - 387, 0, 276, 451, 249, 247, 0, 456, 432, 441, - 263, 0, 262, 261, 775, 13, 416, 97, 93, 95, - 0, 0, 255, 240, 0, 0, 359, 0, 354, 364, - 346, 0, 341, 350, 312, 309, 0, 0, 326, 325, - 334, 306, 0, 308, 0, 0, 81, 85, 104, 0, - 188, 13, 0, 0, 7, 182, 177, 0, 173, 13, - 179, 180, 171, 7, 0, 699, 228, 230, 194, 397, - 0, 681, 775, 775, 0, 775, 680, 627, 628, 659, - 660, 654, 650, 651, 655, 649, 648, 638, 639, 640, - 641, 642, 643, 644, 645, 646, 647, 667, 670, 671, - 637, 652, 653, 656, 657, 658, 661, 662, 663, 664, - 665, 0, 0, 624, 623, 0, 748, 0, 13, 752, - 0, 755, 0, 701, 240, 0, 703, 775, 211, 73, - 510, 511, 74, 477, 788, 481, 0, 542, 543, 537, - 533, 534, 538, 532, 531, 521, 522, 523, 524, 525, - 526, 527, 528, 529, 530, 550, 553, 554, 520, 535, - 536, 539, 540, 541, 544, 545, 546, 547, 548, 0, - 0, 507, 506, 746, 740, 747, 741, 489, 715, 498, - 737, 499, 775, 562, 775, 718, 717, 775, 566, 567, - 775, 0, 770, 367, 386, 240, 0, 0, 101, 0, - 0, 0, 122, 0, 0, 121, 0, 0, 360, 355, - 0, 347, 342, 0, 330, 327, 0, 335, 332, 328, - 465, 87, 189, 151, 0, 13, 140, 142, 143, 144, - 156, 157, 172, 7, 13, 181, 178, 151, 167, 176, - 13, 412, 0, 229, 0, 0, 708, 240, 0, 710, - 709, 625, 626, 767, 768, 769, 764, 316, 762, 749, - 753, 0, 754, 751, 756, 0, 775, 0, 240, 702, - 76, 0, 504, 508, 509, 775, 775, 775, 775, 727, - 728, 724, 726, 0, 775, 279, 433, 0, 13, 98, - 100, 119, 123, 0, 120, 699, 314, 356, 357, 343, - 344, 329, 0, 150, 151, 145, 0, 137, 141, 13, - 0, 0, 151, 183, 0, 0, 430, 0, 699, 765, - 775, 0, 240, 775, 0, 0, 750, 697, 704, 706, - 775, 775, 0, 0, 0, 0, 0, 773, 0, 435, - 99, 0, 124, 0, 358, 345, 0, 0, 74, 111, - 0, 0, 168, 254, 0, 111, 0, 169, 413, 0, - 699, 0, 0, 711, 713, 775, 761, 317, 775, 0, - 691, 705, 75, 776, 742, 744, 743, 745, 771, 125, - 0, 149, 0, 148, 0, 254, 170, 0, 0, 0, - 254, 368, 0, 0, 766, 712, 759, 757, 760, 758, - 696, 0, 254, 775, 0, 0, 0, 0, 254, 0, - 0, 0, 0, 315, 0, 147, 146, 254, 223, 255, - 240, 0, 0, 254, 206, 255, 240, 0, 692, 255, - 0, 405, 406, 0, 221, 0, 0, 192, 184, 255, - 0, 320, 406, 0, 0, 0, 191, 693, 694, 0, - 255, 405, 0, 406, 203, 222, 74, 158, 161, 0, - 255, 405, 0, 406, 199, 74, 164, 695, 159, 162, - 0, 74, 0, 220, 165, 0, 74, 0, 216, 160, - 163, 220, 74, 217, 0, 166, 216, 74, 213, 0, - 0, 220, 218, 200, 0, 216, 214, 196, 201, 0, - 219, 197, 0, 215, 202, 198 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -1336, -1336, -1336, -551, 106, 12, -427, -404, 20, 63, - -1336, 78, -1336, 13, 1448, -1336, 7, -1336, 42, -1104, - -1336, -1336, -1336, -1336, -1336, -1207, -1336, -1336, -1336, -1336, - -335, -869, -1336, 926, -1336, -1336, 607, -1336, -1336, -1336, - -1336, -84, 1285, -1336, 1291, -1336, 1166, -1336, -1336, -1336, - 43, -158, -1336, -1336, -1336, -1336, -1336, 132, -1336, -1336, - -1336, -1000, -1336, -1336, -1336, -1336, -1336, -1336, -992, 299, - -1336, -1336, -1336, -1336, 1417, -1336, -148, -1086, -1254, -1336, - -1336, -1336, -1336, -63, -1108, -529, -429, 486, -1068, -1335, - -1336, -280, -412, 297, -1336, -261, -37, -27, -1336, -1336, - 994, -1336, 1197, -1336, -126, -103, -1336, -1336, 795, -101, - -1336, -514, 963, 333, -1336, -1336, 964, -834, -1336, -836, - -105, -61, 790, -223, 791, -1336, -1336, -290, -1336, -1336, - -1336, -786, -69, -131, 1121, -1336, 1142, -301, -839, -1336, - 654, -71, -362, -303, -222, 652, -259, -1336, -1336, 663, - -797, -51, -289, 2885, -108, -547, 1086, 627, -1336, 741, - -420, -949, -387, -16, 1, 2945, -749, 3027, 1143, -1336, - -439, 3253, -1336, -277, 1105, 144, 811, 95, -647, 513, - -1336, -1336, 233, -1336, 3527, -1336, 53, -1336, -1336, 302, - 304, -1336, -1336, -1172, -1170, 62, -1336, -1336, -1336, -1336, - -1336, -1336, 2157, -18, -273, 1441, -1336, 695, -1336, -432, - -144, -106, -142 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 2, 3, 916, 917, 10, 11, 12, 13, 69, - 162, 14, 15, 561, 17, 43, 793, 45, 46, 47, - 48, 49, 50, 97, 51, 1022, 1472, 52, 363, 213, - 562, 563, 358, 359, 53, 518, 519, 1157, 54, 55, - 56, 82, 204, 205, 206, 522, 329, 1162, 1163, 23, - 135, 136, 57, 379, 58, 1364, 1365, 1366, 1367, 1544, - 1368, 59, 60, 1369, 1370, 1371, 1196, 61, 1197, 1198, - 1199, 1377, 1200, 1201, 62, 63, 208, 1565, 1559, 209, - 425, 1566, 1560, 343, 344, 345, 1265, 773, 1629, 1624, - 1573, 289, 290, 950, 291, 354, 275, 198, 199, 320, - 321, 322, 192, 98, 182, 307, 256, 257, 398, 346, - 1398, 347, 348, 909, 910, 911, 541, 542, 536, 537, - 250, 184, 185, 276, 186, 187, 953, 415, 299, 251, - 252, 493, 494, 259, 254, 240, 241, 318, 506, 507, - 508, 708, 261, 193, 271, 416, 509, 309, 495, 512, - 426, 427, 195, 455, 419, 553, 456, 794, 795, 796, - 806, 1128, 811, 457, 65, 458, 799, 808, 757, 758, - 460, 461, 1510, 412, 462, 1266, 760, 1389, 809, 1091, - 1092, 1093, 1094, 1325, 463, 803, 804, 464, 1258, 1259, - 1260, 1261, 1465, 465, 466, 1396, 467, 468, 469, 470, - 471, 1037, 472, 160, 146, 66, 699, 388, 700, 701, - 702, 703, 704 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 64, 431, 247, 151, 249, 126, 483, 473, 183, 499, - 420, 417, 724, 800, 83, 899, 16, 253, 772, 238, - 927, 20, 16, 44, 929, 791, 503, 72, 16, 564, - 938, 491, 24, 266, 810, 908, 523, 243, 230, 115, - 248, 272, 1152, 1041, 713, 284, 1044, 120, 792, 123, - 124, 125, 1187, 1343, 1187, 1166, 428, 430, 265, 865, - 268, 1170, 1251, 194, 372, 1410, 807, 145, 857, 282, - 367, 83, 292, 295, 111, 300, 1146, 1141, 576, 260, - 375, 258, 71, 1394, 239, 1395, 274, 21, 310, 434, - 218, 1376, -25, 313, 399, 893, 214, 215, 216, 1035, - 411, 200, 870, 737, 228, 976, 380, 231, 148, 9, - 382, -26, 302, 297, 197, 197, 1, 139, 897, 6, - 189, 1463, 5, 6, 7, 5, 6, 7, 383, 148, - 1309, 203, 384, 385, 16, 278, 140, 148, 298, 148, - 212, 1033, -720, 732, 382, 148, 8, 422, 721, 108, - 8, 148, 83, 8, -113, 452, 852, -26, 775, 1018, - 400, 853, 413, 109, 725, 1214, 400, 728, 1407, 148, - 1461, 1464, 161, 733, 220, 279, 292, 4, 280, 190, - 268, 352, 201, 295, 447, 6, 360, 854, 311, 482, - 382, 349, 376, 314, 484, 429, 894, 303, 747, 211, - 722, 526, 871, 5, 6, 7, 312, 530, 150, 877, - 372, 315, 8, 386, 20, 203, -25, 515, 203, 898, - 872, 306, 20, 16, 202, 357, 557, 210, 572, 150, - 281, 8, 527, -231, 565, -235, 529, 150, 532, 150, - 535, 540, 863, 1326, 407, 150, 875, -233, 555, 888, - 306, 150, 306, 889, 1019, 577, 583, 856, 306, 1445, - 1215, 83, 393, 1408, 306, 1462, 394, 148, 374, 150, - 395, 1020, 148, 382, 711, 904, 303, 1020, 6, 221, - 1020, 1523, 1020, -792, 33, 382, 1630, 304, 355, 948, - 401, 709, 233, 438, 402, 273, 1639, 18, 403, 27, - 1569, 731, 715, 717, 303, 8, 918, 106, 19, 30, - 719, 411, 303, 497, 106, 770, 1590, 349, 971, 292, - 117, 349, 22, 349, 239, 349, 349, 409, 707, 566, - 1394, 1349, 1395, 977, 712, -463, 517, 1352, 149, 67, - 567, 263, 264, -464, 27, 118, 774, 68, 571, 73, - 1337, 235, 452, 800, 30, 1144, 800, 479, 711, 222, - 221, 223, 396, 1446, 500, 807, 421, 150, 791, 1034, - 1340, 1021, 150, -792, 480, 292, 858, 1454, 859, 382, - 878, 6, 1450, 1190, 67, 197, 27, 864, 1455, 1613, - 404, 792, 68, 1177, 304, 27, 30, 189, 1618, 1415, - 1416, 807, 421, 400, 1621, 30, 1417, 1418, 8, 1626, - 221, 372, -112, 498, 900, 1631, 730, -153, 926, 121, - 1635, 1150, 755, 755, 488, 489, 67, 27, 122, 1130, - 890, 349, 103, 480, 68, 67, 797, 30, 503, 1151, - 368, 91, 369, 68, 1487, 279, 960, 936, 280, 540, - 915, 6, 1494, 164, 957, 1145, 190, 1491, 972, 165, - 166, 947, 879, 319, 501, 105, 1473, 67, 1475, 104, - 815, 816, 1175, 167, 6, 68, 1579, 800, 8, 106, - -96, 27, -96, 326, 133, 27, 168, 887, 169, 791, - 569, 30, 570, 1016, 1600, 30, 316, 327, 317, 107, - 170, 8, 400, 171, 172, 1158, 955, 400, 956, 834, - 1017, -258, 792, 408, 1438, 349, 6, 925, 113, 1440, - 1636, 67, 1578, -258, 328, 67, 1451, 1443, 349, 68, - 173, 903, -258, 68, 349, 349, 1452, 1207, 174, 1489, - 1089, 175, 1490, 8, 884, 930, 885, 1186, 89, 934, - 110, 90, 937, 176, -154, 177, 940, 178, 1634, 1187, - 179, 1495, 6, 554, 1496, 180, 181, 1642, 114, 499, - 134, 361, 357, 841, 842, 843, 844, 845, 846, 847, - 362, 713, 848, 849, 850, 978, 979, 6, 1257, 8, - 142, -86, 1252, -86, 382, 1138, 552, 381, 552, 381, - 382, 552, 332, 813, 814, 1597, 1142, 1608, 333, 27, - 1619, 27, 452, 233, 8, -90, -90, 1498, 954, 30, - 538, 30, 26, 417, 997, 138, 153, 154, 155, 156, - 77, 78, 79, 80, 27, 334, 197, 28, 27, 143, - 964, 133, 1362, 1374, 30, 5, 774, 7, 30, 67, - 157, 67, 1380, 92, 100, 548, 549, 68, 550, 68, - 1310, 815, 816, 335, 163, 27, 908, 207, 93, 336, - 27, 27, 235, 36, 67, 30, 158, 921, 67, 922, - 30, 30, 68, 244, 245, 246, 68, 337, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 1209, 217, 1011, 1012, 1013, - 834, 923, 338, 924, 94, 67, 339, 270, 340, 1213, - 67, 67, 6, 68, 341, 342, 1443, 273, 68, 68, - 539, 755, 755, 277, 1402, 349, 1403, 219, 283, 1115, - 1116, 349, 27, 755, 755, 755, 305, 711, 27, 8, - 95, 133, 30, 1188, 96, 224, 558, 559, 30, 225, - 382, 1133, 815, 816, 817, 382, 382, 820, 1267, 1537, - 848, 849, 850, -722, 1363, 842, 843, 844, 845, 846, - 847, 1090, 67, 848, 849, 850, 1040, 27, 67, 797, - 68, 1428, 6, 1429, 308, 1388, 68, 30, 319, 1028, - 535, 834, 27, 1169, 540, 133, 323, 1173, 574, 1039, - 1174, 27, 30, 6, 77, 78, 79, 80, 6, 8, - 711, 30, 24, -174, 330, 89, 6, 67, 90, 100, - 1339, -154, 1449, 27, 353, 68, 133, 371, 1085, 1086, - 8, 1257, 67, 30, 1256, 8, 349, 356, 755, -139, - 68, 67, 364, 8, 292, 365, 101, -175, 1402, 68, - 1466, 1132, 838, 839, 840, 841, 842, 843, 844, 845, - 846, 847, 503, 67, 848, 849, 850, 6, 813, 1045, - 27, 68, 377, 133, 27, 349, 27, 128, 349, 349, - 30, 373, 349, 378, 30, 349, 30, 1011, 1012, 1013, - 1269, 27, 1238, 1239, 8, 400, 6, 517, 1399, 1189, - 797, 30, 1345, 387, 899, 335, 6, 1274, 1045, 1193, - 67, 336, 568, 129, 67, 391, 67, 774, 68, 774, - 1432, 1433, 68, 8, 68, 245, 246, -138, 1382, 20, - 36, 67, 392, 8, 1272, 410, 1154, 1480, 1363, 68, - 389, 390, 834, 397, 755, 1319, 405, 1321, 1155, 130, - 1156, 1195, 406, 131, 414, 423, 755, -232, 424, 928, - 1296, 1297, 755, 755, 755, 755, 755, 755, 755, 755, - 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, - 755, 815, 816, 1320, 755, 755, 755, 755, 755, 755, - 755, 755, 755, 755, 755, 27, 1474, 189, 1476, 511, - 481, 1411, 349, 1406, 349, 30, 513, 514, 843, 844, - 845, 846, 847, 521, 1254, 848, 849, 850, 520, 349, - 834, 77, 78, 79, 80, 327, 528, 543, 545, 1598, - 997, 544, 1388, 547, 1331, 67, 81, 485, 1606, 551, - 486, 487, 1609, 68, 552, 1273, 556, 834, 560, 316, - 26, 303, 1614, 578, 1361, 1341, 190, 579, 581, 718, - 720, 726, 27, 1620, 191, 28, 535, 727, 1625, 800, - 540, 729, 30, 452, 1425, 1354, 812, 1426, 855, 978, - 979, 1359, 1312, -236, 1314, 1316, 843, 844, 845, 846, - 847, -234, 860, 848, 849, 850, 1006, 1007, 1008, 1009, - 1010, 36, 67, 1011, 1012, 1013, 867, 873, 868, 869, - 1375, 876, 881, 774, 899, 845, 846, 847, 997, 349, - 848, 849, 850, 882, 27, 901, 1460, 892, 891, 895, - 381, 978, 979, 980, 30, 1344, 983, 896, 933, 1486, - 939, 941, 27, 943, 233, 349, 944, 1470, 407, 946, - 1021, 349, 30, 74, 949, 349, 1397, 813, 1483, 1131, - 349, 504, 1042, 1085, 67, 27, 349, 1083, 1479, 1084, - 997, 1137, 68, 1087, 1088, 30, 1147, 1160, 1161, 64, - 1167, 1501, 67, 857, 1006, 1007, 1008, 1009, 1010, 1164, - 68, 1011, 1012, 1013, 1165, 1176, 755, 755, 349, 755, - 1182, 1505, 997, 235, 36, 67, 1171, 1181, 505, 1180, - 382, 1185, 1195, 68, 1183, 815, 816, 817, 818, 819, - 820, 821, 1191, 1532, 1192, 1194, 1202, 1203, 857, 1204, - 1208, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 349, 1253, 1011, 1012, 1013, 27, 1169, 27, 535, - 1173, 1210, 540, 1212, 834, 1441, 30, 1217, 30, 1262, - 1218, 91, 1255, 815, 816, 1270, 1271, 1319, 1575, 1321, - 1008, 1009, 1010, 1322, 1584, 1011, 1012, 1013, 1574, 1324, - 1323, 1327, 1592, 1328, 1329, 1330, 67, 36, 67, 1335, - 1336, 1346, 1602, 1347, 68, 1348, 68, 1350, 1351, 1577, - 1353, 382, 834, 1612, 1356, 1586, 774, 1360, 1372, 1373, - 1384, 1378, 1391, 1617, 755, 838, 839, 840, 841, 842, - 843, 844, 845, 846, 847, 978, 979, 848, 849, 850, - 382, 411, 349, 1405, 349, 349, 1169, 349, 1173, 1392, - 349, 1404, 1413, 1632, 1412, 1414, 1424, 64, 1430, 1427, - 1447, 1456, 1431, 1434, 1437, 1500, 1439, 1457, 1471, 1484, - 774, 1485, 1492, 1507, 997, 840, 841, 842, 843, 844, - 845, 846, 847, 1497, 1499, 848, 849, 850, 1502, 1508, - 1509, 1514, 1513, 1169, 1173, 1515, 1516, 1195, 1520, 1521, - 1517, 349, 1519, 1195, 1522, 1528, 1526, 1533, 26, 1541, - 1543, 1545, 1547, 1549, 1552, 1524, 1540, 1551, 755, 1556, - 27, 1529, 1558, 28, 1567, 1564, 1561, 349, 1594, 1453, - 30, 349, 1596, 349, 1595, -405, 1604, 1003, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 1605, 1611, 1011, 1012, 1013, - 1616, 1623, 1627, 1628, 755, 349, 1633, 755, 349, 36, - 67, 1640, 1637, 292, 1442, 1443, 1527, 1638, 68, 70, - 70, 1641, 1195, 25, 1444, 1588, 1643, 295, 349, 349, - 75, 83, 76, 1644, 84, 85, 86, 83, 87, 88, - 1645, 532, 99, 102, 1607, 919, 482, 325, 1546, 755, - 292, 1159, 797, 1550, 525, -721, 331, 1448, 1379, 119, - 890, 1583, 942, 1090, 1383, 1554, 1268, 859, 880, 27, - 902, 1562, 502, 1358, 914, 112, 951, 952, 292, 30, - 1570, 710, 116, 1311, 754, 754, 1580, 580, 766, 27, - 1148, 127, 1576, 132, 1153, 292, 1043, 137, 1585, 30, - 1149, 141, 1589, 1184, 144, 764, 147, 152, 349, 67, - 70, 1469, 1599, 965, 188, 196, 1504, 68, 1276, 1421, - 1400, 1539, 1401, 1610, 1534, 0, 349, 0, 36, 67, - 0, 0, 137, 1615, 0, 978, 979, 68, 0, 0, - 226, 227, 763, 229, 188, 349, 188, 0, 0, 188, - 0, 262, 0, 0, 0, 0, 0, 1313, 0, 0, - 0, 0, 0, 27, 188, 188, 188, 0, 188, 0, - 0, 0, 349, 30, 997, 188, 0, 188, 293, 188, - 0, 188, 188, 0, 0, 166, 0, 349, 0, 0, - 0, 0, 0, 381, 0, 0, 0, 0, 381, 0, - 0, 324, 36, 67, 0, 27, 0, 233, 351, 0, - 27, 68, 0, 0, 0, 30, 0, 0, 366, 0, - 30, 0, 370, 137, 874, 170, 137, 0, 171, 0, - 0, 0, 0, 188, 0, 0, 0, 188, 188, 1005, - 1006, 1007, 1008, 1009, 1010, 67, 0, 1011, 1012, 1013, - 67, 0, 0, 68, 0, 173, 1315, 0, 68, 0, - 0, 0, 27, 0, 0, 70, 235, 0, 188, 0, - 165, 188, 30, 0, 188, 0, 0, 0, 0, 0, - 177, 0, 293, 0, 232, 0, 475, 0, 476, 478, - 0, 0, 0, 0, 0, 188, 27, 168, 233, 169, - 188, 36, 67, 0, 490, 147, 30, 188, 0, 0, - 68, 170, 0, 196, 171, 172, 196, 188, 510, 0, - 0, 0, 0, 188, 0, 0, 0, 0, 524, 0, - 0, 0, 0, 188, 351, 0, 67, 0, 351, 188, - 351, 234, 351, 351, 68, 0, 0, 0, 546, 174, - 0, 0, 175, 0, 188, 0, 0, 235, 188, 0, - 0, 0, 0, 0, 0, 0, 188, 0, 178, 137, - 0, 179, 0, 0, 236, 0, 180, 237, 0, 575, - 0, 0, 188, 754, 754, 164, 188, 0, 188, 0, - 0, 165, 166, 0, 0, 754, 754, 754, 262, 0, - 188, 188, 0, 1014, 0, 167, 262, 714, 188, 0, - 0, 0, 188, 0, 0, 0, 188, 27, 168, 233, - 169, 0, 147, 0, 0, 293, 0, 30, 0, 0, - 766, 0, 170, 188, 0, 171, 172, 1036, 735, 0, - 961, 962, 0, 0, 0, 768, 0, 188, 351, 0, - 0, 0, 973, 974, 975, 0, 0, 67, 0, 0, - 0, 0, 173, 0, 0, 68, 0, 0, 0, 0, - 174, 0, 905, 175, 0, 0, 0, 0, 235, 0, - 906, 293, 188, 0, 188, 176, 27, 177, 0, 178, - 188, 0, 179, 1357, 0, 0, 30, 180, 181, 1134, - 754, 906, 0, 301, 0, 0, 188, 27, 0, 0, - 0, 0, 188, 0, 0, 335, 0, 30, 883, 0, - 0, 336, 0, 0, 886, 0, 67, 0, 0, 0, - 0, 0, 351, 0, 68, 0, 335, 0, 0, 907, - 0, 0, 336, 0, 0, 351, 188, 67, 0, 147, - 912, 351, 351, 0, 0, 68, 0, 1136, 0, 0, - 907, 0, 920, 0, 815, 816, 817, 818, 819, 820, - 137, 29, 0, 0, 0, 932, 0, 0, 0, 188, - 0, 31, 32, 0, 0, 33, 0, 0, -155, 0, - 0, 0, 0, 0, 34, 153, 154, 155, 156, 77, - 78, 79, 80, 834, 0, 35, 754, 1026, 0, 0, - 0, 38, 39, 0, 0, 1027, 41, 0, 754, 157, - 0, 42, 0, 0, 754, 754, 754, 754, 754, 754, - 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, - 754, 754, 754, 0, 0, 158, 754, 754, 754, 754, - 754, 754, 754, 754, 754, 754, 754, 0, 0, 0, - 0, 0, 0, 1211, 838, 839, 840, 841, 842, 843, - 844, 845, 846, 847, 0, 1216, 848, 849, 850, 0, - 0, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, - 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, - 0, 0, 0, 1240, 1241, 1242, 1243, 1244, 1245, 1246, - 1247, 1248, 1249, 1250, 0, 0, 0, 0, 0, 0, - 0, 188, 0, 0, 0, 0, 0, 188, 0, 0, - 0, 0, 0, 332, 0, 0, 0, 0, 0, 333, - 0, 963, 351, 0, 0, 0, 968, 0, 351, 0, - 0, 538, 0, 26, 0, 0, 0, 153, 154, 155, - 156, 77, 78, 79, 80, 27, 334, 0, 28, 0, - 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, - 0, 157, 1332, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, - 336, 0, 0, 0, 36, 67, 0, 158, 0, 0, - 0, 0, 0, 68, 147, 1095, 0, 0, 337, 0, - 0, 0, 0, 0, 0, 159, 978, 979, 980, 981, - 982, 983, 984, 338, 0, 188, 188, 339, 0, 340, - 0, 0, 0, 0, 0, 341, 342, 0, 0, 0, - 0, 913, 0, 351, 0, 0, 0, 0, 754, 754, - 0, 754, 0, 0, 188, 997, 0, 0, 0, 188, - 0, 0, 0, 196, 0, 0, 0, 188, 0, 0, - 0, 0, 188, 188, 0, 0, 0, 0, 0, 0, - 0, 0, 351, 0, 0, 351, 351, 0, 0, 351, - 0, 1393, 351, 0, 0, 0, 0, 0, 1178, 1179, - 0, 0, 0, 0, 0, 1385, 1386, 0, 1390, 0, - 0, 0, 0, 0, 350, 0, 1001, 1002, 1003, 1004, - 1005, 1006, 1007, 1008, 1009, 1010, 0, 0, 1011, 1012, - 1013, 0, 262, 0, 714, 0, 0, 1205, 0, 0, - 293, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 754, 815, 816, 817, - 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, - 828, 829, 830, 831, 832, 833, 0, 0, 188, 188, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 834, 0, 0, 351, - 0, 351, 188, 0, 0, 0, 0, 87, 0, 0, - 0, 1459, 0, 1423, 0, 0, 351, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1095, 0, 0, 0, - 350, 0, 0, 0, 350, 0, 350, 533, 350, 350, - 0, 0, 0, 0, 0, 0, 188, 188, 0, 1477, - 754, 0, 0, 835, 0, 836, 837, 838, 839, 840, - 841, 842, 843, 844, 845, 846, 847, 0, 0, 848, - 849, 850, 0, 0, 0, 0, 0, 866, 0, 0, - 0, 0, 0, 0, 0, 165, 754, 0, 0, 754, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, - 0, 0, 0, 0, 1518, 0, 0, 1478, 0, 0, - 0, 27, 168, 233, 169, 0, 351, 0, 1333, 0, - 0, 30, 0, 0, 0, 0, 170, 0, 1393, 171, - 172, 754, 0, 0, 1536, 762, 762, 188, 0, 0, - 0, 188, 351, 1503, 350, 0, 1506, 0, 351, 805, - 0, 67, 351, 0, 0, 0, 234, 351, 1355, 68, - 0, 912, 0, 351, 174, 0, 188, 175, 0, 0, - 0, 0, 235, 0, 0, 0, 978, 979, 980, 981, - 982, 983, 0, 178, 0, 1381, 179, 0, 1535, 0, - 0, 180, 0, 0, 0, 351, 815, 816, 817, 818, - 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 833, 997, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 350, 0, - 0, 0, 0, 0, 0, 834, 0, 0, 351, 0, - 0, 350, 0, 0, 350, 0, 0, 350, 350, 0, - 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1001, 1002, 1003, 1004, - 1005, 1006, 1007, 1008, 1009, 1010, 0, 0, 1011, 1012, - 1013, 0, 835, 0, 836, 837, 838, 839, 840, 841, - 842, 843, 844, 845, 846, 847, 0, 1095, 848, 849, - 850, 0, 0, 0, 0, 0, 931, 188, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1435, 1436, 351, - 0, 351, 351, 0, 351, 0, 0, 351, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1458, 0, 0, 0, 332, - 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1467, 0, 351, 26, - 0, 0, 0, 153, 154, 155, 156, 77, 78, 79, - 80, 27, 334, 0, 28, 0, 0, 0, 188, 0, - 0, 30, 0, 0, 351, 0, 0, 157, 351, 0, - 351, 0, 0, 196, 0, 1488, 0, 0, 0, 0, - 335, 0, 1493, 102, 762, 762, 336, 188, 350, 0, - 36, 67, 351, 158, 350, 351, 762, 762, 762, 68, - 0, 0, 0, 0, 337, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 351, 351, 0, 0, 338, - 0, 1525, 0, 339, 0, 340, 0, 1530, 0, 0, - 1531, 341, 342, 0, 0, 0, 0, 1342, 0, 805, - 0, 0, 805, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1542, 0, 26, 0, 0, 0, 1548, - 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, - 28, 29, 1553, 0, 0, 0, 1557, 30, 188, 0, - 1563, 31, 32, 1568, 0, 33, 0, 0, -155, 293, - 0, 0, 0, 0, 34, 351, 0, 0, 1587, 350, - 0, 762, 476, 478, 0, 35, 36, 37, 0, 0, - 0, 38, 39, 351, 0, 40, 41, 0, 0, 0, - 242, 42, 188, 255, 0, 255, 293, 0, 0, 0, - 0, 0, 351, 0, 0, 0, 0, 0, 350, 255, - 269, 350, 350, 188, 0, 350, 0, 0, 350, 0, - 0, 255, 0, 296, 293, 0, 255, 0, 0, 351, - 0, 0, 0, 805, 0, 0, 0, 0, 0, 0, - 0, 293, 0, 0, 351, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 762, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 762, - 0, 0, 0, 0, 0, 762, 762, 762, 762, 762, - 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, - 762, 762, 762, 762, 0, 418, 0, 762, 762, 762, - 762, 762, 762, 762, 762, 762, 762, 762, 0, 0, - 269, 0, 0, 296, 0, 350, 0, 350, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 255, 350, 496, 0, 0, 164, 0, 0, 0, - 0, 418, 165, 166, 0, 0, 0, 516, 0, 0, - 0, 0, 0, 0, 0, 0, 167, 255, 0, 0, - 0, 0, 0, 255, 0, 0, 0, 0, 27, 168, - 233, 169, 0, 0, 0, 0, 0, 0, 30, 0, - 0, 0, 255, 170, 0, 0, 171, 172, 0, 0, - 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, - 242, 0, 255, 173, 0, 0, 68, 0, 0, 0, - 0, 174, 255, 0, 175, 255, 0, 0, 0, 235, - 255, 0, 350, 0, 0, 0, 176, 0, 177, 0, - 178, 0, 0, 179, 0, 0, 0, 0, 180, 181, - 459, 0, 0, 0, 862, 0, 0, 255, 350, 0, - 0, 0, 0, 0, 350, 0, 0, 0, 350, 0, - 0, 255, 492, 350, 0, 0, 0, 0, 0, 350, - 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, - 825, 826, 827, 828, 829, 830, 831, 832, 833, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 762, - 762, 350, 762, 0, 255, 0, 0, 0, 0, 834, - 0, 0, 0, 756, 756, 0, 0, 0, 0, 0, - 418, 0, 0, 0, 0, 0, 255, 798, 0, 0, - 0, 0, 0, 0, 573, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 350, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 0, 0, 0, 0, 0, 835, 716, 836, 837, - 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, - 0, 0, 848, 849, 850, 0, 0, 0, 0, 0, - 945, 0, 734, 255, 0, 0, 0, 0, 765, 0, - 767, 0, 769, 0, 0, 0, 776, 777, 778, 0, - 0, 0, 0, 0, 0, 0, 0, 762, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 350, 0, 350, 350, 0, - 350, 0, 0, 350, 861, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1046, 1047, 1048, 1049, - 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, - 1060, 1061, 1062, 1063, 1064, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 350, 1065, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 762, 0, 0, 0, 0, 0, 0, 0, 0, - 350, 0, 0, 0, 350, 0, 350, 0, 0, 0, - 0, 0, 0, 0, 0, 418, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 762, 350, 0, - 762, 350, 1066, 0, 1067, 1068, 1069, 1070, 1071, 1072, - 1073, 1074, 1075, 1076, 1077, 1078, 0, 0, 1079, 1080, - 1081, 350, 350, 0, 0, 0, 1082, 0, 26, 0, - 0, 0, 153, 154, 155, 156, 77, 78, 79, 80, - 27, 0, 762, 28, 0, 805, 1025, 0, 0, 0, - 30, 1031, 0, 0, 0, 0, 157, 0, 0, 0, - 0, 0, 756, 756, 0, 0, 0, 0, 0, 0, - 0, 759, 759, 0, 756, 756, 756, 0, 0, 36, - 67, 0, 158, 0, 0, 801, 0, 0, 68, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 350, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 340, 0, 0, 798, 0, 350, - 798, 0, 0, 0, 0, 0, 0, 0, 255, 0, - 0, 0, 0, 255, 1143, 0, 0, 0, 350, 958, - 959, 418, 0, 0, 0, 0, 418, 418, 0, 0, - 966, 967, 0, 969, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 350, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 756, - 350, 0, 1023, 0, 0, 0, 1024, 0, 0, 0, - 1029, 0, 1030, 0, 1032, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, - 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, - 1114, 798, 0, 0, 1117, 1118, 1119, 1120, 1121, 1122, - 1123, 1124, 1125, 1126, 1127, 1129, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1139, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 756, 255, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 756, 0, 0, - 0, 0, 0, 756, 756, 756, 756, 756, 756, 756, - 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, - 756, 756, 0, 0, 0, 756, 756, 756, 756, 756, - 756, 756, 756, 756, 756, 756, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 761, 761, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 802, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 759, 759, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 759, 759, 759, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, - 1058, 1059, 1060, 1061, 1062, 1063, 1064, 0, 1129, 0, - 0, 255, 0, 0, 1263, 801, 0, 0, 801, 0, - 0, 0, 0, 0, 0, 0, 0, 1065, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 0, 0, 1277, 1278, 1279, 1280, 1281, 1282, 1283, - 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, - 1294, 1295, 0, 0, 0, 1298, 1299, 1300, 1301, 1302, - 1303, 1304, 1305, 1306, 1307, 1308, 1129, 759, 0, 0, - 0, 0, 1317, 1318, 1066, 0, 1067, 1068, 1069, 1070, - 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 0, 0, - 1079, 1080, 1081, 0, 0, 0, 0, 0, 1275, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 756, 756, 0, - 756, 0, 0, 0, 0, 0, 0, 0, 0, 801, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1338, 0, 815, 816, 817, 818, 819, 820, 821, - 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, - 832, 833, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, - 0, 418, 834, 0, 0, 759, 0, 0, 0, 0, - 0, 759, 759, 759, 759, 759, 759, 759, 759, 759, - 759, 759, 759, 759, 759, 759, 759, 759, 759, 759, - 0, 0, 0, 759, 759, 759, 759, 759, 759, 759, - 759, 759, 759, 759, 761, 761, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 756, 761, 761, 761, 835, - 0, 836, 837, 838, 839, 840, 841, 842, 843, 844, - 845, 846, 847, 0, 1409, 848, 849, 850, 0, 0, - 332, 851, 0, 0, 0, 0, 333, 0, 0, 0, - 0, 0, 418, 0, 0, 0, 0, 0, 0, 1481, - 26, 0, 802, 0, 153, 154, 155, 156, 77, 78, - 79, 80, 27, 334, 0, 28, 0, 0, 0, 0, - 0, 418, 30, 0, 0, 0, 0, 0, 157, 1419, - 0, 1420, 0, 0, 1422, 0, 0, 0, 0, 0, - 0, 335, 0, 0, 0, 0, 0, 336, 0, 756, - 0, 36, 67, 0, 158, 0, 0, 0, 0, 0, - 68, 761, 0, 0, 0, 337, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 338, 0, 0, 0, 339, 756, 340, 0, 756, 0, - 0, 0, 341, 342, 0, 0, 0, 0, 1482, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 255, 1468, 0, 0, 0, 0, 0, 0, - 0, 0, 1129, 802, 1129, 0, 0, 0, 0, 0, - 756, 0, 0, 798, 0, 0, 0, 1593, 0, 0, - 0, 0, 0, 0, 0, 759, 759, 1603, 759, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 761, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1511, 1512, 761, - 0, 0, 0, 0, 0, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 0, 0, 0, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1555, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 759, 0, 584, 585, 586, 587, 588, - 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, - 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, - 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, - 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, - 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, - 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, - 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, - 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 670, 671, 672, 673, 674, 675, 759, 676, 0, - 0, 677, 0, 678, 679, 680, 681, 682, 683, 684, - 685, 686, 687, 688, 689, 690, 244, 245, 246, 691, - 0, 0, 692, 0, 693, 694, 695, 696, 697, 698, - 0, 0, 0, 759, 0, 0, 759, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 761, - 761, 0, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 759, 0, - 0, 801, 584, 585, 586, 587, 588, 589, 590, 591, - 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, - 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, - 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, - 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, - 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, - 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, - 672, 673, 674, 675, 0, 676, 0, 761, 677, 0, - 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, - 688, 689, 690, 244, 245, 246, 691, 0, 705, 692, - 0, 693, 694, 0, 696, 697, 698, 0, 0, 432, - 0, 0, 0, 0, 0, 433, 434, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 779, 0, 26, - 0, 0, 0, 153, 154, 155, 156, 77, 78, 79, - 80, 27, 0, 233, 780, 29, 0, 0, 0, 0, - 781, 30, 0, 0, 0, 31, 32, 157, 0, 33, - 0, 438, -155, 0, -13, 0, 0, 439, 34, 440, - 0, 761, 0, 0, 782, 0, 0, 783, 0, 35, - 36, 37, 0, 158, -151, 38, 784, 0, 785, 40, - 41, 0, 786, 0, 787, 42, 0, 0, 0, 6, - 0, 0, 235, 0, 0, 0, 0, 761, 0, 446, - 761, 447, 0, 448, 0, 449, 450, 0, 0, 451, - -13, 788, 789, 0, 0, 0, 8, 0, 0, 790, - -470, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 761, 0, 0, 1538, 584, 585, 586, 587, - 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, - 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, - 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, - 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, - 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, - 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 670, 671, 672, 673, 674, 675, 0, 676, - 0, 0, 677, 0, 678, 679, 680, 681, 682, 683, - 684, 685, 686, 687, 688, 689, 690, 244, 245, 246, - 691, 0, 0, 692, 706, 693, 694, 432, 696, 697, - 698, 0, 0, 433, 434, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 779, 0, 26, 0, 0, - 0, 153, 154, 155, 156, 77, 78, 79, 80, 27, - 0, 233, 780, 29, 0, 0, 0, 0, 781, 30, - 0, 0, 0, 31, 32, 157, 0, 33, 0, 438, - -155, 0, -13, 0, 0, 439, 34, 440, 0, 0, - 0, 0, 782, 0, 0, 783, 0, 35, 36, 37, - 0, 158, -151, 38, 784, 0, 785, 40, 41, 0, - 786, 0, 787, 42, 0, 0, 0, 6, 0, 0, - 235, 0, 0, 0, 0, 0, 0, 446, 0, 447, - 0, 448, 0, 449, 450, 432, 0, 451, -13, 788, - 789, 433, 434, 0, 8, 0, 0, 790, -467, 0, - 0, 0, 0, 435, 0, 26, 0, 0, 0, 153, - 154, 155, 156, 77, 78, 79, 80, 27, 0, 233, - 436, 0, 0, 0, 0, 0, 437, 30, 0, 0, - 0, 0, 0, 157, 0, 0, 0, 438, 0, 0, - 0, 0, 0, 439, 0, 440, 0, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 36, 67, 0, 158, - 0, 0, 442, 0, 443, 68, 0, 0, 444, 0, - 445, 0, 0, 0, 0, 0, 0, 0, 235, 0, - 0, 0, 0, 0, 0, 446, 0, 447, 0, 448, - 0, 449, 450, 432, 0, 451, 452, 453, 454, 433, - 434, -484, 0, -484, 0, 0, 0, 0, 0, 0, - 0, 435, 0, 26, 0, 0, 0, 153, 154, 155, - 156, 77, 78, 79, 80, 27, 0, 233, 436, 0, - 0, 0, 0, 0, 437, 30, 0, 0, 0, 0, - 0, 157, 0, 0, 0, 438, 0, 0, 0, 0, - 0, 439, 0, 440, 0, 0, 0, 0, 0, 0, - 0, 441, 0, 0, 36, 67, 0, 158, 0, 0, - 442, 0, 443, 68, 0, 0, 444, 0, 445, 0, - 0, 164, 0, 0, 0, 0, 235, 285, 166, 0, - 0, 0, 0, 446, 0, 447, 0, 448, 0, 449, - 450, 167, 0, 451, 452, 453, 454, 0, 0, 0, - 0, -485, 0, 27, 286, 0, 169, 0, 0, 0, - 0, 0, 0, 30, 0, 0, 0, 0, 170, 0, - 0, 171, 172, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 67, 0, 0, 0, 0, 173, 0, - 0, 68, 0, 0, 0, 0, 174, 0, 0, 175, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 432, 176, 0, 177, 0, 288, 433, 434, 179, 0, - 0, 0, 0, 180, 181, 0, 0, 0, 779, 723, - 26, 0, 0, 0, 153, 154, 155, 156, 77, 78, - 79, 80, 27, 0, 0, 780, 29, 0, 0, 0, - 0, 781, 30, 0, 0, 0, 31, 32, 157, 0, - 33, 0, 0, -155, 0, 0, 0, 0, 0, 34, - 440, 0, 0, 0, 0, 1038, 0, 0, 783, 0, - 35, 36, 37, 0, 158, -151, 38, 39, 0, 785, - 40, 41, 0, 786, 0, 787, 42, 0, 0, 0, - 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 446, 0, 447, 0, 448, 0, 449, 450, 432, 0, - 451, 0, 788, 789, 433, 434, 0, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 435, 0, 26, 0, - 0, 0, 153, 154, 155, 156, 77, 78, 79, 80, - 27, 0, 233, 436, 0, 0, 0, 0, 0, 437, - 30, 0, 0, 0, 0, 0, 157, 0, 0, 0, - 438, 0, 0, 0, 0, 0, 439, 0, 440, 0, - 0, 0, 0, 0, 0, 0, 441, 0, 0, 36, - 67, 0, 158, 0, 0, 442, 0, 443, 68, 0, - 0, 444, 0, 445, 0, 0, 0, 0, 0, 0, - 0, 235, 0, 0, 0, 0, 0, 0, 446, 0, - 447, 0, 448, 0, 449, 450, 432, 0, 451, 452, - 453, 454, 433, 434, -485, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 435, 0, 26, 0, 0, 0, - 153, 154, 155, 156, 77, 78, 79, 80, 27, 0, - 233, 436, 0, 0, 0, 0, 0, 437, 30, 0, - 0, 0, 0, 0, 157, 0, 0, 0, 438, 0, - 0, 0, 0, 0, 439, 0, 440, 0, 0, 0, - 0, 0, 0, 0, 441, 0, 0, 36, 67, 0, - 158, 0, 0, 442, 0, 443, 68, 0, 0, 444, - 0, 445, 0, 0, 0, 0, 0, 0, 0, 235, - 0, 0, 0, 0, 0, 0, 446, 0, 447, 0, - 448, 0, 449, 450, 0, 0, 451, 452, 453, 454, - 0, 0, -487, 815, 816, 817, 818, 819, 820, 821, - 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, - 832, 833, 815, 816, 817, 818, 819, 820, 821, 822, - 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, - 833, 0, 834, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 834, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 978, 979, 980, 981, 982, 983, - 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, 0, 0, 0, 0, 0, 0, 835, - 0, 836, 837, 838, 839, 840, 841, 842, 843, 844, - 845, 846, 847, 997, 0, 848, 849, 850, 835, 1140, - 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, - 846, 847, 0, 0, 848, 849, 850, 0, 1334, 0, - 0, 0, 0, 0, 0, 978, 979, 980, 981, 982, - 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 996, 0, 0, 0, 0, 0, 0, - 998, 0, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, - 1007, 1008, 1009, 1010, 997, 452, 1011, 1012, 1013, 815, - 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, - 826, 827, 828, 829, 830, 831, 832, 833, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 834, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 998, 0, 999, 1000, 1001, 1002, 1003, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 0, 1015, 1011, 1012, 1013, - 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, - 988, 989, 990, 991, 992, 993, 994, 995, 996, 0, - 0, 0, 0, 0, 0, 835, 0, 836, 837, 838, - 839, 840, 841, 842, 843, 844, 845, 846, 847, 997, - 0, 848, 849, 850, 1046, 1047, 1048, 1049, 1050, 1051, - 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, - 1062, 1063, 1064, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1065, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 998, 0, 999, 1000, - 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, - 0, 0, 1011, 1012, 1013, 815, 816, 817, 818, 819, - 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, - 830, 831, 832, -793, 0, 0, 0, 0, 0, 0, - 1066, 0, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, - 1075, 1076, 1077, 1078, 834, 0, 1079, 1080, 1081, 815, - 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, - 826, 827, 828, 829, 830, 831, 832, 833, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 834, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 837, 838, 839, 840, 841, 842, - 843, 844, 845, 846, 847, 0, 0, 848, 849, 850, - 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, - 988, 989, 990, 991, 992, 993, 994, 995, -793, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 837, 838, - 839, 840, 841, 842, 843, 844, 845, 846, 847, 997, - 0, 848, 849, 850, 815, 816, 817, 818, 819, 820, - 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, - 831, 832, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 834, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1000, - 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, - 0, 0, 1011, 1012, 1013, 978, 979, 980, 981, 982, - 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 837, 838, 839, 840, 841, 842, 843, - 844, 845, 846, 847, 997, 0, 848, 849, 850, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1000, 1001, 1002, 1003, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 432, 0, 1011, 1012, 1013, - 0, 433, 434, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -793, 0, 26, 0, 0, 0, 153, - 154, 155, 156, 77, 78, 79, 80, 27, 0, 233, - 436, 0, 0, 0, 0, 0, 437, 30, 0, 0, - 0, 0, 0, 157, 0, 0, -775, 438, 0, 0, - 0, -775, 0, 439, 0, 440, 0, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 36, 67, 0, 158, - 0, 0, 442, 0, 443, 68, 0, -775, 444, 0, - 445, 0, 0, 0, 0, 0, 0, 0, 235, 0, - 0, 0, 0, 0, 0, 446, 0, 447, 0, 448, - 0, 449, 450, 432, 0, 451, 452, 453, 454, 736, - 737, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -793, 0, 26, 0, 0, 0, 153, 154, 155, - 156, 77, 78, 79, 80, 27, 0, 233, 739, 0, - 0, 0, 0, 0, 740, 30, 0, 0, 0, 0, - 0, 157, 0, 0, -775, 438, 0, 0, 0, -775, - 0, 439, 0, 742, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 36, 67, 0, 158, 0, 0, - 442, 0, 744, 68, 0, -775, 745, 0, 746, 0, - 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, - 0, 0, 0, 446, 0, 747, 0, 748, 0, 749, - 750, 432, 0, 751, 452, 752, 753, 433, 434, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 26, 0, 0, 0, 153, 154, 155, 156, 77, - 78, 79, 80, 27, 0, 233, 436, 0, 0, 0, - 0, 0, 437, 30, 0, 0, 0, 0, 0, 157, - 0, 0, -775, 438, 0, 0, 0, -775, 0, 439, - 0, 440, 0, 0, 0, 0, 0, 0, 0, 441, - 0, 0, 36, 67, 0, 158, 0, 0, 442, 0, - 443, 68, 0, -775, 444, 0, 445, 0, 0, 0, - 0, 0, 0, 0, 235, 0, 0, 0, 0, 0, - 0, 446, 0, 447, 0, 448, 0, 449, 450, 432, - 0, 451, 452, 453, 454, 736, 737, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 738, 0, 26, - 0, 0, 0, 153, 154, 155, 156, 77, 78, 79, - 80, 27, 0, 233, 739, 0, 0, 0, 0, 0, - 740, 30, 0, 0, 0, 0, 0, 157, 0, 0, - 0, 438, 0, 0, 741, 0, 0, 439, 0, 742, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 36, 67, 0, 158, 0, 0, 442, 0, 744, 68, - 0, 0, 745, 0, 746, 0, 0, 0, 0, 0, - 0, 0, 235, 0, 0, 0, 0, 0, 0, 446, - 0, 747, 0, 748, 0, 749, 750, 432, 0, 751, - 452, 752, 753, 736, 737, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 738, 0, 26, 0, 0, - 0, 153, 154, 155, 156, 77, 78, 79, 80, 27, - 0, 233, 739, 0, 0, 0, 0, 0, 740, 30, - 0, 0, 0, 0, 0, 157, 0, 0, 0, 438, - 0, 0, 1135, 0, 0, 439, 0, 742, 0, 0, - 0, 0, 0, 0, 0, 743, 0, 0, 36, 67, - 0, 158, 0, 0, 442, 0, 744, 68, 0, 0, - 745, 0, 746, 0, 0, 0, 0, 0, 0, 0, - 235, 0, 0, 0, 0, 0, 0, 446, 0, 747, - 0, 748, 0, 749, 750, 432, 0, 751, 452, 752, - 753, 433, 434, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 435, 0, 26, 0, 0, 0, 153, - 154, 155, 156, 77, 78, 79, 80, 27, 0, 233, - 436, 0, 0, 0, 0, 0, 437, 30, 0, 0, - 0, 0, 0, 157, 0, 0, 0, 438, 0, 0, - 0, 0, 0, 439, 0, 440, 0, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 36, 67, 0, 158, - 0, 0, 442, 0, 443, 68, 0, 0, 444, 0, - 445, 0, 0, 0, 0, 0, 0, 0, 235, 0, - 0, 0, 0, 0, 0, 446, 0, 447, 0, 448, - 0, 449, 450, 432, 0, 451, 452, 453, 454, 736, - 737, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 738, 0, 26, 0, 0, 0, 153, 154, 155, - 156, 77, 78, 79, 80, 27, 0, 233, 739, 0, - 0, 0, 0, 0, 740, 30, 0, 0, 0, 0, - 0, 157, 0, 0, 0, 438, 0, 0, 0, 0, - 0, 439, 0, 742, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 36, 67, 0, 158, 0, 0, - 442, 0, 744, 68, 0, 0, 745, 0, 746, 0, - 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, - 0, 0, 0, 446, 0, 747, 0, 748, 0, 749, - 750, 432, 0, 751, 452, 752, 753, 433, 434, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 779, - 0, 26, 0, 0, 0, 153, 154, 155, 156, 77, - 78, 79, 80, 27, 0, 233, 780, 0, 0, 0, - 0, 0, 781, 30, 0, 0, 0, 0, 0, 157, - 0, 0, 0, 438, 0, 0, 0, 0, 0, 439, - 0, 440, 0, 0, 0, 0, 0, 0, 0, 783, - 0, 0, 36, 67, 0, 158, 0, 0, 442, 0, - 785, 68, 0, 0, 786, 0, 787, 0, 0, 0, - 0, 0, 0, 0, 235, 0, 0, 0, 332, 0, - 0, 446, 0, 447, 333, 448, 0, 449, 450, 0, - 0, 451, 452, 788, 789, 0, 534, 0, 26, 0, - 0, 0, 153, 154, 155, 156, 77, 78, 79, 80, - 27, 334, 0, 28, 0, 0, 0, 0, 0, 0, - 30, 0, 0, 0, 0, 0, 157, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, - 0, 332, 0, 0, 0, 336, 0, 333, 0, 36, - 67, 0, 158, 0, 0, 0, 0, 0, 68, 0, - 0, 26, 0, 337, 0, 153, 154, 155, 156, 77, - 78, 79, 80, 27, 334, 0, 28, 0, 338, 0, - 0, 0, 339, 30, 340, 0, 0, 0, 0, 157, - 341, 342, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 335, 0, 332, 0, 0, 0, 336, 0, - 333, 0, 36, 67, 0, 158, 0, 0, 0, 0, - 0, 68, 0, 0, 26, 0, 337, 0, 153, 154, - 155, 156, 77, 78, 79, 80, 27, 334, 0, 28, - 0, 338, 0, 771, 0, 339, 30, 340, 0, 0, - 0, 0, 157, 341, 342, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 335, 0, 332, 0, 0, - 0, 336, 0, 333, 0, 36, 67, 0, 158, 0, - 0, 0, 0, 0, 68, 1168, 0, 26, 0, 337, - 0, 153, 154, 155, 156, 77, 78, 79, 80, 27, - 334, 0, 28, 0, 338, 0, 970, 0, 339, 30, - 340, 0, 0, 0, 0, 157, 341, 342, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 335, 0, - 332, 0, 0, 0, 336, 0, 333, 0, 36, 67, - 0, 158, 0, 0, 0, 0, 0, 68, 1172, 0, - 26, 0, 337, 0, 153, 154, 155, 156, 77, 78, - 79, 80, 27, 334, 0, 28, 0, 338, 0, 0, - 0, 339, 30, 340, 0, 0, 0, 0, 157, 341, - 342, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 335, 0, 332, 0, 0, 0, 336, 0, 333, - 0, 36, 67, 0, 158, 0, 0, 0, 0, 0, - 68, 0, 0, 26, 0, 337, 0, 153, 154, 155, - 156, 77, 78, 79, 80, 27, 334, 0, 28, 0, - 338, 0, 0, 0, 339, 30, 340, 0, 0, 0, - 0, 157, 341, 342, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 335, 0, 332, 0, 0, 0, - 336, 0, 333, 0, 36, 67, 0, 158, 0, 0, - 0, 0, 0, 68, 0, 0, 26, 0, 337, 0, - 153, 154, 155, 156, 77, 78, 79, 80, 27, 334, - 0, 28, 0, 338, 0, 1264, 0, 339, 30, 340, - 0, 0, 0, 0, 157, 341, 342, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 335, 0, 332, - 0, 0, 0, 336, 0, 333, 0, 36, 67, 0, - 158, 0, 0, 0, 0, 0, 68, 0, 0, 26, - 0, 337, 0, 153, 154, 155, 156, 77, 78, 79, - 80, 27, 334, 233, 0, 0, 338, 0, 1387, 0, - 339, 30, 340, 0, 0, 0, 0, 157, 341, 342, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1601, 0, 0, 0, 0, 0, 336, 0, 0, 0, - 36, 67, 0, 158, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 337, 0, 0, 0, 0, 332, - 0, 0, 235, 0, 0, 333, 0, 0, 0, 338, - 0, 0, 0, 339, 0, 340, 0, 0, 0, 26, - 0, 341, 342, 153, 154, 155, 156, 77, 78, 79, - 80, 27, 334, 0, 28, 0, 0, 0, 0, 0, - 0, 30, 0, 0, 0, 0, 0, 157, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 335, 0, 332, 0, 0, 0, 336, 0, 333, 0, - 36, 67, 0, 158, 0, 0, 0, 0, 0, 68, - 0, 0, 26, 0, 337, 0, 153, 154, 155, 156, - 77, 78, 79, 80, 27, 334, 0, 28, 0, 338, - 0, 0, 0, 339, 30, 340, 0, 0, 0, 0, - 157, 341, 342, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 531, 0, 332, 0, 0, 0, 336, - 0, 333, 0, 36, 67, 0, 158, 0, 0, 0, - 0, 0, 68, 0, 0, 26, 0, 337, 0, 153, - 154, 155, 156, 77, 78, 79, 80, 27, 334, 0, - -406, 0, 338, 0, 0, 0, 339, 30, 340, 0, - 0, 0, 0, 157, 341, 342, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1581, 0, 332, 0, - 0, 0, 336, 0, 333, 0, 36, 67, 0, 158, - 0, 0, 0, 0, 0, 68, 0, 0, 26, 0, - 337, 0, 153, 154, 155, 156, 77, 78, 79, 80, - 27, 334, 0, 0, 0, 338, 0, 0, 0, 1582, - 30, 340, 0, 0, 0, 0, 157, 341, 342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, - 0, 0, 0, 0, 0, 336, 0, 0, 0, 36, - 67, 0, 158, 164, 0, 0, 0, 0, 68, 165, - 166, 0, 0, 337, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 167, 0, 0, 0, 0, 338, 0, - 0, 0, 339, 0, 340, 27, 168, 233, 169, 0, - 341, 342, 0, 0, 0, 30, 0, 0, 0, 0, - 170, 0, 0, 171, 172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 267, 0, 0, 164, 0, 0, - 0, 0, 0, 165, 166, 67, 0, 0, 0, 0, - 173, 0, 0, 68, 0, 0, 0, 167, 174, 0, - 0, 175, 0, 0, 0, 0, 235, 0, 0, 27, - 168, 233, 169, 176, 0, 177, 0, 178, 0, 30, - 179, 0, 0, 0, 170, 180, 181, 171, 172, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 294, 0, - 0, 164, 0, 0, 0, 0, 0, 165, 166, 67, - 0, 0, 0, 0, 173, 0, 0, 68, 0, 0, - 0, 167, 174, 0, 0, 175, 0, 0, 0, 0, - 235, 0, 0, 27, 474, 233, 169, 176, 0, 177, - 0, 178, 0, 30, 179, 0, 0, 0, 170, 180, - 181, 171, 172, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 267, 0, 0, 164, 0, 0, 0, 0, - 0, 165, 166, 67, 0, 0, 0, 0, 173, 0, - 0, 68, 0, 0, 0, 167, 174, 0, 0, 175, - 0, 0, 0, 0, 235, 0, 0, 27, 477, 233, - 169, 176, 0, 177, 0, 178, 0, 30, 179, 0, - 0, 0, 170, 180, 181, 171, 172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 294, 0, 0, 164, - 0, 0, 0, 0, 0, 165, 166, 67, 0, 0, - 0, 0, 173, 0, 0, 68, 0, 582, 0, 167, - 174, 0, 0, 175, 0, 0, 0, 0, 235, 0, - 0, 27, 168, 233, 169, 176, 0, 177, 0, 178, - 0, 30, 179, 0, 0, 0, 170, 180, 181, 171, - 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 164, 0, 0, 0, 0, 0, 165, - 166, 67, 0, 0, 0, 0, 173, 0, 0, 68, - 0, 935, 0, 167, 174, 0, 0, 175, 0, 0, - 0, 0, 235, 0, 0, 27, 168, 233, 169, 176, - 0, 177, 0, 178, 0, 30, 179, 0, 0, 0, - 170, 180, 181, 171, 172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, - 0, 0, 0, 165, 166, 67, 0, 0, 0, 0, - 173, 0, 0, 68, 0, 0, 0, 167, 174, 0, - 0, 175, 0, 0, 0, 0, 235, 0, 0, 27, - 168, 233, 169, 176, 0, 177, 0, 178, 0, 30, - 179, 0, 0, 0, 170, 180, 181, 171, 172, 0, - 0, 0, 0, 0, 0, 0, 164, 0, 0, 0, - 0, 0, 285, 166, 0, 0, 0, 0, 0, 67, - 0, 0, 0, 0, 173, 1206, 167, 68, 0, 0, - 0, 0, 174, 0, 0, 175, 0, 0, 27, 286, - 235, 169, 0, 0, 0, 0, 0, 176, 30, 177, - 0, 178, 0, 170, 179, 0, 171, 172, 0, 180, - 181, 0, 0, 0, 0, 164, 0, 287, 0, 0, - 0, 165, 166, 0, 0, 0, 0, 0, 67, 0, - 0, 0, 0, 173, 0, 167, 68, 0, 0, 0, - 0, 174, 0, 0, 175, 0, 0, 27, 477, 233, - 0, 0, 0, 0, 0, 0, 176, 30, 177, 0, - 288, 0, 170, 179, 0, 171, 172, 0, 180, 181, - 0, 0, 0, 0, 164, 0, 1591, 0, 0, 0, - 285, 166, 0, 0, 0, 0, 0, 67, 0, 0, - 0, 0, 173, 0, 167, 68, 0, 0, 0, 0, - 174, 0, 0, 175, 0, 0, 27, 286, 235, 169, - 0, 0, 0, 0, 0, 176, 30, 177, 0, 178, - 0, 170, 179, 0, 171, 172, 0, 180, 181, 0, - 0, 0, 0, 164, 0, 287, 0, 0, 0, 285, - 166, 0, 0, 0, 0, 0, 67, 0, 0, 0, - 0, 173, 0, 167, 68, 0, 0, 0, 0, 174, - 0, 0, 175, 0, 0, 27, 286, 0, -406, 0, - 0, 0, 0, 0, 176, 30, 177, 0, 288, 0, - 170, 179, 0, 171, 172, 0, 180, 181, 0, 0, - 0, 0, 164, 0, 1571, 0, 0, 0, 165, 166, - 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, - 173, 0, 167, 68, 0, 0, 0, 0, 174, 0, - 0, 175, 0, 0, 27, 168, 0, 169, 0, 0, - 0, 0, 0, 176, 30, 177, 0, 1572, 0, 170, - 179, 0, 171, 172, 0, 180, 181, 0, 0, 0, - 0, 164, 0, 0, 0, 0, 0, 165, 166, 0, - 0, 0, 0, 0, 67, 0, 0, 0, 0, 173, - 0, 167, 68, 0, 0, 0, 0, 174, 0, 0, - 175, 0, 0, 27, 168, 0, 1622, 0, 0, 0, - 0, 0, 176, 30, 177, 0, 178, 0, 170, 179, - 0, 171, 172, 0, 180, 181, 0, 0, 0, 0, - 164, 0, 0, 0, 0, 0, 165, 166, 0, 0, - 0, 0, 0, 67, 0, 0, 0, 0, 173, 0, - 167, 68, 0, 0, 0, 0, 174, 0, 0, 175, - 0, 0, 27, 168, 0, 0, 0, 0, 0, 0, - 0, 176, 30, 177, 0, 178, 0, 170, 179, 0, - 171, 172, 0, 180, 181, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 0, 0, 0, 0, 173, 0, 0, - 68, 0, 0, 0, 0, 174, 0, 0, 175, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 176, 0, 177, 0, 178, 0, 0, 179, 0, 0, - 26, 0, 180, 181, 153, 154, 155, 156, 77, 78, - 79, 80, 27, 0, 233, 739, 0, 0, 0, 0, - 0, 740, 30, 0, 0, 0, 0, 0, 157, 0, - 0, -775, 438, 0, 0, 0, -775, 0, 439, 0, - 742, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 36, 67, 0, 158, 0, 0, 442, 0, 744, - 68, 0, -775, 745, 0, 746, 0, 0, 0, 0, - 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 751 -}; - -static const yytype_int16 yycheck[] = -{ - 16, 281, 146, 106, 146, 89, 296, 284, 113, 312, - 271, 270, 424, 452, 32, 544, 3, 148, 447, 145, - 567, 9, 9, 16, 571, 452, 315, 26, 15, 364, - 581, 304, 12, 164, 454, 549, 326, 145, 143, 76, - 146, 167, 881, 792, 406, 176, 795, 84, 452, 86, - 87, 88, 921, 1161, 923, 891, 278, 280, 163, 491, - 165, 895, 1011, 114, 222, 1272, 453, 104, 480, 174, - 218, 89, 177, 178, 73, 180, 873, 863, 379, 150, - 228, 150, 19, 1255, 145, 1255, 170, 9, 4, 10, - 127, 1195, 0, 4, 42, 21, 123, 124, 125, 58, - 42, 42, 4, 10, 141, 752, 232, 144, 3, 3, - 236, 0, 181, 64, 90, 90, 95, 23, 21, 93, - 37, 55, 92, 93, 94, 92, 93, 94, 236, 3, - 1079, 118, 237, 108, 121, 10, 42, 3, 89, 3, - 116, 788, 21, 433, 270, 3, 120, 273, 421, 102, - 120, 3, 170, 120, 124, 114, 54, 124, 448, 10, - 108, 59, 267, 116, 425, 10, 108, 428, 10, 3, - 10, 105, 109, 434, 131, 50, 281, 0, 53, 96, - 285, 208, 123, 288, 105, 93, 213, 85, 104, 294, - 316, 207, 229, 104, 299, 279, 122, 23, 105, 121, - 423, 332, 104, 92, 93, 94, 122, 338, 103, 510, - 368, 122, 120, 240, 202, 202, 124, 322, 205, 122, - 122, 116, 210, 210, 118, 212, 357, 121, 376, 103, - 105, 120, 333, 99, 365, 99, 337, 103, 339, 103, - 341, 342, 116, 122, 102, 103, 505, 99, 353, 526, - 116, 103, 116, 530, 105, 381, 387, 479, 116, 1363, - 105, 279, 4, 105, 116, 105, 8, 3, 225, 103, - 12, 122, 3, 399, 405, 548, 23, 122, 93, 42, - 122, 1488, 122, 23, 53, 411, 1621, 113, 210, 721, - 4, 399, 37, 55, 8, 23, 1631, 115, 12, 35, - 1554, 432, 407, 411, 23, 120, 121, 23, 115, 45, - 415, 42, 23, 4, 23, 446, 1570, 333, 747, 424, - 89, 337, 68, 339, 385, 341, 342, 264, 397, 366, - 1502, 1167, 1502, 753, 405, 54, 323, 1171, 74, 75, - 367, 121, 122, 54, 35, 114, 447, 83, 375, 23, - 1147, 96, 114, 792, 45, 4, 795, 105, 489, 122, - 42, 124, 104, 1363, 4, 752, 113, 103, 795, 789, - 1156, 99, 103, 113, 122, 480, 481, 1377, 483, 505, - 511, 93, 1374, 930, 75, 90, 35, 490, 1380, 1596, - 104, 795, 83, 907, 113, 35, 45, 37, 1605, 115, - 116, 788, 113, 108, 1611, 45, 115, 116, 120, 1616, - 42, 569, 124, 104, 545, 1622, 105, 56, 566, 114, - 1627, 104, 438, 439, 121, 122, 75, 35, 123, 849, - 531, 447, 78, 122, 83, 75, 452, 45, 727, 122, - 122, 80, 124, 83, 1444, 50, 736, 578, 53, 550, - 551, 93, 1452, 3, 731, 104, 96, 1449, 748, 9, - 10, 720, 513, 54, 104, 113, 1415, 75, 1417, 56, - 3, 4, 904, 23, 93, 83, 1562, 916, 120, 23, - 122, 35, 124, 39, 38, 35, 36, 524, 38, 916, - 122, 45, 124, 770, 1580, 45, 99, 53, 101, 119, - 50, 120, 108, 53, 54, 124, 729, 108, 730, 42, - 771, 102, 916, 121, 1350, 531, 93, 123, 99, 1353, - 1628, 75, 123, 114, 80, 75, 79, 80, 544, 83, - 80, 547, 123, 83, 550, 551, 89, 949, 88, 50, - 813, 91, 53, 120, 122, 572, 124, 124, 50, 576, - 119, 53, 579, 103, 56, 105, 583, 107, 1626, 1428, - 110, 50, 93, 113, 53, 115, 116, 1635, 103, 872, - 124, 114, 559, 106, 107, 108, 109, 110, 111, 112, - 123, 943, 115, 116, 117, 3, 4, 93, 1015, 120, - 53, 122, 1012, 124, 720, 856, 114, 23, 114, 23, - 726, 114, 3, 113, 114, 123, 867, 123, 9, 35, - 123, 35, 114, 37, 120, 121, 122, 1456, 726, 45, - 21, 45, 23, 882, 42, 123, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 90, 38, 35, 99, - 741, 38, 1189, 1194, 45, 92, 747, 94, 45, 75, - 51, 75, 1203, 23, 53, 113, 114, 83, 116, 83, - 1080, 3, 4, 64, 99, 35, 1180, 116, 38, 70, - 35, 35, 96, 74, 75, 45, 77, 122, 75, 124, - 45, 45, 83, 114, 115, 116, 83, 88, 106, 107, - 108, 109, 110, 111, 112, 956, 53, 115, 116, 117, - 42, 122, 103, 124, 74, 75, 107, 99, 109, 970, - 75, 75, 93, 83, 115, 116, 80, 23, 83, 83, - 121, 737, 738, 103, 122, 741, 124, 124, 116, 834, - 835, 747, 35, 749, 750, 751, 102, 868, 35, 120, - 110, 38, 45, 124, 114, 110, 121, 122, 45, 114, - 876, 852, 3, 4, 5, 881, 882, 8, 1019, 1508, - 115, 116, 117, 21, 1191, 107, 108, 109, 110, 111, - 112, 29, 75, 115, 116, 117, 792, 35, 75, 795, - 83, 122, 93, 124, 99, 1214, 83, 45, 54, 782, - 891, 42, 35, 894, 895, 38, 114, 898, 101, 792, - 901, 35, 45, 93, 31, 32, 33, 34, 93, 120, - 941, 45, 792, 124, 124, 50, 93, 75, 53, 53, - 1155, 56, 1373, 35, 24, 83, 38, 124, 122, 123, - 120, 1258, 75, 45, 124, 120, 852, 124, 854, 124, - 83, 75, 114, 120, 949, 102, 80, 124, 122, 83, - 124, 850, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 1151, 75, 115, 116, 117, 93, 113, 114, - 35, 83, 102, 38, 35, 891, 35, 38, 894, 895, - 45, 124, 898, 54, 45, 901, 45, 115, 116, 117, - 1021, 35, 997, 998, 120, 108, 93, 884, 124, 926, - 916, 45, 1163, 54, 1433, 64, 93, 113, 114, 936, - 75, 70, 124, 74, 75, 123, 75, 1018, 83, 1020, - 121, 122, 83, 120, 83, 115, 116, 124, 1205, 917, - 74, 75, 123, 120, 1035, 102, 102, 124, 1365, 83, - 245, 246, 42, 122, 960, 1089, 122, 1089, 114, 110, - 116, 938, 122, 114, 64, 53, 972, 99, 116, 124, - 1065, 1066, 978, 979, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, - 996, 3, 4, 1089, 1000, 1001, 1002, 1003, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 35, 1416, 37, 1418, 102, - 99, 1274, 1018, 1264, 1020, 45, 103, 122, 108, 109, - 110, 111, 112, 124, 1013, 115, 116, 117, 123, 1035, - 42, 31, 32, 33, 34, 53, 64, 121, 99, 1576, - 42, 122, 1461, 22, 1135, 75, 46, 119, 1585, 125, - 122, 123, 1589, 83, 114, 1038, 124, 42, 123, 99, - 23, 23, 1599, 54, 1185, 1160, 96, 121, 114, 104, - 108, 104, 35, 1610, 104, 38, 1167, 122, 1615, 1508, - 1171, 53, 45, 114, 1335, 1176, 99, 1336, 104, 3, - 4, 1182, 1081, 99, 1083, 1084, 108, 109, 110, 111, - 112, 99, 21, 115, 116, 117, 108, 109, 110, 111, - 112, 74, 75, 115, 116, 117, 121, 103, 122, 108, - 83, 108, 99, 1214, 1643, 110, 111, 112, 42, 1135, - 115, 116, 117, 99, 35, 125, 1387, 119, 122, 122, - 23, 3, 4, 5, 45, 1162, 8, 121, 101, 1442, - 114, 122, 35, 122, 37, 1161, 104, 1408, 102, 23, - 99, 1167, 45, 64, 122, 1171, 1257, 113, 1435, 29, - 1176, 54, 124, 122, 75, 35, 1182, 117, 1427, 117, - 42, 23, 83, 119, 121, 45, 103, 99, 116, 1195, - 122, 1458, 75, 1595, 108, 109, 110, 111, 112, 104, - 83, 115, 116, 117, 104, 99, 1212, 1213, 1214, 1215, - 99, 1462, 42, 96, 74, 75, 122, 124, 101, 122, - 1336, 99, 1199, 83, 121, 3, 4, 5, 6, 7, - 8, 9, 114, 1500, 114, 114, 124, 114, 1640, 23, - 121, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 1257, 29, 115, 116, 117, 35, 1348, 35, 1350, - 1351, 104, 1353, 102, 42, 1356, 45, 119, 45, 104, - 121, 80, 48, 3, 4, 119, 121, 1411, 1558, 1411, - 110, 111, 112, 99, 1564, 115, 116, 117, 1558, 21, - 124, 99, 1572, 119, 121, 57, 75, 74, 75, 121, - 104, 23, 1582, 23, 83, 122, 83, 122, 122, 1560, - 122, 1427, 42, 1593, 99, 1566, 1407, 124, 124, 114, - 23, 124, 119, 1603, 1330, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 3, 4, 115, 116, 117, - 1456, 42, 1348, 23, 1350, 1351, 1437, 1353, 1439, 121, - 1356, 122, 119, 1623, 124, 121, 102, 1363, 121, 104, - 124, 108, 123, 123, 122, 1458, 122, 104, 102, 122, - 1461, 122, 124, 1464, 42, 105, 106, 107, 108, 109, - 110, 111, 112, 124, 23, 115, 116, 117, 48, 26, - 23, 119, 123, 1484, 1485, 121, 119, 1374, 104, 123, - 121, 1407, 121, 1380, 53, 53, 124, 104, 23, 23, - 102, 53, 102, 53, 23, 1489, 1509, 104, 1424, 123, - 35, 1495, 116, 38, 23, 116, 1547, 1433, 121, 1377, - 45, 1437, 38, 1439, 122, 38, 121, 105, 106, 107, - 108, 109, 110, 111, 112, 38, 38, 115, 116, 117, - 38, 122, 38, 122, 1460, 1461, 121, 1463, 1464, 74, - 75, 122, 121, 1558, 79, 80, 1493, 121, 83, 18, - 19, 121, 1449, 15, 89, 1568, 122, 1572, 1484, 1485, - 29, 1489, 31, 121, 33, 34, 35, 1495, 37, 38, - 121, 1582, 41, 42, 1587, 559, 1591, 202, 1525, 1505, - 1595, 884, 1508, 1530, 328, 21, 205, 1365, 1199, 82, - 1601, 1564, 707, 29, 1207, 1542, 1020, 1612, 514, 35, - 547, 1548, 315, 1180, 550, 74, 726, 726, 1623, 45, - 1557, 400, 81, 29, 438, 439, 1563, 385, 442, 35, - 876, 90, 1559, 92, 882, 1640, 795, 96, 1565, 45, - 877, 100, 1569, 916, 103, 440, 105, 106, 1564, 75, - 109, 1407, 1579, 742, 113, 114, 1461, 83, 1045, 1326, - 1258, 1508, 1258, 1590, 1502, -1, 1582, -1, 74, 75, - -1, -1, 131, 1600, -1, 3, 4, 83, -1, -1, - 139, 140, 439, 142, 143, 1601, 145, -1, -1, 148, - -1, 150, -1, -1, -1, -1, -1, 29, -1, -1, - -1, -1, -1, 35, 163, 164, 165, -1, 167, -1, - -1, -1, 1628, 45, 42, 174, -1, 176, 177, 178, - -1, 180, 181, -1, -1, 10, -1, 1643, -1, -1, - -1, -1, -1, 23, -1, -1, -1, -1, 23, -1, - -1, 200, 74, 75, -1, 35, -1, 37, 207, -1, - 35, 83, -1, -1, -1, 45, -1, -1, 217, -1, - 45, -1, 221, 222, 54, 50, 225, -1, 53, -1, - -1, -1, -1, 232, -1, -1, -1, 236, 237, 107, - 108, 109, 110, 111, 112, 75, -1, 115, 116, 117, - 75, -1, -1, 83, -1, 80, 29, -1, 83, -1, - -1, -1, 35, -1, -1, 264, 96, -1, 267, -1, - 9, 270, 45, -1, 273, -1, -1, -1, -1, -1, - 105, -1, 281, -1, 23, -1, 285, -1, 287, 288, - -1, -1, -1, -1, -1, 294, 35, 36, 37, 38, - 299, 74, 75, -1, 303, 304, 45, 306, -1, -1, - 83, 50, -1, 312, 53, 54, 315, 316, 317, -1, - -1, -1, -1, 322, -1, -1, -1, -1, 327, -1, - -1, -1, -1, 332, 333, -1, 75, -1, 337, 338, - 339, 80, 341, 342, 83, -1, -1, -1, 347, 88, - -1, -1, 91, -1, 353, -1, -1, 96, 357, -1, - -1, -1, -1, -1, -1, -1, 365, -1, 107, 368, - -1, 110, -1, -1, 113, -1, 115, 116, -1, 378, - -1, -1, 381, 737, 738, 3, 385, -1, 387, -1, - -1, 9, 10, -1, -1, 749, 750, 751, 397, -1, - 399, 400, -1, 757, -1, 23, 405, 406, 407, -1, - -1, -1, 411, -1, -1, -1, 415, 35, 36, 37, - 38, -1, 421, -1, -1, 424, -1, 45, -1, -1, - 784, -1, 50, 432, -1, 53, 54, 791, 437, -1, - 737, 738, -1, -1, -1, 444, -1, 446, 447, -1, - -1, -1, 749, 750, 751, -1, -1, 75, -1, -1, - -1, -1, 80, -1, -1, 83, -1, -1, -1, -1, - 88, -1, 21, 91, -1, -1, -1, -1, 96, -1, - 29, 480, 481, -1, 483, 103, 35, 105, -1, 107, - 489, -1, 110, 21, -1, -1, 45, 115, 116, 853, - 854, 29, -1, 121, -1, -1, 505, 35, -1, -1, - -1, -1, 511, -1, -1, 64, -1, 45, 517, -1, - -1, 70, -1, -1, 523, -1, 75, -1, -1, -1, - -1, -1, 531, -1, 83, -1, 64, -1, -1, 88, - -1, -1, 70, -1, -1, 544, 545, 75, -1, 548, - 549, 550, 551, -1, -1, 83, -1, 854, -1, -1, - 88, -1, 561, -1, 3, 4, 5, 6, 7, 8, - 569, 39, -1, -1, -1, 574, -1, -1, -1, 578, - -1, 49, 50, -1, -1, 53, -1, -1, 56, -1, - -1, -1, -1, -1, 62, 27, 28, 29, 30, 31, - 32, 33, 34, 42, -1, 73, 960, 75, -1, -1, - -1, 79, 80, -1, -1, 83, 84, -1, 972, 51, - -1, 89, -1, -1, 978, 979, 980, 981, 982, 983, - 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, - 994, 995, 996, -1, -1, 77, 1000, 1001, 1002, 1003, - 1004, 1005, 1006, 1007, 1008, 1009, 1010, -1, -1, -1, - -1, -1, -1, 960, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, -1, 972, 115, 116, 117, -1, - -1, 978, 979, 980, 981, 982, 983, 984, 985, 986, - 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, - -1, -1, -1, 1000, 1001, 1002, 1003, 1004, 1005, 1006, - 1007, 1008, 1009, 1010, -1, -1, -1, -1, -1, -1, - -1, 720, -1, -1, -1, -1, -1, 726, -1, -1, - -1, -1, -1, 3, -1, -1, -1, -1, -1, 9, - -1, 740, 741, -1, -1, -1, 745, -1, 747, -1, - -1, 21, -1, 23, -1, -1, -1, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, -1, 38, -1, - -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, - -1, 51, 1136, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, - 70, -1, -1, -1, 74, 75, -1, 77, -1, -1, - -1, -1, -1, 83, 813, 814, -1, -1, 88, -1, - -1, -1, -1, -1, -1, 108, 3, 4, 5, 6, - 7, 8, 9, 103, -1, 834, 835, 107, -1, 109, - -1, -1, -1, -1, -1, 115, 116, -1, -1, -1, - -1, 121, -1, 852, -1, -1, -1, -1, 1212, 1213, - -1, 1215, -1, -1, 863, 42, -1, -1, -1, 868, - -1, -1, -1, 872, -1, -1, -1, 876, -1, -1, - -1, -1, 881, 882, -1, -1, -1, -1, -1, -1, - -1, -1, 891, -1, -1, 894, 895, -1, -1, 898, - -1, 1255, 901, -1, -1, -1, -1, -1, 907, 908, - -1, -1, -1, -1, -1, 1212, 1213, -1, 1215, -1, - -1, -1, -1, -1, 207, -1, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, -1, -1, 115, 116, - 117, -1, 941, -1, 943, -1, -1, 946, -1, -1, - 949, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1330, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, -1, -1, 997, 998, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 42, -1, -1, 1018, - -1, 1020, 1021, -1, -1, -1, -1, 1026, -1, -1, - -1, 1385, -1, 1330, -1, -1, 1035, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1045, -1, -1, -1, - 333, -1, -1, -1, 337, -1, 339, 340, 341, 342, - -1, -1, -1, -1, -1, -1, 1065, 1066, -1, 1423, - 1424, -1, -1, 99, -1, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, -1, -1, 115, - 116, 117, -1, -1, -1, -1, -1, 123, -1, -1, - -1, -1, -1, -1, -1, 9, 1460, -1, -1, 1463, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, - -1, -1, -1, -1, 1478, -1, -1, 1424, -1, -1, - -1, 35, 36, 37, 38, -1, 1135, -1, 1137, -1, - -1, 45, -1, -1, -1, -1, 50, -1, 1502, 53, - 54, 1505, -1, -1, 1508, 438, 439, 1156, -1, -1, - -1, 1160, 1161, 1460, 447, -1, 1463, -1, 1167, 452, - -1, 75, 1171, -1, -1, -1, 80, 1176, 1177, 83, - -1, 1180, -1, 1182, 88, -1, 1185, 91, -1, -1, - -1, -1, 96, -1, -1, -1, 3, 4, 5, 6, - 7, 8, -1, 107, -1, 1204, 110, -1, 1505, -1, - -1, 115, -1, -1, -1, 1214, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 42, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 531, -1, - -1, -1, -1, -1, -1, 42, -1, -1, 1257, -1, - -1, 544, -1, -1, 547, -1, -1, 550, 551, -1, - -1, -1, -1, -1, -1, 1274, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, -1, -1, 115, 116, - 117, -1, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, -1, 1326, 115, 116, - 117, -1, -1, -1, -1, -1, 123, 1336, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1346, 1347, 1348, - -1, 1350, 1351, -1, 1353, -1, -1, 1356, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1384, -1, -1, -1, 3, - -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1405, -1, 1407, 23, - -1, -1, -1, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, -1, 38, -1, -1, -1, 1427, -1, - -1, 45, -1, -1, 1433, -1, -1, 51, 1437, -1, - 1439, -1, -1, 1442, -1, 1444, -1, -1, -1, -1, - 64, -1, 1451, 1452, 737, 738, 70, 1456, 741, -1, - 74, 75, 1461, 77, 747, 1464, 749, 750, 751, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1484, 1485, -1, -1, 103, - -1, 1490, -1, 107, -1, 109, -1, 1496, -1, -1, - 1499, 115, 116, -1, -1, -1, -1, 121, -1, 792, - -1, -1, 795, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1522, -1, 23, -1, -1, -1, 1528, - -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, - 38, 39, 1541, -1, -1, -1, 1545, 45, 1547, -1, - 1549, 49, 50, 1552, -1, 53, -1, -1, 56, 1558, - -1, -1, -1, -1, 62, 1564, -1, -1, 1567, 852, - -1, 854, 1571, 1572, -1, 73, 74, 75, -1, -1, - -1, 79, 80, 1582, -1, 83, 84, -1, -1, -1, - 145, 89, 1591, 148, -1, 150, 1595, -1, -1, -1, - -1, -1, 1601, -1, -1, -1, -1, -1, 891, 164, - 165, 894, 895, 1612, -1, 898, -1, -1, 901, -1, - -1, 176, -1, 178, 1623, -1, 181, -1, -1, 1628, - -1, -1, -1, 916, -1, -1, -1, -1, -1, -1, - -1, 1640, -1, -1, 1643, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 960, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 972, - -1, -1, -1, -1, -1, 978, 979, 980, 981, 982, - 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 996, -1, 270, -1, 1000, 1001, 1002, - 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, -1, -1, - 285, -1, -1, 288, -1, 1018, -1, 1020, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 306, 1035, 308, -1, -1, 3, -1, -1, -1, - -1, 316, 9, 10, -1, -1, -1, 322, -1, -1, - -1, -1, -1, -1, -1, -1, 23, 332, -1, -1, - -1, -1, -1, 338, -1, -1, -1, -1, 35, 36, - 37, 38, -1, -1, -1, -1, -1, -1, 45, -1, - -1, -1, 357, 50, -1, -1, 53, 54, -1, -1, - 365, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, - 385, -1, 387, 80, -1, -1, 83, -1, -1, -1, - -1, 88, 397, -1, 91, 400, -1, -1, -1, 96, - 405, -1, 1135, -1, -1, -1, 103, -1, 105, -1, - 107, -1, -1, 110, -1, -1, -1, -1, 115, 116, - 283, -1, -1, -1, 121, -1, -1, 432, 1161, -1, - -1, -1, -1, -1, 1167, -1, -1, -1, 1171, -1, - -1, 446, 305, 1176, -1, -1, -1, -1, -1, 1182, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1212, - 1213, 1214, 1215, -1, 489, -1, -1, -1, -1, 42, - -1, -1, -1, 438, 439, -1, -1, -1, -1, -1, - 505, -1, -1, -1, -1, -1, 511, 452, -1, -1, - -1, -1, -1, -1, 377, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 1257, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 545, -1, -1, -1, -1, -1, 99, 410, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - -1, -1, 115, 116, 117, -1, -1, -1, -1, -1, - 123, -1, 435, 578, -1, -1, -1, -1, 441, -1, - 443, -1, 445, -1, -1, -1, 449, 450, 451, -1, - -1, -1, -1, -1, -1, -1, -1, 1330, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1348, -1, 1350, 1351, -1, - 1353, -1, -1, 1356, 487, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 1407, 42, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1424, -1, -1, -1, -1, -1, -1, -1, -1, - 1433, -1, -1, -1, 1437, -1, 1439, -1, -1, -1, - -1, -1, -1, -1, -1, 720, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1460, 1461, -1, - 1463, 1464, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, -1, -1, 115, 116, - 117, 1484, 1485, -1, -1, -1, 123, -1, 23, -1, - -1, -1, 27, 28, 29, 30, 31, 32, 33, 34, - 35, -1, 1505, 38, -1, 1508, 781, -1, -1, -1, - 45, 786, -1, -1, -1, -1, 51, -1, -1, -1, - -1, -1, 737, 738, -1, -1, -1, -1, -1, -1, - -1, 438, 439, -1, 749, 750, 751, -1, -1, 74, - 75, -1, 77, -1, -1, 452, -1, -1, 83, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1564, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 109, -1, -1, 792, -1, 1582, - 795, -1, -1, -1, -1, -1, -1, -1, 863, -1, - -1, -1, -1, 868, 869, -1, -1, -1, 1601, 732, - 733, 876, -1, -1, -1, -1, 881, 882, -1, -1, - 743, 744, -1, 746, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1628, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 854, - 1643, -1, 775, -1, -1, -1, 779, -1, -1, -1, - 783, -1, 785, -1, 787, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 941, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 815, 816, 817, 818, 819, 820, 821, 822, - 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, - 833, 916, -1, -1, 837, 838, 839, 840, 841, 842, - 843, 844, 845, 846, 847, 848, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 860, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 960, 1021, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 972, -1, -1, - -1, -1, -1, 978, 979, 980, 981, 982, 983, 984, - 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, - 995, 996, -1, -1, -1, 1000, 1001, 1002, 1003, 1004, - 1005, 1006, 1007, 1008, 1009, 1010, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 438, 439, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 452, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 737, 738, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 749, 750, 751, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, -1, 1011, -1, - -1, 1156, -1, -1, 1017, 792, -1, -1, 795, -1, - -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1185, -1, -1, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, - 1063, 1064, -1, -1, -1, 1068, 1069, 1070, 1071, 1072, - 1073, 1074, 1075, 1076, 1077, 1078, 1079, 854, -1, -1, - -1, -1, 1085, 1086, 99, -1, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, -1, -1, - 115, 116, 117, -1, -1, -1, -1, -1, 123, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1212, 1213, -1, - 1215, -1, -1, -1, -1, -1, -1, -1, -1, 916, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1154, -1, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 960, -1, -1, -1, -1, -1, -1, - -1, 1336, 42, -1, -1, 972, -1, -1, -1, -1, - -1, 978, 979, 980, 981, 982, 983, 984, 985, 986, - 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, - -1, -1, -1, 1000, 1001, 1002, 1003, 1004, 1005, 1006, - 1007, 1008, 1009, 1010, 737, 738, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1330, 749, 750, 751, 99, - -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, -1, 1267, 115, 116, 117, -1, -1, - 3, 121, -1, -1, -1, -1, 9, -1, -1, -1, - -1, -1, 1427, -1, -1, -1, -1, -1, -1, 22, - 23, -1, 795, -1, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, -1, 38, -1, -1, -1, -1, - -1, 1456, 45, -1, -1, -1, -1, -1, 51, 1322, - -1, 1324, -1, -1, 1327, -1, -1, -1, -1, -1, - -1, 64, -1, -1, -1, -1, -1, 70, -1, 1424, - -1, 74, 75, -1, 77, -1, -1, -1, -1, -1, - 83, 854, -1, -1, -1, 88, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 103, -1, -1, -1, 107, 1460, 109, -1, 1463, -1, - -1, -1, 115, 116, -1, -1, -1, -1, 121, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1547, 1406, -1, -1, -1, -1, -1, -1, - -1, -1, 1415, 916, 1417, -1, -1, -1, -1, -1, - 1505, -1, -1, 1508, -1, -1, -1, 1572, -1, -1, - -1, -1, -1, -1, -1, 1212, 1213, 1582, 1215, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 960, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1470, 1471, 972, - -1, -1, -1, -1, -1, 978, 979, 980, 981, 982, - 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 996, -1, -1, -1, 1000, 1001, 1002, - 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1543, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1330, -1, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 1424, 96, -1, - -1, 99, -1, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, -1, 120, -1, 122, 123, 124, 125, 126, 127, - -1, -1, -1, 1460, -1, -1, 1463, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1212, - 1213, -1, 1215, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1505, -1, - -1, 1508, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, -1, 96, -1, 1330, 99, -1, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, -1, 119, 120, - -1, 122, 123, -1, 125, 126, 127, -1, -1, 3, - -1, -1, -1, -1, -1, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 21, -1, 23, - -1, -1, -1, 27, 28, 29, 30, 31, 32, 33, - 34, 35, -1, 37, 38, 39, -1, -1, -1, -1, - 44, 45, -1, -1, -1, 49, 50, 51, -1, 53, - -1, 55, 56, -1, 58, -1, -1, 61, 62, 63, - -1, 1424, -1, -1, 68, -1, -1, 71, -1, 73, - 74, 75, -1, 77, 78, 79, 80, -1, 82, 83, - 84, -1, 86, -1, 88, 89, -1, -1, -1, 93, - -1, -1, 96, -1, -1, -1, -1, 1460, -1, 103, - 1463, 105, -1, 107, -1, 109, 110, -1, -1, 113, - 114, 115, 116, -1, -1, -1, 120, -1, -1, 123, - 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1505, -1, -1, 1508, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, -1, 96, - -1, -1, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, -1, -1, 120, 121, 122, 123, 3, 125, 126, - 127, -1, -1, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 21, -1, 23, -1, -1, - -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, - -1, 37, 38, 39, -1, -1, -1, -1, 44, 45, - -1, -1, -1, 49, 50, 51, -1, 53, -1, 55, - 56, -1, 58, -1, -1, 61, 62, 63, -1, -1, - -1, -1, 68, -1, -1, 71, -1, 73, 74, 75, - -1, 77, 78, 79, 80, -1, 82, 83, 84, -1, - 86, -1, 88, 89, -1, -1, -1, 93, -1, -1, - 96, -1, -1, -1, -1, -1, -1, 103, -1, 105, - -1, 107, -1, 109, 110, 3, -1, 113, 114, 115, - 116, 9, 10, -1, 120, -1, -1, 123, 124, -1, - -1, -1, -1, 21, -1, 23, -1, -1, -1, 27, - 28, 29, 30, 31, 32, 33, 34, 35, -1, 37, - 38, -1, -1, -1, -1, -1, 44, 45, -1, -1, - -1, -1, -1, 51, -1, -1, -1, 55, -1, -1, - -1, -1, -1, 61, -1, 63, -1, -1, -1, -1, - -1, -1, -1, 71, -1, -1, 74, 75, -1, 77, - -1, -1, 80, -1, 82, 83, -1, -1, 86, -1, - 88, -1, -1, -1, -1, -1, -1, -1, 96, -1, - -1, -1, -1, -1, -1, 103, -1, 105, -1, 107, - -1, 109, 110, 3, -1, 113, 114, 115, 116, 9, - 10, 119, -1, 121, -1, -1, -1, -1, -1, -1, - -1, 21, -1, 23, -1, -1, -1, 27, 28, 29, - 30, 31, 32, 33, 34, 35, -1, 37, 38, -1, - -1, -1, -1, -1, 44, 45, -1, -1, -1, -1, - -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, - -1, 61, -1, 63, -1, -1, -1, -1, -1, -1, - -1, 71, -1, -1, 74, 75, -1, 77, -1, -1, - 80, -1, 82, 83, -1, -1, 86, -1, 88, -1, - -1, 3, -1, -1, -1, -1, 96, 9, 10, -1, - -1, -1, -1, 103, -1, 105, -1, 107, -1, 109, - 110, 23, -1, 113, 114, 115, 116, -1, -1, -1, - -1, 121, -1, 35, 36, -1, 38, -1, -1, -1, - -1, -1, -1, 45, -1, -1, -1, -1, 50, -1, - -1, 53, 54, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 75, -1, -1, -1, -1, 80, -1, - -1, 83, -1, -1, -1, -1, 88, -1, -1, 91, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 103, -1, 105, -1, 107, 9, 10, 110, -1, - -1, -1, -1, 115, 116, -1, -1, -1, 21, 121, - 23, -1, -1, -1, 27, 28, 29, 30, 31, 32, - 33, 34, 35, -1, -1, 38, 39, -1, -1, -1, - -1, 44, 45, -1, -1, -1, 49, 50, 51, -1, - 53, -1, -1, 56, -1, -1, -1, -1, -1, 62, - 63, -1, -1, -1, -1, 68, -1, -1, 71, -1, - 73, 74, 75, -1, 77, 78, 79, 80, -1, 82, - 83, 84, -1, 86, -1, 88, 89, -1, -1, -1, - 93, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 103, -1, 105, -1, 107, -1, 109, 110, 3, -1, - 113, -1, 115, 116, 9, 10, -1, 120, -1, -1, - -1, -1, -1, -1, -1, -1, 21, -1, 23, -1, - -1, -1, 27, 28, 29, 30, 31, 32, 33, 34, - 35, -1, 37, 38, -1, -1, -1, -1, -1, 44, - 45, -1, -1, -1, -1, -1, 51, -1, -1, -1, - 55, -1, -1, -1, -1, -1, 61, -1, 63, -1, - -1, -1, -1, -1, -1, -1, 71, -1, -1, 74, - 75, -1, 77, -1, -1, 80, -1, 82, 83, -1, - -1, 86, -1, 88, -1, -1, -1, -1, -1, -1, - -1, 96, -1, -1, -1, -1, -1, -1, 103, -1, - 105, -1, 107, -1, 109, 110, 3, -1, 113, 114, - 115, 116, 9, 10, 119, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 21, -1, 23, -1, -1, -1, - 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, - 37, 38, -1, -1, -1, -1, -1, 44, 45, -1, - -1, -1, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, 61, -1, 63, -1, -1, -1, - -1, -1, -1, -1, 71, -1, -1, 74, 75, -1, - 77, -1, -1, 80, -1, 82, 83, -1, -1, 86, - -1, 88, -1, -1, -1, -1, -1, -1, -1, 96, - -1, -1, -1, -1, -1, -1, 103, -1, 105, -1, - 107, -1, 109, 110, -1, -1, 113, 114, 115, 116, - -1, -1, 119, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, -1, 42, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, -1, -1, -1, -1, -1, -1, 99, - -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 42, -1, 115, 116, 117, 99, 119, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, -1, -1, 115, 116, 117, -1, 119, -1, - -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 42, 114, 115, 116, 117, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 99, -1, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, -1, 114, 115, 116, 117, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, 99, -1, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 42, - -1, 115, 116, 117, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 99, -1, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - -1, -1, 115, 116, 117, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 42, -1, 115, 116, 117, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, -1, -1, 115, 116, 117, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 42, - -1, 115, 116, 117, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - -1, -1, 115, 116, 117, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 42, -1, 115, 116, 117, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 3, -1, 115, 116, 117, - -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 21, -1, 23, -1, -1, -1, 27, - 28, 29, 30, 31, 32, 33, 34, 35, -1, 37, - 38, -1, -1, -1, -1, -1, 44, 45, -1, -1, - -1, -1, -1, 51, -1, -1, 54, 55, -1, -1, - -1, 59, -1, 61, -1, 63, -1, -1, -1, -1, - -1, -1, -1, 71, -1, -1, 74, 75, -1, 77, - -1, -1, 80, -1, 82, 83, -1, 85, 86, -1, - 88, -1, -1, -1, -1, -1, -1, -1, 96, -1, - -1, -1, -1, -1, -1, 103, -1, 105, -1, 107, - -1, 109, 110, 3, -1, 113, 114, 115, 116, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 21, -1, 23, -1, -1, -1, 27, 28, 29, - 30, 31, 32, 33, 34, 35, -1, 37, 38, -1, - -1, -1, -1, -1, 44, 45, -1, -1, -1, -1, - -1, 51, -1, -1, 54, 55, -1, -1, -1, 59, - -1, 61, -1, 63, -1, -1, -1, -1, -1, -1, - -1, 71, -1, -1, 74, 75, -1, 77, -1, -1, - 80, -1, 82, 83, -1, 85, 86, -1, 88, -1, - -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, - -1, -1, -1, 103, -1, 105, -1, 107, -1, 109, - 110, 3, -1, 113, 114, 115, 116, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 23, -1, -1, -1, 27, 28, 29, 30, 31, - 32, 33, 34, 35, -1, 37, 38, -1, -1, -1, - -1, -1, 44, 45, -1, -1, -1, -1, -1, 51, - -1, -1, 54, 55, -1, -1, -1, 59, -1, 61, - -1, 63, -1, -1, -1, -1, -1, -1, -1, 71, - -1, -1, 74, 75, -1, 77, -1, -1, 80, -1, - 82, 83, -1, 85, 86, -1, 88, -1, -1, -1, - -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, - -1, 103, -1, 105, -1, 107, -1, 109, 110, 3, - -1, 113, 114, 115, 116, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 21, -1, 23, - -1, -1, -1, 27, 28, 29, 30, 31, 32, 33, - 34, 35, -1, 37, 38, -1, -1, -1, -1, -1, - 44, 45, -1, -1, -1, -1, -1, 51, -1, -1, - -1, 55, -1, -1, 58, -1, -1, 61, -1, 63, - -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, - 74, 75, -1, 77, -1, -1, 80, -1, 82, 83, - -1, -1, 86, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, -1, -1, -1, -1, -1, -1, 103, - -1, 105, -1, 107, -1, 109, 110, 3, -1, 113, - 114, 115, 116, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 21, -1, 23, -1, -1, - -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, - -1, 37, 38, -1, -1, -1, -1, -1, 44, 45, - -1, -1, -1, -1, -1, 51, -1, -1, -1, 55, - -1, -1, 58, -1, -1, 61, -1, 63, -1, -1, - -1, -1, -1, -1, -1, 71, -1, -1, 74, 75, - -1, 77, -1, -1, 80, -1, 82, 83, -1, -1, - 86, -1, 88, -1, -1, -1, -1, -1, -1, -1, - 96, -1, -1, -1, -1, -1, -1, 103, -1, 105, - -1, 107, -1, 109, 110, 3, -1, 113, 114, 115, - 116, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 21, -1, 23, -1, -1, -1, 27, - 28, 29, 30, 31, 32, 33, 34, 35, -1, 37, - 38, -1, -1, -1, -1, -1, 44, 45, -1, -1, - -1, -1, -1, 51, -1, -1, -1, 55, -1, -1, - -1, -1, -1, 61, -1, 63, -1, -1, -1, -1, - -1, -1, -1, 71, -1, -1, 74, 75, -1, 77, - -1, -1, 80, -1, 82, 83, -1, -1, 86, -1, - 88, -1, -1, -1, -1, -1, -1, -1, 96, -1, - -1, -1, -1, -1, -1, 103, -1, 105, -1, 107, - -1, 109, 110, 3, -1, 113, 114, 115, 116, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 21, -1, 23, -1, -1, -1, 27, 28, 29, - 30, 31, 32, 33, 34, 35, -1, 37, 38, -1, - -1, -1, -1, -1, 44, 45, -1, -1, -1, -1, - -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, - -1, 61, -1, 63, -1, -1, -1, -1, -1, -1, - -1, 71, -1, -1, 74, 75, -1, 77, -1, -1, - 80, -1, 82, 83, -1, -1, 86, -1, 88, -1, - -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, - -1, -1, -1, 103, -1, 105, -1, 107, -1, 109, - 110, 3, -1, 113, 114, 115, 116, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, - -1, 23, -1, -1, -1, 27, 28, 29, 30, 31, - 32, 33, 34, 35, -1, 37, 38, -1, -1, -1, - -1, -1, 44, 45, -1, -1, -1, -1, -1, 51, - -1, -1, -1, 55, -1, -1, -1, -1, -1, 61, - -1, 63, -1, -1, -1, -1, -1, -1, -1, 71, - -1, -1, 74, 75, -1, 77, -1, -1, 80, -1, - 82, 83, -1, -1, 86, -1, 88, -1, -1, -1, - -1, -1, -1, -1, 96, -1, -1, -1, 3, -1, - -1, 103, -1, 105, 9, 107, -1, 109, 110, -1, - -1, 113, 114, 115, 116, -1, 21, -1, 23, -1, - -1, -1, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, -1, 38, -1, -1, -1, -1, -1, -1, - 45, -1, -1, -1, -1, -1, 51, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, - -1, 3, -1, -1, -1, 70, -1, 9, -1, 74, - 75, -1, 77, -1, -1, -1, -1, -1, 83, -1, - -1, 23, -1, 88, -1, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, -1, 38, -1, 103, -1, - -1, -1, 107, 45, 109, -1, -1, -1, -1, 51, - 115, 116, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 64, -1, 3, -1, -1, -1, 70, -1, - 9, -1, 74, 75, -1, 77, -1, -1, -1, -1, - -1, 83, -1, -1, 23, -1, 88, -1, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, -1, 38, - -1, 103, -1, 105, -1, 107, 45, 109, -1, -1, - -1, -1, 51, 115, 116, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 64, -1, 3, -1, -1, - -1, 70, -1, 9, -1, 74, 75, -1, 77, -1, - -1, -1, -1, -1, 83, 21, -1, 23, -1, 88, - -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, -1, 38, -1, 103, -1, 105, -1, 107, 45, - 109, -1, -1, -1, -1, 51, 115, 116, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, - 3, -1, -1, -1, 70, -1, 9, -1, 74, 75, - -1, 77, -1, -1, -1, -1, -1, 83, 21, -1, - 23, -1, 88, -1, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, -1, 38, -1, 103, -1, -1, - -1, 107, 45, 109, -1, -1, -1, -1, 51, 115, - 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 64, -1, 3, -1, -1, -1, 70, -1, 9, - -1, 74, 75, -1, 77, -1, -1, -1, -1, -1, - 83, -1, -1, 23, -1, 88, -1, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, -1, 38, -1, - 103, -1, -1, -1, 107, 45, 109, -1, -1, -1, - -1, 51, 115, 116, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 64, -1, 3, -1, -1, -1, - 70, -1, 9, -1, 74, 75, -1, 77, -1, -1, - -1, -1, -1, 83, -1, -1, 23, -1, 88, -1, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - -1, 38, -1, 103, -1, 105, -1, 107, 45, 109, - -1, -1, -1, -1, 51, 115, 116, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 64, -1, 3, - -1, -1, -1, 70, -1, 9, -1, 74, 75, -1, - 77, -1, -1, -1, -1, -1, 83, -1, -1, 23, - -1, 88, -1, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, -1, -1, 103, -1, 105, -1, - 107, 45, 109, -1, -1, -1, -1, 51, 115, 116, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 64, -1, -1, -1, -1, -1, 70, -1, -1, -1, - 74, 75, -1, 77, -1, -1, -1, -1, -1, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, 3, - -1, -1, 96, -1, -1, 9, -1, -1, -1, 103, - -1, -1, -1, 107, -1, 109, -1, -1, -1, 23, - -1, 115, 116, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, -1, 38, -1, -1, -1, -1, -1, - -1, 45, -1, -1, -1, -1, -1, 51, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 64, -1, 3, -1, -1, -1, 70, -1, 9, -1, - 74, 75, -1, 77, -1, -1, -1, -1, -1, 83, - -1, -1, 23, -1, 88, -1, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, -1, 38, -1, 103, - -1, -1, -1, 107, 45, 109, -1, -1, -1, -1, - 51, 115, 116, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 64, -1, 3, -1, -1, -1, 70, - -1, 9, -1, 74, 75, -1, 77, -1, -1, -1, - -1, -1, 83, -1, -1, 23, -1, 88, -1, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, - 38, -1, 103, -1, -1, -1, 107, 45, 109, -1, - -1, -1, -1, 51, 115, 116, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 64, -1, 3, -1, - -1, -1, 70, -1, 9, -1, 74, 75, -1, 77, - -1, -1, -1, -1, -1, 83, -1, -1, 23, -1, - 88, -1, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, -1, -1, -1, 103, -1, -1, -1, 107, - 45, 109, -1, -1, -1, -1, 51, 115, 116, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, - -1, -1, -1, -1, -1, 70, -1, -1, -1, 74, - 75, -1, 77, 3, -1, -1, -1, -1, 83, 9, - 10, -1, -1, 88, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 23, -1, -1, -1, -1, 103, -1, - -1, -1, 107, -1, 109, 35, 36, 37, 38, -1, - 115, 116, -1, -1, -1, 45, -1, -1, -1, -1, - 50, -1, -1, 53, 54, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 64, -1, -1, 3, -1, -1, - -1, -1, -1, 9, 10, 75, -1, -1, -1, -1, - 80, -1, -1, 83, -1, -1, -1, 23, 88, -1, - -1, 91, -1, -1, -1, -1, 96, -1, -1, 35, - 36, 37, 38, 103, -1, 105, -1, 107, -1, 45, - 110, -1, -1, -1, 50, 115, 116, 53, 54, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, - -1, 3, -1, -1, -1, -1, -1, 9, 10, 75, - -1, -1, -1, -1, 80, -1, -1, 83, -1, -1, - -1, 23, 88, -1, -1, 91, -1, -1, -1, -1, - 96, -1, -1, 35, 36, 37, 38, 103, -1, 105, - -1, 107, -1, 45, 110, -1, -1, -1, 50, 115, - 116, 53, 54, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 64, -1, -1, 3, -1, -1, -1, -1, - -1, 9, 10, 75, -1, -1, -1, -1, 80, -1, - -1, 83, -1, -1, -1, 23, 88, -1, -1, 91, - -1, -1, -1, -1, 96, -1, -1, 35, 36, 37, - 38, 103, -1, 105, -1, 107, -1, 45, 110, -1, - -1, -1, 50, 115, 116, 53, 54, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 64, -1, -1, 3, - -1, -1, -1, -1, -1, 9, 10, 75, -1, -1, - -1, -1, 80, -1, -1, 83, -1, 21, -1, 23, - 88, -1, -1, 91, -1, -1, -1, -1, 96, -1, - -1, 35, 36, 37, 38, 103, -1, 105, -1, 107, - -1, 45, 110, -1, -1, -1, 50, 115, 116, 53, - 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3, -1, -1, -1, -1, -1, 9, - 10, 75, -1, -1, -1, -1, 80, -1, -1, 83, - -1, 21, -1, 23, 88, -1, -1, 91, -1, -1, - -1, -1, 96, -1, -1, 35, 36, 37, 38, 103, - -1, 105, -1, 107, -1, 45, 110, -1, -1, -1, - 50, 115, 116, 53, 54, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, - -1, -1, -1, 9, 10, 75, -1, -1, -1, -1, - 80, -1, -1, 83, -1, -1, -1, 23, 88, -1, - -1, 91, -1, -1, -1, -1, 96, -1, -1, 35, - 36, 37, 38, 103, -1, 105, -1, 107, -1, 45, - 110, -1, -1, -1, 50, 115, 116, 53, 54, -1, - -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, - -1, -1, 9, 10, -1, -1, -1, -1, -1, 75, - -1, -1, -1, -1, 80, 22, 23, 83, -1, -1, - -1, -1, 88, -1, -1, 91, -1, -1, 35, 36, - 96, 38, -1, -1, -1, -1, -1, 103, 45, 105, - -1, 107, -1, 50, 110, -1, 53, 54, -1, 115, - 116, -1, -1, -1, -1, 3, -1, 64, -1, -1, - -1, 9, 10, -1, -1, -1, -1, -1, 75, -1, - -1, -1, -1, 80, -1, 23, 83, -1, -1, -1, - -1, 88, -1, -1, 91, -1, -1, 35, 36, 37, - -1, -1, -1, -1, -1, -1, 103, 45, 105, -1, - 107, -1, 50, 110, -1, 53, 54, -1, 115, 116, - -1, -1, -1, -1, 3, -1, 64, -1, -1, -1, - 9, 10, -1, -1, -1, -1, -1, 75, -1, -1, - -1, -1, 80, -1, 23, 83, -1, -1, -1, -1, - 88, -1, -1, 91, -1, -1, 35, 36, 96, 38, - -1, -1, -1, -1, -1, 103, 45, 105, -1, 107, - -1, 50, 110, -1, 53, 54, -1, 115, 116, -1, - -1, -1, -1, 3, -1, 64, -1, -1, -1, 9, - 10, -1, -1, -1, -1, -1, 75, -1, -1, -1, - -1, 80, -1, 23, 83, -1, -1, -1, -1, 88, - -1, -1, 91, -1, -1, 35, 36, -1, 38, -1, - -1, -1, -1, -1, 103, 45, 105, -1, 107, -1, - 50, 110, -1, 53, 54, -1, 115, 116, -1, -1, - -1, -1, 3, -1, 64, -1, -1, -1, 9, 10, - -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, - 80, -1, 23, 83, -1, -1, -1, -1, 88, -1, - -1, 91, -1, -1, 35, 36, -1, 38, -1, -1, - -1, -1, -1, 103, 45, 105, -1, 107, -1, 50, - 110, -1, 53, 54, -1, 115, 116, -1, -1, -1, - -1, 3, -1, -1, -1, -1, -1, 9, 10, -1, - -1, -1, -1, -1, 75, -1, -1, -1, -1, 80, - -1, 23, 83, -1, -1, -1, -1, 88, -1, -1, - 91, -1, -1, 35, 36, -1, 38, -1, -1, -1, - -1, -1, 103, 45, 105, -1, 107, -1, 50, 110, - -1, 53, 54, -1, 115, 116, -1, -1, -1, -1, - 3, -1, -1, -1, -1, -1, 9, 10, -1, -1, - -1, -1, -1, 75, -1, -1, -1, -1, 80, -1, - 23, 83, -1, -1, -1, -1, 88, -1, -1, 91, - -1, -1, 35, 36, -1, -1, -1, -1, -1, -1, - -1, 103, 45, 105, -1, 107, -1, 50, 110, -1, - 53, 54, -1, 115, 116, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 75, -1, -1, -1, -1, 80, -1, -1, - 83, -1, -1, -1, -1, 88, -1, -1, 91, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 103, -1, 105, -1, 107, -1, -1, 110, -1, -1, - 23, -1, 115, 116, 27, 28, 29, 30, 31, 32, - 33, 34, 35, -1, 37, 38, -1, -1, -1, -1, - -1, 44, 45, -1, -1, -1, -1, -1, 51, -1, - -1, 54, 55, -1, -1, -1, 59, -1, 61, -1, - 63, -1, -1, -1, -1, -1, -1, -1, 71, -1, - -1, 74, 75, -1, 77, -1, -1, 80, -1, 82, - 83, -1, 85, 86, -1, 88, -1, -1, -1, -1, - -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 113 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = -{ - 0, 95, 129, 130, 0, 92, 93, 94, 120, 132, - 133, 134, 135, 136, 139, 140, 141, 142, 115, 115, - 133, 139, 68, 177, 136, 142, 23, 35, 38, 39, - 45, 49, 50, 53, 62, 73, 74, 75, 79, 80, - 83, 84, 89, 143, 144, 145, 146, 147, 148, 149, - 150, 152, 155, 162, 166, 167, 168, 180, 182, 189, - 190, 195, 202, 203, 291, 292, 333, 75, 83, 137, - 333, 137, 292, 23, 64, 333, 333, 31, 32, 33, - 34, 46, 169, 331, 333, 333, 333, 333, 333, 50, - 53, 80, 23, 38, 74, 110, 114, 151, 231, 333, - 53, 80, 333, 78, 56, 113, 23, 119, 102, 116, - 119, 292, 333, 99, 103, 224, 333, 89, 114, 202, - 224, 114, 123, 224, 224, 224, 169, 333, 38, 74, - 110, 114, 333, 38, 124, 178, 179, 333, 123, 23, - 42, 333, 53, 99, 333, 224, 332, 333, 3, 74, - 103, 233, 333, 27, 28, 29, 30, 51, 77, 330, - 331, 137, 138, 99, 3, 9, 10, 23, 36, 38, - 50, 53, 54, 80, 88, 91, 103, 105, 107, 110, - 115, 116, 232, 248, 249, 250, 252, 253, 333, 37, - 96, 104, 230, 271, 279, 280, 333, 90, 225, 226, - 42, 123, 132, 141, 170, 171, 172, 116, 204, 207, - 132, 139, 116, 157, 225, 225, 225, 53, 224, 124, - 178, 42, 122, 124, 110, 114, 333, 333, 224, 333, - 248, 224, 23, 37, 80, 96, 113, 116, 232, 249, - 263, 264, 281, 282, 114, 115, 116, 338, 339, 340, - 248, 257, 258, 261, 262, 281, 234, 235, 260, 261, - 269, 270, 333, 121, 122, 248, 261, 64, 248, 281, - 99, 272, 232, 23, 169, 224, 251, 103, 10, 50, - 53, 105, 248, 116, 261, 9, 36, 64, 107, 219, - 220, 222, 248, 333, 64, 248, 281, 64, 89, 256, - 248, 121, 260, 23, 113, 102, 116, 233, 99, 275, - 4, 104, 122, 4, 104, 122, 99, 101, 265, 54, - 227, 228, 229, 114, 333, 170, 39, 53, 80, 174, - 124, 172, 3, 9, 36, 64, 70, 88, 103, 107, - 109, 115, 116, 211, 212, 213, 237, 239, 240, 291, - 330, 333, 225, 24, 223, 139, 124, 141, 160, 161, - 225, 114, 123, 156, 114, 102, 333, 204, 122, 124, - 333, 124, 179, 124, 178, 204, 224, 102, 54, 181, - 232, 23, 232, 282, 248, 108, 225, 54, 335, 335, - 335, 123, 123, 4, 8, 12, 104, 122, 236, 42, - 108, 4, 8, 12, 104, 122, 122, 102, 121, 137, - 102, 42, 301, 248, 64, 255, 273, 274, 281, 282, - 223, 113, 232, 53, 116, 208, 278, 279, 272, 169, - 251, 219, 3, 9, 10, 21, 38, 44, 55, 61, - 63, 71, 80, 82, 86, 88, 103, 105, 107, 109, - 110, 113, 114, 115, 116, 281, 284, 291, 293, 295, - 298, 299, 302, 312, 315, 321, 322, 324, 325, 326, - 327, 328, 330, 301, 36, 333, 333, 36, 333, 105, - 122, 99, 248, 255, 248, 119, 122, 123, 121, 122, - 333, 332, 295, 259, 260, 276, 281, 4, 104, 271, - 4, 104, 230, 280, 54, 101, 266, 267, 268, 274, - 333, 102, 277, 103, 122, 248, 281, 141, 163, 164, - 123, 124, 173, 255, 333, 174, 261, 237, 64, 237, - 261, 64, 237, 330, 21, 237, 246, 247, 21, 121, - 237, 244, 245, 121, 122, 99, 333, 22, 113, 114, - 116, 125, 114, 283, 113, 248, 124, 261, 121, 122, - 123, 141, 158, 159, 158, 261, 224, 225, 124, 122, - 124, 225, 204, 295, 101, 333, 265, 232, 54, 121, - 264, 114, 21, 261, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 96, 99, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 117, 120, 122, 123, 124, 125, 126, 127, 334, - 336, 337, 338, 339, 340, 119, 121, 260, 269, 282, - 262, 261, 269, 270, 333, 248, 295, 282, 104, 248, - 108, 332, 251, 121, 220, 223, 104, 122, 223, 53, - 105, 261, 255, 223, 295, 333, 9, 10, 21, 38, - 44, 58, 63, 71, 82, 86, 88, 105, 107, 109, - 110, 113, 115, 116, 284, 291, 293, 296, 297, 299, - 304, 312, 330, 296, 302, 295, 284, 295, 333, 295, - 261, 105, 214, 215, 237, 255, 295, 295, 295, 21, - 38, 44, 68, 71, 80, 82, 86, 88, 115, 116, - 123, 134, 135, 144, 285, 286, 287, 291, 293, 294, - 298, 299, 312, 313, 314, 330, 288, 290, 295, 306, - 288, 290, 99, 113, 114, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 42, 99, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 115, 116, - 117, 121, 54, 59, 85, 104, 272, 220, 248, 248, - 21, 295, 121, 116, 233, 337, 123, 121, 122, 108, - 4, 104, 122, 103, 54, 274, 108, 265, 261, 279, - 228, 99, 99, 333, 122, 124, 333, 224, 301, 301, - 237, 122, 119, 21, 122, 122, 121, 21, 122, 213, - 261, 125, 240, 291, 332, 21, 29, 88, 239, 241, - 242, 243, 333, 121, 244, 237, 131, 132, 121, 161, - 333, 122, 124, 122, 124, 123, 204, 283, 124, 283, - 225, 123, 333, 101, 225, 21, 261, 225, 131, 114, - 225, 122, 236, 122, 104, 123, 23, 274, 337, 122, - 221, 250, 252, 254, 282, 251, 272, 301, 295, 295, - 255, 296, 296, 333, 237, 304, 295, 295, 333, 295, - 105, 214, 255, 296, 296, 296, 306, 288, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 42, 99, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 115, 116, 117, 284, 114, 301, 223, 10, 105, - 122, 99, 153, 295, 295, 281, 75, 83, 144, 295, - 295, 281, 295, 306, 288, 58, 284, 329, 68, 144, - 291, 294, 124, 287, 294, 114, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 42, 99, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 115, - 116, 117, 123, 117, 117, 122, 123, 119, 121, 332, - 29, 307, 308, 309, 310, 333, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 248, 248, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 289, 295, - 288, 29, 292, 237, 284, 58, 296, 23, 223, 295, - 119, 259, 223, 281, 4, 104, 278, 103, 268, 277, - 104, 122, 266, 273, 102, 114, 116, 165, 124, 164, - 99, 116, 175, 176, 104, 104, 247, 122, 21, 237, - 245, 122, 21, 237, 237, 337, 99, 239, 333, 333, - 122, 124, 99, 121, 285, 99, 124, 159, 124, 225, - 283, 114, 114, 225, 114, 141, 194, 196, 197, 198, - 200, 201, 124, 114, 23, 333, 22, 220, 121, 223, - 104, 296, 102, 223, 10, 105, 296, 119, 121, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 248, 248, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 289, 288, 29, 292, 48, 124, 134, 316, 317, - 318, 319, 104, 295, 105, 214, 303, 223, 215, 261, - 119, 121, 237, 144, 113, 123, 307, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 248, 248, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 289, - 288, 29, 292, 29, 292, 29, 292, 295, 295, 338, - 339, 340, 99, 124, 21, 311, 122, 99, 119, 121, - 57, 237, 284, 333, 119, 121, 104, 278, 295, 158, - 259, 248, 121, 212, 225, 223, 23, 23, 122, 247, - 122, 122, 245, 122, 237, 333, 99, 21, 241, 237, - 124, 261, 283, 134, 183, 184, 185, 186, 188, 191, - 192, 193, 124, 114, 131, 83, 147, 199, 124, 197, - 131, 333, 301, 221, 23, 296, 296, 105, 214, 305, - 296, 119, 121, 284, 321, 322, 323, 237, 238, 124, - 317, 318, 122, 124, 122, 23, 223, 10, 105, 295, - 153, 332, 124, 119, 121, 115, 116, 115, 116, 295, - 295, 310, 295, 296, 102, 223, 274, 104, 122, 124, - 121, 123, 121, 122, 123, 333, 333, 122, 247, 122, - 245, 237, 79, 80, 89, 147, 189, 124, 185, 131, - 196, 79, 89, 146, 189, 196, 108, 104, 333, 284, - 223, 10, 105, 55, 105, 320, 124, 333, 295, 303, - 223, 102, 154, 289, 288, 289, 288, 284, 296, 274, - 124, 22, 121, 301, 122, 122, 271, 189, 333, 50, - 53, 196, 124, 333, 189, 50, 53, 124, 266, 23, - 233, 301, 48, 296, 305, 223, 296, 237, 26, 23, - 300, 295, 295, 123, 119, 121, 119, 121, 284, 121, - 104, 123, 53, 153, 169, 333, 124, 224, 53, 169, - 333, 333, 301, 104, 323, 296, 284, 294, 312, 314, - 233, 23, 333, 102, 187, 53, 224, 102, 333, 53, - 224, 104, 23, 333, 224, 295, 123, 333, 116, 206, - 210, 261, 224, 333, 116, 205, 209, 23, 333, 206, - 224, 64, 107, 218, 219, 255, 225, 223, 123, 205, - 224, 64, 107, 211, 255, 225, 223, 333, 233, 225, - 206, 64, 255, 281, 121, 122, 38, 123, 283, 225, - 205, 64, 255, 281, 121, 38, 283, 233, 123, 283, - 225, 38, 255, 153, 283, 225, 38, 255, 153, 123, - 283, 153, 38, 122, 217, 283, 153, 38, 122, 216, - 217, 153, 219, 121, 216, 153, 212, 121, 121, 217, - 122, 121, 216, 122, 121, 121 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = -{ - 0, 128, 129, 129, 130, 130, 131, 131, 132, 132, - 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, - 137, 137, 138, 138, 138, 139, 139, 140, 140, 141, - 142, 143, 143, 144, 144, 144, 144, 144, 145, 145, - 146, 147, 147, 147, 148, 148, 148, 148, 149, 150, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, - 152, 152, 152, 153, 153, 154, 154, 155, 155, 155, - 156, 156, 157, 157, 158, 158, 158, 159, 160, 160, - 160, 161, 162, 162, 163, 163, 163, 164, 165, 165, - 165, 165, 165, 166, 166, 167, 167, 167, 168, 168, - 169, 169, 170, 170, 171, 171, 172, 172, 172, 173, - 174, 175, 176, 176, 176, 176, 177, 177, 178, 178, - 178, 179, 179, 180, 181, 181, 181, 182, 183, 183, - 184, 184, 185, 185, 185, 185, 186, 187, 187, 188, - 189, 189, 190, 190, 190, 190, 191, 191, 192, 192, - 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, - 195, 195, 195, 196, 196, 197, 197, 198, 198, 198, - 198, 199, 199, 200, 201, 202, 202, 203, 203, 203, - 204, 205, 206, 207, 208, 208, 209, 209, 209, 209, - 210, 210, 210, 210, 211, 211, 211, 212, 212, 213, - 214, 214, 215, 216, 216, 216, 216, 217, 217, 217, - 217, 218, 218, 218, 219, 219, 220, 220, 221, 221, - 221, 222, 222, 222, 222, 222, 222, 222, 223, 223, - 223, 224, 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 225, 225, 226, 226, 227, - 227, 228, 228, 229, 229, 230, 230, 231, 231, 231, - 231, 231, 231, 231, 232, 232, 232, 232, 232, 232, - 233, 233, 233, 233, 233, 233, 233, 233, 234, 235, - 235, 235, 235, 235, 235, 236, 236, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, - 237, 237, 237, 237, 237, 237, 238, 238, 239, 239, - 239, 240, 240, 240, 241, 241, 241, 241, 241, 241, - 241, 242, 242, 243, 243, 243, 243, 243, 244, 244, - 244, 244, 244, 244, 244, 244, 244, 244, 244, 245, - 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 247, 247, 248, 248, 248, 248, 248, - 248, 248, 249, 249, 249, 249, 249, 249, 249, 249, - 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, - 249, 249, 250, 250, 250, 250, 251, 252, 252, 252, - 252, 253, 254, 254, 254, 255, 255, 256, 256, 256, - 257, 257, 258, 258, 259, 259, 259, 260, 260, 261, - 261, 262, 262, 263, 263, 264, 264, 265, 265, 266, - 266, 267, 267, 268, 268, 268, 268, 269, 269, 270, - 271, 271, 272, 272, 273, 273, 274, 274, 275, 275, - 276, 276, 277, 277, 278, 278, 278, 279, 279, 280, - 280, 281, 281, 282, 282, 283, 284, 285, 285, 285, - 285, 286, 286, 287, 287, 287, 287, 287, 287, 287, - 287, 287, 287, 288, 288, 288, 289, 289, 290, 290, - 291, 291, 291, 292, 292, 292, 292, 292, 293, 293, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 296, 296, 296, 296, 296, 297, 297, 297, - 297, 297, 297, 297, 298, 298, 298, 298, 298, 298, - 298, 299, 299, 299, 299, 299, 300, 300, 301, 301, - 302, 302, 302, 302, 303, 303, 303, 304, 304, 304, - 304, 305, 305, 305, 306, 306, 307, 307, 307, 307, - 308, 308, 308, 309, 309, 310, 310, 310, 311, 312, - 312, 312, 312, 312, 312, 312, 312, 312, 313, 313, - 314, 314, 314, 314, 314, 314, 314, 314, 315, 315, - 315, 315, 316, 316, 317, 317, 317, 318, 318, 319, - 319, 320, 320, 321, 321, 322, 322, 323, 323, 323, - 324, 325, 326, 327, 328, 328, 329, 330, 330, 330, - 330, 330, 330, 330, 331, 331, 331, 331, 332, 332, - 333, 333, 333, 333, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 334, 334, 335, 335, - 336, 336, 337, 337, 337, 338, 339, 340 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 3, 2, 1, 0, 1, 0, 1, 2, - 4, 1, 1, 0, 1, 2, 4, 1, 1, 3, - 4, 5, 0, 1, 3, 1, 0, 1, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 7, 8, - 7, 5, 4, 5, 1, 1, 4, 6, 3, 3, - 1, 4, 3, 5, 4, 6, 5, 3, 2, 1, - 2, 3, 4, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 0, 2, 0, 5, 6, 5, - 3, 4, 3, 4, 1, 3, 0, 4, 1, 3, - 0, 2, 7, 8, 1, 3, 0, 3, 3, 4, - 3, 2, 0, 7, 8, 3, 5, 6, 5, 6, - 1, 0, 1, 0, 1, 2, 3, 2, 3, 5, - 6, 2, 2, 3, 4, 5, 1, 0, 1, 3, - 3, 1, 1, 7, 3, 3, 0, 10, 1, 0, - 1, 2, 1, 1, 1, 2, 6, 2, 0, 4, - 1, 0, 2, 1, 1, 0, 1, 1, 8, 9, - 10, 8, 9, 10, 9, 10, 11, 9, 11, 11, - 12, 8, 9, 1, 0, 1, 2, 1, 2, 1, - 1, 1, 0, 3, 8, 6, 7, 7, 8, 9, - 2, 2, 2, 3, 4, 2, 6, 7, 8, 3, - 6, 7, 8, 3, 1, 2, 0, 1, 3, 3, - 1, 3, 2, 1, 2, 3, 0, 1, 2, 3, - 0, 1, 2, 0, 1, 3, 3, 1, 2, 3, - 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 0, 2, 3, 4, 3, 4, 5, 6, 5, 6, - 3, 4, 3, 4, 0, 0, 1, 2, 3, 1, - 3, 4, 4, 4, 0, 1, 3, 1, 2, 1, - 2, 1, 2, 3, 1, 2, 5, 3, 4, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, - 2, 3, 1, 2, 0, 2, 0, 1, 2, 3, - 2, 2, 3, 3, 1, 3, 4, 3, 4, 4, - 2, 3, 4, 2, 6, 10, 1, 3, 1, 2, - 1, 1, 1, 2, 1, 2, 2, 3, 3, 4, - 3, 1, 3, 1, 2, 3, 1, 0, 1, 2, - 2, 3, 4, 5, 5, 6, 3, 4, 1, 1, - 3, 1, 2, 2, 3, 4, 5, 5, 6, 3, - 4, 1, 0, 1, 3, 1, 1, 6, 10, 3, - 4, 2, 1, 2, 3, 4, 5, 2, 3, 2, - 3, 2, 3, 4, 4, 3, 6, 5, 4, 1, - 1, 1, 2, 3, 4, 5, 3, 6, 5, 4, - 3, 5, 1, 1, 1, 1, 0, 1, 1, 0, - 2, 4, 6, 8, 1, 2, 0, 1, 3, 1, - 3, 1, 1, 1, 3, 1, 1, 2, 0, 1, - 0, 1, 3, 5, 1, 6, 2, 1, 3, 3, - 3, 5, 2, 0, 1, 3, 1, 1, 2, 0, - 1, 3, 2, 0, 1, 2, 0, 1, 3, 2, - 1, 1, 1, 1, 2, 4, 3, 1, 2, 1, - 0, 1, 2, 2, 1, 2, 2, 3, 1, 2, - 2, 3, 1, 1, 2, 0, 1, 0, 1, 3, - 1, 2, 3, 1, 1, 3, 3, 3, 4, 4, - 1, 1, 1, 1, 4, 2, 3, 3, 4, 4, - 3, 3, 1, 2, 1, 2, 1, 2, 1, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - 3, 2, 1, 3, 3, 2, 1, 1, 1, 1, - 1, 1, 4, 2, 3, 3, 4, 4, 3, 3, - 1, 2, 1, 2, 1, 2, 1, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, - 1, 3, 3, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 3, 4, 4, 3, 3, 1, - 2, 1, 2, 1, 2, 1, 2, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 3, 2, 1, - 3, 3, 2, 1, 1, 1, 1, 2, 2, 2, - 3, 3, 1, 2, 2, 2, 2, 3, 3, 1, - 2, 7, 10, 11, 11, 12, 2, 0, 2, 0, - 3, 4, 5, 4, 3, 4, 3, 2, 4, 4, - 4, 3, 4, 3, 1, 3, 1, 2, 2, 0, - 1, 2, 0, 1, 3, 1, 3, 3, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, - 3, 3, 6, 6, 6, 6, 3, 3, 4, 5, - 6, 5, 1, 2, 2, 1, 2, 5, 5, 5, - 5, 2, 0, 3, 5, 6, 8, 1, 1, 1, - 4, 7, 3, 6, 2, 0, 5, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, - 1, 1, 1, 1, 1, 3, 3, 3 -}; - - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif - - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep) -{ - FILE *yyoutput = yyo; - YYUSE (yyoutput); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyo, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep) -{ - YYFPRINTF (yyo, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - - yy_symbol_value_print (yyo, yytype, yyvaluep); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) -{ - unsigned long yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &yyvsp[(yyi + 1) - (yynrhs)] - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - else - goto append; - - append: - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return 2; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - default: /* Avoid compiler warnings. */ - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return 2; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -{ - YYUSE (yyvaluep); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; -/* Number of syntax errors so far. */ -int yynerrs; - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (void) -{ - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yynewstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - *yyssp = (yytype_int16) yystate; - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (); - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 210 "parser-lalr.y" - { mk_node("crate", 2, yyvsp[-1], yyvsp[0]); } -#line 4054 "parser.tab.c" - break; - - case 3: -#line 211 "parser-lalr.y" - { mk_node("crate", 1, yyvsp[0]); } -#line 4060 "parser.tab.c" - break; - - case 7: -#line 221 "parser-lalr.y" - { yyval = mk_none(); } -#line 4066 "parser.tab.c" - break; - - case 8: -#line 225 "parser-lalr.y" - { yyval = mk_node("InnerAttrs", 1, yyvsp[0]); } -#line 4072 "parser.tab.c" - break; - - case 9: -#line 226 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4078 "parser.tab.c" - break; - - case 10: -#line 230 "parser-lalr.y" - { yyval = mk_node("InnerAttr", 1, yyvsp[-1]); } -#line 4084 "parser.tab.c" - break; - - case 11: -#line 231 "parser-lalr.y" - { yyval = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); } -#line 4090 "parser.tab.c" - break; - - case 13: -#line 236 "parser-lalr.y" - { yyval = mk_none(); } -#line 4096 "parser.tab.c" - break; - - case 14: -#line 240 "parser-lalr.y" - { yyval = mk_node("OuterAttrs", 1, yyvsp[0]); } -#line 4102 "parser.tab.c" - break; - - case 15: -#line 241 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4108 "parser.tab.c" - break; - - case 16: -#line 245 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 4114 "parser.tab.c" - break; - - case 17: -#line 246 "parser-lalr.y" - { yyval = mk_node("doc-comment", 1, mk_atom(yytext)); } -#line 4120 "parser.tab.c" - break; - - case 18: -#line 250 "parser-lalr.y" - { yyval = mk_node("MetaWord", 1, yyvsp[0]); } -#line 4126 "parser.tab.c" - break; - - case 19: -#line 251 "parser-lalr.y" - { yyval = mk_node("MetaNameValue", 2, yyvsp[-2], yyvsp[0]); } -#line 4132 "parser.tab.c" - break; - - case 20: -#line 252 "parser-lalr.y" - { yyval = mk_node("MetaList", 2, yyvsp[-3], yyvsp[-1]); } -#line 4138 "parser.tab.c" - break; - - case 21: -#line 253 "parser-lalr.y" - { yyval = mk_node("MetaList", 2, yyvsp[-4], yyvsp[-2]); } -#line 4144 "parser.tab.c" - break; - - case 22: -#line 257 "parser-lalr.y" - { yyval = mk_none(); } -#line 4150 "parser.tab.c" - break; - - case 23: -#line 258 "parser-lalr.y" - { yyval = mk_node("MetaItems", 1, yyvsp[0]); } -#line 4156 "parser.tab.c" - break; - - case 24: -#line 259 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 4162 "parser.tab.c" - break; - - case 26: -#line 264 "parser-lalr.y" - { yyval = mk_none(); } -#line 4168 "parser.tab.c" - break; - - case 27: -#line 268 "parser-lalr.y" - { yyval = mk_node("Items", 1, yyvsp[0]); } -#line 4174 "parser.tab.c" - break; - - case 28: -#line 269 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4180 "parser.tab.c" - break; - - case 29: -#line 273 "parser-lalr.y" - { yyval = mk_node("AttrsAndVis", 2, yyvsp[-1], yyvsp[0]); } -#line 4186 "parser.tab.c" - break; - - case 30: -#line 277 "parser-lalr.y" - { yyval = mk_node("Item", 2, yyvsp[-1], yyvsp[0]); } -#line 4192 "parser.tab.c" - break; - - case 38: -#line 296 "parser-lalr.y" - { yyval = mk_node("ItemStatic", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 4198 "parser.tab.c" - break; - - case 39: -#line 297 "parser-lalr.y" - { yyval = mk_node("ItemStatic", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 4204 "parser.tab.c" - break; - - case 40: -#line 301 "parser-lalr.y" - { yyval = mk_node("ItemConst", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 4210 "parser.tab.c" - break; - - case 41: -#line 305 "parser-lalr.y" - { yyval = mk_node("ItemMacro", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 4216 "parser.tab.c" - break; - - case 42: -#line 306 "parser-lalr.y" - { yyval = mk_node("ItemMacro", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 4222 "parser.tab.c" - break; - - case 43: -#line 307 "parser-lalr.y" - { yyval = mk_node("ItemMacro", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 4228 "parser.tab.c" - break; - - case 46: -#line 313 "parser-lalr.y" - { yyval = mk_node("ViewItemExternCrate", 1, yyvsp[-1]); } -#line 4234 "parser.tab.c" - break; - - case 47: -#line 314 "parser-lalr.y" - { yyval = mk_node("ViewItemExternCrate", 2, yyvsp[-3], yyvsp[-1]); } -#line 4240 "parser.tab.c" - break; - - case 48: -#line 318 "parser-lalr.y" - { yyval = mk_node("ViewItemExternFn", 2, yyvsp[-1], yyvsp[0]); } -#line 4246 "parser.tab.c" - break; - - case 49: -#line 322 "parser-lalr.y" - { yyval = mk_node("ViewItemUse", 1, yyvsp[-1]); } -#line 4252 "parser.tab.c" - break; - - case 50: -#line 326 "parser-lalr.y" - { yyval = mk_node("ViewPathSimple", 1, yyvsp[0]); } -#line 4258 "parser.tab.c" - break; - - case 51: -#line 327 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 2, yyvsp[-3], mk_atom("ViewPathListEmpty")); } -#line 4264 "parser.tab.c" - break; - - case 52: -#line 328 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); } -#line 4270 "parser.tab.c" - break; - - case 53: -#line 329 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 2, yyvsp[-4], yyvsp[-1]); } -#line 4276 "parser.tab.c" - break; - - case 54: -#line 330 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 1, yyvsp[-1]); } -#line 4282 "parser.tab.c" - break; - - case 55: -#line 331 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 2, yyvsp[-5], yyvsp[-2]); } -#line 4288 "parser.tab.c" - break; - - case 56: -#line 332 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 1, yyvsp[-2]); } -#line 4294 "parser.tab.c" - break; - - case 57: -#line 333 "parser-lalr.y" - { yyval = mk_node("ViewPathGlob", 1, yyvsp[-2]); } -#line 4300 "parser.tab.c" - break; - - case 58: -#line 334 "parser-lalr.y" - { yyval = mk_atom("ViewPathGlob"); } -#line 4306 "parser.tab.c" - break; - - case 59: -#line 335 "parser-lalr.y" - { yyval = mk_atom("ViewPathGlob"); } -#line 4312 "parser.tab.c" - break; - - case 60: -#line 336 "parser-lalr.y" - { yyval = mk_atom("ViewPathListEmpty"); } -#line 4318 "parser.tab.c" - break; - - case 61: -#line 337 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 1, yyvsp[-1]); } -#line 4324 "parser.tab.c" - break; - - case 62: -#line 338 "parser-lalr.y" - { yyval = mk_node("ViewPathList", 1, yyvsp[-2]); } -#line 4330 "parser.tab.c" - break; - - case 63: -#line 339 "parser-lalr.y" - { yyval = mk_node("ViewPathSimple", 2, yyvsp[-2], yyvsp[0]); } -#line 4336 "parser.tab.c" - break; - - case 67: -#line 346 "parser-lalr.y" - { yyval = mk_node("ItemForeignMod", 1, yyvsp[0]); } -#line 4342 "parser.tab.c" - break; - - case 73: -#line 355 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 4348 "parser.tab.c" - break; - - case 74: -#line 356 "parser-lalr.y" - { yyval = mk_none(); } -#line 4354 "parser.tab.c" - break; - - case 75: -#line 360 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 4360 "parser.tab.c" - break; - - case 76: -#line 361 "parser-lalr.y" - { yyval = mk_none(); } -#line 4366 "parser.tab.c" - break; - - case 77: -#line 367 "parser-lalr.y" - { - yyval = mk_node("ItemStruct", 4, yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4374 "parser.tab.c" - break; - - case 78: -#line 371 "parser-lalr.y" - { - yyval = mk_node("ItemStruct", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1]); -} -#line 4382 "parser.tab.c" - break; - - case 79: -#line 375 "parser-lalr.y" - { - yyval = mk_node("ItemStruct", 3, yyvsp[-3], yyvsp[-2], yyvsp[-1]); -} -#line 4390 "parser.tab.c" - break; - - case 80: -#line 381 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 4396 "parser.tab.c" - break; - - case 81: -#line 382 "parser-lalr.y" - { yyval = yyvsp[-2]; } -#line 4402 "parser.tab.c" - break; - - case 82: -#line 386 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 4408 "parser.tab.c" - break; - - case 83: -#line 387 "parser-lalr.y" - { yyval = yyvsp[-2]; } -#line 4414 "parser.tab.c" - break; - - case 84: -#line 391 "parser-lalr.y" - { yyval = mk_node("StructFields", 1, yyvsp[0]); } -#line 4420 "parser.tab.c" - break; - - case 85: -#line 392 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 4426 "parser.tab.c" - break; - - case 86: -#line 393 "parser-lalr.y" - { yyval = mk_none(); } -#line 4432 "parser.tab.c" - break; - - case 87: -#line 397 "parser-lalr.y" - { yyval = mk_node("StructField", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 4438 "parser.tab.c" - break; - - case 88: -#line 401 "parser-lalr.y" - { yyval = mk_node("StructFields", 1, yyvsp[0]); } -#line 4444 "parser.tab.c" - break; - - case 89: -#line 402 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 4450 "parser.tab.c" - break; - - case 90: -#line 403 "parser-lalr.y" - { yyval = mk_none(); } -#line 4456 "parser.tab.c" - break; - - case 91: -#line 407 "parser-lalr.y" - { yyval = mk_node("StructField", 2, yyvsp[-1], yyvsp[0]); } -#line 4462 "parser.tab.c" - break; - - case 92: -#line 412 "parser-lalr.y" - { yyval = mk_node("ItemEnum", 0); } -#line 4468 "parser.tab.c" - break; - - case 93: -#line 413 "parser-lalr.y" - { yyval = mk_node("ItemEnum", 0); } -#line 4474 "parser.tab.c" - break; - - case 94: -#line 417 "parser-lalr.y" - { yyval = mk_node("EnumDefs", 1, yyvsp[0]); } -#line 4480 "parser.tab.c" - break; - - case 95: -#line 418 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 4486 "parser.tab.c" - break; - - case 96: -#line 419 "parser-lalr.y" - { yyval = mk_none(); } -#line 4492 "parser.tab.c" - break; - - case 97: -#line 423 "parser-lalr.y" - { yyval = mk_node("EnumDef", 3, yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 4498 "parser.tab.c" - break; - - case 98: -#line 427 "parser-lalr.y" - { yyval = mk_node("EnumArgs", 1, yyvsp[-1]); } -#line 4504 "parser.tab.c" - break; - - case 99: -#line 428 "parser-lalr.y" - { yyval = mk_node("EnumArgs", 1, yyvsp[-2]); } -#line 4510 "parser.tab.c" - break; - - case 100: -#line 429 "parser-lalr.y" - { yyval = mk_node("EnumArgs", 1, yyvsp[-1]); } -#line 4516 "parser.tab.c" - break; - - case 101: -#line 430 "parser-lalr.y" - { yyval = mk_node("EnumArgs", 1, yyvsp[0]); } -#line 4522 "parser.tab.c" - break; - - case 102: -#line 431 "parser-lalr.y" - { yyval = mk_none(); } -#line 4528 "parser.tab.c" - break; - - case 103: -#line 436 "parser-lalr.y" - { yyval = mk_node("ItemUnion", 0); } -#line 4534 "parser.tab.c" - break; - - case 104: -#line 437 "parser-lalr.y" - { yyval = mk_node("ItemUnion", 0); } -#line 4540 "parser.tab.c" - break; - - case 105: -#line 440 "parser-lalr.y" - { yyval = mk_node("ItemMod", 1, yyvsp[-1]); } -#line 4546 "parser.tab.c" - break; - - case 106: -#line 441 "parser-lalr.y" - { yyval = mk_node("ItemMod", 2, yyvsp[-3], yyvsp[-1]); } -#line 4552 "parser.tab.c" - break; - - case 107: -#line 442 "parser-lalr.y" - { yyval = mk_node("ItemMod", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 4558 "parser.tab.c" - break; - - case 108: -#line 446 "parser-lalr.y" - { yyval = mk_node("ItemForeignMod", 1, yyvsp[-1]); } -#line 4564 "parser.tab.c" - break; - - case 109: -#line 447 "parser-lalr.y" - { yyval = mk_node("ItemForeignMod", 2, yyvsp[-2], yyvsp[-1]); } -#line 4570 "parser.tab.c" - break; - - case 111: -#line 452 "parser-lalr.y" - { yyval = mk_none(); } -#line 4576 "parser.tab.c" - break; - - case 113: -#line 457 "parser-lalr.y" - { yyval = mk_none(); } -#line 4582 "parser.tab.c" - break; - - case 114: -#line 461 "parser-lalr.y" - { yyval = mk_node("ForeignItems", 1, yyvsp[0]); } -#line 4588 "parser.tab.c" - break; - - case 115: -#line 462 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4594 "parser.tab.c" - break; - - case 116: -#line 466 "parser-lalr.y" - { yyval = mk_node("ForeignItem", 2, yyvsp[-2], yyvsp[0]); } -#line 4600 "parser.tab.c" - break; - - case 117: -#line 467 "parser-lalr.y" - { yyval = mk_node("ForeignItem", 2, yyvsp[-1], yyvsp[0]); } -#line 4606 "parser.tab.c" - break; - - case 118: -#line 468 "parser-lalr.y" - { yyval = mk_node("ForeignItem", 2, yyvsp[-2], yyvsp[0]); } -#line 4612 "parser.tab.c" - break; - - case 119: -#line 472 "parser-lalr.y" - { yyval = mk_node("StaticItem", 3, yyvsp[-4], yyvsp[-3], yyvsp[-1]); } -#line 4618 "parser.tab.c" - break; - - case 120: -#line 476 "parser-lalr.y" - { yyval = mk_node("ForeignFn", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1]); } -#line 4624 "parser.tab.c" - break; - - case 121: -#line 480 "parser-lalr.y" - { yyval = mk_node("FnDecl", 2, yyvsp[-1], yyvsp[0]); } -#line 4630 "parser.tab.c" - break; - - case 122: -#line 484 "parser-lalr.y" - { yyval = mk_none(); } -#line 4636 "parser.tab.c" - break; - - case 123: -#line 485 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 4642 "parser.tab.c" - break; - - case 124: -#line 486 "parser-lalr.y" - { yyval = yyvsp[-2]; } -#line 4648 "parser.tab.c" - break; - - case 125: -#line 487 "parser-lalr.y" - { yyval = yyvsp[-3]; } -#line 4654 "parser.tab.c" - break; - - case 126: -#line 491 "parser-lalr.y" - { yyval = mk_atom("Public"); } -#line 4660 "parser.tab.c" - break; - - case 127: -#line 492 "parser-lalr.y" - { yyval = mk_atom("Inherited"); } -#line 4666 "parser.tab.c" - break; - - case 128: -#line 496 "parser-lalr.y" - { yyval = mk_node("IdentsOrSelf", 1, yyvsp[0]); } -#line 4672 "parser.tab.c" - break; - - case 129: -#line 497 "parser-lalr.y" - { yyval = mk_node("IdentsOrSelf", 2, yyvsp[-2], yyvsp[0]); } -#line 4678 "parser.tab.c" - break; - - case 130: -#line 498 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 4684 "parser.tab.c" - break; - - case 132: -#line 503 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 4690 "parser.tab.c" - break; - - case 133: -#line 507 "parser-lalr.y" - { yyval = mk_node("ItemTy", 4, yyvsp[-5], yyvsp[-4], yyvsp[-3], yyvsp[-1]); } -#line 4696 "parser.tab.c" - break; - - case 134: -#line 511 "parser-lalr.y" - { yyval = mk_node("ForSized", 1, yyvsp[0]); } -#line 4702 "parser.tab.c" - break; - - case 135: -#line 512 "parser-lalr.y" - { yyval = mk_node("ForSized", 1, yyvsp[-1]); } -#line 4708 "parser.tab.c" - break; - - case 136: -#line 513 "parser-lalr.y" - { yyval = mk_none(); } -#line 4714 "parser.tab.c" - break; - - case 137: -#line 518 "parser-lalr.y" - { - yyval = mk_node("ItemTrait", 7, yyvsp[-9], yyvsp[-7], yyvsp[-6], yyvsp[-5], yyvsp[-4], yyvsp[-3], yyvsp[-1]); -} -#line 4722 "parser.tab.c" - break; - - case 139: -#line 525 "parser-lalr.y" - { yyval = mk_none(); } -#line 4728 "parser.tab.c" - break; - - case 140: -#line 529 "parser-lalr.y" - { yyval = mk_node("TraitItems", 1, yyvsp[0]); } -#line 4734 "parser.tab.c" - break; - - case 141: -#line 530 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4740 "parser.tab.c" - break; - - case 145: -#line 537 "parser-lalr.y" - { yyval = mk_node("TraitMacroItem", 2, yyvsp[-1], yyvsp[0]); } -#line 4746 "parser.tab.c" - break; - - case 146: -#line 541 "parser-lalr.y" - { yyval = mk_node("ConstTraitItem", 4, yyvsp[-5], yyvsp[-3], yyvsp[-2], yyvsp[-1]); } -#line 4752 "parser.tab.c" - break; - - case 147: -#line 545 "parser-lalr.y" - { yyval = mk_node("ConstDefault", 1, yyvsp[0]); } -#line 4758 "parser.tab.c" - break; - - case 148: -#line 546 "parser-lalr.y" - { yyval = mk_none(); } -#line 4764 "parser.tab.c" - break; - - case 149: -#line 550 "parser-lalr.y" - { yyval = mk_node("TypeTraitItem", 2, yyvsp[-3], yyvsp[-1]); } -#line 4770 "parser.tab.c" - break; - - case 150: -#line 554 "parser-lalr.y" - { yyval = mk_atom("Unsafe"); } -#line 4776 "parser.tab.c" - break; - - case 151: -#line 555 "parser-lalr.y" - { yyval = mk_none(); } -#line 4782 "parser.tab.c" - break; - - case 152: -#line 559 "parser-lalr.y" - { yyval = mk_atom("DefaultUnsafe"); } -#line 4788 "parser.tab.c" - break; - - case 153: -#line 560 "parser-lalr.y" - { yyval = mk_atom("Default"); } -#line 4794 "parser.tab.c" - break; - - case 154: -#line 561 "parser-lalr.y" - { yyval = mk_atom("Unsafe"); } -#line 4800 "parser.tab.c" - break; - - case 155: -#line 562 "parser-lalr.y" - { yyval = mk_none(); } -#line 4806 "parser.tab.c" - break; - - case 156: -#line 565 "parser-lalr.y" - { yyval = mk_node("Required", 1, yyvsp[0]); } -#line 4812 "parser.tab.c" - break; - - case 157: -#line 566 "parser-lalr.y" - { yyval = mk_node("Provided", 1, yyvsp[0]); } -#line 4818 "parser.tab.c" - break; - - case 158: -#line 571 "parser-lalr.y" - { - yyval = mk_node("TypeMethod", 6, yyvsp[-7], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1]); -} -#line 4826 "parser.tab.c" - break; - - case 159: -#line 575 "parser-lalr.y" - { - yyval = mk_node("TypeMethod", 6, yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1]); -} -#line 4834 "parser.tab.c" - break; - - case 160: -#line 579 "parser-lalr.y" - { - yyval = mk_node("TypeMethod", 7, yyvsp[-9], yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1]); -} -#line 4842 "parser.tab.c" - break; - - case 161: -#line 586 "parser-lalr.y" - { - yyval = mk_node("Method", 7, yyvsp[-7], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4850 "parser.tab.c" - break; - - case 162: -#line 590 "parser-lalr.y" - { - yyval = mk_node("Method", 7, yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4858 "parser.tab.c" - break; - - case 163: -#line 594 "parser-lalr.y" - { - yyval = mk_node("Method", 8, yyvsp[-9], yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4866 "parser.tab.c" - break; - - case 164: -#line 601 "parser-lalr.y" - { - yyval = mk_node("Method", 8, yyvsp[-8], yyvsp[-7], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4874 "parser.tab.c" - break; - - case 165: -#line 605 "parser-lalr.y" - { - yyval = mk_node("Method", 8, yyvsp[-9], yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4882 "parser.tab.c" - break; - - case 166: -#line 609 "parser-lalr.y" - { - yyval = mk_node("Method", 9, yyvsp[-10], yyvsp[-9], yyvsp[-8], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4890 "parser.tab.c" - break; - - case 167: -#line 631 "parser-lalr.y" - { - yyval = mk_node("ItemImpl", 6, yyvsp[-8], yyvsp[-6], yyvsp[-5], yyvsp[-4], yyvsp[-2], yyvsp[-1]); -} -#line 4898 "parser.tab.c" - break; - - case 168: -#line 635 "parser-lalr.y" - { - yyval = mk_node("ItemImpl", 6, yyvsp[-10], yyvsp[-8], 5, yyvsp[-5], yyvsp[-2], yyvsp[-1]); -} -#line 4906 "parser.tab.c" - break; - - case 169: -#line 639 "parser-lalr.y" - { - yyval = mk_node("ItemImpl", 6, yyvsp[-8], yyvsp[-7], yyvsp[-5], yyvsp[-4], yyvsp[-2], yyvsp[-1]); -} -#line 4914 "parser.tab.c" - break; - - case 170: -#line 643 "parser-lalr.y" - { - yyval = mk_node("ItemImplNeg", 7, yyvsp[-11], yyvsp[-9], yyvsp[-7], yyvsp[-5], yyvsp[-4], yyvsp[-2], yyvsp[-1]); -} -#line 4922 "parser.tab.c" - break; - - case 171: -#line 647 "parser-lalr.y" - { - yyval = mk_node("ItemImplDefault", 3, yyvsp[-7], yyvsp[-5], yyvsp[-4]); -} -#line 4930 "parser.tab.c" - break; - - case 172: -#line 651 "parser-lalr.y" - { - yyval = mk_node("ItemImplDefaultNeg", 3, yyvsp[-8], yyvsp[-6], yyvsp[-5]); -} -#line 4938 "parser.tab.c" - break; - - case 174: -#line 658 "parser-lalr.y" - { yyval = mk_none(); } -#line 4944 "parser.tab.c" - break; - - case 175: -#line 662 "parser-lalr.y" - { yyval = mk_node("ImplItems", 1, yyvsp[0]); } -#line 4950 "parser.tab.c" - break; - - case 176: -#line 663 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 4956 "parser.tab.c" - break; - - case 178: -#line 668 "parser-lalr.y" - { yyval = mk_node("ImplMacroItem", 2, yyvsp[-1], yyvsp[0]); } -#line 4962 "parser.tab.c" - break; - - case 181: -#line 674 "parser-lalr.y" - { yyval = mk_atom("Default"); } -#line 4968 "parser.tab.c" - break; - - case 182: -#line 675 "parser-lalr.y" - { yyval = mk_none(); } -#line 4974 "parser.tab.c" - break; - - case 183: -#line 679 "parser-lalr.y" - { yyval = mk_node("ImplConst", 3, yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 4980 "parser.tab.c" - break; - - case 184: -#line 683 "parser-lalr.y" - { yyval = mk_node("ImplType", 5, yyvsp[-7], yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-1]); } -#line 4986 "parser.tab.c" - break; - - case 185: -#line 688 "parser-lalr.y" - { - yyval = mk_node("ItemFn", 5, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 4994 "parser.tab.c" - break; - - case 186: -#line 692 "parser-lalr.y" - { - yyval = mk_node("ItemFn", 5, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 5002 "parser.tab.c" - break; - - case 187: -#line 699 "parser-lalr.y" - { - yyval = mk_node("ItemUnsafeFn", 5, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 5010 "parser.tab.c" - break; - - case 188: -#line 703 "parser-lalr.y" - { - yyval = mk_node("ItemUnsafeFn", 5, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 5018 "parser.tab.c" - break; - - case 189: -#line 707 "parser-lalr.y" - { - yyval = mk_node("ItemUnsafeFn", 6, yyvsp[-6], yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[-1], yyvsp[0]); -} -#line 5026 "parser.tab.c" - break; - - case 190: -#line 713 "parser-lalr.y" - { yyval = mk_node("FnDecl", 2, yyvsp[-1], yyvsp[0]); } -#line 5032 "parser.tab.c" - break; - - case 191: -#line 717 "parser-lalr.y" - { yyval = mk_node("FnDecl", 2, yyvsp[-1], yyvsp[0]); } -#line 5038 "parser.tab.c" - break; - - case 192: -#line 721 "parser-lalr.y" - { yyval = mk_node("FnDecl", 2, yyvsp[-1], yyvsp[0]); } -#line 5044 "parser.tab.c" - break; - - case 193: -#line 725 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 5050 "parser.tab.c" - break; - - case 194: -#line 729 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[-1]); } -#line 5056 "parser.tab.c" - break; - - case 195: -#line 730 "parser-lalr.y" - { yyval = mk_none(); } -#line 5062 "parser.tab.c" - break; - - case 196: -#line 734 "parser-lalr.y" - { yyval = mk_node("SelfLower", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5068 "parser.tab.c" - break; - - case 197: -#line 735 "parser-lalr.y" - { yyval = mk_node("SelfRegion", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5074 "parser.tab.c" - break; - - case 198: -#line 736 "parser-lalr.y" - { yyval = mk_node("SelfRegion", 4, yyvsp[-5], yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5080 "parser.tab.c" - break; - - case 199: -#line 737 "parser-lalr.y" - { yyval = mk_node("SelfStatic", 1, yyvsp[-1]); } -#line 5086 "parser.tab.c" - break; - - case 200: -#line 741 "parser-lalr.y" - { yyval = mk_node("SelfLower", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5092 "parser.tab.c" - break; - - case 201: -#line 742 "parser-lalr.y" - { yyval = mk_node("SelfRegion", 3, yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5098 "parser.tab.c" - break; - - case 202: -#line 743 "parser-lalr.y" - { yyval = mk_node("SelfRegion", 4, yyvsp[-5], yyvsp[-4], yyvsp[-2], yyvsp[-1]); } -#line 5104 "parser.tab.c" - break; - - case 203: -#line 744 "parser-lalr.y" - { yyval = mk_node("SelfStatic", 1, yyvsp[-1]); } -#line 5110 "parser.tab.c" - break; - - case 206: -#line 750 "parser-lalr.y" - { yyval = mk_none(); } -#line 5116 "parser.tab.c" - break; - - case 207: -#line 754 "parser-lalr.y" - { yyval = mk_node("Args", 1, yyvsp[0]); } -#line 5122 "parser.tab.c" - break; - - case 208: -#line 755 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5128 "parser.tab.c" - break; - - case 209: -#line 759 "parser-lalr.y" - { yyval = mk_node("Arg", 2, yyvsp[-2], yyvsp[0]); } -#line 5134 "parser.tab.c" - break; - - case 210: -#line 763 "parser-lalr.y" - { yyval = mk_node("InferrableParams", 1, yyvsp[0]); } -#line 5140 "parser.tab.c" - break; - - case 211: -#line 764 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5146 "parser.tab.c" - break; - - case 212: -#line 768 "parser-lalr.y" - { yyval = mk_node("InferrableParam", 2, yyvsp[-1], yyvsp[0]); } -#line 5152 "parser.tab.c" - break; - - case 213: -#line 772 "parser-lalr.y" - { yyval = mk_none(); } -#line 5158 "parser.tab.c" - break; - - case 214: -#line 773 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5164 "parser.tab.c" - break; - - case 215: -#line 774 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 5170 "parser.tab.c" - break; - - case 216: -#line 775 "parser-lalr.y" - { yyval = mk_none(); } -#line 5176 "parser.tab.c" - break; - - case 217: -#line 779 "parser-lalr.y" - { yyval = mk_none(); } -#line 5182 "parser.tab.c" - break; - - case 218: -#line 780 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5188 "parser.tab.c" - break; - - case 219: -#line 781 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 5194 "parser.tab.c" - break; - - case 220: -#line 782 "parser-lalr.y" - { yyval = mk_none(); } -#line 5200 "parser.tab.c" - break; - - case 223: -#line 788 "parser-lalr.y" - { yyval = mk_none(); } -#line 5206 "parser.tab.c" - break; - - case 224: -#line 792 "parser-lalr.y" - { yyval = mk_node("Args", 1, yyvsp[0]); } -#line 5212 "parser.tab.c" - break; - - case 225: -#line 793 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5218 "parser.tab.c" - break; - - case 226: -#line 799 "parser-lalr.y" - { yyval = mk_node("Arg", 2, yyvsp[-2], yyvsp[0]); } -#line 5224 "parser.tab.c" - break; - - case 228: -#line 804 "parser-lalr.y" - { yyval = mk_none(); } -#line 5230 "parser.tab.c" - break; - - case 229: -#line 805 "parser-lalr.y" - { yyval = mk_node("Args", 2, yyvsp[-1], yyvsp[0]); } -#line 5236 "parser.tab.c" - break; - - case 230: -#line 806 "parser-lalr.y" - { yyval = mk_none(); } -#line 5242 "parser.tab.c" - break; - - case 232: -#line 811 "parser-lalr.y" - { yyval = mk_atom("PatWild"); } -#line 5248 "parser.tab.c" - break; - - case 233: -#line 812 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5254 "parser.tab.c" - break; - - case 234: -#line 813 "parser-lalr.y" - { yyval = mk_atom("PatWild"); } -#line 5260 "parser.tab.c" - break; - - case 235: -#line 814 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5266 "parser.tab.c" - break; - - case 236: -#line 815 "parser-lalr.y" - { yyval = mk_atom("PatWild"); } -#line 5272 "parser.tab.c" - break; - - case 237: -#line 816 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5278 "parser.tab.c" - break; - - case 238: -#line 820 "parser-lalr.y" - { yyval = mk_none(); } -#line 5284 "parser.tab.c" - break; - - case 239: -#line 821 "parser-lalr.y" - { yyval = mk_node("ret-ty", 1, yyvsp[0]); } -#line 5290 "parser.tab.c" - break; - - case 240: -#line 822 "parser-lalr.y" - { yyval = mk_none(); } -#line 5296 "parser.tab.c" - break; - - case 241: -#line 826 "parser-lalr.y" - { yyval = mk_node("Generics", 2, mk_none(), mk_none()); } -#line 5302 "parser.tab.c" - break; - - case 242: -#line 827 "parser-lalr.y" - { yyval = mk_node("Generics", 2, yyvsp[-1], mk_none()); } -#line 5308 "parser.tab.c" - break; - - case 243: -#line 828 "parser-lalr.y" - { yyval = mk_node("Generics", 2, yyvsp[-2], mk_none()); } -#line 5314 "parser.tab.c" - break; - - case 244: -#line 829 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, yyvsp[-1], mk_none()); } -#line 5320 "parser.tab.c" - break; - - case 245: -#line 830 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, yyvsp[-2], mk_none()); } -#line 5326 "parser.tab.c" - break; - - case 246: -#line 831 "parser-lalr.y" - { yyval = mk_node("Generics", 2, yyvsp[-3], yyvsp[-1]); } -#line 5332 "parser.tab.c" - break; - - case 247: -#line 832 "parser-lalr.y" - { yyval = mk_node("Generics", 2, yyvsp[-4], yyvsp[-2]); } -#line 5338 "parser.tab.c" - break; - - case 248: -#line 833 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, yyvsp[-3], yyvsp[-1]); } -#line 5344 "parser.tab.c" - break; - - case 249: -#line 834 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, yyvsp[-4], yyvsp[-2]); } -#line 5350 "parser.tab.c" - break; - - case 250: -#line 835 "parser-lalr.y" - { yyval = mk_node("Generics", 2, mk_none(), yyvsp[-1]); } -#line 5356 "parser.tab.c" - break; - - case 251: -#line 836 "parser-lalr.y" - { yyval = mk_node("Generics", 2, mk_none(), yyvsp[-2]); } -#line 5362 "parser.tab.c" - break; - - case 252: -#line 837 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, mk_none(), yyvsp[-1]); } -#line 5368 "parser.tab.c" - break; - - case 253: -#line 838 "parser-lalr.y" - { push_back('>'); yyval = mk_node("Generics", 2, mk_none(), yyvsp[-2]); } -#line 5374 "parser.tab.c" - break; - - case 254: -#line 839 "parser-lalr.y" - { yyval = mk_none(); } -#line 5380 "parser.tab.c" - break; - - case 255: -#line 843 "parser-lalr.y" - { yyval = mk_none(); } -#line 5386 "parser.tab.c" - break; - - case 257: -#line 848 "parser-lalr.y" - { yyval = mk_node("WhereClause", 1, yyvsp[0]); } -#line 5392 "parser.tab.c" - break; - - case 258: -#line 849 "parser-lalr.y" - { yyval = mk_node("WhereClause", 1, yyvsp[-1]); } -#line 5398 "parser.tab.c" - break; - - case 259: -#line 853 "parser-lalr.y" - { yyval = mk_node("WherePredicates", 1, yyvsp[0]); } -#line 5404 "parser.tab.c" - break; - - case 260: -#line 854 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5410 "parser.tab.c" - break; - - case 261: -#line 858 "parser-lalr.y" - { yyval = mk_node("WherePredicate", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 5416 "parser.tab.c" - break; - - case 262: -#line 859 "parser-lalr.y" - { yyval = mk_node("WherePredicate", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 5422 "parser.tab.c" - break; - - case 263: -#line 863 "parser-lalr.y" - { yyval = mk_none(); } -#line 5428 "parser.tab.c" - break; - - case 264: -#line 864 "parser-lalr.y" - { yyval = mk_none(); } -#line 5434 "parser.tab.c" - break; - - case 265: -#line 867 "parser-lalr.y" - { yyval = mk_node("TyParams", 1, yyvsp[0]); } -#line 5440 "parser.tab.c" - break; - - case 266: -#line 868 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5446 "parser.tab.c" - break; - - case 267: -#line 876 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, yyvsp[0]); } -#line 5452 "parser.tab.c" - break; - - case 268: -#line 877 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, yyvsp[0]); } -#line 5458 "parser.tab.c" - break; - - case 269: -#line 878 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, mk_atom("Self")); } -#line 5464 "parser.tab.c" - break; - - case 270: -#line 879 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, mk_atom("Self")); } -#line 5470 "parser.tab.c" - break; - - case 271: -#line 880 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, mk_atom("Super")); } -#line 5476 "parser.tab.c" - break; - - case 272: -#line 881 "parser-lalr.y" - { yyval = mk_node("ViewPath", 1, mk_atom("Super")); } -#line 5482 "parser.tab.c" - break; - - case 273: -#line 882 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5488 "parser.tab.c" - break; - - case 274: -#line 898 "parser-lalr.y" - { yyval = mk_node("components", 1, yyvsp[0]); } -#line 5494 "parser.tab.c" - break; - - case 275: -#line 900 "parser-lalr.y" - { yyval = mk_node("components", 2, yyvsp[-1], yyvsp[0]); } -#line 5500 "parser.tab.c" - break; - - case 276: -#line 902 "parser-lalr.y" - { yyval = mk_node("components", 2, yyvsp[-4], yyvsp[-2]); } -#line 5506 "parser.tab.c" - break; - - case 277: -#line 904 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5512 "parser.tab.c" - break; - - case 278: -#line 906 "parser-lalr.y" - { yyval = ext_node(yyvsp[-3], 2, yyvsp[-1], yyvsp[0]); } -#line 5518 "parser.tab.c" - break; - - case 279: -#line 908 "parser-lalr.y" - { yyval = ext_node(yyvsp[-6], 2, yyvsp[-4], yyvsp[-2]); } -#line 5524 "parser.tab.c" - break; - - case 280: -#line 912 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 5530 "parser.tab.c" - break; - - case 281: -#line 913 "parser-lalr.y" - { push_back('>'); yyval = yyvsp[-1]; } -#line 5536 "parser.tab.c" - break; - - case 282: -#line 914 "parser-lalr.y" - { push_back('='); yyval = yyvsp[-1]; } -#line 5542 "parser.tab.c" - break; - - case 283: -#line 915 "parser-lalr.y" - { push_back('>'); push_back('='); yyval = yyvsp[-1]; } -#line 5548 "parser.tab.c" - break; - - case 284: -#line 920 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 5554 "parser.tab.c" - break; - - case 285: -#line 921 "parser-lalr.y" - { push_back('>'); yyval = yyvsp[-1]; } -#line 5560 "parser.tab.c" - break; - - case 286: -#line 922 "parser-lalr.y" - { push_back('='); yyval = yyvsp[-1]; } -#line 5566 "parser.tab.c" - break; - - case 287: -#line 923 "parser-lalr.y" - { push_back('>'); push_back('='); yyval = yyvsp[-1]; } -#line 5572 "parser.tab.c" - break; - - case 288: -#line 927 "parser-lalr.y" - { yyval = mk_node("GenericValues", 1, yyvsp[0]); } -#line 5578 "parser.tab.c" - break; - - case 291: -#line 933 "parser-lalr.y" - { yyval = mk_node("TySumsAndBindings", 2, yyvsp[-2], yyvsp[0]); } -#line 5584 "parser.tab.c" - break; - - case 294: -#line 936 "parser-lalr.y" - { yyval = mk_none(); } -#line 5590 "parser.tab.c" - break; - - case 295: -#line 940 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 5596 "parser.tab.c" - break; - - case 296: -#line 941 "parser-lalr.y" - { yyval = mk_none(); } -#line 5602 "parser.tab.c" - break; - - case 297: -#line 949 "parser-lalr.y" - { yyval = mk_atom("PatWild"); } -#line 5608 "parser.tab.c" - break; - - case 298: -#line 950 "parser-lalr.y" - { yyval = mk_node("PatRegion", 1, yyvsp[0]); } -#line 5614 "parser.tab.c" - break; - - case 299: -#line 951 "parser-lalr.y" - { yyval = mk_node("PatRegion", 1, yyvsp[0]); } -#line 5620 "parser.tab.c" - break; - - case 300: -#line 952 "parser-lalr.y" - { yyval = mk_node("PatRegion", 1, mk_node("PatRegion", 1, yyvsp[0])); } -#line 5626 "parser.tab.c" - break; - - case 301: -#line 953 "parser-lalr.y" - { yyval = mk_atom("PatUnit"); } -#line 5632 "parser.tab.c" - break; - - case 302: -#line 954 "parser-lalr.y" - { yyval = mk_node("PatTup", 1, yyvsp[-1]); } -#line 5638 "parser.tab.c" - break; - - case 303: -#line 955 "parser-lalr.y" - { yyval = mk_node("PatVec", 1, yyvsp[-1]); } -#line 5644 "parser.tab.c" - break; - - case 305: -#line 957 "parser-lalr.y" - { yyval = mk_node("PatRange", 2, yyvsp[-2], yyvsp[0]); } -#line 5650 "parser.tab.c" - break; - - case 306: -#line 958 "parser-lalr.y" - { yyval = mk_node("PatStruct", 2, yyvsp[-3], yyvsp[-1]); } -#line 5656 "parser.tab.c" - break; - - case 307: -#line 959 "parser-lalr.y" - { yyval = mk_node("PatEnum", 2, yyvsp[-2], mk_none()); } -#line 5662 "parser.tab.c" - break; - - case 308: -#line 960 "parser-lalr.y" - { yyval = mk_node("PatEnum", 2, yyvsp[-3], yyvsp[-1]); } -#line 5668 "parser.tab.c" - break; - - case 309: -#line 961 "parser-lalr.y" - { yyval = mk_node("PatMac", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 5674 "parser.tab.c" - break; - - case 310: -#line 962 "parser-lalr.y" - { yyval = mk_node("PatIdent", 2, yyvsp[-1], yyvsp[0]); } -#line 5680 "parser.tab.c" - break; - - case 311: -#line 963 "parser-lalr.y" - { yyval = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), yyvsp[-2], yyvsp[0]); } -#line 5686 "parser.tab.c" - break; - - case 312: -#line 964 "parser-lalr.y" - { yyval = mk_node("PatIdent", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 5692 "parser.tab.c" - break; - - case 313: -#line 965 "parser-lalr.y" - { yyval = mk_node("PatUniq", 1, yyvsp[0]); } -#line 5698 "parser.tab.c" - break; - - case 314: -#line 966 "parser-lalr.y" - { yyval = mk_node("PatQualifiedPath", 3, yyvsp[-4], yyvsp[-3], yyvsp[0]); } -#line 5704 "parser.tab.c" - break; - - case 315: -#line 968 "parser-lalr.y" - { - yyval = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, yyvsp[-8], yyvsp[-7], yyvsp[-4]), yyvsp[-3], yyvsp[0]); -} -#line 5712 "parser.tab.c" - break; - - case 316: -#line 974 "parser-lalr.y" - { yyval = mk_node("Pats", 1, yyvsp[0]); } -#line 5718 "parser.tab.c" - break; - - case 317: -#line 975 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5724 "parser.tab.c" - break; - - case 318: -#line 979 "parser-lalr.y" - { yyval = mk_node("BindByRef", 1, mk_atom("MutImmutable")); } -#line 5730 "parser.tab.c" - break; - - case 319: -#line 980 "parser-lalr.y" - { yyval = mk_node("BindByRef", 1, mk_atom("MutMutable")); } -#line 5736 "parser.tab.c" - break; - - case 320: -#line 981 "parser-lalr.y" - { yyval = mk_node("BindByValue", 1, mk_atom("MutMutable")); } -#line 5742 "parser.tab.c" - break; - - case 321: -#line 985 "parser-lalr.y" - { yyval = mk_node("PatLit", 1, yyvsp[0]); } -#line 5748 "parser.tab.c" - break; - - case 322: -#line 986 "parser-lalr.y" - { yyval = mk_node("PatLit", 1, yyvsp[0]); } -#line 5754 "parser.tab.c" - break; - - case 323: -#line 987 "parser-lalr.y" - { yyval = mk_node("PatLit", 1, yyvsp[0]); } -#line 5760 "parser.tab.c" - break; - - case 324: -#line 991 "parser-lalr.y" - { yyval = mk_node("PatField", 1, yyvsp[0]); } -#line 5766 "parser.tab.c" - break; - - case 325: -#line 992 "parser-lalr.y" - { yyval = mk_node("PatField", 2, yyvsp[-1], yyvsp[0]); } -#line 5772 "parser.tab.c" - break; - - case 326: -#line 993 "parser-lalr.y" - { yyval = mk_node("PatField", 2, mk_atom("box"), yyvsp[0]); } -#line 5778 "parser.tab.c" - break; - - case 327: -#line 994 "parser-lalr.y" - { yyval = mk_node("PatField", 3, mk_atom("box"), yyvsp[-1], yyvsp[0]); } -#line 5784 "parser.tab.c" - break; - - case 328: -#line 995 "parser-lalr.y" - { yyval = mk_node("PatField", 2, yyvsp[-2], yyvsp[0]); } -#line 5790 "parser.tab.c" - break; - - case 329: -#line 996 "parser-lalr.y" - { yyval = mk_node("PatField", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 5796 "parser.tab.c" - break; - - case 330: -#line 997 "parser-lalr.y" - { yyval = mk_node("PatField", 2, mk_atom(yytext), yyvsp[0]); } -#line 5802 "parser.tab.c" - break; - - case 331: -#line 1001 "parser-lalr.y" - { yyval = mk_node("PatFields", 1, yyvsp[0]); } -#line 5808 "parser.tab.c" - break; - - case 332: -#line 1002 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5814 "parser.tab.c" - break; - - case 333: -#line 1006 "parser-lalr.y" - { yyval = mk_node("PatStruct", 2, yyvsp[0], mk_atom("false")); } -#line 5820 "parser.tab.c" - break; - - case 334: -#line 1007 "parser-lalr.y" - { yyval = mk_node("PatStruct", 2, yyvsp[-1], mk_atom("false")); } -#line 5826 "parser.tab.c" - break; - - case 335: -#line 1008 "parser-lalr.y" - { yyval = mk_node("PatStruct", 2, yyvsp[-2], mk_atom("true")); } -#line 5832 "parser.tab.c" - break; - - case 336: -#line 1009 "parser-lalr.y" - { yyval = mk_node("PatStruct", 1, mk_atom("true")); } -#line 5838 "parser.tab.c" - break; - - case 337: -#line 1010 "parser-lalr.y" - { yyval = mk_node("PatStruct", 1, mk_none()); } -#line 5844 "parser.tab.c" - break; - - case 338: -#line 1014 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[0], mk_none()); } -#line 5850 "parser.tab.c" - break; - - case 339: -#line 1015 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-1], mk_none()); } -#line 5856 "parser.tab.c" - break; - - case 340: -#line 1016 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-1], mk_none()); } -#line 5862 "parser.tab.c" - break; - - case 341: -#line 1017 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-2], mk_none()); } -#line 5868 "parser.tab.c" - break; - - case 342: -#line 1018 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-3], yyvsp[0]); } -#line 5874 "parser.tab.c" - break; - - case 343: -#line 1019 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-4], yyvsp[-1]); } -#line 5880 "parser.tab.c" - break; - - case 344: -#line 1020 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-4], yyvsp[0]); } -#line 5886 "parser.tab.c" - break; - - case 345: -#line 1021 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, yyvsp[-5], yyvsp[-1]); } -#line 5892 "parser.tab.c" - break; - - case 346: -#line 1022 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, mk_none(), yyvsp[0]); } -#line 5898 "parser.tab.c" - break; - - case 347: -#line 1023 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, mk_none(), yyvsp[-1]); } -#line 5904 "parser.tab.c" - break; - - case 348: -#line 1024 "parser-lalr.y" - { yyval = mk_node("PatTup", 2, mk_none(), mk_none()); } -#line 5910 "parser.tab.c" - break; - - case 349: -#line 1028 "parser-lalr.y" - { yyval = mk_node("PatTupElts", 1, yyvsp[0]); } -#line 5916 "parser.tab.c" - break; - - case 350: -#line 1029 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 5922 "parser.tab.c" - break; - - case 351: -#line 1033 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[0], mk_none()); } -#line 5928 "parser.tab.c" - break; - - case 352: -#line 1034 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-1], mk_none()); } -#line 5934 "parser.tab.c" - break; - - case 353: -#line 1035 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-1], mk_none()); } -#line 5940 "parser.tab.c" - break; - - case 354: -#line 1036 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-2], mk_none()); } -#line 5946 "parser.tab.c" - break; - - case 355: -#line 1037 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-3], yyvsp[0]); } -#line 5952 "parser.tab.c" - break; - - case 356: -#line 1038 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-4], yyvsp[-1]); } -#line 5958 "parser.tab.c" - break; - - case 357: -#line 1039 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-4], yyvsp[0]); } -#line 5964 "parser.tab.c" - break; - - case 358: -#line 1040 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, yyvsp[-5], yyvsp[-1]); } -#line 5970 "parser.tab.c" - break; - - case 359: -#line 1041 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, mk_none(), yyvsp[0]); } -#line 5976 "parser.tab.c" - break; - - case 360: -#line 1042 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, mk_none(), yyvsp[-1]); } -#line 5982 "parser.tab.c" - break; - - case 361: -#line 1043 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, mk_none(), mk_none()); } -#line 5988 "parser.tab.c" - break; - - case 362: -#line 1044 "parser-lalr.y" - { yyval = mk_node("PatVec", 2, mk_none(), mk_none()); } -#line 5994 "parser.tab.c" - break; - - case 363: -#line 1048 "parser-lalr.y" - { yyval = mk_node("PatVecElts", 1, yyvsp[0]); } -#line 6000 "parser.tab.c" - break; - - case 364: -#line 1049 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6006 "parser.tab.c" - break; - - case 367: -#line 1059 "parser-lalr.y" - { yyval = mk_node("TyQualifiedPath", 3, yyvsp[-4], yyvsp[-3], yyvsp[0]); } -#line 6012 "parser.tab.c" - break; - - case 368: -#line 1060 "parser-lalr.y" - { yyval = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, yyvsp[-8], yyvsp[-7], yyvsp[-4]), yyvsp[-3], yyvsp[0]); } -#line 6018 "parser.tab.c" - break; - - case 369: -#line 1061 "parser-lalr.y" - { yyval = mk_node("TyTup", 1, yyvsp[-1]); } -#line 6024 "parser.tab.c" - break; - - case 370: -#line 1062 "parser-lalr.y" - { yyval = mk_node("TyTup", 1, yyvsp[-2]); } -#line 6030 "parser.tab.c" - break; - - case 371: -#line 1063 "parser-lalr.y" - { yyval = mk_atom("TyNil"); } -#line 6036 "parser.tab.c" - break; - - case 372: -#line 1067 "parser-lalr.y" - { yyval = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), yyvsp[0]); } -#line 6042 "parser.tab.c" - break; - - case 373: -#line 1068 "parser-lalr.y" - { yyval = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), yyvsp[0]); } -#line 6048 "parser.tab.c" - break; - - case 374: -#line 1069 "parser-lalr.y" - { yyval = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), yyvsp[0]); } -#line 6054 "parser.tab.c" - break; - - case 375: -#line 1070 "parser-lalr.y" - { yyval = mk_node("TyMacro", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6060 "parser.tab.c" - break; - - case 376: -#line 1071 "parser-lalr.y" - { yyval = mk_node("TyMacro", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6066 "parser.tab.c" - break; - - case 377: -#line 1072 "parser-lalr.y" - { yyval = mk_node("TyBox", 1, yyvsp[0]); } -#line 6072 "parser.tab.c" - break; - - case 378: -#line 1073 "parser-lalr.y" - { yyval = mk_node("TyPtr", 2, yyvsp[-1], yyvsp[0]); } -#line 6078 "parser.tab.c" - break; - - case 379: -#line 1074 "parser-lalr.y" - { yyval = mk_node("TyRptr", 2, mk_atom("MutImmutable"), yyvsp[0]); } -#line 6084 "parser.tab.c" - break; - - case 380: -#line 1075 "parser-lalr.y" - { yyval = mk_node("TyRptr", 2, mk_atom("MutMutable"), yyvsp[0]); } -#line 6090 "parser.tab.c" - break; - - case 381: -#line 1076 "parser-lalr.y" - { yyval = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), yyvsp[0])); } -#line 6096 "parser.tab.c" - break; - - case 382: -#line 1077 "parser-lalr.y" - { yyval = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), yyvsp[0])); } -#line 6102 "parser.tab.c" - break; - - case 383: -#line 1078 "parser-lalr.y" - { yyval = mk_node("TyRptr", 3, yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 6108 "parser.tab.c" - break; - - case 384: -#line 1079 "parser-lalr.y" - { yyval = mk_node("TyRptr", 1, mk_node("TyRptr", 3, yyvsp[-2], yyvsp[-1], yyvsp[0])); } -#line 6114 "parser.tab.c" - break; - - case 385: -#line 1080 "parser-lalr.y" - { yyval = mk_node("TyVec", 1, yyvsp[-1]); } -#line 6120 "parser.tab.c" - break; - - case 386: -#line 1081 "parser-lalr.y" - { yyval = mk_node("TyFixedLengthVec", 2, yyvsp[-4], yyvsp[-1]); } -#line 6126 "parser.tab.c" - break; - - case 387: -#line 1082 "parser-lalr.y" - { yyval = mk_node("TyFixedLengthVec", 2, yyvsp[-3], yyvsp[-1]); } -#line 6132 "parser.tab.c" - break; - - case 388: -#line 1083 "parser-lalr.y" - { yyval = mk_node("TyTypeof", 1, yyvsp[-1]); } -#line 6138 "parser.tab.c" - break; - - case 389: -#line 1084 "parser-lalr.y" - { yyval = mk_atom("TyInfer"); } -#line 6144 "parser.tab.c" - break; - - case 392: -#line 1090 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6150 "parser.tab.c" - break; - - case 393: -#line 1091 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6156 "parser.tab.c" - break; - - case 394: -#line 1092 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6162 "parser.tab.c" - break; - - case 395: -#line 1093 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6168 "parser.tab.c" - break; - - case 396: -#line 1097 "parser-lalr.y" - { yyval = mk_node("TyFnDecl", 3, yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 6174 "parser.tab.c" - break; - - case 397: -#line 1101 "parser-lalr.y" - { yyval = mk_node("TyClosure", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6180 "parser.tab.c" - break; - - case 398: -#line 1102 "parser-lalr.y" - { yyval = mk_node("TyClosure", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6186 "parser.tab.c" - break; - - case 399: -#line 1103 "parser-lalr.y" - { yyval = mk_node("TyClosure", 2, yyvsp[-1], yyvsp[0]); } -#line 6192 "parser.tab.c" - break; - - case 400: -#line 1104 "parser-lalr.y" - { yyval = mk_node("TyClosure", 2, yyvsp[-1], yyvsp[0]); } -#line 6198 "parser.tab.c" - break; - - case 401: -#line 1108 "parser-lalr.y" - { yyval = mk_node("ForInType", 2, yyvsp[-2], yyvsp[0]); } -#line 6204 "parser.tab.c" - break; - - case 405: -#line 1118 "parser-lalr.y" - { yyval = mk_atom("MutMutable"); } -#line 6210 "parser.tab.c" - break; - - case 406: -#line 1119 "parser-lalr.y" - { yyval = mk_atom("MutImmutable"); } -#line 6216 "parser.tab.c" - break; - - case 407: -#line 1123 "parser-lalr.y" - { yyval = mk_atom("MutMutable"); } -#line 6222 "parser.tab.c" - break; - - case 408: -#line 1124 "parser-lalr.y" - { yyval = mk_atom("MutImmutable"); } -#line 6228 "parser.tab.c" - break; - - case 409: -#line 1125 "parser-lalr.y" - { yyval = mk_atom("MutImmutable"); } -#line 6234 "parser.tab.c" - break; - - case 410: -#line 1130 "parser-lalr.y" - { - yyval = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, yyvsp[-1])), yyvsp[0]); -} -#line 6242 "parser.tab.c" - break; - - case 411: -#line 1134 "parser-lalr.y" - { - yyval = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, yyvsp[-3], yyvsp[-1]), yyvsp[0]); -} -#line 6250 "parser.tab.c" - break; - - case 412: -#line 1140 "parser-lalr.y" - { yyval = mk_node("TyQualifiedPath", 3, yyvsp[-5], yyvsp[-3], yyvsp[0]); } -#line 6256 "parser.tab.c" - break; - - case 413: -#line 1141 "parser-lalr.y" - { yyval = mk_node("TyQualifiedPath", 3, yyvsp[-7], yyvsp[-5], yyvsp[-2]); } -#line 6262 "parser.tab.c" - break; - - case 416: -#line 1147 "parser-lalr.y" - { yyval = mk_none(); } -#line 6268 "parser.tab.c" - break; - - case 417: -#line 1151 "parser-lalr.y" - { yyval = mk_node("TySums", 1, yyvsp[0]); } -#line 6274 "parser.tab.c" - break; - - case 418: -#line 1152 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6280 "parser.tab.c" - break; - - case 419: -#line 1156 "parser-lalr.y" - { yyval = mk_node("TySum", 1, yyvsp[0]); } -#line 6286 "parser.tab.c" - break; - - case 420: -#line 1157 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6292 "parser.tab.c" - break; - - case 423: -#line 1166 "parser-lalr.y" - { yyval = mk_node("TySum", 1, yyvsp[0]); } -#line 6298 "parser.tab.c" - break; - - case 424: -#line 1167 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6304 "parser.tab.c" - break; - - case 427: -#line 1176 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6310 "parser.tab.c" - break; - - case 428: -#line 1177 "parser-lalr.y" - { yyval = mk_none(); } -#line 6316 "parser.tab.c" - break; - - case 430: -#line 1182 "parser-lalr.y" - { yyval = mk_none(); } -#line 6322 "parser.tab.c" - break; - - case 432: -#line 1187 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6328 "parser.tab.c" - break; - - case 433: -#line 1191 "parser-lalr.y" - { yyval = mk_node("PolyBound", 2, yyvsp[-2], yyvsp[0]); } -#line 6334 "parser.tab.c" - break; - - case 435: -#line 1193 "parser-lalr.y" - { yyval = mk_node("PolyBound", 2, yyvsp[-2], yyvsp[0]); } -#line 6340 "parser.tab.c" - break; - - case 436: -#line 1194 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6346 "parser.tab.c" - break; - - case 437: -#line 1198 "parser-lalr.y" - { yyval = mk_node("Bindings", 1, yyvsp[0]); } -#line 6352 "parser.tab.c" - break; - - case 438: -#line 1199 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6358 "parser.tab.c" - break; - - case 439: -#line 1203 "parser-lalr.y" - { mk_node("Binding", 2, yyvsp[-2], yyvsp[0]); } -#line 6364 "parser.tab.c" - break; - - case 440: -#line 1207 "parser-lalr.y" - { yyval = mk_node("TyParam", 3, yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 6370 "parser.tab.c" - break; - - case 441: -#line 1208 "parser-lalr.y" - { yyval = mk_node("TyParam", 4, yyvsp[-4], yyvsp[-2], yyvsp[-1], yyvsp[0]); } -#line 6376 "parser.tab.c" - break; - - case 442: -#line 1213 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6382 "parser.tab.c" - break; - - case 443: -#line 1214 "parser-lalr.y" - { yyval = mk_none(); } -#line 6388 "parser.tab.c" - break; - - case 444: -#line 1218 "parser-lalr.y" - { yyval = mk_node("bounds", 1, yyvsp[0]); } -#line 6394 "parser.tab.c" - break; - - case 445: -#line 1219 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6400 "parser.tab.c" - break; - - case 448: -#line 1229 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6406 "parser.tab.c" - break; - - case 449: -#line 1230 "parser-lalr.y" - { yyval = mk_none(); } -#line 6412 "parser.tab.c" - break; - - case 450: -#line 1234 "parser-lalr.y" - { yyval = mk_node("ltbounds", 1, yyvsp[0]); } -#line 6418 "parser.tab.c" - break; - - case 451: -#line 1235 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6424 "parser.tab.c" - break; - - case 452: -#line 1239 "parser-lalr.y" - { yyval = mk_node("TyDefault", 1, yyvsp[0]); } -#line 6430 "parser.tab.c" - break; - - case 453: -#line 1240 "parser-lalr.y" - { yyval = mk_none(); } -#line 6436 "parser.tab.c" - break; - - case 456: -#line 1246 "parser-lalr.y" - { yyval = mk_none(); } -#line 6442 "parser.tab.c" - break; - - case 457: -#line 1250 "parser-lalr.y" - { yyval = mk_node("Lifetimes", 1, yyvsp[0]); } -#line 6448 "parser.tab.c" - break; - - case 458: -#line 1251 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6454 "parser.tab.c" - break; - - case 459: -#line 1255 "parser-lalr.y" - { yyval = mk_node("lifetime", 2, mk_atom(yytext), yyvsp[0]); } -#line 6460 "parser.tab.c" - break; - - case 460: -#line 1256 "parser-lalr.y" - { yyval = mk_atom("static_lifetime"); } -#line 6466 "parser.tab.c" - break; - - case 461: -#line 1260 "parser-lalr.y" - { yyval = mk_node("lifetime", 1, mk_atom(yytext)); } -#line 6472 "parser.tab.c" - break; - - case 462: -#line 1261 "parser-lalr.y" - { yyval = mk_atom("static_lifetime"); } -#line 6478 "parser.tab.c" - break; - - case 464: -#line 1266 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6484 "parser.tab.c" - break; - - case 465: -#line 1274 "parser-lalr.y" - { yyval = mk_node("ExprBlock", 2, yyvsp[-2], yyvsp[-1]); } -#line 6490 "parser.tab.c" - break; - - case 466: -#line 1278 "parser-lalr.y" - { yyval = mk_node("ExprBlock", 1, yyvsp[-1]); } -#line 6496 "parser.tab.c" - break; - - case 468: -#line 1283 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 6502 "parser.tab.c" - break; - - case 470: -#line 1285 "parser-lalr.y" - { yyval = mk_none(); } -#line 6508 "parser.tab.c" - break; - - case 471: -#line 1313 "parser-lalr.y" - { yyval = mk_node("stmts", 1, yyvsp[0]); } -#line 6514 "parser.tab.c" - break; - - case 472: -#line 1314 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 6520 "parser.tab.c" - break; - - case 473: -#line 1318 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6526 "parser.tab.c" - break; - - case 475: -#line 1320 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6532 "parser.tab.c" - break; - - case 476: -#line 1321 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6538 "parser.tab.c" - break; - - case 477: -#line 1322 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6544 "parser.tab.c" - break; - - case 479: -#line 1324 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6550 "parser.tab.c" - break; - - case 481: -#line 1326 "parser-lalr.y" - { yyval = yyvsp[-1]; } -#line 6556 "parser.tab.c" - break; - - case 482: -#line 1327 "parser-lalr.y" - { yyval = mk_none(); } -#line 6562 "parser.tab.c" - break; - - case 485: -#line 1333 "parser-lalr.y" - { yyval = mk_none(); } -#line 6568 "parser.tab.c" - break; - - case 487: -#line 1338 "parser-lalr.y" - { yyval = mk_none(); } -#line 6574 "parser.tab.c" - break; - - case 488: -#line 1342 "parser-lalr.y" - { yyval = mk_node("exprs", 1, yyvsp[0]); } -#line 6580 "parser.tab.c" - break; - - case 489: -#line 1343 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6586 "parser.tab.c" - break; - - case 491: -#line 1348 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 6592 "parser.tab.c" - break; - - case 492: -#line 1349 "parser-lalr.y" - { yyval = mk_node("SelfPath", 1, yyvsp[0]); } -#line 6598 "parser.tab.c" - break; - - case 493: -#line 1358 "parser-lalr.y" - { yyval = mk_node("components", 1, yyvsp[0]); } -#line 6604 "parser.tab.c" - break; - - case 494: -#line 1359 "parser-lalr.y" - { yyval = mk_atom("Super"); } -#line 6610 "parser.tab.c" - break; - - case 495: -#line 1360 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6616 "parser.tab.c" - break; - - case 496: -#line 1361 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, mk_atom("Super")); } -#line 6622 "parser.tab.c" - break; - - case 497: -#line 1362 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 6628 "parser.tab.c" - break; - - case 498: -#line 1367 "parser-lalr.y" - { yyval = mk_node("MacroExpr", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6634 "parser.tab.c" - break; - - case 499: -#line 1368 "parser-lalr.y" - { yyval = mk_node("MacroExpr", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 6640 "parser.tab.c" - break; - - case 500: -#line 1372 "parser-lalr.y" - { yyval = mk_node("ExprLit", 1, yyvsp[0]); } -#line 6646 "parser.tab.c" - break; - - case 501: -#line 1374 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, yyvsp[0]); } -#line 6652 "parser.tab.c" - break; - - case 502: -#line 1375 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -#line 6658 "parser.tab.c" - break; - - case 503: -#line 1376 "parser-lalr.y" - { yyval = mk_node("ExprMac", 1, yyvsp[0]); } -#line 6664 "parser.tab.c" - break; - - case 504: -#line 1377 "parser-lalr.y" - { yyval = mk_node("ExprStruct", 2, yyvsp[-3], yyvsp[-1]); } -#line 6670 "parser.tab.c" - break; - - case 505: -#line 1378 "parser-lalr.y" - { yyval = mk_node("ExprTry", 1, yyvsp[-1]); } -#line 6676 "parser.tab.c" - break; - - case 506: -#line 1379 "parser-lalr.y" - { yyval = mk_node("ExprField", 2, yyvsp[-2], yyvsp[0]); } -#line 6682 "parser.tab.c" - break; - - case 507: -#line 1380 "parser-lalr.y" - { yyval = mk_node("ExprTupleIndex", 1, yyvsp[-2]); } -#line 6688 "parser.tab.c" - break; - - case 508: -#line 1381 "parser-lalr.y" - { yyval = mk_node("ExprIndex", 2, yyvsp[-3], yyvsp[-1]); } -#line 6694 "parser.tab.c" - break; - - case 509: -#line 1382 "parser-lalr.y" - { yyval = mk_node("ExprCall", 2, yyvsp[-3], yyvsp[-1]); } -#line 6700 "parser.tab.c" - break; - - case 510: -#line 1383 "parser-lalr.y" - { yyval = mk_node("ExprVec", 1, yyvsp[-1]); } -#line 6706 "parser.tab.c" - break; - - case 511: -#line 1384 "parser-lalr.y" - { yyval = mk_node("ExprParen", 1, yyvsp[-1]); } -#line 6712 "parser.tab.c" - break; - - case 512: -#line 1385 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 0); } -#line 6718 "parser.tab.c" - break; - - case 513: -#line 1386 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 1, yyvsp[0]); } -#line 6724 "parser.tab.c" - break; - - case 514: -#line 1387 "parser-lalr.y" - { yyval = mk_node("ExprRet", 0); } -#line 6730 "parser.tab.c" - break; - - case 515: -#line 1388 "parser-lalr.y" - { yyval = mk_node("ExprRet", 1, yyvsp[0]); } -#line 6736 "parser.tab.c" - break; - - case 516: -#line 1389 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 0); } -#line 6742 "parser.tab.c" - break; - - case 517: -#line 1390 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 1, yyvsp[0]); } -#line 6748 "parser.tab.c" - break; - - case 518: -#line 1391 "parser-lalr.y" - { yyval = mk_node("ExprYield", 0); } -#line 6754 "parser.tab.c" - break; - - case 519: -#line 1392 "parser-lalr.y" - { yyval = mk_node("ExprYield", 1, yyvsp[0]); } -#line 6760 "parser.tab.c" - break; - - case 520: -#line 1393 "parser-lalr.y" - { yyval = mk_node("ExprAssign", 2, yyvsp[-2], yyvsp[0]); } -#line 6766 "parser.tab.c" - break; - - case 521: -#line 1394 "parser-lalr.y" - { yyval = mk_node("ExprAssignShl", 2, yyvsp[-2], yyvsp[0]); } -#line 6772 "parser.tab.c" - break; - - case 522: -#line 1395 "parser-lalr.y" - { yyval = mk_node("ExprAssignShr", 2, yyvsp[-2], yyvsp[0]); } -#line 6778 "parser.tab.c" - break; - - case 523: -#line 1396 "parser-lalr.y" - { yyval = mk_node("ExprAssignSub", 2, yyvsp[-2], yyvsp[0]); } -#line 6784 "parser.tab.c" - break; - - case 524: -#line 1397 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitAnd", 2, yyvsp[-2], yyvsp[0]); } -#line 6790 "parser.tab.c" - break; - - case 525: -#line 1398 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitOr", 2, yyvsp[-2], yyvsp[0]); } -#line 6796 "parser.tab.c" - break; - - case 526: -#line 1399 "parser-lalr.y" - { yyval = mk_node("ExprAssignAdd", 2, yyvsp[-2], yyvsp[0]); } -#line 6802 "parser.tab.c" - break; - - case 527: -#line 1400 "parser-lalr.y" - { yyval = mk_node("ExprAssignMul", 2, yyvsp[-2], yyvsp[0]); } -#line 6808 "parser.tab.c" - break; - - case 528: -#line 1401 "parser-lalr.y" - { yyval = mk_node("ExprAssignDiv", 2, yyvsp[-2], yyvsp[0]); } -#line 6814 "parser.tab.c" - break; - - case 529: -#line 1402 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitXor", 2, yyvsp[-2], yyvsp[0]); } -#line 6820 "parser.tab.c" - break; - - case 530: -#line 1403 "parser-lalr.y" - { yyval = mk_node("ExprAssignRem", 2, yyvsp[-2], yyvsp[0]); } -#line 6826 "parser.tab.c" - break; - - case 531: -#line 1404 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiOr"), yyvsp[-2], yyvsp[0]); } -#line 6832 "parser.tab.c" - break; - - case 532: -#line 1405 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAnd"), yyvsp[-2], yyvsp[0]); } -#line 6838 "parser.tab.c" - break; - - case 533: -#line 1406 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiEq"), yyvsp[-2], yyvsp[0]); } -#line 6844 "parser.tab.c" - break; - - case 534: -#line 1407 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiNe"), yyvsp[-2], yyvsp[0]); } -#line 6850 "parser.tab.c" - break; - - case 535: -#line 1408 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLt"), yyvsp[-2], yyvsp[0]); } -#line 6856 "parser.tab.c" - break; - - case 536: -#line 1409 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGt"), yyvsp[-2], yyvsp[0]); } -#line 6862 "parser.tab.c" - break; - - case 537: -#line 1410 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLe"), yyvsp[-2], yyvsp[0]); } -#line 6868 "parser.tab.c" - break; - - case 538: -#line 1411 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGe"), yyvsp[-2], yyvsp[0]); } -#line 6874 "parser.tab.c" - break; - - case 539: -#line 1412 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), yyvsp[-2], yyvsp[0]); } -#line 6880 "parser.tab.c" - break; - - case 540: -#line 1413 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), yyvsp[-2], yyvsp[0]); } -#line 6886 "parser.tab.c" - break; - - case 541: -#line 1414 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), yyvsp[-2], yyvsp[0]); } -#line 6892 "parser.tab.c" - break; - - case 542: -#line 1415 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShl"), yyvsp[-2], yyvsp[0]); } -#line 6898 "parser.tab.c" - break; - - case 543: -#line 1416 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShr"), yyvsp[-2], yyvsp[0]); } -#line 6904 "parser.tab.c" - break; - - case 544: -#line 1417 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAdd"), yyvsp[-2], yyvsp[0]); } -#line 6910 "parser.tab.c" - break; - - case 545: -#line 1418 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiSub"), yyvsp[-2], yyvsp[0]); } -#line 6916 "parser.tab.c" - break; - - case 546: -#line 1419 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiMul"), yyvsp[-2], yyvsp[0]); } -#line 6922 "parser.tab.c" - break; - - case 547: -#line 1420 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiDiv"), yyvsp[-2], yyvsp[0]); } -#line 6928 "parser.tab.c" - break; - - case 548: -#line 1421 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiRem"), yyvsp[-2], yyvsp[0]); } -#line 6934 "parser.tab.c" - break; - - case 549: -#line 1422 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-1], mk_none()); } -#line 6940 "parser.tab.c" - break; - - case 550: -#line 1423 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-2], yyvsp[0]); } -#line 6946 "parser.tab.c" - break; - - case 551: -#line 1424 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), yyvsp[0]); } -#line 6952 "parser.tab.c" - break; - - case 552: -#line 1425 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), mk_none()); } -#line 6958 "parser.tab.c" - break; - - case 553: -#line 1426 "parser-lalr.y" - { yyval = mk_node("ExprCast", 2, yyvsp[-2], yyvsp[0]); } -#line 6964 "parser.tab.c" - break; - - case 554: -#line 1427 "parser-lalr.y" - { yyval = mk_node("ExprTypeAscr", 2, yyvsp[-2], yyvsp[0]); } -#line 6970 "parser.tab.c" - break; - - case 555: -#line 1428 "parser-lalr.y" - { yyval = mk_node("ExprBox", 1, yyvsp[0]); } -#line 6976 "parser.tab.c" - break; - - case 558: -#line 1434 "parser-lalr.y" - { yyval = mk_node("ExprLit", 1, yyvsp[0]); } -#line 6982 "parser.tab.c" - break; - - case 559: -#line 1436 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, yyvsp[0]); } -#line 6988 "parser.tab.c" - break; - - case 560: -#line 1437 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -#line 6994 "parser.tab.c" - break; - - case 561: -#line 1438 "parser-lalr.y" - { yyval = mk_node("ExprMac", 1, yyvsp[0]); } -#line 7000 "parser.tab.c" - break; - - case 562: -#line 1439 "parser-lalr.y" - { yyval = mk_node("ExprStruct", 2, yyvsp[-3], yyvsp[-1]); } -#line 7006 "parser.tab.c" - break; - - case 563: -#line 1440 "parser-lalr.y" - { yyval = mk_node("ExprTry", 1, yyvsp[-1]); } -#line 7012 "parser.tab.c" - break; - - case 564: -#line 1441 "parser-lalr.y" - { yyval = mk_node("ExprField", 2, yyvsp[-2], yyvsp[0]); } -#line 7018 "parser.tab.c" - break; - - case 565: -#line 1442 "parser-lalr.y" - { yyval = mk_node("ExprTupleIndex", 1, yyvsp[-2]); } -#line 7024 "parser.tab.c" - break; - - case 566: -#line 1443 "parser-lalr.y" - { yyval = mk_node("ExprIndex", 2, yyvsp[-3], yyvsp[-1]); } -#line 7030 "parser.tab.c" - break; - - case 567: -#line 1444 "parser-lalr.y" - { yyval = mk_node("ExprCall", 2, yyvsp[-3], yyvsp[-1]); } -#line 7036 "parser.tab.c" - break; - - case 568: -#line 1445 "parser-lalr.y" - { yyval = mk_node("ExprParen", 1, yyvsp[-1]); } -#line 7042 "parser.tab.c" - break; - - case 569: -#line 1446 "parser-lalr.y" - { yyval = mk_node("ExprVec", 1, yyvsp[-1]); } -#line 7048 "parser.tab.c" - break; - - case 570: -#line 1447 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 0); } -#line 7054 "parser.tab.c" - break; - - case 571: -#line 1448 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 1, yyvsp[0]); } -#line 7060 "parser.tab.c" - break; - - case 572: -#line 1449 "parser-lalr.y" - { yyval = mk_node("ExprRet", 0); } -#line 7066 "parser.tab.c" - break; - - case 573: -#line 1450 "parser-lalr.y" - { yyval = mk_node("ExprRet", 1, yyvsp[0]); } -#line 7072 "parser.tab.c" - break; - - case 574: -#line 1451 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 0); } -#line 7078 "parser.tab.c" - break; - - case 575: -#line 1452 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 1, yyvsp[0]); } -#line 7084 "parser.tab.c" - break; - - case 576: -#line 1453 "parser-lalr.y" - { yyval = mk_node("ExprYield", 0); } -#line 7090 "parser.tab.c" - break; - - case 577: -#line 1454 "parser-lalr.y" - { yyval = mk_node("ExprYield", 1, yyvsp[0]); } -#line 7096 "parser.tab.c" - break; - - case 578: -#line 1455 "parser-lalr.y" - { yyval = mk_node("ExprAssign", 2, yyvsp[-2], yyvsp[0]); } -#line 7102 "parser.tab.c" - break; - - case 579: -#line 1456 "parser-lalr.y" - { yyval = mk_node("ExprAssignShl", 2, yyvsp[-2], yyvsp[0]); } -#line 7108 "parser.tab.c" - break; - - case 580: -#line 1457 "parser-lalr.y" - { yyval = mk_node("ExprAssignShr", 2, yyvsp[-2], yyvsp[0]); } -#line 7114 "parser.tab.c" - break; - - case 581: -#line 1458 "parser-lalr.y" - { yyval = mk_node("ExprAssignSub", 2, yyvsp[-2], yyvsp[0]); } -#line 7120 "parser.tab.c" - break; - - case 582: -#line 1459 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitAnd", 2, yyvsp[-2], yyvsp[0]); } -#line 7126 "parser.tab.c" - break; - - case 583: -#line 1460 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitOr", 2, yyvsp[-2], yyvsp[0]); } -#line 7132 "parser.tab.c" - break; - - case 584: -#line 1461 "parser-lalr.y" - { yyval = mk_node("ExprAssignAdd", 2, yyvsp[-2], yyvsp[0]); } -#line 7138 "parser.tab.c" - break; - - case 585: -#line 1462 "parser-lalr.y" - { yyval = mk_node("ExprAssignMul", 2, yyvsp[-2], yyvsp[0]); } -#line 7144 "parser.tab.c" - break; - - case 586: -#line 1463 "parser-lalr.y" - { yyval = mk_node("ExprAssignDiv", 2, yyvsp[-2], yyvsp[0]); } -#line 7150 "parser.tab.c" - break; - - case 587: -#line 1464 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitXor", 2, yyvsp[-2], yyvsp[0]); } -#line 7156 "parser.tab.c" - break; - - case 588: -#line 1465 "parser-lalr.y" - { yyval = mk_node("ExprAssignRem", 2, yyvsp[-2], yyvsp[0]); } -#line 7162 "parser.tab.c" - break; - - case 589: -#line 1466 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiOr"), yyvsp[-2], yyvsp[0]); } -#line 7168 "parser.tab.c" - break; - - case 590: -#line 1467 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAnd"), yyvsp[-2], yyvsp[0]); } -#line 7174 "parser.tab.c" - break; - - case 591: -#line 1468 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiEq"), yyvsp[-2], yyvsp[0]); } -#line 7180 "parser.tab.c" - break; - - case 592: -#line 1469 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiNe"), yyvsp[-2], yyvsp[0]); } -#line 7186 "parser.tab.c" - break; - - case 593: -#line 1470 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLt"), yyvsp[-2], yyvsp[0]); } -#line 7192 "parser.tab.c" - break; - - case 594: -#line 1471 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGt"), yyvsp[-2], yyvsp[0]); } -#line 7198 "parser.tab.c" - break; - - case 595: -#line 1472 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLe"), yyvsp[-2], yyvsp[0]); } -#line 7204 "parser.tab.c" - break; - - case 596: -#line 1473 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGe"), yyvsp[-2], yyvsp[0]); } -#line 7210 "parser.tab.c" - break; - - case 597: -#line 1474 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), yyvsp[-2], yyvsp[0]); } -#line 7216 "parser.tab.c" - break; - - case 598: -#line 1475 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), yyvsp[-2], yyvsp[0]); } -#line 7222 "parser.tab.c" - break; - - case 599: -#line 1476 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), yyvsp[-2], yyvsp[0]); } -#line 7228 "parser.tab.c" - break; - - case 600: -#line 1477 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShl"), yyvsp[-2], yyvsp[0]); } -#line 7234 "parser.tab.c" - break; - - case 601: -#line 1478 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShr"), yyvsp[-2], yyvsp[0]); } -#line 7240 "parser.tab.c" - break; - - case 602: -#line 1479 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAdd"), yyvsp[-2], yyvsp[0]); } -#line 7246 "parser.tab.c" - break; - - case 603: -#line 1480 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiSub"), yyvsp[-2], yyvsp[0]); } -#line 7252 "parser.tab.c" - break; - - case 604: -#line 1481 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiMul"), yyvsp[-2], yyvsp[0]); } -#line 7258 "parser.tab.c" - break; - - case 605: -#line 1482 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiDiv"), yyvsp[-2], yyvsp[0]); } -#line 7264 "parser.tab.c" - break; - - case 606: -#line 1483 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiRem"), yyvsp[-2], yyvsp[0]); } -#line 7270 "parser.tab.c" - break; - - case 607: -#line 1484 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-1], mk_none()); } -#line 7276 "parser.tab.c" - break; - - case 608: -#line 1485 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-2], yyvsp[0]); } -#line 7282 "parser.tab.c" - break; - - case 609: -#line 1486 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), yyvsp[0]); } -#line 7288 "parser.tab.c" - break; - - case 610: -#line 1487 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), mk_none()); } -#line 7294 "parser.tab.c" - break; - - case 611: -#line 1488 "parser-lalr.y" - { yyval = mk_node("ExprCast", 2, yyvsp[-2], yyvsp[0]); } -#line 7300 "parser.tab.c" - break; - - case 612: -#line 1489 "parser-lalr.y" - { yyval = mk_node("ExprTypeAscr", 2, yyvsp[-2], yyvsp[0]); } -#line 7306 "parser.tab.c" - break; - - case 613: -#line 1490 "parser-lalr.y" - { yyval = mk_node("ExprBox", 1, yyvsp[0]); } -#line 7312 "parser.tab.c" - break; - - case 618: -#line 1498 "parser-lalr.y" - { yyval = mk_node("ExprLit", 1, yyvsp[0]); } -#line 7318 "parser.tab.c" - break; - - case 619: -#line 1500 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, yyvsp[0]); } -#line 7324 "parser.tab.c" - break; - - case 620: -#line 1501 "parser-lalr.y" - { yyval = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -#line 7330 "parser.tab.c" - break; - - case 621: -#line 1502 "parser-lalr.y" - { yyval = mk_node("ExprMac", 1, yyvsp[0]); } -#line 7336 "parser.tab.c" - break; - - case 622: -#line 1503 "parser-lalr.y" - { yyval = mk_node("ExprTry", 1, yyvsp[-1]); } -#line 7342 "parser.tab.c" - break; - - case 623: -#line 1504 "parser-lalr.y" - { yyval = mk_node("ExprField", 2, yyvsp[-2], yyvsp[0]); } -#line 7348 "parser.tab.c" - break; - - case 624: -#line 1505 "parser-lalr.y" - { yyval = mk_node("ExprTupleIndex", 1, yyvsp[-2]); } -#line 7354 "parser.tab.c" - break; - - case 625: -#line 1506 "parser-lalr.y" - { yyval = mk_node("ExprIndex", 2, yyvsp[-3], yyvsp[-1]); } -#line 7360 "parser.tab.c" - break; - - case 626: -#line 1507 "parser-lalr.y" - { yyval = mk_node("ExprCall", 2, yyvsp[-3], yyvsp[-1]); } -#line 7366 "parser.tab.c" - break; - - case 627: -#line 1508 "parser-lalr.y" - { yyval = mk_node("ExprVec", 1, yyvsp[-1]); } -#line 7372 "parser.tab.c" - break; - - case 628: -#line 1509 "parser-lalr.y" - { yyval = mk_node("ExprParen", 1, yyvsp[-1]); } -#line 7378 "parser.tab.c" - break; - - case 629: -#line 1510 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 0); } -#line 7384 "parser.tab.c" - break; - - case 630: -#line 1511 "parser-lalr.y" - { yyval = mk_node("ExprAgain", 1, yyvsp[0]); } -#line 7390 "parser.tab.c" - break; - - case 631: -#line 1512 "parser-lalr.y" - { yyval = mk_node("ExprRet", 0); } -#line 7396 "parser.tab.c" - break; - - case 632: -#line 1513 "parser-lalr.y" - { yyval = mk_node("ExprRet", 1, yyvsp[0]); } -#line 7402 "parser.tab.c" - break; - - case 633: -#line 1514 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 0); } -#line 7408 "parser.tab.c" - break; - - case 634: -#line 1515 "parser-lalr.y" - { yyval = mk_node("ExprBreak", 1, yyvsp[0]); } -#line 7414 "parser.tab.c" - break; - - case 635: -#line 1516 "parser-lalr.y" - { yyval = mk_node("ExprYield", 0); } -#line 7420 "parser.tab.c" - break; - - case 636: -#line 1517 "parser-lalr.y" - { yyval = mk_node("ExprYield", 1, yyvsp[0]); } -#line 7426 "parser.tab.c" - break; - - case 637: -#line 1518 "parser-lalr.y" - { yyval = mk_node("ExprAssign", 2, yyvsp[-2], yyvsp[0]); } -#line 7432 "parser.tab.c" - break; - - case 638: -#line 1519 "parser-lalr.y" - { yyval = mk_node("ExprAssignShl", 2, yyvsp[-2], yyvsp[0]); } -#line 7438 "parser.tab.c" - break; - - case 639: -#line 1520 "parser-lalr.y" - { yyval = mk_node("ExprAssignShr", 2, yyvsp[-2], yyvsp[0]); } -#line 7444 "parser.tab.c" - break; - - case 640: -#line 1521 "parser-lalr.y" - { yyval = mk_node("ExprAssignSub", 2, yyvsp[-2], yyvsp[0]); } -#line 7450 "parser.tab.c" - break; - - case 641: -#line 1522 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitAnd", 2, yyvsp[-2], yyvsp[0]); } -#line 7456 "parser.tab.c" - break; - - case 642: -#line 1523 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitOr", 2, yyvsp[-2], yyvsp[0]); } -#line 7462 "parser.tab.c" - break; - - case 643: -#line 1524 "parser-lalr.y" - { yyval = mk_node("ExprAssignAdd", 2, yyvsp[-2], yyvsp[0]); } -#line 7468 "parser.tab.c" - break; - - case 644: -#line 1525 "parser-lalr.y" - { yyval = mk_node("ExprAssignMul", 2, yyvsp[-2], yyvsp[0]); } -#line 7474 "parser.tab.c" - break; - - case 645: -#line 1526 "parser-lalr.y" - { yyval = mk_node("ExprAssignDiv", 2, yyvsp[-2], yyvsp[0]); } -#line 7480 "parser.tab.c" - break; - - case 646: -#line 1527 "parser-lalr.y" - { yyval = mk_node("ExprAssignBitXor", 2, yyvsp[-2], yyvsp[0]); } -#line 7486 "parser.tab.c" - break; - - case 647: -#line 1528 "parser-lalr.y" - { yyval = mk_node("ExprAssignRem", 2, yyvsp[-2], yyvsp[0]); } -#line 7492 "parser.tab.c" - break; - - case 648: -#line 1529 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiOr"), yyvsp[-2], yyvsp[0]); } -#line 7498 "parser.tab.c" - break; - - case 649: -#line 1530 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAnd"), yyvsp[-2], yyvsp[0]); } -#line 7504 "parser.tab.c" - break; - - case 650: -#line 1531 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiEq"), yyvsp[-2], yyvsp[0]); } -#line 7510 "parser.tab.c" - break; - - case 651: -#line 1532 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiNe"), yyvsp[-2], yyvsp[0]); } -#line 7516 "parser.tab.c" - break; - - case 652: -#line 1533 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLt"), yyvsp[-2], yyvsp[0]); } -#line 7522 "parser.tab.c" - break; - - case 653: -#line 1534 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGt"), yyvsp[-2], yyvsp[0]); } -#line 7528 "parser.tab.c" - break; - - case 654: -#line 1535 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiLe"), yyvsp[-2], yyvsp[0]); } -#line 7534 "parser.tab.c" - break; - - case 655: -#line 1536 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiGe"), yyvsp[-2], yyvsp[0]); } -#line 7540 "parser.tab.c" - break; - - case 656: -#line 1537 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), yyvsp[-2], yyvsp[0]); } -#line 7546 "parser.tab.c" - break; - - case 657: -#line 1538 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), yyvsp[-2], yyvsp[0]); } -#line 7552 "parser.tab.c" - break; - - case 658: -#line 1539 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), yyvsp[-2], yyvsp[0]); } -#line 7558 "parser.tab.c" - break; - - case 659: -#line 1540 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShl"), yyvsp[-2], yyvsp[0]); } -#line 7564 "parser.tab.c" - break; - - case 660: -#line 1541 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiShr"), yyvsp[-2], yyvsp[0]); } -#line 7570 "parser.tab.c" - break; - - case 661: -#line 1542 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiAdd"), yyvsp[-2], yyvsp[0]); } -#line 7576 "parser.tab.c" - break; - - case 662: -#line 1543 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiSub"), yyvsp[-2], yyvsp[0]); } -#line 7582 "parser.tab.c" - break; - - case 663: -#line 1544 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiMul"), yyvsp[-2], yyvsp[0]); } -#line 7588 "parser.tab.c" - break; - - case 664: -#line 1545 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiDiv"), yyvsp[-2], yyvsp[0]); } -#line 7594 "parser.tab.c" - break; - - case 665: -#line 1546 "parser-lalr.y" - { yyval = mk_node("ExprBinary", 3, mk_atom("BiRem"), yyvsp[-2], yyvsp[0]); } -#line 7600 "parser.tab.c" - break; - - case 666: -#line 1547 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-1], mk_none()); } -#line 7606 "parser.tab.c" - break; - - case 667: -#line 1548 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, yyvsp[-2], yyvsp[0]); } -#line 7612 "parser.tab.c" - break; - - case 668: -#line 1549 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), yyvsp[0]); } -#line 7618 "parser.tab.c" - break; - - case 669: -#line 1550 "parser-lalr.y" - { yyval = mk_node("ExprRange", 2, mk_none(), mk_none()); } -#line 7624 "parser.tab.c" - break; - - case 670: -#line 1551 "parser-lalr.y" - { yyval = mk_node("ExprCast", 2, yyvsp[-2], yyvsp[0]); } -#line 7630 "parser.tab.c" - break; - - case 671: -#line 1552 "parser-lalr.y" - { yyval = mk_node("ExprTypeAscr", 2, yyvsp[-2], yyvsp[0]); } -#line 7636 "parser.tab.c" - break; - - case 672: -#line 1553 "parser-lalr.y" - { yyval = mk_node("ExprBox", 1, yyvsp[0]); } -#line 7642 "parser.tab.c" - break; - - case 677: -#line 1561 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnNeg"), yyvsp[0]); } -#line 7648 "parser.tab.c" - break; - - case 678: -#line 1562 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnNot"), yyvsp[0]); } -#line 7654 "parser.tab.c" - break; - - case 679: -#line 1563 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnDeref"), yyvsp[0]); } -#line 7660 "parser.tab.c" - break; - - case 680: -#line 1564 "parser-lalr.y" - { yyval = mk_node("ExprAddrOf", 2, yyvsp[-1], yyvsp[0]); } -#line 7666 "parser.tab.c" - break; - - case 681: -#line 1565 "parser-lalr.y" - { yyval = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, yyvsp[-1], yyvsp[0])); } -#line 7672 "parser.tab.c" - break; - - case 683: -#line 1567 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 7678 "parser.tab.c" - break; - - case 684: -#line 1571 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnNeg"), yyvsp[0]); } -#line 7684 "parser.tab.c" - break; - - case 685: -#line 1572 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnNot"), yyvsp[0]); } -#line 7690 "parser.tab.c" - break; - - case 686: -#line 1573 "parser-lalr.y" - { yyval = mk_node("ExprUnary", 2, mk_atom("UnDeref"), yyvsp[0]); } -#line 7696 "parser.tab.c" - break; - - case 687: -#line 1574 "parser-lalr.y" - { yyval = mk_node("ExprAddrOf", 2, yyvsp[-1], yyvsp[0]); } -#line 7702 "parser.tab.c" - break; - - case 688: -#line 1575 "parser-lalr.y" - { yyval = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, yyvsp[-1], yyvsp[0])); } -#line 7708 "parser.tab.c" - break; - - case 690: -#line 1577 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 7714 "parser.tab.c" - break; - - case 691: -#line 1582 "parser-lalr.y" - { - yyval = mk_node("ExprQualifiedPath", 4, yyvsp[-5], yyvsp[-4], yyvsp[-1], yyvsp[0]); -} -#line 7722 "parser.tab.c" - break; - - case 692: -#line 1586 "parser-lalr.y" - { - yyval = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, yyvsp[-8], yyvsp[-7], yyvsp[-4]), yyvsp[-3], yyvsp[0]); -} -#line 7730 "parser.tab.c" - break; - - case 693: -#line 1590 "parser-lalr.y" - { - yyval = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, yyvsp[-9], yyvsp[-8], yyvsp[-5], yyvsp[-4]), yyvsp[-3], yyvsp[0]); -} -#line 7738 "parser.tab.c" - break; - - case 694: -#line 1594 "parser-lalr.y" - { - yyval = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, yyvsp[-9], yyvsp[-8], yyvsp[-5]), yyvsp[-4], yyvsp[-1], yyvsp[0]); -} -#line 7746 "parser.tab.c" - break; - - case 695: -#line 1598 "parser-lalr.y" - { - yyval = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, yyvsp[-10], yyvsp[-9], yyvsp[-6], yyvsp[-5]), yyvsp[-4], yyvsp[-1], yyvsp[0]); -} -#line 7754 "parser.tab.c" - break; - - case 696: -#line 1603 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 7760 "parser.tab.c" - break; - - case 697: -#line 1604 "parser-lalr.y" - { yyval = mk_none(); } -#line 7766 "parser.tab.c" - break; - - case 698: -#line 1608 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 7772 "parser.tab.c" - break; - - case 699: -#line 1609 "parser-lalr.y" - { yyval = mk_none(); } -#line 7778 "parser.tab.c" - break; - - case 700: -#line 1614 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, mk_none(), yyvsp[-1], yyvsp[0]); } -#line 7784 "parser.tab.c" - break; - - case 701: -#line 1616 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, mk_none(), yyvsp[-1], yyvsp[0]); } -#line 7790 "parser.tab.c" - break; - - case 702: -#line 1618 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 7796 "parser.tab.c" - break; - - case 703: -#line 1620 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-2], mk_none(), yyvsp[0]); } -#line 7802 "parser.tab.c" - break; - - case 704: -#line 1625 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, mk_none(), yyvsp[-1], yyvsp[0]); } -#line 7808 "parser.tab.c" - break; - - case 705: -#line 1627 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 7814 "parser.tab.c" - break; - - case 706: -#line 1629 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-2], mk_none(), yyvsp[0]); } -#line 7820 "parser.tab.c" - break; - - case 707: -#line 1634 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 2, mk_none(), yyvsp[0]); } -#line 7826 "parser.tab.c" - break; - - case 708: -#line 1636 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, mk_none(), yyvsp[-1], yyvsp[0]); } -#line 7832 "parser.tab.c" - break; - - case 709: -#line 1638 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 2, yyvsp[-2], yyvsp[0]); } -#line 7838 "parser.tab.c" - break; - - case 710: -#line 1640 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-2], mk_none(), yyvsp[0]); } -#line 7844 "parser.tab.c" - break; - - case 711: -#line 1645 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, mk_none(), yyvsp[-1], yyvsp[0]); } -#line 7850 "parser.tab.c" - break; - - case 712: -#line 1647 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 7856 "parser.tab.c" - break; - - case 713: -#line 1649 "parser-lalr.y" - { yyval = mk_node("ExprFnBlock", 3, yyvsp[-2], mk_none(), yyvsp[0]); } -#line 7862 "parser.tab.c" - break; - - case 715: -#line 1654 "parser-lalr.y" - { yyval = mk_node("VecRepeat", 2, yyvsp[-2], yyvsp[0]); } -#line 7868 "parser.tab.c" - break; - - case 718: -#line 1660 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 7874 "parser.tab.c" - break; - - case 719: -#line 1661 "parser-lalr.y" - { yyval = mk_none(); } -#line 7880 "parser.tab.c" - break; - - case 722: -#line 1667 "parser-lalr.y" - { yyval = mk_none(); } -#line 7886 "parser.tab.c" - break; - - case 723: -#line 1671 "parser-lalr.y" - { yyval = mk_node("FieldInits", 1, yyvsp[0]); } -#line 7892 "parser.tab.c" - break; - - case 724: -#line 1672 "parser-lalr.y" - { yyval = ext_node(yyvsp[-2], 1, yyvsp[0]); } -#line 7898 "parser.tab.c" - break; - - case 725: -#line 1676 "parser-lalr.y" - { yyval = mk_node("FieldInit", 1, yyvsp[0]); } -#line 7904 "parser.tab.c" - break; - - case 726: -#line 1677 "parser-lalr.y" - { yyval = mk_node("FieldInit", 2, yyvsp[-2], yyvsp[0]); } -#line 7910 "parser.tab.c" - break; - - case 727: -#line 1678 "parser-lalr.y" - { yyval = mk_node("FieldInit", 2, mk_atom(yytext), yyvsp[0]); } -#line 7916 "parser.tab.c" - break; - - case 728: -#line 1682 "parser-lalr.y" - { yyval = mk_node("DefaultFieldInit", 1, yyvsp[0]); } -#line 7922 "parser.tab.c" - break; - - case 736: -#line 1693 "parser-lalr.y" - { yyval = mk_node("UnsafeBlock", 1, yyvsp[0]); } -#line 7928 "parser.tab.c" - break; - - case 737: -#line 1694 "parser-lalr.y" - { yyval = mk_node("Macro", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 7934 "parser.tab.c" - break; - - case 740: -#line 1703 "parser-lalr.y" - { yyval = mk_node("ExprField", 2, yyvsp[-2], yyvsp[0]); } -#line 7940 "parser.tab.c" - break; - - case 741: -#line 1704 "parser-lalr.y" - { yyval = mk_node("ExprField", 2, yyvsp[-2], yyvsp[0]); } -#line 7946 "parser.tab.c" - break; - - case 742: -#line 1705 "parser-lalr.y" - { yyval = mk_node("ExprIndex", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 7952 "parser.tab.c" - break; - - case 743: -#line 1706 "parser-lalr.y" - { yyval = mk_node("ExprIndex", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 7958 "parser.tab.c" - break; - - case 744: -#line 1707 "parser-lalr.y" - { yyval = mk_node("ExprCall", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 7964 "parser.tab.c" - break; - - case 745: -#line 1708 "parser-lalr.y" - { yyval = mk_node("ExprCall", 3, yyvsp[-5], yyvsp[-3], yyvsp[-1]); } -#line 7970 "parser.tab.c" - break; - - case 746: -#line 1709 "parser-lalr.y" - { yyval = mk_node("ExprTupleIndex", 1, yyvsp[-2]); } -#line 7976 "parser.tab.c" - break; - - case 747: -#line 1710 "parser-lalr.y" - { yyval = mk_node("ExprTupleIndex", 1, yyvsp[-2]); } -#line 7982 "parser.tab.c" - break; - - case 748: -#line 1714 "parser-lalr.y" - { yyval = mk_node("ExprMatch", 1, yyvsp[-2]); } -#line 7988 "parser.tab.c" - break; - - case 749: -#line 1715 "parser-lalr.y" - { yyval = mk_node("ExprMatch", 2, yyvsp[-3], yyvsp[-1]); } -#line 7994 "parser.tab.c" - break; - - case 750: -#line 1716 "parser-lalr.y" - { yyval = mk_node("ExprMatch", 2, yyvsp[-4], ext_node(yyvsp[-2], 1, yyvsp[-1])); } -#line 8000 "parser.tab.c" - break; - - case 751: -#line 1717 "parser-lalr.y" - { yyval = mk_node("ExprMatch", 2, yyvsp[-3], mk_node("Arms", 1, yyvsp[-1])); } -#line 8006 "parser.tab.c" - break; - - case 752: -#line 1721 "parser-lalr.y" - { yyval = mk_node("Arms", 1, yyvsp[0]); } -#line 8012 "parser.tab.c" - break; - - case 753: -#line 1722 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 8018 "parser.tab.c" - break; - - case 757: -#line 1732 "parser-lalr.y" - { yyval = mk_node("ArmNonblock", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8024 "parser.tab.c" - break; - - case 758: -#line 1733 "parser-lalr.y" - { yyval = mk_node("ArmNonblock", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8030 "parser.tab.c" - break; - - case 759: -#line 1737 "parser-lalr.y" - { yyval = mk_node("ArmBlock", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8036 "parser.tab.c" - break; - - case 760: -#line 1738 "parser-lalr.y" - { yyval = mk_node("ArmBlock", 4, yyvsp[-4], yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8042 "parser.tab.c" - break; - - case 761: -#line 1742 "parser-lalr.y" - { yyval = yyvsp[0]; } -#line 8048 "parser.tab.c" - break; - - case 762: -#line 1743 "parser-lalr.y" - { yyval = mk_none(); } -#line 8054 "parser.tab.c" - break; - - case 763: -#line 1747 "parser-lalr.y" - { yyval = mk_node("ExprIf", 2, yyvsp[-1], yyvsp[0]); } -#line 8060 "parser.tab.c" - break; - - case 764: -#line 1748 "parser-lalr.y" - { yyval = mk_node("ExprIf", 3, yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8066 "parser.tab.c" - break; - - case 765: -#line 1752 "parser-lalr.y" - { yyval = mk_node("ExprIfLet", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 8072 "parser.tab.c" - break; - - case 766: -#line 1753 "parser-lalr.y" - { yyval = mk_node("ExprIfLet", 4, yyvsp[-5], yyvsp[-3], yyvsp[-2], yyvsp[0]); } -#line 8078 "parser.tab.c" - break; - - case 770: -#line 1763 "parser-lalr.y" - { yyval = mk_node("ExprWhile", 3, yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 8084 "parser.tab.c" - break; - - case 771: -#line 1767 "parser-lalr.y" - { yyval = mk_node("ExprWhileLet", 4, yyvsp[-6], yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 8090 "parser.tab.c" - break; - - case 772: -#line 1771 "parser-lalr.y" - { yyval = mk_node("ExprLoop", 2, yyvsp[-2], yyvsp[0]); } -#line 8096 "parser.tab.c" - break; - - case 773: -#line 1775 "parser-lalr.y" - { yyval = mk_node("ExprForLoop", 4, yyvsp[-5], yyvsp[-3], yyvsp[-1], yyvsp[0]); } -#line 8102 "parser.tab.c" - break; - - case 775: -#line 1780 "parser-lalr.y" - { yyval = mk_none(); } -#line 8108 "parser.tab.c" - break; - - case 776: -#line 1784 "parser-lalr.y" - { yyval = mk_node("DeclLocal", 3, yyvsp[-3], yyvsp[-2], yyvsp[-1]); } -#line 8114 "parser.tab.c" - break; - - case 777: -#line 1792 "parser-lalr.y" - { yyval = mk_node("LitByte", 1, mk_atom(yytext)); } -#line 8120 "parser.tab.c" - break; - - case 778: -#line 1793 "parser-lalr.y" - { yyval = mk_node("LitChar", 1, mk_atom(yytext)); } -#line 8126 "parser.tab.c" - break; - - case 779: -#line 1794 "parser-lalr.y" - { yyval = mk_node("LitInteger", 1, mk_atom(yytext)); } -#line 8132 "parser.tab.c" - break; - - case 780: -#line 1795 "parser-lalr.y" - { yyval = mk_node("LitFloat", 1, mk_atom(yytext)); } -#line 8138 "parser.tab.c" - break; - - case 781: -#line 1796 "parser-lalr.y" - { yyval = mk_node("LitBool", 1, mk_atom(yytext)); } -#line 8144 "parser.tab.c" - break; - - case 782: -#line 1797 "parser-lalr.y" - { yyval = mk_node("LitBool", 1, mk_atom(yytext)); } -#line 8150 "parser.tab.c" - break; - - case 784: -#line 1802 "parser-lalr.y" - { yyval = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); } -#line 8156 "parser.tab.c" - break; - - case 785: -#line 1803 "parser-lalr.y" - { yyval = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); } -#line 8162 "parser.tab.c" - break; - - case 786: -#line 1804 "parser-lalr.y" - { yyval = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); } -#line 8168 "parser.tab.c" - break; - - case 787: -#line 1805 "parser-lalr.y" - { yyval = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); } -#line 8174 "parser.tab.c" - break; - - case 788: -#line 1809 "parser-lalr.y" - { yyval = mk_none(); } -#line 8180 "parser.tab.c" - break; - - case 790: -#line 1814 "parser-lalr.y" - { yyval = mk_node("ident", 1, mk_atom(yytext)); } -#line 8186 "parser.tab.c" - break; - - case 791: -#line 1816 "parser-lalr.y" - { yyval = mk_node("ident", 1, mk_atom(yytext)); } -#line 8192 "parser.tab.c" - break; - - case 792: -#line 1817 "parser-lalr.y" - { yyval = mk_node("ident", 1, mk_atom(yytext)); } -#line 8198 "parser.tab.c" - break; - - case 793: -#line 1818 "parser-lalr.y" - { yyval = mk_node("ident", 1, mk_atom(yytext)); } -#line 8204 "parser.tab.c" - break; - - case 794: -#line 1822 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8210 "parser.tab.c" - break; - - case 795: -#line 1823 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8216 "parser.tab.c" - break; - - case 796: -#line 1824 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8222 "parser.tab.c" - break; - - case 797: -#line 1825 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8228 "parser.tab.c" - break; - - case 798: -#line 1826 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8234 "parser.tab.c" - break; - - case 799: -#line 1827 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8240 "parser.tab.c" - break; - - case 800: -#line 1828 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8246 "parser.tab.c" - break; - - case 801: -#line 1829 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8252 "parser.tab.c" - break; - - case 802: -#line 1830 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8258 "parser.tab.c" - break; - - case 803: -#line 1831 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8264 "parser.tab.c" - break; - - case 804: -#line 1832 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8270 "parser.tab.c" - break; - - case 805: -#line 1833 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8276 "parser.tab.c" - break; - - case 806: -#line 1834 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8282 "parser.tab.c" - break; - - case 807: -#line 1835 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8288 "parser.tab.c" - break; - - case 808: -#line 1836 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8294 "parser.tab.c" - break; - - case 809: -#line 1837 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8300 "parser.tab.c" - break; - - case 810: -#line 1838 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8306 "parser.tab.c" - break; - - case 811: -#line 1839 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8312 "parser.tab.c" - break; - - case 812: -#line 1840 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8318 "parser.tab.c" - break; - - case 813: -#line 1841 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8324 "parser.tab.c" - break; - - case 814: -#line 1842 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8330 "parser.tab.c" - break; - - case 815: -#line 1843 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8336 "parser.tab.c" - break; - - case 816: -#line 1844 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8342 "parser.tab.c" - break; - - case 817: -#line 1845 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8348 "parser.tab.c" - break; - - case 818: -#line 1846 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8354 "parser.tab.c" - break; - - case 819: -#line 1847 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8360 "parser.tab.c" - break; - - case 820: -#line 1848 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8366 "parser.tab.c" - break; - - case 821: -#line 1849 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8372 "parser.tab.c" - break; - - case 822: -#line 1850 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8378 "parser.tab.c" - break; - - case 823: -#line 1851 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8384 "parser.tab.c" - break; - - case 824: -#line 1852 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8390 "parser.tab.c" - break; - - case 825: -#line 1853 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8396 "parser.tab.c" - break; - - case 826: -#line 1854 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8402 "parser.tab.c" - break; - - case 827: -#line 1855 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8408 "parser.tab.c" - break; - - case 828: -#line 1856 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8414 "parser.tab.c" - break; - - case 829: -#line 1857 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8420 "parser.tab.c" - break; - - case 830: -#line 1858 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8426 "parser.tab.c" - break; - - case 831: -#line 1859 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8432 "parser.tab.c" - break; - - case 832: -#line 1860 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8438 "parser.tab.c" - break; - - case 833: -#line 1861 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8444 "parser.tab.c" - break; - - case 834: -#line 1862 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8450 "parser.tab.c" - break; - - case 835: -#line 1863 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8456 "parser.tab.c" - break; - - case 836: -#line 1864 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8462 "parser.tab.c" - break; - - case 837: -#line 1865 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8468 "parser.tab.c" - break; - - case 838: -#line 1866 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8474 "parser.tab.c" - break; - - case 839: -#line 1867 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8480 "parser.tab.c" - break; - - case 840: -#line 1868 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8486 "parser.tab.c" - break; - - case 841: -#line 1869 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8492 "parser.tab.c" - break; - - case 842: -#line 1870 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8498 "parser.tab.c" - break; - - case 843: -#line 1871 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8504 "parser.tab.c" - break; - - case 844: -#line 1872 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8510 "parser.tab.c" - break; - - case 845: -#line 1873 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8516 "parser.tab.c" - break; - - case 846: -#line 1874 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8522 "parser.tab.c" - break; - - case 847: -#line 1875 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8528 "parser.tab.c" - break; - - case 848: -#line 1876 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8534 "parser.tab.c" - break; - - case 849: -#line 1877 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8540 "parser.tab.c" - break; - - case 850: -#line 1878 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8546 "parser.tab.c" - break; - - case 851: -#line 1879 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8552 "parser.tab.c" - break; - - case 852: -#line 1880 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8558 "parser.tab.c" - break; - - case 853: -#line 1881 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8564 "parser.tab.c" - break; - - case 854: -#line 1882 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8570 "parser.tab.c" - break; - - case 855: -#line 1883 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8576 "parser.tab.c" - break; - - case 856: -#line 1884 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8582 "parser.tab.c" - break; - - case 857: -#line 1885 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8588 "parser.tab.c" - break; - - case 858: -#line 1886 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8594 "parser.tab.c" - break; - - case 859: -#line 1887 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8600 "parser.tab.c" - break; - - case 860: -#line 1888 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8606 "parser.tab.c" - break; - - case 861: -#line 1889 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8612 "parser.tab.c" - break; - - case 862: -#line 1890 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8618 "parser.tab.c" - break; - - case 863: -#line 1891 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8624 "parser.tab.c" - break; - - case 864: -#line 1892 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8630 "parser.tab.c" - break; - - case 865: -#line 1893 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8636 "parser.tab.c" - break; - - case 866: -#line 1894 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8642 "parser.tab.c" - break; - - case 867: -#line 1895 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8648 "parser.tab.c" - break; - - case 868: -#line 1896 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8654 "parser.tab.c" - break; - - case 869: -#line 1897 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8660 "parser.tab.c" - break; - - case 870: -#line 1898 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8666 "parser.tab.c" - break; - - case 871: -#line 1899 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8672 "parser.tab.c" - break; - - case 872: -#line 1900 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8678 "parser.tab.c" - break; - - case 873: -#line 1901 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8684 "parser.tab.c" - break; - - case 874: -#line 1902 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8690 "parser.tab.c" - break; - - case 875: -#line 1903 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8696 "parser.tab.c" - break; - - case 876: -#line 1904 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8702 "parser.tab.c" - break; - - case 877: -#line 1905 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8708 "parser.tab.c" - break; - - case 878: -#line 1906 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8714 "parser.tab.c" - break; - - case 879: -#line 1907 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8720 "parser.tab.c" - break; - - case 880: -#line 1908 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8726 "parser.tab.c" - break; - - case 881: -#line 1909 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8732 "parser.tab.c" - break; - - case 882: -#line 1910 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8738 "parser.tab.c" - break; - - case 883: -#line 1911 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8744 "parser.tab.c" - break; - - case 884: -#line 1912 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8750 "parser.tab.c" - break; - - case 885: -#line 1913 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8756 "parser.tab.c" - break; - - case 886: -#line 1914 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8762 "parser.tab.c" - break; - - case 887: -#line 1915 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8768 "parser.tab.c" - break; - - case 888: -#line 1916 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8774 "parser.tab.c" - break; - - case 889: -#line 1917 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8780 "parser.tab.c" - break; - - case 890: -#line 1918 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8786 "parser.tab.c" - break; - - case 891: -#line 1919 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8792 "parser.tab.c" - break; - - case 892: -#line 1920 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8798 "parser.tab.c" - break; - - case 893: -#line 1921 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8804 "parser.tab.c" - break; - - case 894: -#line 1922 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8810 "parser.tab.c" - break; - - case 895: -#line 1923 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8816 "parser.tab.c" - break; - - case 896: -#line 1924 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8822 "parser.tab.c" - break; - - case 897: -#line 1925 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8828 "parser.tab.c" - break; - - case 898: -#line 1926 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8834 "parser.tab.c" - break; - - case 899: -#line 1927 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8840 "parser.tab.c" - break; - - case 900: -#line 1928 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8846 "parser.tab.c" - break; - - case 901: -#line 1929 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8852 "parser.tab.c" - break; - - case 902: -#line 1930 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8858 "parser.tab.c" - break; - - case 903: -#line 1931 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8864 "parser.tab.c" - break; - - case 904: -#line 1932 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8870 "parser.tab.c" - break; - - case 905: -#line 1933 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8876 "parser.tab.c" - break; - - case 906: -#line 1934 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8882 "parser.tab.c" - break; - - case 907: -#line 1935 "parser-lalr.y" - { yyval = mk_atom(yytext); } -#line 8888 "parser.tab.c" - break; - - case 908: -#line 1939 "parser-lalr.y" - { yyval = mk_node("TokenTrees", 0); } -#line 8894 "parser.tab.c" - break; - - case 909: -#line 1940 "parser-lalr.y" - { yyval = ext_node(yyvsp[-1], 1, yyvsp[0]); } -#line 8900 "parser.tab.c" - break; - - case 911: -#line 1945 "parser-lalr.y" - { yyval = mk_node("TTTok", 1, yyvsp[0]); } -#line 8906 "parser.tab.c" - break; - - case 915: -#line 1956 "parser-lalr.y" - { - yyval = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("(")), - yyvsp[-1], - mk_node("TTTok", 1, mk_atom(")"))); -} -#line 8917 "parser.tab.c" - break; - - case 916: -#line 1966 "parser-lalr.y" - { - yyval = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("{")), - yyvsp[-1], - mk_node("TTTok", 1, mk_atom("}"))); -} -#line 8928 "parser.tab.c" - break; - - case 917: -#line 1976 "parser-lalr.y" - { - yyval = mk_node("TTDelim", 3, - mk_node("TTTok", 1, mk_atom("[")), - yyvsp[-1], - mk_node("TTTok", 1, mk_atom("]"))); -} -#line 8939 "parser.tab.c" - break; - - -#line 8943 "parser.tab.c" - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - - -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - return yyresult; -} diff --git a/gcc/rust/test/rustc_bison_test/token.h b/gcc/rust/test/rustc_bison_test/token.h deleted file mode 100644 index d3bec02..0000000 --- a/gcc/rust/test/rustc_bison_test/token.h +++ /dev/null @@ -1,167 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.4.1. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* Undocumented macros, especially those whose name start with YY_, - are private implementation details. Do not rely on them. */ - -#ifndef YY_YY_TOKEN_H_INCLUDED -#define YY_YY_TOKEN_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -#define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ -#ifndef YYTOKENTYPE -#define YYTOKENTYPE -enum yytokentype { - SHL = 258, - SHR = 259, - LE = 260, - EQEQ = 261, - NE = 262, - GE = 263, - ANDAND = 264, - OROR = 265, - SHLEQ = 266, - SHREQ = 267, - MINUSEQ = 268, - ANDEQ = 269, - OREQ = 270, - PLUSEQ = 271, - STAREQ = 272, - SLASHEQ = 273, - CARETEQ = 274, - PERCENTEQ = 275, - DOTDOT = 276, - DOTDOTDOT = 277, - MOD_SEP = 278, - RARROW = 279, - LARROW = 280, - FAT_ARROW = 281, - LIT_BYTE = 282, - LIT_CHAR = 283, - LIT_INTEGER = 284, - LIT_FLOAT = 285, - LIT_STR = 286, - LIT_STR_RAW = 287, - LIT_BYTE_STR = 288, - LIT_BYTE_STR_RAW = 289, - IDENT = 290, - UNDERSCORE = 291, - LIFETIME = 292, - - // keywords - SELF = 293, - STATIC = 294, - ABSTRACT = 295, - ALIGNOF = 296, - AS = 297, - BECOME = 298, - BREAK = 299, - CATCH = 300, - CRATE = 301, - DO = 302, - ELSE = 303, - ENUM = 304, - EXTERN = 305, - FALSE = 306, - FINAL = 307, - FN = 308, - FOR = 309, - IF = 310, - IMPL = 311, - IN = 312, - LET = 313, - LOOP = 314, - MACRO = 315, - MATCH = 316, - MOD = 317, - MOVE = 318, - MUT = 319, - OFFSETOF = 320, - OVERRIDE = 321, - PRIV = 322, - PUB = 323, - PURE = 324, - REF = 325, - RETURN = 326, - SIZEOF = 327, - STRUCT = 328, - SUPER = 329, - UNION = 330, - UNSIZED = 331, - TRUE = 332, - TRAIT = 333, - TYPE = 334, - UNSAFE = 335, - VIRTUAL = 336, - YIELD = 337, - DEFAULT = 338, - USE = 339, - WHILE = 340, - CONTINUE = 341, - PROC = 342, - BOX = 343, - CONST = 344, - WHERE = 345, - TYPEOF = 346, - INNER_DOC_COMMENT = 347, - OUTER_DOC_COMMENT = 348, - - SHEBANG = 349, - SHEBANG_LINE = 350, - STATIC_LIFETIME = 351, - - LAMBDA = 352, - SHIFTPLUS = 353, - FORTYPE = 354, - RANGE = 355 -}; -#endif - -/* Value type. */ -#if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -#define YYSTYPE_IS_TRIVIAL 1 -#define YYSTYPE_IS_DECLARED 1 -#endif - -extern YYSTYPE yylval; - -int yyparse(void); - -#endif /* !YY_YY_TOKEN_H_INCLUDED */ diff --git a/gcc/rust/test/test1..s b/gcc/rust/test/test1..s deleted file mode 100644 index 32e351a..0000000 --- a/gcc/rust/test/test1..s +++ /dev/null @@ -1 +0,0 @@ - .file "test1." diff --git a/gcc/rust/test/test1.rs b/gcc/rust/test/test1.rs deleted file mode 100644 index e6cfaae..0000000 --- a/gcc/rust/test/test1.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let x = 1; - let y = x; -} diff --git a/gcc/rust/test/test1.s b/gcc/rust/test/test1.s deleted file mode 100644 index d3126f9..0000000 --- a/gcc/rust/test/test1.s +++ /dev/null @@ -1,17 +0,0 @@ - .file "test1.rs" - .text -.Ltext0: - .section .note.GNU-split-stack,"",@progbits - .text -.Letext0: - .section .debug_line,"",@progbits -.Ldebug_line0: - .section .debug_str,"MS",@progbits,1 -.LASF0: - .string "../gccrs/gcc/rust/test/test1.rs" -.LASF1: - .string "/home/redbrain/workspace/gccrs-build" -.LASF2: - .string "GNU Rust 10.0.0 20191127 (experimental) -O0" - .ident "GCC: (GNU) 10.0.0 20191127 (experimental)" - .section .note.GNU-stack,"",@progbits diff --git a/gcc/rust/test/test2-minimal.rs b/gcc/rust/test/test2-minimal.rs deleted file mode 100644 index 3999215..0000000 --- a/gcc/rust/test/test2-minimal.rs +++ /dev/null @@ -1,25 +0,0 @@ -macro_rules! println { - () => { ... }; - ($($arg:tt)*) => { ... }; -} - -// if macro stuff is commented out, parses fine. -// if everything but macro stuff is commented out, segfault. so segfault occurs due to macro stuff - -// Function that returns a boolean value -/*fn is_divisible_by(lhs: u32, rhs: u32) -> bool { - // Corner case, early return - if rhs == 0 { - return false; - } - - // This is an expression, the `return` keyword is not necessary here - lhs % rhs == 0 -} - - - -fn main() { - let mut x = is_divisible(3, 12); -}*/ - diff --git a/gcc/rust/test/test2.rs b/gcc/rust/test/test2.rs deleted file mode 100644 index 976f1f3..0000000 --- a/gcc/rust/test/test2.rs +++ /dev/null @@ -1,18 +0,0 @@ - -// Function that returns a boolean value -fn is_divisible_by(lhs: u32, rhs: u32) -> bool { - // Corner case, early return - if rhs == 0 { - return false; - } - - // This is an expression, the `return` keyword is not necessary here - lhs % rhs == 0 -} - - - -fn main() { - let mut x:i32 = is_divisible(3, 12); -} - diff --git a/gcc/rust/test/test2.s b/gcc/rust/test/test2.s deleted file mode 100644 index 75ff5c4..0000000 --- a/gcc/rust/test/test2.s +++ /dev/null @@ -1,17 +0,0 @@ - .file "test2.rs" - .text -.Ltext0: - .section .note.GNU-split-stack,"",@progbits - .text -.Letext0: - .section .debug_line,"",@progbits -.Ldebug_line0: - .section .debug_str,"MS",@progbits,1 -.LASF0: - .string "/home/redbrain/workspace/gccrs-build" -.LASF1: - .string "../gccrs/gcc/rust/test/test2.rs" -.LASF2: - .string "GNU Rust 10.0.0 20191127 (experimental)" - .ident "GCC: (GNU) 10.0.0 20191127 (experimental)" - .section .note.GNU-stack,"",@progbits diff --git a/gcc/rust/test/test_jit.c b/gcc/rust/test/test_jit.c deleted file mode 100644 index f35de3a..0000000 --- a/gcc/rust/test/test_jit.c +++ /dev/null @@ -1,331 +0,0 @@ -#include -#include - -#include - -// fix - shouldn't exist -#define MAX_OPEN_PARENS 20 - -typedef struct bf_compiler { - const char* filename; - int line; - int column; - - gcc_jit_context* ctxt; - - gcc_jit_type* void_type; - gcc_jit_type* int_type; - gcc_jit_type* byte_type; - gcc_jit_type* array_type; - - gcc_jit_function* func_getchar; - gcc_jit_function* func_putchar; - - gcc_jit_function* func; - gcc_jit_block* curblock; - - gcc_jit_rvalue* int_zero; - gcc_jit_rvalue* int_one; - gcc_jit_rvalue* byte_zero; - gcc_jit_rvalue* byte_one; - gcc_jit_lvalue* data_cells; - gcc_jit_lvalue* idx; - - int num_open_parens; - gcc_jit_block* paren_test[MAX_OPEN_PARENS]; - gcc_jit_block* paren_body[MAX_OPEN_PARENS]; - gcc_jit_block* paren_after[MAX_OPEN_PARENS]; -} bf_compiler; - -// Bail out with message on stderr -static void fatal_error(bf_compiler* bfc, const char* msg) { - fprintf(stderr, "%s:%i:%i: %s", bfc->filename, bfc->line, bfc->column, msg); - abort(); -} - -/* Get "data_cells[idx]" as an lvalue. */ - -static gcc_jit_lvalue* bf_get_current_data(bf_compiler* bfc, gcc_jit_location* loc) { - return gcc_jit_context_new_array_access( - bfc->ctxt, - loc, - gcc_jit_lvalue_as_rvalue(bfc->data_cells), - gcc_jit_lvalue_as_rvalue(bfc->idx)); -} - -/* Get "data_cells[idx] == 0" as a boolean rvalue. */ - -static gcc_jit_rvalue* bf_current_data_is_zero(bf_compiler* bfc, gcc_jit_location* loc) { - return gcc_jit_context_new_comparison( - bfc->ctxt, - loc, - GCC_JIT_COMPARISON_EQ, - gcc_jit_lvalue_as_rvalue(bf_get_current_data(bfc, loc)), - bfc->byte_zero); -} - -/* Compile one bf character. */ - -static void bf_compile_char(bf_compiler* bfc, unsigned char ch) { - gcc_jit_location* loc = - gcc_jit_context_new_location(bfc->ctxt, - bfc->filename, - bfc->line, - bfc->column); - - /* Turn this on to trace execution, by injecting putchar () - of each source char. */ - if (0) { - gcc_jit_rvalue* arg = - gcc_jit_context_new_rvalue_from_int( - bfc->ctxt, - bfc->int_type, - ch); - gcc_jit_rvalue* call = - gcc_jit_context_new_call(bfc->ctxt, - loc, - bfc->func_putchar, - 1, - &arg); - gcc_jit_block_add_eval(bfc->curblock, - loc, - call); - } - - switch (ch) { - case '>': - gcc_jit_block_add_comment(bfc->curblock, - loc, - "'>': idx += 1;"); - gcc_jit_block_add_assignment_op(bfc->curblock, - loc, - bfc->idx, - GCC_JIT_BINARY_OP_PLUS, - bfc->int_one); - break; - - case '<': - gcc_jit_block_add_comment(bfc->curblock, - loc, - "'<': idx -= 1;"); - gcc_jit_block_add_assignment_op(bfc->curblock, - loc, - bfc->idx, - GCC_JIT_BINARY_OP_MINUS, - bfc->int_one); - break; - - case '+': - gcc_jit_block_add_comment(bfc->curblock, - loc, - "'+': data[idx] += 1;"); - gcc_jit_block_add_assignment_op(bfc->curblock, - loc, - bf_get_current_data(bfc, loc), - GCC_JIT_BINARY_OP_PLUS, - bfc->byte_one); - break; - - case '-': - gcc_jit_block_add_comment(bfc->curblock, - loc, - "'-': data[idx] -= 1;"); - gcc_jit_block_add_assignment_op(bfc->curblock, - loc, - bf_get_current_data(bfc, loc), - GCC_JIT_BINARY_OP_MINUS, - bfc->byte_one); - break; - - case '.': { - gcc_jit_rvalue* arg = - gcc_jit_context_new_cast( - bfc->ctxt, - loc, - gcc_jit_lvalue_as_rvalue(bf_get_current_data(bfc, loc)), - bfc->int_type); - gcc_jit_rvalue* call = - gcc_jit_context_new_call(bfc->ctxt, - loc, - bfc->func_putchar, - 1, - &arg); - gcc_jit_block_add_comment(bfc->curblock, - loc, - "'.': putchar ((int)data[idx]);"); - gcc_jit_block_add_eval(bfc->curblock, - loc, - call); - } break; - - case ',': { - gcc_jit_rvalue* call = - gcc_jit_context_new_call(bfc->ctxt, - loc, - bfc->func_getchar, - 0, - NULL); - gcc_jit_block_add_comment( - bfc->curblock, - loc, - "',': data[idx] = (unsigned char)getchar ();"); - gcc_jit_block_add_assignment(bfc->curblock, - loc, - bf_get_current_data(bfc, loc), - gcc_jit_context_new_cast( - bfc->ctxt, - loc, - call, - bfc->byte_type)); - } break; - - case '[': { - gcc_jit_block* loop_test = - gcc_jit_function_new_block(bfc->func, NULL); - gcc_jit_block* on_zero = - gcc_jit_function_new_block(bfc->func, NULL); - gcc_jit_block* on_non_zero = - gcc_jit_function_new_block(bfc->func, NULL); - - if (bfc->num_open_parens == MAX_OPEN_PARENS) - fatal_error(bfc, "too many open parens"); - - gcc_jit_block_end_with_jump( - bfc->curblock, - loc, - loop_test); - - gcc_jit_block_add_comment( - loop_test, - loc, - "'['"); - gcc_jit_block_end_with_conditional( - loop_test, - loc, - bf_current_data_is_zero(bfc, loc), - on_zero, - on_non_zero); - bfc->paren_test[bfc->num_open_parens] = loop_test; - bfc->paren_body[bfc->num_open_parens] = on_non_zero; - bfc->paren_after[bfc->num_open_parens] = on_zero; - bfc->num_open_parens += 1; - bfc->curblock = on_non_zero; - } break; - - case ']': { - gcc_jit_block_add_comment( - bfc->curblock, - loc, - "']'"); - - if (bfc->num_open_parens == 0) - fatal_error(bfc, "mismatching parens"); - bfc->num_open_parens -= 1; - gcc_jit_block_end_with_jump( - bfc->curblock, - loc, - bfc->paren_test[bfc->num_open_parens]); - bfc->curblock = bfc->paren_after[bfc->num_open_parens]; - } break; - - case '\n': - bfc->line += 1; - bfc->column = 0; - break; - } - - if (ch != '\n') - bfc->column += 1; -} - -/* Compile the given .bf file into a gcc_jit_context, containing a - single "main" function suitable for compiling into an executable. */ - -gcc_jit_context* bf_compile(const char* filename) { - bf_compiler bfc; - FILE* f_in; - int ch; - - memset(&bfc, 0, sizeof(bfc)); - - bfc.filename = filename; - f_in = fopen(filename, "r"); - if (!f_in) - fatal_error(&bfc, "unable to open file"); - bfc.line = 1; - - bfc.ctxt = gcc_jit_context_acquire(); - - gcc_jit_context_set_int_option( - bfc.ctxt, - GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, - 3); - gcc_jit_context_set_bool_option( - bfc.ctxt, - GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, - 0); - gcc_jit_context_set_bool_option( - bfc.ctxt, - GCC_JIT_BOOL_OPTION_DEBUGINFO, - 1); - gcc_jit_context_set_bool_option( - bfc.ctxt, - GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, - 0); - gcc_jit_context_set_bool_option( - bfc.ctxt, - GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, - 0); - - bfc.void_type = - gcc_jit_context_get_type(bfc.ctxt, GCC_JIT_TYPE_VOID); - bfc.int_type = - gcc_jit_context_get_type(bfc.ctxt, GCC_JIT_TYPE_INT); - bfc.byte_type = - gcc_jit_context_get_type(bfc.ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR); - bfc.array_type = - gcc_jit_context_new_array_type(bfc.ctxt, - NULL, - bfc.byte_type, - 30000); - - bfc.func_getchar = - gcc_jit_context_new_function(bfc.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, bfc.int_type, "getchar", 0, NULL, 0); - - gcc_jit_param* param_c = - gcc_jit_context_new_param(bfc.ctxt, NULL, bfc.int_type, "c"); - bfc.func_putchar = - gcc_jit_context_new_function(bfc.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, bfc.void_type, "putchar", 1, ¶m_c, 0); - - bfc.func = make_main(bfc.ctxt); - bfc.curblock = - gcc_jit_function_new_block(bfc.func, "initial"); - bfc.int_zero = gcc_jit_context_zero(bfc.ctxt, bfc.int_type); - bfc.int_one = gcc_jit_context_one(bfc.ctxt, bfc.int_type); - bfc.byte_zero = gcc_jit_context_zero(bfc.ctxt, bfc.byte_type); - bfc.byte_one = gcc_jit_context_one(bfc.ctxt, bfc.byte_type); - - bfc.data_cells = - gcc_jit_context_new_global(bfc.ctxt, NULL, GCC_JIT_GLOBAL_INTERNAL, bfc.array_type, "data_cells"); - bfc.idx = - gcc_jit_function_new_local(bfc.func, NULL, bfc.int_type, "idx"); - - gcc_jit_block_add_comment(bfc.curblock, - NULL, - "idx = 0;"); - gcc_jit_block_add_assignment(bfc.curblock, - NULL, - bfc.idx, - bfc.int_zero); - - bfc.num_open_parens = 0; - - while (EOF != (ch = fgetc(f_in))) - bf_compile_char(&bfc, (unsigned char)ch); - - gcc_jit_block_end_with_return(bfc.curblock, NULL, bfc.int_zero); - - fclose(f_in); - - return bfc.ctxt; -} \ No newline at end of file diff --git a/gcc/rust/test2/rust-c.h b/gcc/rust/test2/rust-c.h deleted file mode 100644 index 718040b..0000000 --- a/gcc/rust/test2/rust-c.h +++ /dev/null @@ -1,65 +0,0 @@ -/* rust-c.h -- Header file for Rust frontend gcc C interface. - -Copyright stuff, whatever */ - -#ifndef RUST_RUST_C_H -#define RUST_RUST_C_H - -#define RUST_EXTERN_C - -// re-enable if rust versions of these are required -//class Linemap; -//class Backend; - -/* Functions defined in the Rust frontend proper called by the GCC - interface. TODO move around */ - -extern int rust_enable_dump(const char*); -extern int rust_enable_optimize(const char*, int); - -extern void grs_add_search_path(const char*); - -struct rust_create_rustrust_args { - int int_type_size; - int pointer_size; - const char* pkgpath; - const char* prefix; - const char* relative_import_path; - const char* c_header; - //Backend* backend; - //Linemap* linemap; - bool check_divide_by_zero; - bool check_divide_overflow; - bool compiling_runtime; - int debug_escape_level; - const char* debug_escape_hash; - int64_t nil_check_size_threshold; - bool debug_optimization; -}; - -extern void rust_create_rustrust(const struct rust_create_rustrust_args*); - -extern void grs_parse_input_files(const char**, unsigned int, bool only_check_syntax, - bool require_return_statement); -extern void rust_write_globals(void); - -/* Functions defined in the GCC interface called by the Rust frontend - proper. TODO: move around */ - -extern void grs_preserve_from_gc(tree); - -extern bool saw_errors(void); - -extern const char* rust_localize_identifier(const char*); - -extern unsigned int rust_field_alignment(tree); - -extern void rust_imported_unsafe(void); - -extern void rust_write_export_data(const char*, unsigned int); - -extern const char* rust_read_export_data(int, off_t, char**, size_t*, int*); - -extern GTY(()) tree rust_non_zero_struct; - -#endif /* !defined(RUST_RUST_C_H) */ diff --git a/gcc/rust/test2/rust-lang.c b/gcc/rust/test2/rust-lang.c deleted file mode 100644 index a21984c..0000000 --- a/gcc/rust/test2/rust-lang.c +++ /dev/null @@ -1,512 +0,0 @@ -/* Rust-lang.c - Rust frontend GCC interface - -License, copyright stuff, etc, whatever. */ - -#include "common/common-target.h" -#include "config.h" -#include "convert.h" -#include "coretypes.h" -#include "debug.h" -#include "diagnostic.h" -#include "fold-const.h" -#include "gimple-expr.h" -#include "gimplify.h" -#include "langhooks-def.h" -#include "langhooks.h" -#include "opts.h" -#include "stor-layout.h" -#include "system.h" -#include "target.h" -#include "tree.h" - -#include - -#include "rust-c.h" -//#include "rust-gcc.h" - -/* Language-dependent contents of a type. */ -// seems to be a "gengtype" of some kind -struct GTY(()) lang_type { - char dummy; -}; - -/* Language-dependent contents of a decl. */ -struct GTY(()) lang_decl { - char dummy; -}; - -/* Language-dependent contents of an identifier. This must include a - tree_identifier. */ -struct GTY(()) lang_identifier { - struct tree_identifier common; -}; - -/* The resulting tree type. */ -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) - lang_tree_node { - union tree_node GTY((tag("0"), - desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; -}; - -/* We don't use language_function. */ -struct GTY(()) language_function { - int dummy; -}; - -/* Option information we need to pass to rust_create_rustrust. */ -static const char* rust_pkgpath = NULL; -static const char* rust_prefix = NULL; -static const char* rust_relative_import_path = NULL; -static const char* rust_c_header = NULL; - -/* Language hooks. */ -static bool grs_langhook_init(void) { - build_common_tree_nodes(false); - - /* I don't know why this has to be done explicitly. */ - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - /* We must create the rustrust IR after calling build_common_tree_nodes - (because Gorust::define_builtin_function_trees refers indirectly - to, e.g., unsigned_char_type_node) but before calling - build_common_builtin_nodes (because it calls, indirectly, - rust_type_for_size). */ - struct rust_create_rustrust_args args; - args.int_type_size = INT_TYPE_SIZE; - args.pointer_size = POINTER_SIZE; - args.pkgpath = rust_pkgpath; - args.prefix = rust_prefix; - args.relative_import_path = rust_relative_import_path; - args.c_header = rust_c_header; - args.check_divide_by_zero = rust_check_divide_zero; - args.check_divide_overflow = rust_check_divide_overflow; - args.compiling_runtime = rust_compiling_runtime; - args.debug_escape_level = rust_debug_escape_level; - args.debug_escape_hash = rust_debug_escape_hash; - args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096; - args.debug_optimization = rust_debug_optimization; - args.linemap = rust_get_linemap(); - args.backend = rust_get_backend(); - rust_create_rustrust(&args); - - build_common_builtin_nodes(); - - /* The default precision for floating point numbers. This is used - for floating point constants with abstract type. This may - eventually be controllable by a command line option. */ - mpfr_set_default_prec(256); - - /* Go uses exceptions. */ - using_eh_for_cleanups(); - - return true; -} - -/* The option mask. */ -static unsigned int grs_langhook_option_lang_mask(void) { - return CL_Go; -} - -/* Initialize the options structure. */ -static void grs_langhook_init_options_struct(struct gcc_options* opts) { - /* Go says that signed overflow is precisely defined. */ - opts->x_flag_wrapv = 1; - - /* We default to using strict aliasing, since Go pointers are safe. - This is turned off for code that imports the "unsafe" package, - because using unsafe.pointer violates C style aliasing - requirements. */ - opts->x_flag_strict_aliasing = 1; - - /* Default to avoiding range issues for complex multiply and - divide. */ - opts->x_flag_complex_method = 2; - - /* The builtin math functions should not set errno. */ - opts->x_flag_errno_math = 0; - opts->frontend_set_flag_errno_math = true; - - /* Exceptions are used to handle recovering from panics. */ - opts->x_flag_exceptions = 1; - opts->x_flag_non_call_exceptions = 1; - - /* We need to keep pointers live for the garbage collector. */ - opts->x_flag_keep_gc_roots_live = 1; - - /* Go programs expect runtime.Callers to work, and that uses - libbacktrace that uses debug info. Set the debug info level to 1 - by default. In post_options we will set the debug type if the - debug info level was not set back to 0 on the command line. */ - opts->x_debug_info_level = DINFO_LEVEL_TERSE; -} - -/* Infrastructure for a vector of char * pointers. */ -typedef const char* rust_char_p; - -/* The list of directories to search after all the Go specific - directories have been searched. */ -static vec rust_search_dirs; - -/* Handle Go specific options. Return 0 if we didn't do anything. */ -static bool grs_langhook_handle_option( - size_t scode, - const char* arg, - HOST_WIDE_INT value, - int kind ATTRIBUTE_UNUSED, - location_t loc ATTRIBUTE_UNUSED, - const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - enum opt_code code = (enum opt_code)scode; - bool ret = true; - - switch (code) { - case OPT_I: - rust_add_search_path(arg); - break; - - case OPT_L: - /* A -L option is assumed to come from the compiler driver. - This is a system directory. We search the following - directories, if they exist, before this one: - dir/rust/VERSION - dir/rust/VERSION/MACHINE - This is like include/c++. */ - { - static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; - size_t len; - char* p; - struct stat st; - - len = strlen(arg); - p = XALLOCAVEC(char, - (len + sizeof "rust" + sizeof DEFAULT_TARGET_VERSION + - sizeof DEFAULT_TARGET_MACHINE + 3)); - strcpy(p, arg); - if (len > 0 && !IS_DIR_SEPARATOR(p[len - 1])) - strcat(p, dir_separator_str); - strcat(p, "rust"); - strcat(p, dir_separator_str); - strcat(p, DEFAULT_TARGET_VERSION); - if (stat(p, &st) == 0 && S_ISDIR(st.st_mode)) { - rust_add_search_path(p); - strcat(p, dir_separator_str); - strcat(p, DEFAULT_TARGET_MACHINE); - if (stat(p, &st) == 0 && S_ISDIR(st.st_mode)) - rust_add_search_path(p); - } - - /* Search ARG too, but only after we've searched to Go - specific directories for all -L arguments. */ - rust_search_dirs.safe_push(arg); - } - break; - - case OPT_frust_dump_: - ret = rust_enable_dump(arg) ? true : false; - break; - - case OPT_frust_optimize_: - ret = rust_enable_optimize(arg, value) ? true : false; - break; - - case OPT_frust_pkgpath_: - rust_pkgpath = arg; - break; - - case OPT_frust_prefix_: - rust_prefix = arg; - break; - - case OPT_frust_relative_import_path_: - rust_relative_import_path = arg; - break; - - case OPT_frust_c_header_: - rust_c_header = arg; - break; - - default: - /* Just return 1 to indicate that the option is valid. */ - break; - } - - return ret; -} - -/* Run after parsing options. */ -static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { - unsigned int ix; - const char* dir; - - gcc_assert(num_in_fnames > 0); - - FOR_EACH_VEC_ELT(rust_search_dirs, ix, dir) - rust_add_search_path(dir); - rust_search_dirs.release(); - - if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT) - flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD; - - /* Tail call optimizations can confuse uses of runtime.Callers. */ - if (!global_options_set.x_flag_optimize_sibling_calls) - global_options.x_flag_optimize_sibling_calls = 0; - - /* If the debug info level is still 1, as set in init_options, make - sure that some debugging type is selected. */ - if (global_options.x_debug_info_level == DINFO_LEVEL_TERSE - && global_options.x_write_symbols == NO_DEBUG) - global_options.x_write_symbols = PREFERRED_DEBUGGING_TYPE; - - /* We turn on stack splitting if we can. */ - if (!global_options_set.x_flag_split_stack - && targetm_common.supports_split_stack(false, &global_options)) - global_options.x_flag_split_stack = 1; - - /* If stack splitting is turned on, and the user did not explicitly - request function partitioning, turn off partitioning, as it - confuses the linker when trying to handle partitioned split-stack - code that calls a non-split-stack function. */ - if (global_options.x_flag_split_stack && global_options.x_flag_reorder_blocks_and_partition - && !global_options_set.x_flag_reorder_blocks_and_partition) - global_options.x_flag_reorder_blocks_and_partition = 0; - - /* Returning false means that the backend should be used. */ - return false; -} - -/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and - * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. - * This function must create a complete parse tree in a global var, and then return. - * - * Some consider this the "start of compilation". */ -static void grs_langhook_parse_file(void) { - grs_parse_input_files(in_fnames, num_in_fnames, flag_syntax_only, rust_require_return_statement); - - /* Final processing of globals and early debug info generation. */ - rust_write_globals(); -} - -static tree grs_langhook_type_for_size(unsigned int bits, int unsignedp) { - tree type; - if (unsignedp) { - if (bits == INT_TYPE_SIZE) - type = unsigned_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = unsigned_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_unsigned_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_unsigned_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_unsigned_type_node; - else - type = make_unsigned_type(bits); - } else { - if (bits == INT_TYPE_SIZE) - type = integer_type_node; - else if (bits == CHAR_TYPE_SIZE) - type = signed_char_type_node; - else if (bits == SHORT_TYPE_SIZE) - type = short_integer_type_node; - else if (bits == LONG_TYPE_SIZE) - type = long_integer_type_node; - else if (bits == LONG_LONG_TYPE_SIZE) - type = long_long_integer_type_node; - else - type = make_signed_type(bits); - } - return type; -} - -static tree grs_langhook_type_for_mode(machine_mode mode, int unsignedp) { - tree type; - /* Go has no vector types. Build them here. FIXME: It does not - make sense for the middle-end to ask the frontend for a type - which the frontend does not support. However, at least for now - it is required. See PR 46805. */ - if (GET_MODE_CLASS(mode) == MODE_VECTOR_BOOL && valid_vector_subparts_p(GET_MODE_NUNITS(mode))) { - unsigned int elem_bits = vector_element_size(GET_MODE_BITSIZE(mode), - GET_MODE_NUNITS(mode)); - tree bool_type = build_nonstandard_boolean_type(elem_bits); - return build_vector_type_for_mode(bool_type, mode); - } else if (VECTOR_MODE_P(mode) && valid_vector_subparts_p(GET_MODE_NUNITS(mode))) { - tree inner; - - inner = grs_langhook_type_for_mode(GET_MODE_INNER(mode), unsignedp); - if (inner != NULL_TREE) - return build_vector_type_for_mode(inner, mode); - return NULL_TREE; - } - - scalar_int_mode imode; - scalar_float_mode fmode; - complex_mode cmode; - if (is_int_mode(mode, &imode)) - return grs_langhook_type_for_size(GET_MODE_BITSIZE(imode), unsignedp); - else if (is_float_mode(mode, &fmode)) { - switch (GET_MODE_BITSIZE(fmode)) { - case 32: - return float_type_node; - case 64: - return double_type_node; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (fmode == TYPE_MODE(long_double_type_node)) - return long_double_type_node; - } - } else if (is_complex_float_mode(mode, &cmode)) { - switch (GET_MODE_BITSIZE(cmode)) { - case 64: - return complex_float_type_node; - case 128: - return complex_double_type_node; - default: - // We have to check for long double in order to support - // i386 excess precision. - if (cmode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - } - } - -#if HOST_BITS_PER_WIDE_INT >= 64 - /* The middle-end and some backends rely on TImode being supported - for 64-bit HWI. */ - if (mode == TImode) { - type = build_nonstandard_integer_type(GET_MODE_BITSIZE(TImode), - unsignedp); - if (type && TYPE_MODE(type) == TImode) - return type; - } -#endif - return NULL_TREE; -} - -/* Record a builtin function. We just ignore builtin functions. */ - -static tree grs_langhook_builtin_function(tree decl) { - return decl; -} - -/* Return true if we are in the global binding level. */ - -static bool grs_langhook_global_bindings_p(void) { - return current_function_decl == NULL_TREE; -} - -/* Push a declaration into the current binding level. We can't - usefully implement this since we don't want to convert from tree - back to one of our internal data structures. I think the only way - this is used is to record a decl which is to be returned by - getdecls, and we could implement it for that purpose if - necessary. */ - -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); -} - -/* This hook is used to get the current list of declarations as trees. - We don't support that; instead we use the write_globals hook. This - can't simply crash because it is called by -gstabs. */ - -static tree grs_langhook_getdecls(void) { - return NULL; -} - -/* Go specific gimplification. We need to gimplify - CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle - it. */ - -static int grs_langhook_gimplify_expr(tree* expr_p, gimple_seq* pre_p, gimple_seq* post_p) { - if (TREE_CODE(*expr_p) == CALL_EXPR && CALL_EXPR_STATIC_CHAIN(*expr_p) != NULL_TREE) - gimplify_expr(&CALL_EXPR_STATIC_CHAIN(*expr_p), pre_p, post_p, is_gimple_val, fb_rvalue); - return GS_UNHANDLED; -} - -/* Return a decl for the exception personality function. The function - itself is implemented in librust/runtime/rust-unwind.c. */ - -static tree grs_langhook_eh_personality(void) { - static tree personality_decl; - if (personality_decl == NULL_TREE) { - personality_decl = build_personality_function("gccrust"); - rust_preserve_from_gc(personality_decl); - } - return personality_decl; -} - -/* Functions called directly by the generic backend. */ - -tree convert(tree type, tree expr) { - if (type == error_mark_node || expr == error_mark_node || TREE_TYPE(expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE(expr)) - return expr; - - if (TYPE_MAIN_VARIANT(type) == TYPE_MAIN_VARIANT(TREE_TYPE(expr))) - return fold_convert(type, expr); - - switch (TREE_CODE(type)) { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert(type, expr); - case INTEGER_TYPE: - return fold(convert_to_integer(type, expr)); - case POINTER_TYPE: - return fold(convert_to_pointer(type, expr)); - case REAL_TYPE: - return fold(convert_to_real(type, expr)); - case COMPLEX_TYPE: - return fold(convert_to_complex(type, expr)); - default: - break; - } - - gcc_unreachable(); -} - -/* Convert an identifier for use in an error message. */ - -const char* rust_localize_identifier(const char* ident) { - return identifier_to_locale(ident); -} - -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -#undef LANG_HOOKS_OPTION_LANG_MASK -#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -#undef LANG_HOOKS_HANDLE_OPTION -#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -#undef LANG_HOOKS_GIMPLIFY_EXPR -#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT grs_langhook_init -#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask -#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct -#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option -#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl -#define LANG_HOOKS_GETDECLS grs_langhook_getdecls -#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr -#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality - -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -// These are for GCC's garbage collector to work properly or something -#include "gt-rust-rust-lang.h" -#include "gtype-rust.h" diff --git a/gcc/rust/test2/rustfrontend/eTokenType.enum.h b/gcc/rust/test2/rustfrontend/eTokenType.enum.h deleted file mode 100644 index 5104142..0000000 --- a/gcc/rust/test2/rustfrontend/eTokenType.enum.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * parse/eTokenType.enum.h - * - Multi-include file for defining the eTokenType enum - */ -_(TOK_NULL) -_(TOK_EOF) - -_(TOK_NEWLINE) -_(TOK_WHITESPACE) -_(TOK_COMMENT) - -_(TOK_INTERPOLATED_IDENT) -_(TOK_INTERPOLATED_PATH) -_(TOK_INTERPOLATED_TYPE) -_(TOK_INTERPOLATED_PATTERN) -_(TOK_INTERPOLATED_EXPR) -_(TOK_INTERPOLATED_STMT) -_(TOK_INTERPOLATED_BLOCK) -_(TOK_INTERPOLATED_META) -_(TOK_INTERPOLATED_ITEM) - -// Value tokens -_(TOK_IDENT) -_(TOK_LIFETIME) -_(TOK_INTEGER) -_(TOK_CHAR) -_(TOK_FLOAT) -_(TOK_STRING) -_(TOK_BYTESTRING) - -_(TOK_HASH) - -_(TOK_UNDERSCORE) - -// Symbols -_(TOK_PAREN_OPEN) _(TOK_PAREN_CLOSE) -_(TOK_BRACE_OPEN) _(TOK_BRACE_CLOSE) -_(TOK_LT) _(TOK_GT) -_(TOK_SQUARE_OPEN) _(TOK_SQUARE_CLOSE) -_(TOK_COMMA) -_(TOK_SEMICOLON) -_(TOK_COLON) -_(TOK_DOUBLE_COLON) -_(TOK_STAR) _(TOK_AMP) -_(TOK_PIPE) - -_(TOK_FATARROW) // => -_(TOK_THINARROW) // -> -_(TOK_THINARROW_LEFT) // <- - -_(TOK_PLUS) _(TOK_DASH) -_(TOK_EXCLAM) -_(TOK_PERCENT) -_(TOK_SLASH) - -_(TOK_DOT) -_(TOK_DOUBLE_DOT) -_(TOK_TRIPLE_DOT) - -_(TOK_EQUAL) -_(TOK_PLUS_EQUAL) -_(TOK_DASH_EQUAL) -_(TOK_PERCENT_EQUAL) -_(TOK_SLASH_EQUAL) -_(TOK_STAR_EQUAL) -_(TOK_AMP_EQUAL) -_(TOK_PIPE_EQUAL) - -_(TOK_DOUBLE_EQUAL) -_(TOK_EXCLAM_EQUAL) -_(TOK_GTE) -_(TOK_LTE) - -_(TOK_DOUBLE_AMP) -_(TOK_DOUBLE_PIPE) -_(TOK_DOUBLE_LT) -_(TOK_DOUBLE_GT) -_(TOK_DOUBLE_LT_EQUAL) -_(TOK_DOUBLE_GT_EQUAL) - -_(TOK_DOLLAR) - -_(TOK_QMARK) -_(TOK_AT) -_(TOK_TILDE) -_(TOK_BACKSLASH) -_(TOK_CARET) -_(TOK_CARET_EQUAL) -_(TOK_BACKTICK) - -// Reserved Words -// NOTE: ORDERING MATTERS! _PUB must be the first, and no non-rword tokens should follow -_(TOK_RWORD_PUB) -_(TOK_RWORD_PRIV) -_(TOK_RWORD_MUT) -_(TOK_RWORD_CONST) -_(TOK_RWORD_STATIC) -_(TOK_RWORD_UNSAFE) -_(TOK_RWORD_EXTERN) - -_(TOK_RWORD_CRATE) -_(TOK_RWORD_MOD) -_(TOK_RWORD_STRUCT) -_(TOK_RWORD_ENUM) -_(TOK_RWORD_TRAIT) -_(TOK_RWORD_FN) -_(TOK_RWORD_USE) -_(TOK_RWORD_IMPL) -_(TOK_RWORD_TYPE) - -_(TOK_RWORD_WHERE) -_(TOK_RWORD_AS) - -_(TOK_RWORD_LET) -_(TOK_RWORD_MATCH) -_(TOK_RWORD_IF) -_(TOK_RWORD_ELSE) -_(TOK_RWORD_LOOP) -_(TOK_RWORD_WHILE) -_(TOK_RWORD_FOR) -_(TOK_RWORD_IN) -_(TOK_RWORD_DO) - -_(TOK_RWORD_CONTINUE) -_(TOK_RWORD_BREAK) -_(TOK_RWORD_RETURN) -_(TOK_RWORD_YIELD) -_(TOK_RWORD_BOX) -_(TOK_RWORD_REF) - -_(TOK_RWORD_FALSE) -_(TOK_RWORD_TRUE) -_(TOK_RWORD_SELF) -_(TOK_RWORD_SUPER) - -_(TOK_RWORD_PROC) -_(TOK_RWORD_MOVE) - -_(TOK_RWORD_ABSTRACT) -_(TOK_RWORD_FINAL) -_(TOK_RWORD_PURE) -_(TOK_RWORD_OVERRIDE) -_(TOK_RWORD_VIRTUAL) - -_(TOK_RWORD_ALIGNOF) -_(TOK_RWORD_OFFSETOF) -_(TOK_RWORD_SIZEOF) -_(TOK_RWORD_TYPEOF) - -_(TOK_RWORD_BE) -_(TOK_RWORD_UNSIZED) diff --git a/gcc/rust/test2/rustfrontend/rs-generic-converter.cc b/gcc/rust/test2/rustfrontend/rs-generic-converter.cc deleted file mode 100644 index 4d2958a..0000000 --- a/gcc/rust/test2/rustfrontend/rs-generic-converter.cc +++ /dev/null @@ -1,7 +0,0 @@ -// rs-generic-converter.cc - converts internal AST representation to GENERIC - -// Copyright, etc. - -#include "coretypes.h" - -static tree gccTree; \ No newline at end of file diff --git a/gcc/rust/test2/rustfrontend/rs-lex.cc b/gcc/rust/test2/rustfrontend/rs-lex.cc deleted file mode 100644 index 309c83f..0000000 --- a/gcc/rust/test2/rustfrontend/rs-lex.cc +++ /dev/null @@ -1,2884 +0,0 @@ -// lex.cc -- Go frontend lexer. - -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//#include "go-system.h" -//#include "go-diagnostics.h" - -#include "rs-lex.h" - -// Manage mapping from keywords to the Keyword codes. - -class Keywords { - public: - // The structure which maps keywords to codes. - struct Mapping { - // Keyword string. - const char* keystring; - // Keyword code. - Keyword keycode; - }; - - // Return the parsecode corresponding to KEYSTRING, or - // KEYWORD_INVALID if it is not a keyword. - Keyword keyword_to_code(const char* keyword, size_t len) const; - - // Return the string for a keyword. - const char* keyword_to_string(Keyword) const; - - private: - static const Mapping mapping_[]; - static const int count_; -}; - -// Mapping from keyword string to keyword code. This array must be -// kept in sorted order, and the order must match the Keyword enum. -// Strings are looked up using bsearch. - -const Keywords::Mapping - Keywords::mapping_[] = { - { NULL, KEYWORD_INVALID }, - { "_", KEYWORD_UNDERSCORE }, - { "abstract", KEYWORD_ABSTRACT }, - { "alignof", KEYWORD_ALIGNOF }, - { "as", KEYWORD_AS }, - { "be", KEYWORD_BE }, - { "box", KEYWORD_BOX }, - { "break", KEYWORD_BREAK }, - { "const", KEYWORD_CONST }, - { "continue", KEYWORD_CONTINUE }, - { "crate", KEYWORD_CRATE }, - { "do", KEYWORD_DO }, - { "else", KEYWORD_ELSE }, - { "enum", KEYWORD_ENUM }, - { "extern", KEYWORD_EXTERN }, - { "false", KEYWORD_FALSE }, - { "final", KEYWORD_FINAL }, - { "fn", KEYWORD_FN }, - { "for", KEYWORD_FOR }, - { "if", KEYWORD_IF }, - { "impl", KEYWORD_IMPL }, - { "in", KEYWORD_IN }, - { "let", KEYWORD_LET }, - { "loop", KEYWORD_LOOP }, - { "match", KEYWORD_MATCH }, - { "mod", KEYWORD_MOD }, - { "move", KEYWORD_MOVE }, - { "mut", KEYWORD_MUT }, - { "offsetof", KEYWORD_OFFSETOF }, - { "override", KEYWORD_OVERRIDE }, - { "priv", KEYWORD_PRIV }, - { "proc", KEYWORD_PROC }, - { "pub", KEYWORD_PUB }, - { "pure", KEYWORD_PURE }, - { "ref", KEYWORD_REF }, - { "return", KEYWORD_RETURN }, - { "self", KEYWORD_SELF }, - { "sizeof", KEYWORD_SIZEOF }, - { "static", KEYWORD_STATIC }, - { "struct", KEYWORD_STRUCT }, - { "switch", KEYWORD_SUPER }, - { "trait", KEYWORD_TRAIT }, - { "true", KEYWORD_TRUE }, - { "type", KEYWORD_TYPE }, - { "typeof", KEYWORD_TYPEOF }, - { "unsafe", KEYWORD_UNSAFE }, - { "unsized", KEYWORD_UNSIZED }, - { "use", KEYWORD_USE }, - { "virtual", KEYWORD_VIRTUAL }, - { "where", KEYWORD_WHERE }, - { "while", KEYWORD_WHILE }, - { "yield", KEYWORD_YIELD } - }; - -// Number of entries in the map. - -const int Keywords::count_ = sizeof(Keywords::mapping_) / sizeof(Keywords::mapping_[0]); - -// Comparison function passed to bsearch. - -extern "C" { - -struct Keywords_search_key { - const char* str; - size_t len; -}; - -static int keyword_compare(const void* keyv, const void* mapv) { - const Keywords_search_key* key = static_cast(keyv); - const Keywords::Mapping* map = static_cast(mapv); - - if (map->keystring == NULL) - return 1; - - int i = strncmp(key->str, map->keystring, key->len); - - if (i != 0) - return i; - - if (map->keystring[key->len] != '\0') - return -1; - - return 0; -} - -} // End extern "C". - -// Convert a string to a keyword code. Return KEYWORD_INVALID if the -// string is not a keyword. - -Keyword Keywords::keyword_to_code(const char* keyword, size_t len) const { - Keywords_search_key key; - key.str = keyword; - key.len = len; - - void* mapv = bsearch(&key, - this->mapping_, - this->count_, - sizeof(this->mapping_[0]), - keyword_compare); - if (mapv == NULL) - return KEYWORD_INVALID; - - Mapping* map = static_cast(mapv); - - return map->keycode; -} - -// Convert a keyword code to a string. - -const char* Keywords::keyword_to_string(Keyword code) const { - gcc_assert(code > KEYWORD_INVALID && code < this->count_); - const Mapping* map = &this->mapping_[code]; - gcc_assert(map->keycode == code); - return map->keystring; -} - -// There is one instance of the Keywords class. - -static Keywords keywords; - -// Class Token. - -// Make a general token. - -Token::Token(Classification classification, Location location) - : classification_(classification), location_(location) { -} - -// Destroy a token. - -Token::~Token() { - this->clear(); -} - -// Clear a token--release memory. - -void Token::clear() { - if (this->classification_ == TOKEN_INTEGER || this->classification_ == TOKEN_CHARACTER) - mpz_clear(this->u_.integer_value); - else if (this->classification_ == TOKEN_FLOAT || this->classification_ == TOKEN_IMAGINARY) - mpfr_clear(this->u_.float_value); -} - -// Construct a token. - -Token::Token(const Token& tok) : classification_(tok.classification_), location_(tok.location_) { - switch (this->classification_) { - case TOKEN_INVALID: - case TOKEN_EOF: - break; - case TOKEN_KEYWORD: - this->u_.keyword = tok.u_.keyword; - break; - case TOKEN_IDENTIFIER: - case TOKEN_STRING: - this->u_.string_value = tok.u_.string_value; - break; - case TOKEN_OPERATOR: - this->u_.op = tok.u_.op; - break; - case TOKEN_CHARACTER: - case TOKEN_INTEGER: - mpz_init_set(this->u_.integer_value, tok.u_.integer_value); - break; - case TOKEN_FLOAT: - case TOKEN_IMAGINARY: - mpfr_init_set(this->u_.float_value, tok.u_.float_value, GMP_RNDN); - break; - default: - gcc_unreachable(); - } -} - -// Assign to a token. - -Token& -Token::operator=(const Token& tok) { - this->clear(); - this->classification_ = tok.classification_; - this->location_ = tok.location_; - switch (tok.classification_) { - case TOKEN_INVALID: - case TOKEN_EOF: - break; - case TOKEN_KEYWORD: - this->u_.keyword = tok.u_.keyword; - break; - case TOKEN_IDENTIFIER: - this->u_.identifier_value.name = tok.u_.identifier_value.name; - this->u_.identifier_value.is_exported = - tok.u_.identifier_value.is_exported; - break; - case TOKEN_STRING: - this->u_.string_value = tok.u_.string_value; - break; - case TOKEN_OPERATOR: - this->u_.op = tok.u_.op; - break; - case TOKEN_CHARACTER: - case TOKEN_INTEGER: - mpz_init_set(this->u_.integer_value, tok.u_.integer_value); - break; - case TOKEN_FLOAT: - case TOKEN_IMAGINARY: - mpfr_init_set(this->u_.float_value, tok.u_.float_value, GMP_RNDN); - break; - default: - go_unreachable(); - } - return *this; -} - -// Print the token for debugging. - -void Token::print(FILE* file) const { - switch (this->classification_) { - case TOKEN_INVALID: - fprintf(file, "invalid"); - break; - case TOKEN_EOF: - fprintf(file, "EOF"); - break; - case TOKEN_KEYWORD: - fprintf(file, "keyword %s", keywords.keyword_to_string(this->u_.keyword)); - break; - case TOKEN_IDENTIFIER: - fprintf(file, "identifier \"%s\"", this->u_.string_value->c_str()); - break; - case TOKEN_STRING: - fprintf(file, "quoted string \"%s\"", this->u_.string_value->c_str()); - break; - case TOKEN_CHARACTER: - fprintf(file, "character "); - mpz_out_str(file, 10, this->u_.integer_value); - break; - case TOKEN_INTEGER: - fprintf(file, "integer "); - mpz_out_str(file, 10, this->u_.integer_value); - break; - case TOKEN_FLOAT: - fprintf(file, "float "); - mpfr_out_str(file, 10, 0, this->u_.float_value, GMP_RNDN); - break; - case TOKEN_IMAGINARY: - fprintf(file, "imaginary "); - mpfr_out_str(file, 10, 0, this->u_.float_value, GMP_RNDN); - break; - case TOKEN_OPERATOR: - fprintf(file, "operator "); - switch (this->u_.op) { - case OPERATOR_INVALID: - fprintf(file, "invalid"); - break; - case OPERATOR_DOUBLE_PIPE: - fprintf(file, "||"); - break; - case OPERATOR_DOUBLE_AMP: - fprintf(file, "&&"); - break; - case OPERATOR_DOUBLE_EQ: - fprintf(file, "=="); - break; - case OPERATOR_EXCLAM_EQ: - fprintf(file, "!="); - break; - case OPERATOR_LT: - fprintf(file, "<"); - break; - case OPERATOR_LE: - fprintf(file, "<="); - break; - case OPERATOR_GT: - fprintf(file, ">"); - break; - case OPERATOR_GE: - fprintf(file, ">="); - break; - case OPERATOR_PLUS: - fprintf(file, "+"); - break; - case OPERATOR_MINUS: - fprintf(file, "-"); - break; - case OPERATOR_PIPE: - fprintf(file, "|"); - break; - case OPERATOR_CARET: - fprintf(file, "^"); - break; - case OPERATOR_MULT: - fprintf(file, "*"); - break; - case OPERATOR_DIV: - fprintf(file, "/"); - break; - case OPERATOR_PERCENT: - fprintf(file, "%%"); - break; - case OPERATOR_LSHIFT: - fprintf(file, "<<"); - break; - case OPERATOR_RSHIFT: - fprintf(file, ">>"); - break; - case OPERATOR_AMP: - fprintf(file, "&"); - break; - /* case OPERATOR_BITCLEAR: - fprintf(file, "&^"); - break;*/ - case OPERATOR_EXCLAM: - fprintf(file, "!"); - break; - case OPERATOR_LEFT_ARROW: - fprintf(file, "<-"); - break; - case OPERATOR_RIGHT_ARROW: - fprintf(file, "->"); - break; - case OPERATOR_EQ: - fprintf(file, "="); - break; - case OPERATOR_PLUS_EQ: - fprintf(file, "+="); - break; - case OPERATOR_MINUS_EQ: - fprintf(file, "-="); - break; - case OPERATOR_PIPE_EQ: - fprintf(file, "|="); - break; - case OPERATOR_CARET_EQ: - fprintf(file, "^="); - break; - case OPERATOR_MULT_EQ: - fprintf(file, "*="); - break; - case OPERATOR_DIV_EQ: - fprintf(file, "/="); - break; - case OPERATOR_PERCENT_EQ: - fprintf(file, "%%="); - break; - case OPERATOR_LSHIFTEQ: - fprintf(file, "<<="); - break; - case OPERATOR_RSHIFTEQ: - fprintf(file, ">>="); - break; - case OPERATOR_AMP_EQ: - fprintf(file, "&="); - break; - /* case OPERATOR_BITCLEAREQ: - fprintf(file, "&^="); - break; - case OPERATOR_PLUSPLUS: - fprintf(file, "++"); - break; - case OPERATOR_MINUSMINUS: - fprintf(file, "--"); - break;*/ - case OPERATOR_COLON: - fprintf(file, ":"); - break; - case OPERATOR_DOUBLE_COLON: - fprintf(file, "::"); - /* case OPERATOR_COLONEQ: - fprintf(file, ":="); - break;*/ - case OPERATOR_SEMICOLON: - fprintf(file, ";"); - break; - case OPERATOR_DOT: - fprintf(file, "."); - break; - case OPERATOR_DOUBLE_DOT: - fprintf(file, ".."); - break; - case OPERATOR_ELLIPSIS: - fprintf(file, "..."); - break; - case OPERATOR_COMMA: - fprintf(file, ","); - break; - case OPERATOR_LPAREN: - fprintf(file, "("); - break; - case OPERATOR_RPAREN: - fprintf(file, ")"); - break; - case OPERATOR_LCURLY: - fprintf(file, "{"); - break; - case OPERATOR_RCURLY: - fprintf(file, "}"); - break; - case OPERATOR_LSQUARE: - fprintf(file, "["); - break; - case OPERATOR_RSQUARE: - fprintf(file, "]"); - break; - case OPERATOR_TILDE: - fprintf(file, "~"); - break; - case OPERATOR_HASH: - fprintf(file, "#"); - break; - case OPERATOR_DOUBLE_QUOTE: - fprintf(file, "\""); - break; - case OPERATOR_SINGLE_QUOTE: - fprintf(file, "'"); - break; - case OPERATOR_DOLLAR: - fprintf(file, "$"); - break; - case OPERATOR_FSLASH: - fprintf(file, "/"); - break; - case OPERATOR_BACKSLASH: - fprintf(file, "\\"); - break; - case OPERATOR_BLOCK_COMMENT: - fprintf(file, "/*"); - break; - case OPERATOR_LINE_COMMENT: - fprintf(file, "//"); - break; - case OPERATOR_QMARK: - fprintf(file, "?"); - break; - case OPERATOR_AT: - fprintf(file, "@"); - break; - case OPERATOR_BACKTICK: - fprintf(file, "`"); - break; - default: - gcc_unreachable(); - } - break; - default: - gcc_unreachable(); - } -} - -// Class Lex. - -Lex::Lex(const char* input_file_name, FILE* input_file, Linemap* linemap) - : input_file_name_(input_file_name) - , input_file_(input_file) - , linemap_(linemap) - , linebuf_(NULL) - , linebufsize_(120) - , linesize_(0) - , lineoff_(0) - , lineno_(0) - , add_semi_at_eol_(false) - , pragmas_(0) - , extern_() - , linknames_(NULL) { - this->linebuf_ = new char[this->linebufsize_]; - this->linemap_->start_file(input_file_name, 0); -} - -Lex::~Lex() { - delete[] this->linebuf_; -} - -// Read a new line from the file. - -ssize_t -Lex::get_line() { - char* buf = this->linebuf_; - size_t size = this->linebufsize_; - - FILE* file = this->input_file_; - size_t cur = 0; - while (true) { - int c = getc(file); - if (c == EOF) { - if (cur == 0) - return -1; - break; - } - if (cur + 1 >= size) { - size_t ns = 2 * size + 1; - if (ns < size || static_cast(ns) < 0) - go_error_at(this->location(), "out of memory"); - char* nb = new char[ns]; - memcpy(nb, buf, cur); - delete[] buf; - buf = nb; - size = ns; - } - buf[cur] = c; - ++cur; - - if (c == '\n') - break; - } - - buf[cur] = '\0'; - - this->linebuf_ = buf; - this->linebufsize_ = size; - - return cur; -} - -// See if we need to read a new line. Return true if there is a new -// line, false if we are at EOF. - -bool Lex::require_line() { - if (this->lineoff_ < this->linesize_) - return true; - - ssize_t got = this->get_line(); - if (got < 0) - return false; - ++this->lineno_; - this->linesize_ = got; - this->lineoff_ = 0; - - this->linemap_->start_line(this->lineno_, this->linesize_); - - return true; -} - -// Get the current location. - -Location -Lex::location() const { - return this->linemap_->get_location(this->lineoff_ + 1); -} - -// Get a location slightly before the current one. This is used for -// slightly more efficient handling of operator tokens. - -Location -Lex::earlier_location(int chars) const { - return this->linemap_->get_location(this->lineoff_ + 1 - chars); -} - -// Get the next token. - -Token Lex::next_token() { - bool saw_cpp_comment = false; - while (true) { - if (!this->require_line()) { - bool add_semi_at_eol = this->add_semi_at_eol_; - this->add_semi_at_eol_ = false; - if (add_semi_at_eol) - return this->make_operator(OPERATOR_SEMICOLON, 1); - return this->make_eof_token(); - } - - if (!saw_cpp_comment) - this->extern_.clear(); - saw_cpp_comment = false; - - const char* p = this->linebuf_ + this->lineoff_; - const char* pend = this->linebuf_ + this->linesize_; - - while (p < pend) { - unsigned char cc = *p; - switch (cc) { - case ' ': - case '\t': - case '\r': - ++p; - // Skip whitespace quickly. - while (*p == ' ' || *p == '\t' || *p == '\r') - ++p; - break; - - case '\n': { - ++p; - bool add_semi_at_eol = this->add_semi_at_eol_; - this->add_semi_at_eol_ = false; - if (add_semi_at_eol) { - this->lineoff_ = p - this->linebuf_; - return this->make_operator(OPERATOR_SEMICOLON, 1); - } - } break; - - case '/': - if (p[1] == '/') { - this->lineoff_ = p + 2 - this->linebuf_; - this->skip_cpp_comment(); - p = pend; - if (p[-1] == '\n' && this->add_semi_at_eol_) - --p; - saw_cpp_comment = true; - } else if (p[1] == '*') { - this->lineoff_ = p + 2 - this->linebuf_; - Location location = this->location(); - bool found_newline = false; - if (!this->skip_c_comment(&found_newline)) - return Token::make_invalid_token(location); - if (found_newline && this->add_semi_at_eol_) { - this->add_semi_at_eol_ = false; - return this->make_operator(OPERATOR_SEMICOLON, 1); - } - p = this->linebuf_ + this->lineoff_; - pend = this->linebuf_ + this->linesize_; - } else if (p[1] == '=') { - this->add_semi_at_eol_ = false; - this->lineoff_ = p + 2 - this->linebuf_; - return this->make_operator(OPERATOR_DIVEQ, 2); - } else { - this->add_semi_at_eol_ = false; - this->lineoff_ = p + 1 - this->linebuf_; - return this->make_operator(OPERATOR_DIV, 1); - } - break; - - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': - case '_': - this->lineoff_ = p - this->linebuf_; - return this->gather_identifier(); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - return this->gather_number(); - - case '\'': - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - return this->gather_character(); - - case '"': - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - return this->gather_string(); - - case '`': - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - return this->gather_raw_string(); - - case '<': - case '>': - case '&': - if (p + 2 < pend) { - this->add_semi_at_eol_ = false; - Operator op = this->three_character_operator(cc, p[1], p[2]); - if (op != OPERATOR_INVALID) { - this->lineoff_ = p + 3 - this->linebuf_; - return this->make_operator(op, 3); - } - } - // Fall through. - case '|': - case '=': - case '!': - case '+': - case '-': - case '^': - case '*': - // '/' handled above. - case '%': - case ':': - case ';': - case ',': - case '(': - case ')': - case '{': - case '}': - case '[': - case ']': { - this->add_semi_at_eol_ = false; - Operator op = this->two_character_operator(cc, p[1]); - int chars; - if (op != OPERATOR_INVALID) { - ++p; - chars = 2; - } else { - op = this->one_character_operator(cc); - chars = 1; - } - this->lineoff_ = p + 1 - this->linebuf_; - return this->make_operator(op, chars); - } - - case '.': - if (p[1] >= '0' && p[1] <= '9') { - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - return this->gather_number(); - } - if (p[1] == '.' && p[2] == '.') { - this->add_semi_at_eol_ = false; - this->lineoff_ = p + 3 - this->linebuf_; - return this->make_operator(OPERATOR_ELLIPSIS, 3); - } - this->add_semi_at_eol_ = false; - this->lineoff_ = p + 1 - this->linebuf_; - return this->make_operator(OPERATOR_DOT, 1); - - default: { - unsigned int ci; - bool issued_error; - this->lineoff_ = p - this->linebuf_; - const char* pnext = this->advance_one_utf8_char(p, &ci, &issued_error); - - // Ignore byte order mark at start of file. - if (ci == 0xfeff) { - p = pnext; - break; - } - - if (Lex::is_unicode_letter(ci)) - return this->gather_identifier(); - - if (!issued_error) - go_error_at(this->location(), - "invalid character 0x%x in input file", - ci); - - p = pend; - - break; - } - } - } - - this->lineoff_ = p - this->linebuf_; - } -} - -// Fetch one UTF-8 character from a string. Set *VALUE to the value. -// Return the number of bytes read from the string. Returns 0 if the -// string does not point to a valid UTF-8 character. - -int Lex::fetch_char(const char* p, unsigned int* value) { - unsigned char c = *p; - if (c <= 0x7f) { - *value = c; - return 1; - } else if ((c & 0xe0) == 0xc0 && (p[1] & 0xc0) == 0x80) { - *value = (((c & 0x1f) << 6) + (p[1] & 0x3f)); - if (*value <= 0x7f) { - *value = 0xfffd; - return 0; - } - return 2; - } else if ((c & 0xf0) == 0xe0 && (p[1] & 0xc0) == 0x80 && (p[2] & 0xc0) == 0x80) { - *value = (((c & 0xf) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f)); - if (*value <= 0x7ff) { - *value = 0xfffd; - return 0; - } - return 3; - } else if ((c & 0xf8) == 0xf0 && (p[1] & 0xc0) == 0x80 && (p[2] & 0xc0) == 0x80 && (p[3] & 0xc0) == 0x80) { - *value = (((c & 0x7) << 18) + ((p[1] & 0x3f) << 12) + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f)); - if (*value <= 0xffff) { - *value = 0xfffd; - return 0; - } - return 4; - } else { - /* Invalid encoding. Return the Unicode replacement - character. */ - *value = 0xfffd; - return 0; - } -} - -// Advance one UTF-8 character. Return the pointer beyond the -// character. Set *VALUE to the value. Set *ISSUED_ERROR if an error -// was issued. - -const char* -Lex::advance_one_utf8_char(const char* p, unsigned int* value, bool* issued_error) { - *issued_error = false; - - if (*p == '\0') { - go_error_at(this->location(), "invalid NUL byte"); - *issued_error = true; - *value = 0; - return p + 1; - } - - int adv = Lex::fetch_char(p, value); - if (adv == 0) { - go_error_at(this->location(), "invalid UTF-8 encoding"); - *issued_error = true; - return p + 1; - } - - // Warn about byte order mark, except at start of file. - if (*value == 0xfeff && (this->lineno_ != 1 || this->lineoff_ != 0)) { - go_error_at(this->location(), "Unicode (UTF-8) BOM in middle of file"); - *issued_error = true; - } - - return p + adv; -} - -// Pick up an identifier. - -Token Lex::gather_identifier() { - const char* pstart = this->linebuf_ + this->lineoff_; - const char* p = pstart; - const char* pend = this->linebuf_ + this->linesize_; - bool is_first = true; - bool is_exported = false; - bool has_non_ascii_char = false; - std::string buf; - while (p < pend) { - unsigned char cc = *p; - if (cc <= 0x7f) { - if ((cc < 'A' || cc > 'Z') && (cc < 'a' || cc > 'z') && cc != '_' && (cc < '0' || cc > '9')) { - // Check for an invalid character here, as we get better - // error behaviour if we swallow them as part of the - // identifier we are building. - if ((cc >= ' ' && cc < 0x7f) || cc == '\t' || cc == '\r' || cc == '\n') - break; - - this->lineoff_ = p - this->linebuf_; - go_error_at(this->location(), - "invalid character 0x%x in identifier", - cc); - if (!has_non_ascii_char) { - buf.assign(pstart, p - pstart); - has_non_ascii_char = true; - } - if (!Lex::is_invalid_identifier(buf)) - buf.append("$INVALID$"); - } - ++p; - if (is_first) { - is_exported = cc >= 'A' && cc <= 'Z'; - is_first = false; - } - if (has_non_ascii_char) - buf.push_back(cc); - } else { - unsigned int ci; - bool issued_error; - this->lineoff_ = p - this->linebuf_; - const char* pnext = this->advance_one_utf8_char(p, &ci, &issued_error); - bool is_invalid = false; - if (!Lex::is_unicode_letter(ci) && !Lex::is_unicode_digit(ci)) { - // There is no valid place for a non-ASCII character - // other than an identifier, so we get better error - // handling behaviour if we swallow this character after - // giving an error. - if (!issued_error) - go_error_at(this->location(), - "invalid character 0x%x in identifier", - ci); - is_invalid = true; - } - if (is_first) { - is_exported = Lex::is_unicode_uppercase(ci); - is_first = false; - } - if (!has_non_ascii_char) { - buf.assign(pstart, p - pstart); - has_non_ascii_char = true; - } - if (is_invalid && !Lex::is_invalid_identifier(buf)) - buf.append("$INVALID$"); - buf.append(p, pnext - p); - p = pnext; - } - } - Location location = this->location(); - this->add_semi_at_eol_ = true; - this->lineoff_ = p - this->linebuf_; - if (has_non_ascii_char) - return Token::make_identifier_token(buf, is_exported, location); - else { - Keyword code = keywords.keyword_to_code(pstart, p - pstart); - if (code == KEYWORD_INVALID) - return Token::make_identifier_token(std::string(pstart, p - pstart), - is_exported, - location); - else { - switch (code) { - case KEYWORD_BREAK: - case KEYWORD_CONTINUE: - case KEYWORD_FALLTHROUGH: - case KEYWORD_RETURN: - break; - default: - this->add_semi_at_eol_ = false; - break; - } - return Token::make_keyword_token(code, location); - } - } -} - -// Return whether C is a hex digit. - -bool Lex::is_hex_digit(char c) { - return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); -} - -// not a hex value -#define NHV 100 - -// for use by Lex::hex_val -static const unsigned char hex_value_lookup_table[256] = - { - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // NUL SOH STX ETX EOT ENQ ACK BEL - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // BS HT LF VT FF CR SO SI - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // DLE DC1 DC2 DC3 DC4 NAK SYN ETB - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // CAN EM SUB ESC FS GS RS US - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // SP ! " # $ % & ' - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // ( ) * + , - . / - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, // 0 1 2 3 4 5 6 7 - 8, - 9, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // 8 9 : ; < = > ? - NHV, - 10, - 11, - 12, - 13, - 14, - 15, - NHV, // @ A B C D E F G - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // H I J K L M N O - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // P Q R S T U V W - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // X Y Z [ \ ] ^ _ - NHV, - 10, - 11, - 12, - 13, - 14, - 15, - NHV, // ` a b c d e f g - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // h i j k l m n o - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // p q r s t u v w - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // x y z { | } ~ - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, // - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV, - NHV // - }; - -unsigned -Lex::hex_val(char c) { - return hex_value_lookup_table[static_cast(c)]; -} - -// Return whether an exponent could start at P. - -bool Lex::could_be_exponent(const char* p, const char* pend) { - if (*p != 'e' && *p != 'E') - return false; - ++p; - if (p >= pend) - return false; - if (*p == '+' || *p == '-') { - ++p; - if (p >= pend) - return false; - } - return *p >= '0' && *p <= '9'; -} - -// Pick up a number. - -Token Lex::gather_number() { - const char* pstart = this->linebuf_ + this->lineoff_; - const char* p = pstart; - const char* pend = this->linebuf_ + this->linesize_; - - Location location = this->location(); - - bool neg = false; - if (*p == '+') - ++p; - else if (*p == '-') { - ++p; - neg = true; - } - - const char* pnum = p; - if (*p == '0') { - int base; - if ((p[1] == 'x' || p[1] == 'X') && Lex::is_hex_digit(p[2])) { - base = 16; - p += 2; - pnum = p; - while (p < pend) { - if (!Lex::is_hex_digit(*p)) - break; - ++p; - } - } else { - base = 8; - pnum = p; - while (p < pend) { - if (*p < '0' || *p > '9') - break; - ++p; - } - } - - // A partial token that looks like an octal literal might actually be the - // beginning of a floating-point or imaginary literal. - if (base == 16 || (*p != '.' && *p != 'i' && !Lex::could_be_exponent(p, pend))) { - std::string s(pnum, p - pnum); - mpz_t val; - int r = mpz_init_set_str(val, s.c_str(), base); - if (r != 0) { - if (base == 8) - go_error_at(this->location(), "invalid octal literal"); - else - go_error_at(this->location(), "invalid hex literal"); - } - - if (neg) - mpz_neg(val, val); - - this->lineoff_ = p - this->linebuf_; - Token ret = Token::make_integer_token(val, location); - mpz_clear(val); - return ret; - } - } - - while (p < pend) { - if (*p < '0' || *p > '9') - break; - ++p; - } - - if (*p != '.' && *p != 'i' && !Lex::could_be_exponent(p, pend)) { - std::string s(pnum, p - pnum); - mpz_t val; - int r = mpz_init_set_str(val, s.c_str(), 10); - go_assert(r == 0); - - if (neg) - mpz_neg(val, val); - - this->lineoff_ = p - this->linebuf_; - Token ret = Token::make_integer_token(val, location); - mpz_clear(val); - return ret; - } - - if (*p != 'i') { - bool dot = *p == '.'; - - ++p; - - if (!dot) { - if (*p == '+' || *p == '-') - ++p; - } - - while (p < pend) { - if (*p < '0' || *p > '9') - break; - ++p; - } - - if (dot && Lex::could_be_exponent(p, pend)) { - ++p; - if (*p == '+' || *p == '-') - ++p; - while (p < pend) { - if (*p < '0' || *p > '9') - break; - ++p; - } - } - } - - std::string s(pnum, p - pnum); - mpfr_t val; - int r = mpfr_init_set_str(val, s.c_str(), 10, GMP_RNDN); - go_assert(r == 0); - - if (neg) - mpfr_neg(val, val, GMP_RNDN); - - bool is_imaginary = *p == 'i'; - if (is_imaginary) - ++p; - - this->lineoff_ = p - this->linebuf_; - if (is_imaginary) { - Token ret = Token::make_imaginary_token(val, location); - mpfr_clear(val); - return ret; - } else { - Token ret = Token::make_float_token(val, location); - mpfr_clear(val); - return ret; - } -} - -// Advance one character, possibly escaped. Return the pointer beyond -// the character. Set *VALUE to the character. Set *IS_CHARACTER if -// this is a character (e.g., 'a' or '\u1234') rather than a byte -// value (e.g., '\001'). - -const char* -Lex::advance_one_char(const char* p, bool is_single_quote, unsigned int* value, bool* is_character) { - *value = 0; - *is_character = true; - if (*p != '\\') { - bool issued_error; - const char* ret = this->advance_one_utf8_char(p, value, &issued_error); - if (is_single_quote && (*value == '\'' || *value == '\n') && !issued_error) - go_error_at(this->location(), "invalid character literal"); - return ret; - } else { - ++p; - switch (*p) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - *is_character = false; - if (p[1] >= '0' && p[1] <= '7' && p[2] >= '0' && p[2] <= '7') { - *value = ((Lex::octal_value(p[0]) << 6) + (Lex::octal_value(p[1]) << 3) + Lex::octal_value(p[2])); - if (*value > 255) { - go_error_at(this->location(), "invalid octal constant"); - *value = 255; - } - return p + 3; - } - go_error_at(this->location(), "invalid octal character"); - return (p[1] >= '0' && p[1] <= '7' - ? p + 2 - : p + 1); - - case 'x': - *is_character = false; - if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2])) { - *value = (Lex::hex_val(p[1]) << 4) + Lex::hex_val(p[2]); - return p + 3; - } - go_error_at(this->location(), "invalid hex character"); - return (Lex::is_hex_digit(p[1]) - ? p + 2 - : p + 1); - - case 'a': - *value = '\a'; - return p + 1; - case 'b': - *value = '\b'; - return p + 1; - case 'f': - *value = '\f'; - return p + 1; - case 'n': - *value = '\n'; - return p + 1; - case 'r': - *value = '\r'; - return p + 1; - case 't': - *value = '\t'; - return p + 1; - case 'v': - *value = '\v'; - return p + 1; - case '\\': - *value = '\\'; - return p + 1; - case '\'': - if (!is_single_quote) - go_error_at(this->location(), "invalid quoted character"); - *value = '\''; - return p + 1; - case '"': - if (is_single_quote) - go_error_at(this->location(), "invalid quoted character"); - *value = '"'; - return p + 1; - - case 'u': - if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2]) && Lex::is_hex_digit(p[3]) && Lex::is_hex_digit(p[4])) { - *value = ((Lex::hex_val(p[1]) << 12) + (Lex::hex_val(p[2]) << 8) + (Lex::hex_val(p[3]) << 4) + Lex::hex_val(p[4])); - if (*value >= 0xd800 && *value < 0xe000) { - go_error_at(this->location(), - "invalid unicode code point 0x%x", - *value); - // Use the replacement character. - *value = 0xfffd; - } - return p + 5; - } - go_error_at(this->location(), "invalid little unicode code point"); - return p + 1; - - case 'U': - if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2]) && Lex::is_hex_digit(p[3]) && Lex::is_hex_digit(p[4]) && Lex::is_hex_digit(p[5]) && Lex::is_hex_digit(p[6]) && Lex::is_hex_digit(p[7]) && Lex::is_hex_digit(p[8])) { - *value = ((Lex::hex_val(p[1]) << 28) + (Lex::hex_val(p[2]) << 24) + (Lex::hex_val(p[3]) << 20) + (Lex::hex_val(p[4]) << 16) + (Lex::hex_val(p[5]) << 12) + (Lex::hex_val(p[6]) << 8) + (Lex::hex_val(p[7]) << 4) + Lex::hex_val(p[8])); - if (*value > 0x10ffff || (*value >= 0xd800 && *value < 0xe000)) { - go_error_at(this->location(), - "invalid unicode code point 0x%x", - *value); - // Use the replacement character. - *value = 0xfffd; - } - return p + 9; - } - go_error_at(this->location(), "invalid big unicode code point"); - return p + 1; - - default: - go_error_at(this->location(), "invalid character after %<\\%>"); - *value = *p; - return p + 1; - } - } -} - -// Append V to STR. IS_CHARACTER is true for a character which should -// be stored in UTF-8, false for a general byte value which should be -// stored directly. - -void Lex::append_char(unsigned int v, bool is_character, std::string* str, Location location) { - char buf[4]; - size_t len; - if (v <= 0x7f || !is_character) { - buf[0] = v; - len = 1; - } else if (v <= 0x7ff) { - buf[0] = 0xc0 + (v >> 6); - buf[1] = 0x80 + (v & 0x3f); - len = 2; - } else { - if (v > 0x10ffff) { - go_warning_at(location, 0, "unicode code point 0x%x out of range in string", v); - // Turn it into the "replacement character". - v = 0xfffd; - } - if (v >= 0xd800 && v < 0xe000) { - go_warning_at(location, 0, "unicode code point 0x%x is invalid surrogate pair", v); - v = 0xfffd; - } - if (v <= 0xffff) { - buf[0] = 0xe0 + (v >> 12); - buf[1] = 0x80 + ((v >> 6) & 0x3f); - buf[2] = 0x80 + (v & 0x3f); - len = 3; - } else { - buf[0] = 0xf0 + (v >> 18); - buf[1] = 0x80 + ((v >> 12) & 0x3f); - buf[2] = 0x80 + ((v >> 6) & 0x3f); - buf[3] = 0x80 + (v & 0x3f); - len = 4; - } - } - str->append(buf, len); -} - -// Pick up a character literal. - -Token Lex::gather_character() { - ++this->lineoff_; - const char* pstart = this->linebuf_ + this->lineoff_; - const char* p = pstart; - - unsigned int value; - bool is_character; - p = this->advance_one_char(p, true, &value, &is_character); - - if (*p != '\'') { - go_error_at(this->location(), "unterminated character constant"); - this->lineoff_ = p - this->linebuf_; - return this->make_invalid_token(); - } - - mpz_t val; - mpz_init_set_ui(val, value); - - Location location = this->location(); - this->lineoff_ = p + 1 - this->linebuf_; - Token ret = Token::make_character_token(val, location); - mpz_clear(val); - return ret; -} - -// Pick up a quoted string. - -Token Lex::gather_string() { - const char* pstart = this->linebuf_ + this->lineoff_ + 1; - const char* p = pstart; - const char* pend = this->linebuf_ + this->linesize_; - - std::string value; - while (*p != '"') { - Location loc = this->location(); - unsigned int c; - bool is_character; - this->lineoff_ = p - this->linebuf_; - p = this->advance_one_char(p, false, &c, &is_character); - if (p >= pend) { - go_error_at(this->location(), "unterminated string"); - --p; - break; - } - Lex::append_char(c, is_character, &value, loc); - } - - Location location = this->location(); - this->lineoff_ = p + 1 - this->linebuf_; - return Token::make_string_token(value, location); -} - -// Pick up a raw string. - -Token Lex::gather_raw_string() { - const char* p = this->linebuf_ + this->lineoff_ + 1; - const char* pend = this->linebuf_ + this->linesize_; - Location location = this->location(); - - std::string value; - while (true) { - while (p < pend) { - if (*p == '`') { - this->lineoff_ = p + 1 - this->linebuf_; - return Token::make_string_token(value, location); - } - Location loc = this->location(); - unsigned int c; - bool issued_error; - this->lineoff_ = p - this->linebuf_; - p = this->advance_one_utf8_char(p, &c, &issued_error); - // "Carriage return characters ('\r') inside raw string literals - // are discarded from the raw string value." - if (c != '\r') - Lex::append_char(c, true, &value, loc); - } - this->lineoff_ = p - this->linebuf_; - if (!this->require_line()) { - go_error_at(location, "unterminated raw string"); - return Token::make_string_token(value, location); - } - p = this->linebuf_ + this->lineoff_; - pend = this->linebuf_ + this->linesize_; - } -} - -// If C1 C2 C3 are a three character operator, return the code. - -Operator -Lex::three_character_operator(char c1, char c2, char c3) { - if (c3 == '=') { - if (c1 == '<' && c2 == '<') - return OPERATOR_LSHIFTEQ; - else if (c1 == '>' && c2 == '>') - return OPERATOR_RSHIFTEQ; - else if (c1 == '&' && c2 == '^') - return OPERATOR_BITCLEAREQ; - } - return OPERATOR_INVALID; -} - -// If C1 C2 are a two character operator, return the code. - -Operator -Lex::two_character_operator(char c1, char c2) { - switch (c1) { - case '|': - if (c2 == '|') - return OPERATOR_OROR; - else if (c2 == '=') - return OPERATOR_OREQ; - break; - case '&': - if (c2 == '&') - return OPERATOR_ANDAND; - else if (c2 == '^') - return OPERATOR_BITCLEAR; - else if (c2 == '=') - return OPERATOR_ANDEQ; - break; - case '^': - if (c2 == '=') - return OPERATOR_XOREQ; - break; - case '=': - if (c2 == '=') - return OPERATOR_EQEQ; - break; - case '!': - if (c2 == '=') - return OPERATOR_NOTEQ; - break; - case '<': - if (c2 == '=') - return OPERATOR_LE; - else if (c2 == '<') - return OPERATOR_LSHIFT; - else if (c2 == '-') - return OPERATOR_CHANOP; - break; - case '>': - if (c2 == '=') - return OPERATOR_GE; - else if (c2 == '>') - return OPERATOR_RSHIFT; - break; - case '*': - if (c2 == '=') - return OPERATOR_MULTEQ; - break; - case '/': - if (c2 == '=') - return OPERATOR_DIVEQ; - break; - case '%': - if (c2 == '=') - return OPERATOR_MODEQ; - break; - case '+': - if (c2 == '+') { - this->add_semi_at_eol_ = true; - return OPERATOR_PLUSPLUS; - } else if (c2 == '=') - return OPERATOR_PLUSEQ; - break; - case '-': - if (c2 == '-') { - this->add_semi_at_eol_ = true; - return OPERATOR_MINUSMINUS; - } else if (c2 == '=') - return OPERATOR_MINUSEQ; - break; - case ':': - if (c2 == '=') - return OPERATOR_COLONEQ; - break; - default: - break; - } - return OPERATOR_INVALID; -} - -// If character C is an operator, return the code. - -Operator -Lex::one_character_operator(char c) { - switch (c) { - case '<': - return OPERATOR_LT; - case '>': - return OPERATOR_GT; - case '+': - return OPERATOR_PLUS; - case '-': - return OPERATOR_MINUS; - case '|': - return OPERATOR_OR; - case '^': - return OPERATOR_XOR; - case '*': - return OPERATOR_MULT; - case '/': - return OPERATOR_DIV; - case '%': - return OPERATOR_MOD; - case '&': - return OPERATOR_AND; - case '!': - return OPERATOR_NOT; - case '=': - return OPERATOR_EQ; - case ':': - return OPERATOR_COLON; - case ';': - return OPERATOR_SEMICOLON; - case '.': - return OPERATOR_DOT; - case ',': - return OPERATOR_COMMA; - case '(': - return OPERATOR_LPAREN; - case ')': - this->add_semi_at_eol_ = true; - return OPERATOR_RPAREN; - case '{': - return OPERATOR_LCURLY; - case '}': - this->add_semi_at_eol_ = true; - return OPERATOR_RCURLY; - case '[': - return OPERATOR_LSQUARE; - case ']': - this->add_semi_at_eol_ = true; - return OPERATOR_RSQUARE; - default: - return OPERATOR_INVALID; - } -} - -// Skip a C-style comment. - -bool Lex::skip_c_comment(bool* found_newline) { - while (true) { - if (!this->require_line()) { - go_error_at(this->location(), "unterminated comment"); - return false; - } - - const char* p = this->linebuf_ + this->lineoff_; - const char* pend = this->linebuf_ + this->linesize_; - - while (p < pend) { - if (p[0] == '*' && p + 1 < pend && p[1] == '/') { - this->lineoff_ = p + 2 - this->linebuf_; - return true; - } - - if (p[0] == '\n') - *found_newline = true; - - this->lineoff_ = p - this->linebuf_; - unsigned int c; - bool issued_error; - p = this->advance_one_utf8_char(p, &c, &issued_error); - } - - this->lineoff_ = p - this->linebuf_; - } -} - -// Skip a C++-style comment. - -void Lex::skip_cpp_comment() { - // Ensure that if EXTERN_ is set, it means that we just saw a - // //extern comment. - this->extern_.clear(); - - Location loc = this->location(); - size_t lineoff = this->lineoff_; - - const char* p = this->linebuf_ + lineoff; - const char* pend = this->linebuf_ + this->linesize_; - - const char* pcheck = p; - bool saw_error = false; - while (pcheck < pend) { - this->lineoff_ = pcheck - this->linebuf_; - unsigned int c; - bool issued_error; - pcheck = this->advance_one_utf8_char(pcheck, &c, &issued_error); - if (issued_error) - saw_error = true; - } - - if (saw_error) - return; - - // Recognize various magic comments at the start of a line. - - if (lineoff != 2) { - // Not at the start of the line. (lineoff == 2 because of the - // two characters in "//"). - return; - } - - while (pend > p && (pend[-1] == ' ' || pend[-1] == '\t' || pend[-1] == '\r' || pend[-1] == '\n')) - --pend; - - // A C++ comment at the start of the line of the form - // //line FILE:LINENO - // is interpreted as setting the file name and line number of the - // next source line. - if (pend - p > 5 && memcmp(p, "line ", 5) == 0) { - p += 5; - while (p < pend && *p == ' ') - ++p; - const char* pcolon = static_cast(memchr(p, ':', pend - p)); - if (pcolon != NULL && pcolon[1] >= '0' && pcolon[1] <= '9') { - char* plend; - long lineno = strtol(pcolon + 1, &plend, 10); - if (plend > pcolon + 1 && (plend == pend || *plend < '0' || *plend > '9') && lineno > 0 && lineno < 0x7fffffff) { - unsigned int filelen = pcolon - p; - char* file = new char[filelen + 1]; - memcpy(file, p, filelen); - file[filelen] = '\0'; - - this->linemap_->start_file(file, lineno); - this->lineno_ = lineno - 1; - - p = plend; - } - } - return; - } - - // As a special gccgo extension, a C++ comment at the start of the - // line of the form - // //extern NAME - // which immediately precedes a function declaration means that the - // external name of the function declaration is NAME. This is - // normally used to permit Go code to call a C function. - if (pend - p > 7 && memcmp(p, "extern ", 7) == 0) { - p += 7; - while (p < pend && (*p == ' ' || *p == '\t')) - ++p; - if (pend > p) - this->extern_ = std::string(p, pend - p); - return; - } - - // All other special comments start with "go:". - - if (pend - p < 4 || memcmp(p, "go:", 3) != 0) - return; - - const char* ps = p + 3; - while (ps < pend && *ps != ' ' && *ps != '\t') - ++ps; - std::string verb = std::string(p, ps - p); - - if (verb == "go:linkname") { - // As in the gc compiler, set the external link name for a Go symbol. - std::string go_name; - std::string ext_name; - bool is_exported = false; - if (ps < pend) { - while (ps < pend && (*ps == ' ' || *ps == '\t')) - ++ps; - if (ps < pend) { - const char* pg = ps; - - unsigned int c; - bool issued_error; - ps = this->advance_one_utf8_char(ps, &c, &issued_error); - is_exported = Lex::is_unicode_uppercase(c); - - while (ps < pend && *ps != ' ' && *ps != '\t') - ++ps; - if (ps < pend) - go_name = std::string(pg, ps - pg); - while (ps < pend && (*ps == ' ' || *ps == '\t')) - ++ps; - } - if (ps < pend) { - const char* pc = ps; - while (ps < pend && *ps != ' ' && *ps != '\t') - ++ps; - if (ps <= pend) - ext_name = std::string(pc, ps - pc); - } - if (ps != pend) { - go_name.clear(); - ext_name.clear(); - } - } - if (go_name.empty() || ext_name.empty()) - go_error_at(loc, "usage: //go:linkname localname linkname"); - else { - if (this->linknames_ == NULL) - this->linknames_ = new Linknames(); - (*this->linknames_)[go_name] = Linkname(ext_name, is_exported, loc); - } - } else if (verb == "go:nointerface") { - // For field tracking analysis: a //go:nointerface comment means - // that the next interface method should not be stored in the - // type descriptor. This permits it to be discarded if it is - // not needed. - this->pragmas_ |= GOPRAGMA_NOINTERFACE; - } else if (verb == "go:noescape") { - // Applies to the next function declaration. Any arguments do - // not escape. - // FIXME: Not implemented. - this->pragmas_ |= GOPRAGMA_NOESCAPE; - } else if (verb == "go:nosplit") { - // Applies to the next function. Do not split the stack when - // entering the function. - this->pragmas_ |= GOPRAGMA_NOSPLIT; - } else if (verb == "go:noinline") { - // Applies to the next function. Do not inline the function. - this->pragmas_ |= GOPRAGMA_NOINLINE; - } else if (verb == "go:notinheap") { - // Applies to the next type. The type does not live in the heap. - this->pragmas_ |= GOPRAGMA_NOTINHEAP; - } else if (verb == "go:systemstack") { - // Applies to the next function. It must run on the system stack. - // FIXME: Should only work when compiling the runtime package. - // FIXME: Not implemented. - this->pragmas_ |= GOPRAGMA_SYSTEMSTACK; - } else if (verb == "go:nowritebarrier") { - // Applies to the next function. If the function needs to use - // any write barriers, it should emit an error instead. - // FIXME: Should only work when compiling the runtime package. - this->pragmas_ |= GOPRAGMA_NOWRITEBARRIER; - } else if (verb == "go:nowritebarrierrec") { - // Applies to the next function. If the function, or any - // function that it calls, needs to use any write barriers, it - // should emit an error instead. - // FIXME: Should only work when compiling the runtime package. - this->pragmas_ |= GOPRAGMA_NOWRITEBARRIERREC; - } else if (verb == "go:yeswritebarrierrec") { - // Applies to the next function. Disables go:nowritebarrierrec - // when looking at callees; write barriers are permitted here. - // FIXME: Should only work when compiling the runtime package. - this->pragmas_ |= GOPRAGMA_YESWRITEBARRIERREC; - } else if (verb == "go:cgo_unsafe_args") { - // Applies to the next function. Taking the address of any - // argument implies taking the address of all arguments. - // FIXME: Not implemented. - this->pragmas_ |= GOPRAGMA_CGOUNSAFEARGS; - } else if (verb == "go:uintptrescapes") { - // Applies to the next function. If an argument is a pointer - // converted to uintptr, then the pointer escapes. - // FIXME: Not implemented. - this->pragmas_ |= GOPRAGMA_UINTPTRESCAPES; - } -} - -// The Unicode tables use this struct. - -struct Unicode_range { - // The low end of the range. - unsigned int low; - // The high end of the range. - unsigned int high; - // The stride. This entries represents low, low + stride, low + 2 * - // stride, etc., up to high. - unsigned int stride; -}; - -// A table of whitespace characters--Unicode code points classified as -// "Space", "C" locale whitespace characters, the "next line" control -// character (0085), the line separator (2028), the paragraph -// separator (2029), and the "zero-width non-break space" (feff). - -static const Unicode_range unicode_space[] = - { - { 0x0009, 0x000d, 1 }, - { 0x0020, 0x0020, 1 }, - { 0x0085, 0x0085, 1 }, - { 0x00a0, 0x00a0, 1 }, - { 0x1680, 0x1680, 1 }, - { 0x180e, 0x180e, 1 }, - { 0x2000, 0x200a, 1 }, - { 0x2028, 0x2029, 1 }, - { 0x202f, 0x202f, 1 }, - { 0x205f, 0x205f, 1 }, - { 0x3000, 0x3000, 1 }, - { 0xfeff, 0xfeff, 1 }, - }; - -// A table of Unicode digits--Unicode code points classified as -// "Digit". - -static const Unicode_range unicode_digits[] = - { - { 0x0030, 0x0039, 1 }, - { 0x0660, 0x0669, 1 }, - { 0x06f0, 0x06f9, 1 }, - { 0x07c0, 0x07c9, 1 }, - { 0x0966, 0x096f, 1 }, - { 0x09e6, 0x09ef, 1 }, - { 0x0a66, 0x0a6f, 1 }, - { 0x0ae6, 0x0aef, 1 }, - { 0x0b66, 0x0b6f, 1 }, - { 0x0be6, 0x0bef, 1 }, - { 0x0c66, 0x0c6f, 1 }, - { 0x0ce6, 0x0cef, 1 }, - { 0x0d66, 0x0d6f, 1 }, - { 0x0e50, 0x0e59, 1 }, - { 0x0ed0, 0x0ed9, 1 }, - { 0x0f20, 0x0f29, 1 }, - { 0x1040, 0x1049, 1 }, - { 0x17e0, 0x17e9, 1 }, - { 0x1810, 0x1819, 1 }, - { 0x1946, 0x194f, 1 }, - { 0x19d0, 0x19d9, 1 }, - { 0x1b50, 0x1b59, 1 }, - { 0xff10, 0xff19, 1 }, - { 0x104a0, 0x104a9, 1 }, - { 0x1d7ce, 0x1d7ff, 1 }, - }; - -// A table of Unicode letters--Unicode code points classified as -// "Letter". - -static const Unicode_range unicode_letters[] = - { - { 0x0041, 0x005a, 1 }, - { 0x0061, 0x007a, 1 }, - { 0x00aa, 0x00b5, 11 }, - { 0x00ba, 0x00c0, 6 }, - { 0x00c1, 0x00d6, 1 }, - { 0x00d8, 0x00f6, 1 }, - { 0x00f8, 0x02c1, 1 }, - { 0x02c6, 0x02d1, 1 }, - { 0x02e0, 0x02e4, 1 }, - { 0x02ec, 0x02ee, 2 }, - { 0x0370, 0x0374, 1 }, - { 0x0376, 0x0377, 1 }, - { 0x037a, 0x037d, 1 }, - { 0x037f, 0x0386, 7 }, - { 0x0388, 0x038a, 1 }, - { 0x038c, 0x038e, 2 }, - { 0x038f, 0x03a1, 1 }, - { 0x03a3, 0x03f5, 1 }, - { 0x03f7, 0x0481, 1 }, - { 0x048a, 0x052f, 1 }, - { 0x0531, 0x0556, 1 }, - { 0x0559, 0x0561, 8 }, - { 0x0562, 0x0587, 1 }, - { 0x05d0, 0x05ea, 1 }, - { 0x05f0, 0x05f2, 1 }, - { 0x0620, 0x064a, 1 }, - { 0x066e, 0x066f, 1 }, - { 0x0671, 0x06d3, 1 }, - { 0x06d5, 0x06e5, 16 }, - { 0x06e6, 0x06ee, 8 }, - { 0x06ef, 0x06fa, 11 }, - { 0x06fb, 0x06fc, 1 }, - { 0x06ff, 0x0710, 17 }, - { 0x0712, 0x072f, 1 }, - { 0x074d, 0x07a5, 1 }, - { 0x07b1, 0x07ca, 25 }, - { 0x07cb, 0x07ea, 1 }, - { 0x07f4, 0x07f5, 1 }, - { 0x07fa, 0x0800, 6 }, - { 0x0801, 0x0815, 1 }, - { 0x081a, 0x0824, 10 }, - { 0x0828, 0x0840, 24 }, - { 0x0841, 0x0858, 1 }, - { 0x08a0, 0x08b4, 1 }, - { 0x0904, 0x0939, 1 }, - { 0x093d, 0x0950, 19 }, - { 0x0958, 0x0961, 1 }, - { 0x0971, 0x0980, 1 }, - { 0x0985, 0x098c, 1 }, - { 0x098f, 0x0990, 1 }, - { 0x0993, 0x09a8, 1 }, - { 0x09aa, 0x09b0, 1 }, - { 0x09b2, 0x09b6, 4 }, - { 0x09b7, 0x09b9, 1 }, - { 0x09bd, 0x09ce, 17 }, - { 0x09dc, 0x09dd, 1 }, - { 0x09df, 0x09e1, 1 }, - { 0x09f0, 0x09f1, 1 }, - { 0x0a05, 0x0a0a, 1 }, - { 0x0a0f, 0x0a10, 1 }, - { 0x0a13, 0x0a28, 1 }, - { 0x0a2a, 0x0a30, 1 }, - { 0x0a32, 0x0a33, 1 }, - { 0x0a35, 0x0a36, 1 }, - { 0x0a38, 0x0a39, 1 }, - { 0x0a59, 0x0a5c, 1 }, - { 0x0a5e, 0x0a72, 20 }, - { 0x0a73, 0x0a74, 1 }, - { 0x0a85, 0x0a8d, 1 }, - { 0x0a8f, 0x0a91, 1 }, - { 0x0a93, 0x0aa8, 1 }, - { 0x0aaa, 0x0ab0, 1 }, - { 0x0ab2, 0x0ab3, 1 }, - { 0x0ab5, 0x0ab9, 1 }, - { 0x0abd, 0x0ad0, 19 }, - { 0x0ae0, 0x0ae1, 1 }, - { 0x0af9, 0x0b05, 12 }, - { 0x0b06, 0x0b0c, 1 }, - { 0x0b0f, 0x0b10, 1 }, - { 0x0b13, 0x0b28, 1 }, - { 0x0b2a, 0x0b30, 1 }, - { 0x0b32, 0x0b33, 1 }, - { 0x0b35, 0x0b39, 1 }, - { 0x0b3d, 0x0b5c, 31 }, - { 0x0b5d, 0x0b5f, 2 }, - { 0x0b60, 0x0b61, 1 }, - { 0x0b71, 0x0b83, 18 }, - { 0x0b85, 0x0b8a, 1 }, - { 0x0b8e, 0x0b90, 1 }, - { 0x0b92, 0x0b95, 1 }, - { 0x0b99, 0x0b9a, 1 }, - { 0x0b9c, 0x0b9e, 2 }, - { 0x0b9f, 0x0ba3, 4 }, - { 0x0ba4, 0x0ba8, 4 }, - { 0x0ba9, 0x0baa, 1 }, - { 0x0bae, 0x0bb9, 1 }, - { 0x0bd0, 0x0c05, 53 }, - { 0x0c06, 0x0c0c, 1 }, - { 0x0c0e, 0x0c10, 1 }, - { 0x0c12, 0x0c28, 1 }, - { 0x0c2a, 0x0c39, 1 }, - { 0x0c3d, 0x0c58, 27 }, - { 0x0c59, 0x0c5a, 1 }, - { 0x0c60, 0x0c61, 1 }, - { 0x0c85, 0x0c8c, 1 }, - { 0x0c8e, 0x0c90, 1 }, - { 0x0c92, 0x0ca8, 1 }, - { 0x0caa, 0x0cb3, 1 }, - { 0x0cb5, 0x0cb9, 1 }, - { 0x0cbd, 0x0cde, 33 }, - { 0x0ce0, 0x0ce1, 1 }, - { 0x0cf1, 0x0cf2, 1 }, - { 0x0d05, 0x0d0c, 1 }, - { 0x0d0e, 0x0d10, 1 }, - { 0x0d12, 0x0d3a, 1 }, - { 0x0d3d, 0x0d5f, 17 }, - { 0x0d60, 0x0d61, 1 }, - { 0x0d7a, 0x0d7f, 1 }, - { 0x0d85, 0x0d96, 1 }, - { 0x0d9a, 0x0db1, 1 }, - { 0x0db3, 0x0dbb, 1 }, - { 0x0dbd, 0x0dc0, 3 }, - { 0x0dc1, 0x0dc6, 1 }, - { 0x0e01, 0x0e30, 1 }, - { 0x0e32, 0x0e33, 1 }, - { 0x0e40, 0x0e46, 1 }, - { 0x0e81, 0x0e82, 1 }, - { 0x0e84, 0x0e87, 3 }, - { 0x0e88, 0x0e8a, 2 }, - { 0x0e8d, 0x0e94, 7 }, - { 0x0e95, 0x0e97, 1 }, - { 0x0e99, 0x0e9f, 1 }, - { 0x0ea1, 0x0ea3, 1 }, - { 0x0ea5, 0x0ea7, 2 }, - { 0x0eaa, 0x0eab, 1 }, - { 0x0ead, 0x0eb0, 1 }, - { 0x0eb2, 0x0eb3, 1 }, - { 0x0ebd, 0x0ec0, 3 }, - { 0x0ec1, 0x0ec4, 1 }, - { 0x0ec6, 0x0edc, 22 }, - { 0x0edd, 0x0edf, 1 }, - { 0x0f00, 0x0f40, 64 }, - { 0x0f41, 0x0f47, 1 }, - { 0x0f49, 0x0f6c, 1 }, - { 0x0f88, 0x0f8c, 1 }, - { 0x1000, 0x102a, 1 }, - { 0x103f, 0x1050, 17 }, - { 0x1051, 0x1055, 1 }, - { 0x105a, 0x105d, 1 }, - { 0x1061, 0x1065, 4 }, - { 0x1066, 0x106e, 8 }, - { 0x106f, 0x1070, 1 }, - { 0x1075, 0x1081, 1 }, - { 0x108e, 0x10a0, 18 }, - { 0x10a1, 0x10c5, 1 }, - { 0x10c7, 0x10cd, 6 }, - { 0x10d0, 0x10fa, 1 }, - { 0x10fc, 0x1248, 1 }, - { 0x124a, 0x124d, 1 }, - { 0x1250, 0x1256, 1 }, - { 0x1258, 0x125a, 2 }, - { 0x125b, 0x125d, 1 }, - { 0x1260, 0x1288, 1 }, - { 0x128a, 0x128d, 1 }, - { 0x1290, 0x12b0, 1 }, - { 0x12b2, 0x12b5, 1 }, - { 0x12b8, 0x12be, 1 }, - { 0x12c0, 0x12c2, 2 }, - { 0x12c3, 0x12c5, 1 }, - { 0x12c8, 0x12d6, 1 }, - { 0x12d8, 0x1310, 1 }, - { 0x1312, 0x1315, 1 }, - { 0x1318, 0x135a, 1 }, - { 0x1380, 0x138f, 1 }, - { 0x13a0, 0x13f5, 1 }, - { 0x13f8, 0x13fd, 1 }, - { 0x1401, 0x166c, 1 }, - { 0x166f, 0x167f, 1 }, - { 0x1681, 0x169a, 1 }, - { 0x16a0, 0x16ea, 1 }, - { 0x16f1, 0x16f8, 1 }, - { 0x1700, 0x170c, 1 }, - { 0x170e, 0x1711, 1 }, - { 0x1720, 0x1731, 1 }, - { 0x1740, 0x1751, 1 }, - { 0x1760, 0x176c, 1 }, - { 0x176e, 0x1770, 1 }, - { 0x1780, 0x17b3, 1 }, - { 0x17d7, 0x17dc, 5 }, - { 0x1820, 0x1877, 1 }, - { 0x1880, 0x18a8, 1 }, - { 0x18aa, 0x18b0, 6 }, - { 0x18b1, 0x18f5, 1 }, - { 0x1900, 0x191e, 1 }, - { 0x1950, 0x196d, 1 }, - { 0x1970, 0x1974, 1 }, - { 0x1980, 0x19ab, 1 }, - { 0x19b0, 0x19c9, 1 }, - { 0x1a00, 0x1a16, 1 }, - { 0x1a20, 0x1a54, 1 }, - { 0x1aa7, 0x1b05, 94 }, - { 0x1b06, 0x1b33, 1 }, - { 0x1b45, 0x1b4b, 1 }, - { 0x1b83, 0x1ba0, 1 }, - { 0x1bae, 0x1baf, 1 }, - { 0x1bba, 0x1be5, 1 }, - { 0x1c00, 0x1c23, 1 }, - { 0x1c4d, 0x1c4f, 1 }, - { 0x1c5a, 0x1c7d, 1 }, - { 0x1ce9, 0x1cec, 1 }, - { 0x1cee, 0x1cf1, 1 }, - { 0x1cf5, 0x1cf6, 1 }, - { 0x1d00, 0x1dbf, 1 }, - { 0x1e00, 0x1f15, 1 }, - { 0x1f18, 0x1f1d, 1 }, - { 0x1f20, 0x1f45, 1 }, - { 0x1f48, 0x1f4d, 1 }, - { 0x1f50, 0x1f57, 1 }, - { 0x1f59, 0x1f5f, 2 }, - { 0x1f60, 0x1f7d, 1 }, - { 0x1f80, 0x1fb4, 1 }, - { 0x1fb6, 0x1fbc, 1 }, - { 0x1fbe, 0x1fc2, 4 }, - { 0x1fc3, 0x1fc4, 1 }, - { 0x1fc6, 0x1fcc, 1 }, - { 0x1fd0, 0x1fd3, 1 }, - { 0x1fd6, 0x1fdb, 1 }, - { 0x1fe0, 0x1fec, 1 }, - { 0x1ff2, 0x1ff4, 1 }, - { 0x1ff6, 0x1ffc, 1 }, - { 0x2071, 0x207f, 14 }, - { 0x2090, 0x209c, 1 }, - { 0x2102, 0x2107, 5 }, - { 0x210a, 0x2113, 1 }, - { 0x2115, 0x2119, 4 }, - { 0x211a, 0x211d, 1 }, - { 0x2124, 0x212a, 2 }, - { 0x212b, 0x212d, 1 }, - { 0x212f, 0x2139, 1 }, - { 0x213c, 0x213f, 1 }, - { 0x2145, 0x2149, 1 }, - { 0x214e, 0x2183, 53 }, - { 0x2184, 0x2c00, 2684 }, - { 0x2c01, 0x2c2e, 1 }, - { 0x2c30, 0x2c5e, 1 }, - { 0x2c60, 0x2ce4, 1 }, - { 0x2ceb, 0x2cee, 1 }, - { 0x2cf2, 0x2cf3, 1 }, - { 0x2d00, 0x2d25, 1 }, - { 0x2d27, 0x2d2d, 6 }, - { 0x2d30, 0x2d67, 1 }, - { 0x2d6f, 0x2d80, 17 }, - { 0x2d81, 0x2d96, 1 }, - { 0x2da0, 0x2da6, 1 }, - { 0x2da8, 0x2dae, 1 }, - { 0x2db0, 0x2db6, 1 }, - { 0x2db8, 0x2dbe, 1 }, - { 0x2dc0, 0x2dc6, 1 }, - { 0x2dc8, 0x2dce, 1 }, - { 0x2dd0, 0x2dd6, 1 }, - { 0x2dd8, 0x2dde, 1 }, - { 0x2e2f, 0x3005, 470 }, - { 0x3006, 0x3031, 43 }, - { 0x3032, 0x3035, 1 }, - { 0x303b, 0x303c, 1 }, - { 0x3041, 0x3096, 1 }, - { 0x309d, 0x309f, 1 }, - { 0x30a1, 0x30fa, 1 }, - { 0x30fc, 0x30ff, 1 }, - { 0x3105, 0x312d, 1 }, - { 0x3131, 0x318e, 1 }, - { 0x31a0, 0x31ba, 1 }, - { 0x31f0, 0x31ff, 1 }, - { 0x3400, 0x4db5, 1 }, - { 0x4e00, 0x9fd5, 1 }, - { 0xa000, 0xa48c, 1 }, - { 0xa4d0, 0xa4fd, 1 }, - { 0xa500, 0xa60c, 1 }, - { 0xa610, 0xa61f, 1 }, - { 0xa62a, 0xa62b, 1 }, - { 0xa640, 0xa66e, 1 }, - { 0xa67f, 0xa69d, 1 }, - { 0xa6a0, 0xa6e5, 1 }, - { 0xa717, 0xa71f, 1 }, - { 0xa722, 0xa788, 1 }, - { 0xa78b, 0xa7ad, 1 }, - { 0xa7b0, 0xa7b7, 1 }, - { 0xa7f7, 0xa801, 1 }, - { 0xa803, 0xa805, 1 }, - { 0xa807, 0xa80a, 1 }, - { 0xa80c, 0xa822, 1 }, - { 0xa840, 0xa873, 1 }, - { 0xa882, 0xa8b3, 1 }, - { 0xa8f2, 0xa8f7, 1 }, - { 0xa8fb, 0xa8fd, 2 }, - { 0xa90a, 0xa925, 1 }, - { 0xa930, 0xa946, 1 }, - { 0xa960, 0xa97c, 1 }, - { 0xa984, 0xa9b2, 1 }, - { 0xa9cf, 0xa9e0, 17 }, - { 0xa9e1, 0xa9e4, 1 }, - { 0xa9e6, 0xa9ef, 1 }, - { 0xa9fa, 0xa9fe, 1 }, - { 0xaa00, 0xaa28, 1 }, - { 0xaa40, 0xaa42, 1 }, - { 0xaa44, 0xaa4b, 1 }, - { 0xaa60, 0xaa76, 1 }, - { 0xaa7a, 0xaa7e, 4 }, - { 0xaa7f, 0xaaaf, 1 }, - { 0xaab1, 0xaab5, 4 }, - { 0xaab6, 0xaab9, 3 }, - { 0xaaba, 0xaabd, 1 }, - { 0xaac0, 0xaac2, 2 }, - { 0xaadb, 0xaadd, 1 }, - { 0xaae0, 0xaaea, 1 }, - { 0xaaf2, 0xaaf4, 1 }, - { 0xab01, 0xab06, 1 }, - { 0xab09, 0xab0e, 1 }, - { 0xab11, 0xab16, 1 }, - { 0xab20, 0xab26, 1 }, - { 0xab28, 0xab2e, 1 }, - { 0xab30, 0xab5a, 1 }, - { 0xab5c, 0xab65, 1 }, - { 0xab70, 0xabe2, 1 }, - { 0xac00, 0xd7a3, 1 }, - { 0xd7b0, 0xd7c6, 1 }, - { 0xd7cb, 0xd7fb, 1 }, - { 0xf900, 0xfa6d, 1 }, - { 0xfa70, 0xfad9, 1 }, - { 0xfb00, 0xfb06, 1 }, - { 0xfb13, 0xfb17, 1 }, - { 0xfb1d, 0xfb1f, 2 }, - { 0xfb20, 0xfb28, 1 }, - { 0xfb2a, 0xfb36, 1 }, - { 0xfb38, 0xfb3c, 1 }, - { 0xfb3e, 0xfb40, 2 }, - { 0xfb41, 0xfb43, 2 }, - { 0xfb44, 0xfb46, 2 }, - { 0xfb47, 0xfbb1, 1 }, - { 0xfbd3, 0xfd3d, 1 }, - { 0xfd50, 0xfd8f, 1 }, - { 0xfd92, 0xfdc7, 1 }, - { 0xfdf0, 0xfdfb, 1 }, - { 0xfe70, 0xfe74, 1 }, - { 0xfe76, 0xfefc, 1 }, - { 0xff21, 0xff3a, 1 }, - { 0xff41, 0xff5a, 1 }, - { 0xff66, 0xffbe, 1 }, - { 0xffc2, 0xffc7, 1 }, - { 0xffca, 0xffcf, 1 }, - { 0xffd2, 0xffd7, 1 }, - { 0xffda, 0xffdc, 1 }, - { 0x10000, 0x1000b, 1 }, - { 0x1000d, 0x10026, 1 }, - { 0x10028, 0x1003a, 1 }, - { 0x1003c, 0x1003d, 1 }, - { 0x1003f, 0x1004d, 1 }, - { 0x10050, 0x1005d, 1 }, - { 0x10080, 0x100fa, 1 }, - { 0x10280, 0x1029c, 1 }, - { 0x102a0, 0x102d0, 1 }, - { 0x10300, 0x1031f, 1 }, - { 0x10330, 0x10340, 1 }, - { 0x10342, 0x10349, 1 }, - { 0x10350, 0x10375, 1 }, - { 0x10380, 0x1039d, 1 }, - { 0x103a0, 0x103c3, 1 }, - { 0x103c8, 0x103cf, 1 }, - { 0x10400, 0x1049d, 1 }, - { 0x10500, 0x10527, 1 }, - { 0x10530, 0x10563, 1 }, - { 0x10600, 0x10736, 1 }, - { 0x10740, 0x10755, 1 }, - { 0x10760, 0x10767, 1 }, - { 0x10800, 0x10805, 1 }, - { 0x10808, 0x1080a, 2 }, - { 0x1080b, 0x10835, 1 }, - { 0x10837, 0x10838, 1 }, - { 0x1083c, 0x1083f, 3 }, - { 0x10840, 0x10855, 1 }, - { 0x10860, 0x10876, 1 }, - { 0x10880, 0x1089e, 1 }, - { 0x108e0, 0x108f2, 1 }, - { 0x108f4, 0x108f5, 1 }, - { 0x10900, 0x10915, 1 }, - { 0x10920, 0x10939, 1 }, - { 0x10980, 0x109b7, 1 }, - { 0x109be, 0x109bf, 1 }, - { 0x10a00, 0x10a10, 16 }, - { 0x10a11, 0x10a13, 1 }, - { 0x10a15, 0x10a17, 1 }, - { 0x10a19, 0x10a33, 1 }, - { 0x10a60, 0x10a7c, 1 }, - { 0x10a80, 0x10a9c, 1 }, - { 0x10ac0, 0x10ac7, 1 }, - { 0x10ac9, 0x10ae4, 1 }, - { 0x10b00, 0x10b35, 1 }, - { 0x10b40, 0x10b55, 1 }, - { 0x10b60, 0x10b72, 1 }, - { 0x10b80, 0x10b91, 1 }, - { 0x10c00, 0x10c48, 1 }, - { 0x10c80, 0x10cb2, 1 }, - { 0x10cc0, 0x10cf2, 1 }, - { 0x11003, 0x11037, 1 }, - { 0x11083, 0x110af, 1 }, - { 0x110d0, 0x110e8, 1 }, - { 0x11103, 0x11126, 1 }, - { 0x11150, 0x11172, 1 }, - { 0x11176, 0x11183, 13 }, - { 0x11184, 0x111b2, 1 }, - { 0x111c1, 0x111c4, 1 }, - { 0x111da, 0x111dc, 2 }, - { 0x11200, 0x11211, 1 }, - { 0x11213, 0x1122b, 1 }, - { 0x11280, 0x11286, 1 }, - { 0x11288, 0x1128a, 2 }, - { 0x1128b, 0x1128d, 1 }, - { 0x1128f, 0x1129d, 1 }, - { 0x1129f, 0x112a8, 1 }, - { 0x112b0, 0x112de, 1 }, - { 0x11305, 0x1130c, 1 }, - { 0x1130f, 0x11310, 1 }, - { 0x11313, 0x11328, 1 }, - { 0x1132a, 0x11330, 1 }, - { 0x11332, 0x11333, 1 }, - { 0x11335, 0x11339, 1 }, - { 0x1133d, 0x11350, 19 }, - { 0x1135d, 0x11361, 1 }, - { 0x11480, 0x114af, 1 }, - { 0x114c4, 0x114c5, 1 }, - { 0x114c7, 0x11580, 185 }, - { 0x11581, 0x115ae, 1 }, - { 0x115d8, 0x115db, 1 }, - { 0x11600, 0x1162f, 1 }, - { 0x11644, 0x11680, 60 }, - { 0x11681, 0x116aa, 1 }, - { 0x11700, 0x11719, 1 }, - { 0x118a0, 0x118df, 1 }, - { 0x118ff, 0x11ac0, 449 }, - { 0x11ac1, 0x11af8, 1 }, - { 0x12000, 0x12399, 1 }, - { 0x12480, 0x12543, 1 }, - { 0x13000, 0x1342e, 1 }, - { 0x14400, 0x14646, 1 }, - { 0x16800, 0x16a38, 1 }, - { 0x16a40, 0x16a5e, 1 }, - { 0x16ad0, 0x16aed, 1 }, - { 0x16b00, 0x16b2f, 1 }, - { 0x16b40, 0x16b43, 1 }, - { 0x16b63, 0x16b77, 1 }, - { 0x16b7d, 0x16b8f, 1 }, - { 0x16f00, 0x16f44, 1 }, - { 0x16f50, 0x16f93, 67 }, - { 0x16f94, 0x16f9f, 1 }, - { 0x1b000, 0x1b001, 1 }, - { 0x1bc00, 0x1bc6a, 1 }, - { 0x1bc70, 0x1bc7c, 1 }, - { 0x1bc80, 0x1bc88, 1 }, - { 0x1bc90, 0x1bc99, 1 }, - { 0x1d400, 0x1d454, 1 }, - { 0x1d456, 0x1d49c, 1 }, - { 0x1d49e, 0x1d49f, 1 }, - { 0x1d4a2, 0x1d4a5, 3 }, - { 0x1d4a6, 0x1d4a9, 3 }, - { 0x1d4aa, 0x1d4ac, 1 }, - { 0x1d4ae, 0x1d4b9, 1 }, - { 0x1d4bb, 0x1d4bd, 2 }, - { 0x1d4be, 0x1d4c3, 1 }, - { 0x1d4c5, 0x1d505, 1 }, - { 0x1d507, 0x1d50a, 1 }, - { 0x1d50d, 0x1d514, 1 }, - { 0x1d516, 0x1d51c, 1 }, - { 0x1d51e, 0x1d539, 1 }, - { 0x1d53b, 0x1d53e, 1 }, - { 0x1d540, 0x1d544, 1 }, - { 0x1d546, 0x1d54a, 4 }, - { 0x1d54b, 0x1d550, 1 }, - { 0x1d552, 0x1d6a5, 1 }, - { 0x1d6a8, 0x1d6c0, 1 }, - { 0x1d6c2, 0x1d6da, 1 }, - { 0x1d6dc, 0x1d6fa, 1 }, - { 0x1d6fc, 0x1d714, 1 }, - { 0x1d716, 0x1d734, 1 }, - { 0x1d736, 0x1d74e, 1 }, - { 0x1d750, 0x1d76e, 1 }, - { 0x1d770, 0x1d788, 1 }, - { 0x1d78a, 0x1d7a8, 1 }, - { 0x1d7aa, 0x1d7c2, 1 }, - { 0x1d7c4, 0x1d7cb, 1 }, - { 0x1e800, 0x1e8c4, 1 }, - { 0x1ee00, 0x1ee03, 1 }, - { 0x1ee05, 0x1ee1f, 1 }, - { 0x1ee21, 0x1ee22, 1 }, - { 0x1ee24, 0x1ee27, 3 }, - { 0x1ee29, 0x1ee32, 1 }, - { 0x1ee34, 0x1ee37, 1 }, - { 0x1ee39, 0x1ee3b, 2 }, - { 0x1ee42, 0x1ee47, 5 }, - { 0x1ee49, 0x1ee4d, 2 }, - { 0x1ee4e, 0x1ee4f, 1 }, - { 0x1ee51, 0x1ee52, 1 }, - { 0x1ee54, 0x1ee57, 3 }, - { 0x1ee59, 0x1ee61, 2 }, - { 0x1ee62, 0x1ee64, 2 }, - { 0x1ee67, 0x1ee6a, 1 }, - { 0x1ee6c, 0x1ee72, 1 }, - { 0x1ee74, 0x1ee77, 1 }, - { 0x1ee79, 0x1ee7c, 1 }, - { 0x1ee7e, 0x1ee80, 2 }, - { 0x1ee81, 0x1ee89, 1 }, - { 0x1ee8b, 0x1ee9b, 1 }, - { 0x1eea1, 0x1eea3, 1 }, - { 0x1eea5, 0x1eea9, 1 }, - { 0x1eeab, 0x1eebb, 1 }, - { 0x20000, 0x2a6d6, 1 }, - { 0x2a700, 0x2b734, 1 }, - { 0x2b740, 0x2b81d, 1 }, - { 0x2b820, 0x2cea1, 1 }, - { 0x2f800, 0x2fa1d, 1 }, - }; - -// A table of Unicode uppercase letters--Unicode code points -// classified as "Letter, uppercase". - -static const Unicode_range unicode_uppercase_letters[] = - { - { 0x0041, 0x005a, 1 }, - { 0x00c0, 0x00d6, 1 }, - { 0x00d8, 0x00de, 1 }, - { 0x0100, 0x0136, 2 }, - { 0x0139, 0x0147, 2 }, - { 0x014a, 0x0178, 2 }, - { 0x0179, 0x017d, 2 }, - { 0x0181, 0x0182, 1 }, - { 0x0184, 0x0186, 2 }, - { 0x0187, 0x0189, 2 }, - { 0x018a, 0x018b, 1 }, - { 0x018e, 0x0191, 1 }, - { 0x0193, 0x0194, 1 }, - { 0x0196, 0x0198, 1 }, - { 0x019c, 0x019d, 1 }, - { 0x019f, 0x01a0, 1 }, - { 0x01a2, 0x01a6, 2 }, - { 0x01a7, 0x01a9, 2 }, - { 0x01ac, 0x01ae, 2 }, - { 0x01af, 0x01b1, 2 }, - { 0x01b2, 0x01b3, 1 }, - { 0x01b5, 0x01b7, 2 }, - { 0x01b8, 0x01bc, 4 }, - { 0x01c4, 0x01cd, 3 }, - { 0x01cf, 0x01db, 2 }, - { 0x01de, 0x01ee, 2 }, - { 0x01f1, 0x01f4, 3 }, - { 0x01f6, 0x01f8, 1 }, - { 0x01fa, 0x0232, 2 }, - { 0x023a, 0x023b, 1 }, - { 0x023d, 0x023e, 1 }, - { 0x0241, 0x0243, 2 }, - { 0x0244, 0x0246, 1 }, - { 0x0248, 0x024e, 2 }, - { 0x0370, 0x0372, 2 }, - { 0x0376, 0x037f, 9 }, - { 0x0386, 0x0388, 2 }, - { 0x0389, 0x038a, 1 }, - { 0x038c, 0x038e, 2 }, - { 0x038f, 0x0391, 2 }, - { 0x0392, 0x03a1, 1 }, - { 0x03a3, 0x03ab, 1 }, - { 0x03cf, 0x03d2, 3 }, - { 0x03d3, 0x03d4, 1 }, - { 0x03d8, 0x03ee, 2 }, - { 0x03f4, 0x03f7, 3 }, - { 0x03f9, 0x03fa, 1 }, - { 0x03fd, 0x042f, 1 }, - { 0x0460, 0x0480, 2 }, - { 0x048a, 0x04c0, 2 }, - { 0x04c1, 0x04cd, 2 }, - { 0x04d0, 0x052e, 2 }, - { 0x0531, 0x0556, 1 }, - { 0x10a0, 0x10c5, 1 }, - { 0x10c7, 0x10cd, 6 }, - { 0x1e00, 0x1e94, 2 }, - { 0x1e9e, 0x1efe, 2 }, - { 0x1f08, 0x1f0f, 1 }, - { 0x1f18, 0x1f1d, 1 }, - { 0x1f28, 0x1f2f, 1 }, - { 0x1f38, 0x1f3f, 1 }, - { 0x1f48, 0x1f4d, 1 }, - { 0x1f59, 0x1f5f, 2 }, - { 0x1f68, 0x1f6f, 1 }, - { 0x1fb8, 0x1fbb, 1 }, - { 0x1fc8, 0x1fcb, 1 }, - { 0x1fd8, 0x1fdb, 1 }, - { 0x1fe8, 0x1fec, 1 }, - { 0x1ff8, 0x1ffb, 1 }, - { 0x2102, 0x2107, 5 }, - { 0x210b, 0x210d, 1 }, - { 0x2110, 0x2112, 1 }, - { 0x2115, 0x2119, 4 }, - { 0x211a, 0x211d, 1 }, - { 0x2124, 0x212a, 2 }, - { 0x212b, 0x212d, 1 }, - { 0x2130, 0x2133, 1 }, - { 0x213e, 0x213f, 1 }, - { 0x2145, 0x2183, 62 }, - { 0x2c00, 0x2c2e, 1 }, - { 0x2c60, 0x2c62, 2 }, - { 0x2c63, 0x2c64, 1 }, - { 0x2c67, 0x2c6d, 2 }, - { 0x2c6e, 0x2c70, 1 }, - { 0x2c72, 0x2c75, 3 }, - { 0x2c7e, 0x2c80, 1 }, - { 0x2c82, 0x2ce2, 2 }, - { 0x2ceb, 0x2ced, 2 }, - { 0x2cf2, 0xa640, 31054 }, - { 0xa642, 0xa66c, 2 }, - { 0xa680, 0xa69a, 2 }, - { 0xa722, 0xa72e, 2 }, - { 0xa732, 0xa76e, 2 }, - { 0xa779, 0xa77d, 2 }, - { 0xa77e, 0xa786, 2 }, - { 0xa78b, 0xa78d, 2 }, - { 0xa790, 0xa792, 2 }, - { 0xa796, 0xa7aa, 2 }, - { 0xa7ab, 0xa7ad, 1 }, - { 0xa7b0, 0xa7b1, 1 }, - { 0xff21, 0xff3a, 1 }, - { 0x10400, 0x10427, 1 }, - { 0x118a0, 0x118bf, 1 }, - { 0x1d400, 0x1d419, 1 }, - { 0x1d434, 0x1d44d, 1 }, - { 0x1d468, 0x1d481, 1 }, - { 0x1d49c, 0x1d49e, 2 }, - { 0x1d49f, 0x1d4a5, 3 }, - { 0x1d4a6, 0x1d4a9, 3 }, - { 0x1d4aa, 0x1d4ac, 1 }, - { 0x1d4ae, 0x1d4b5, 1 }, - { 0x1d4d0, 0x1d4e9, 1 }, - { 0x1d504, 0x1d505, 1 }, - { 0x1d507, 0x1d50a, 1 }, - { 0x1d50d, 0x1d514, 1 }, - { 0x1d516, 0x1d51c, 1 }, - { 0x1d538, 0x1d539, 1 }, - { 0x1d53b, 0x1d53e, 1 }, - { 0x1d540, 0x1d544, 1 }, - { 0x1d546, 0x1d54a, 4 }, - { 0x1d54b, 0x1d550, 1 }, - { 0x1d56c, 0x1d585, 1 }, - { 0x1d5a0, 0x1d5b9, 1 }, - { 0x1d5d4, 0x1d5ed, 1 }, - { 0x1d608, 0x1d621, 1 }, - { 0x1d63c, 0x1d655, 1 }, - { 0x1d670, 0x1d689, 1 }, - { 0x1d6a8, 0x1d6c0, 1 }, - { 0x1d6e2, 0x1d6fa, 1 }, - { 0x1d71c, 0x1d734, 1 }, - { 0x1d756, 0x1d76e, 1 }, - { 0x1d790, 0x1d7a8, 1 }, - { 0x1d7ca, 0x1d7ca, 1 }, - }; - -// Return true if C is in RANGES. - -bool Lex::is_in_unicode_range(unsigned int c, const Unicode_range* ranges, size_t range_size) { - if (c < 0x100) { - // The common case is a small value, and we know that it will be - // in the first few entries of the table. Do a linear scan - // rather than a binary search. - for (size_t i = 0; i < range_size; ++i) { - const Unicode_range* p = &ranges[i]; - if (c <= p->high) { - if (c < p->low) - return false; - return (c - p->low) % p->stride == 0; - } - } - return false; - } else { - size_t lo = 0; - size_t hi = range_size; - while (lo < hi) { - size_t mid = lo + (hi - lo) / 2; - const Unicode_range* p = &ranges[mid]; - if (c < p->low) - hi = mid; - else if (c > p->high) - lo = mid + 1; - else - return (c - p->low) % p->stride == 0; - } - return false; - } -} - -// Return whether C is a space character. - -bool Lex::is_unicode_space(unsigned int c) { - return Lex::is_in_unicode_range(c, unicode_space, ARRAY_SIZE(unicode_space)); -} - -// Return whether C is a Unicode digit--a Unicode code point -// classified as "Digit". - -bool Lex::is_unicode_digit(unsigned int c) { - return Lex::is_in_unicode_range(c, unicode_digits, ARRAY_SIZE(unicode_digits)); -} - -// Return whether C is a Unicode letter--a Unicode code point -// classified as "Letter". - -bool Lex::is_unicode_letter(unsigned int c) { - return Lex::is_in_unicode_range(c, unicode_letters, ARRAY_SIZE(unicode_letters)); -} - -// Return whether C is a Unicode uppercase letter. a Unicode code -// point classified as "Letter, uppercase". - -bool Lex::is_unicode_uppercase(unsigned int c) { - return Lex::is_in_unicode_range(c, unicode_uppercase_letters, ARRAY_SIZE(unicode_uppercase_letters)); -} - -// Return whether the identifier NAME should be exported. NAME is a -// mangled name which includes only ASCII characters. - -bool Lex::is_exported_mangled_name(const std::string& name) { - unsigned char c = name[0]; - if (c != '.') - return c >= 'A' && c <= 'Z'; - else { - const char* p = name.data(); - size_t len = name.length(); - if (len < 4 || p[1] != '.' || (p[2] != 'u' && p[2] != 'U')) - return false; - unsigned int ci = 0; - size_t want = (p[2] == 'u' ? 4 : 8); - if (len < want + 3) - return false; - for (size_t i = 3; i < want; ++i) { - c = p[i]; - if (!Lex::is_hex_digit(c)) - return false; - ci <<= 4; - ci |= Lex::hex_val(c); - } - return Lex::is_unicode_uppercase(ci); - } -} - -// Return whether the identifier NAME should be exported. NAME is a -// an unmangled utf-8 string and may contain non-ASCII characters. - -bool Lex::is_exported_name(const std::string& name) { - unsigned int uchar; - if (Lex::fetch_char(name.c_str(), &uchar) != 0) - return Lex::is_unicode_letter(uchar) && Lex::is_unicode_uppercase(uchar); - return false; -} - -// Return whether the identifier NAME contains an invalid character. -// This is based on how we handle invalid characters in -// gather_identifier. - -bool Lex::is_invalid_identifier(const std::string& name) { - return name.find("$INVALID$") != std::string::npos; -} diff --git a/gcc/rust/test2/rustfrontend/rs-lex.h b/gcc/rust/test2/rustfrontend/rs-lex.h deleted file mode 100644 index 5835f42..0000000 --- a/gcc/rust/test2/rustfrontend/rs-lex.h +++ /dev/null @@ -1,361 +0,0 @@ -// rs-lex.h -- Rust frontend lexer. -*- C++ -*- - -// Copyright etc - -#ifndef RUST_LEX_H -#define RUST_LEX_H - -#include - -#include "rs-token.h" -//#include "go-linemap.h" - -// Operators -enum Operator { - OPERATOR_INVALID, - OPERATOR_DOUBLE_PIPE, // || - OPERATOR_DOUBLE_AMP, // && - OPERATOR_DOUBLE_EQ, // == - OPERATOR_EXCLAM_EQ, // != - OPERATOR_LT, // < - OPERATOR_LE, // <= - OPERATOR_GT, // > - OPERATOR_GE, // >= - OPERATOR_PLUS, // + - OPERATOR_MINUS, // - - OPERATOR_PIPE, // | - OPERATOR_CARET, // ^ - OPERATOR_MULT, // * - OPERATOR_DIV, // / - OPERATOR_PERCENT, // % - OPERATOR_LSHIFT, // << - OPERATOR_RSHIFT, // >> - OPERATOR_AMP, // & - OPERATOR_EXCLAM, // ! - //OPERATOR_BITCLEAR, // &^ - OPERATOR_LEFT_ARROW, // <- - OPERATOR_RIGHT_ARROW, // -> - - OPERATOR_EQ, // = - OPERATOR_PLUS_EQ, // += - OPERATOR_MINUS_EQ, // -= - OPERATOR_PIPE_EQ, // |= - OPERATOR_CARET_EQ, // ^= - OPERATOR_MULT_EQ, // *= - OPERATOR_DIV_EQ, // /= - OPERATOR_PERCENT_EQ, // %= - OPERATOR_LSHIFTEQ, // <<= - OPERATOR_RSHIFTEQ, // >>= - OPERATOR_AMP_EQ, // &= - //OPERATOR_BITCLEAREQ, // &^= - //OPERATOR_PLUSPLUS, // ++ - //OPERATOR_MINUSMINUS, // -- - - OPERATOR_COLON, // : - OPERATOR_DOUBLE_COLON, // :: - //OPERATOR_COLONEQ, // := - OPERATOR_SEMICOLON, // ; - OPERATOR_DOT, // . - OPERATOR_DOUBLE_DOT, // .. - OPERATOR_ELLIPSIS, // ... - OPERATOR_COMMA, // , - OPERATOR_LPAREN, // ( - OPERATOR_RPAREN, // ) - OPERATOR_LCURLY, // { - OPERATOR_RCURLY, // } - OPERATOR_LSQUARE, // [ - OPERATOR_RSQUARE, // ] - OPERATOR_TILDE, // ~ - OPERATOR_HASH, // # - OPERATOR_DOUBLE_QUOTE, // " - OPERATOR_SINGLE_QUOTE, // ' - OPERATOR_DOLLAR, // $ - OPERATOR_FSLASH, // / - OPERATOR_BACKSLASH, /* \ */ - OPERATOR_BLOCK_COMMENT, // /* - OPERATOR_LINE_COMMENT, // // - OPERATOR_QMARK, // ? - OPERATOR_AT, // @ - OPERATOR_BACKTICK // ` -}; - -struct Unicode_range; - -// The keywords. These must be in sorted order, other than -// KEYWORD_INVALID. They must match the Keywords::mapping_ array in -// lex.cc. - -enum Keyword { - KEYWORD_INVALID, // Not a keyword. - KEYWORD_UNDERSCORE, // _ - KEYWORD_ABSTRACT, // abstract - KEYWORD_ALIGNOF, // alignof - KEYWORD_AS, // as - KEYWORD_BE, // be - KEYWORD_BOX, // box - KEYWORD_BREAK, // break - KEYWORD_CONST, // const - KEYWORD_CONTINUE, // continue - KEYWORD_CRATE, // crate - KEYWORD_DO, // do - KEYWORD_ELSE, // else - KEYWORD_ENUM, // enum - KEYWORD_EXTERN, // extern - KEYWORD_FALSE, // false - KEYWORD_FINAL, // final - KEYWORD_FN, // fn - KEYWORD_FOR, // for - KEYWORD_IF, // if - KEYWORD_IMPL, // impl - KEYWORD_IN, // in - KEYWORD_LET, // let - KEYWORD_LOOP, // loop - KEYWORD_MATCH, // match - KEYWORD_MOD, // mod - KEYWORD_MOVE, // move - KEYWORD_MUT, // mut - KEYWORD_OFFSETOF, // offsetof - KEYWORD_OVERRIDE, // override - KEYWORD_PRIV, // priv - KEYWORD_PROC, // proc - KEYWORD_PUB, // pub - KEYWORD_PURE, // pure - KEYWORD_REF, // ref - KEYWORD_RETURN, // return - KEYWORD_SELF, // self - KEYWORD_SIZEOF, // sizeof - KEYWORD_STATIC, // static - KEYWORD_STRUCT, // struct - KEYWORD_SUPER, // super - KEYWORD_TRAIT, // trait - KEYWORD_TRUE, // true - KEYWORD_TYPE, // type - KEYWORD_TYPEOF, // typeof - KEYWORD_UNSAFE, // unsafe - KEYWORD_UNSIZED, // unsized - KEYWORD_USE, // use - KEYWORD_VIRTUAL, // virtual - KEYWORD_WHERE, // where - KEYWORD_WHILE, // while - KEYWORD_YIELD // yield -}; - -// Pragmas built from magic comments and recorded for functions. -// These are used as bits in a bitmask. -// The set of values is intended to be the same as the gc compiler. - -// I doubt these are in rust -/* enum RustPragma { - RUSTPRAGMA_NOINTERFACE = 1 << 0, // Method not in type descriptor. - RUSTPRAGMA_NOESCAPE = 1 << 1, // Args do not escape. - RUSTPRAGMA_NORACE = 1 << 2, // No race detector. - RUSTPRAGMA_NOSPLIT = 1 << 3, // Do not split stack. - RUSTPRAGMA_NOINLINE = 1 << 4, // Do not inline. - RUSTPRAGMA_SYSTEMSTACK = 1 << 5, // Must run on system stack. - RUSTPRAGMA_NOWRITEBARRIER = 1 << 6, // No write barriers. - RUSTPRAGMA_NOWRITEBARRIERREC = 1 << 7, // No write barriers here or callees. - RUSTPRAGMA_YESWRITEBARRIERREC = 1 << 8, // Stops nowritebarrierrec. - RUSTPRAGMA_MARK = 1 << 9, // Marker for nowritebarrierrec. - RUSTPRAGMA_CGOUNSAFEARGS = 1 << 10, // Pointer to arg is pointer to all. - RUSTPRAGMA_UINTPTRESCAPES = 1 << 11, // uintptr(p) escapes. - RUSTPRAGMA_NOTINHEAP = 1 << 12 // type is not in heap. -};*/ - -// The lexer itself. - -class Lex { - public: - Lex(const char* input_file_name, FILE* input_file, Linemap* linemap); - - ~Lex(); - - // Return the next token. - Token - next_token(); - - // Return the contents of any current //extern comment. - const std::string& - extern_name() const { return this->extern_; } - - // Return the current set of pragmas, and clear them. - unsigned int - get_and_clear_pragmas() { - unsigned int ret = this->pragmas_; - this->pragmas_ = 0; - return ret; - } - - struct Linkname { - std::string ext_name; // External name. - bool is_exported; // Whether the internal name is exported. - Location loc; // Location of go:linkname directive. - - Linkname() - : ext_name() - , is_exported(false) - , loc() {} - - Linkname(const std::string& ext_name_a, bool is_exported_a, Location loc_a) - : ext_name(ext_name_a) - , is_exported(is_exported_a) - , loc(loc_a) {} - }; - - typedef std::map Linknames; - - // Return the linknames seen so far, or NULL if none, and clear the - // set. These are from go:linkname compiler directives. - Linknames* - get_and_clear_linknames() { - Linknames* ret = this->linknames_; - this->linknames_ = NULL; - return ret; - } - - // Return whether the identifier NAME should be exported. NAME is a - // mangled name which includes only ASCII characters. - static bool - is_exported_mangled_name(const std::string& name); - - // Return whether the identifier NAME should be exported. NAME is - // an unmangled utf-8 string and may contain non-ASCII characters. - static bool - is_exported_name(const std::string& name); - - // Return whether the identifier NAME is invalid. When we see an - // invalid character we still build an identifier, but we use a - // magic string to indicate that the identifier is invalid. We then - // use this to avoid knockon errors. - static bool - is_invalid_identifier(const std::string& name); - - // A helper function. Append V to STR. IS_CHARACTER is true if V - // is a Unicode character which should be converted into UTF-8, - // false if it is a byte value to be appended directly. The - // location is used to warn about an out of range character. - static void - append_char(unsigned int v, bool is_charater, std::string* str, Location); - - // A helper function. Fetch a UTF-8 character from STR and store it - // in *VALUE. Return the number of bytes read from STR. Return 0 - // if STR does not point to a valid UTF-8 character. - static int - fetch_char(const char* str, unsigned int* value); - - // Return whether C is a Unicode or "C" locale space character. - static bool - is_unicode_space(unsigned int c); - - // Convert the specified hex char into an unsigned integer value. - static unsigned - hex_val(char c); - - private: - ssize_t - get_line(); - - bool - require_line(); - - // The current location. - Location - location() const; - - // A position CHARS column positions before the current location. - Location - earlier_location(int chars) const; - - static bool - is_hex_digit(char); - - static unsigned char - octal_value(char c) { return c - '0'; } - - Token - make_invalid_token() { return Token::make_invalid_token(this->location()); } - - Token - make_eof_token() { return Token::make_eof_token(this->location()); } - - Token - make_operator(Operator op, int chars) { return Token::make_operator_token(op, this->earlier_location(chars)); } - - Token - gather_identifier(); - - static bool - could_be_exponent(const char*, const char*); - - Token - gather_number(); - - Token - gather_character(); - - Token - gather_string(); - - Token - gather_raw_string(); - - const char* - advance_one_utf8_char(const char*, unsigned int*, bool*); - - const char* - advance_one_char(const char*, bool, unsigned int*, bool*); - - static bool - is_unicode_digit(unsigned int c); - - static bool - is_unicode_letter(unsigned int c); - - static bool - is_unicode_uppercase(unsigned int c); - - static bool - is_in_unicode_range(unsigned int C, const Unicode_range* ranges, size_t range_size); - - Operator - three_character_operator(char, char, char); - - Operator - two_character_operator(char, char); - - Operator - one_character_operator(char); - - bool - skip_c_comment(bool* found_newline); - - void - skip_cpp_comment(); - - // The input file name. - const char* input_file_name_; - // The input file. - FILE* input_file_; - // The object used to keep track of file names and line numbers. - Linemap* linemap_; - // The line buffer. This holds the current line. - char* linebuf_; - // The size of the line buffer. - size_t linebufsize_; - // The nmber of characters in the current line. - size_t linesize_; - // The current offset in linebuf_. - size_t lineoff_; - // The current line number. - size_t lineno_; - // Whether to add a semicolon if we see a newline now. - bool add_semi_at_eol_; - // Pragmas for the next function, from magic comments. - unsigned int pragmas_; - // The external name to use for a function declaration, from a magic - // //extern comment. - std::string extern_; - // The list of //go:linkname comments, if any. - Linknames* linknames_; -}; - -#endif // !defined(GO_LEX_H) diff --git a/gcc/rust/test2/rustfrontend/rs-token.h b/gcc/rust/test2/rustfrontend/rs-token.h deleted file mode 100644 index e3c4d39..0000000 --- a/gcc/rust/test2/rustfrontend/rs-token.h +++ /dev/null @@ -1,284 +0,0 @@ -// rs-token.h -- Rust frontend token thing idk. -*- C++ -*- - -// Copyright etc - -#ifndef RUST_TOKEN_H -#define RUST_TOKEN_H - -#include - -enum eTokenType { -#define _(t) t, -#include "eTokenType.enum.h" -#undef _ -}; - -// Location of a token -class Location { - public: - std::string filename; - unsigned int line; - unsigned int char_num; - - Location() - : filename("") - , line(0) - , char_num(0) {} - - Location(std::string filename, unsigned int line, unsigned int ofs) - : filename(filename) - , line(line) - , char_num(ofs) { - } -}; - -// A token returned from the lexer. - -class Token { - public: - // Token classification. -- going to replace with eTokenType, probably - /* enum Classification { - // Token is invalid. - TOKEN_INVALID, - // Token indicates end of input. - TOKEN_EOF, - // Token is a keyword. - TOKEN_KEYWORD, - // Token is an identifier. - TOKEN_IDENTIFIER, - // Token is a string of characters. - TOKEN_STRING, - // Token is an operator. - TOKEN_OPERATOR, - // Token is a character constant. - TOKEN_CHARACTER, - // Token is an integer. - TOKEN_INTEGER, - // Token is a floating point number. - TOKEN_FLOAT, - // Token is an imaginary number. - TOKEN_IMAGINARY - };*/ - - ~Token(); - Token(const Token&); - Token& operator=(const Token&); - - // Get token classification. - Classification - classification() const { return this->classification_; } - - // Make a token for an invalid value. - static Token - make_invalid_token(Location location) { return Token(TOKEN_INVALID, location); } - - // Make a token representing end of file. - static Token - make_eof_token(Location location) { return Token(TOKEN_EOF, location); } - - // Make a keyword token. - static Token - make_keyword_token(Keyword keyword, Location location) { - Token tok(TOKEN_KEYWORD, location); - tok.u_.keyword = keyword; - return tok; - } - - // Make an identifier token. - static Token - make_identifier_token(const std::string& value, bool is_exported, Location location) { - Token tok(TOKEN_IDENTIFIER, location); - tok.u_.identifier_value.name = new std::string(value); - tok.u_.identifier_value.is_exported = is_exported; - return tok; - } - - // Make a quoted string token. - static Token - make_string_token(const std::string& value, Location location) { - Token tok(TOKEN_STRING, location); - tok.u_.string_value = new std::string(value); - return tok; - } - - // Make an operator token. - static Token - make_operator_token(Operator op, Location location) { - Token tok(TOKEN_OPERATOR, location); - tok.u_.op = op; - return tok; - } - - // Make a character constant token. - static Token - make_character_token(mpz_t val, Location location) { - Token tok(TOKEN_CHARACTER, location); - mpz_init(tok.u_.integer_value); - mpz_swap(tok.u_.integer_value, val); - return tok; - } - - // Make an integer token. - static Token - make_integer_token(mpz_t val, Location location) { - Token tok(TOKEN_INTEGER, location); - mpz_init(tok.u_.integer_value); - mpz_swap(tok.u_.integer_value, val); - return tok; - } - - // Make a float token. - static Token - make_float_token(mpfr_t val, Location location) { - Token tok(TOKEN_FLOAT, location); - mpfr_init(tok.u_.float_value); - mpfr_swap(tok.u_.float_value, val); - return tok; - } - - // Make a token for an imaginary number. - static Token - make_imaginary_token(mpfr_t val, Location location) { - Token tok(TOKEN_IMAGINARY, location); - mpfr_init(tok.u_.float_value); - mpfr_swap(tok.u_.float_value, val); - return tok; - } - - // Get the location of the token. - Location - location() const { return this->location_; } - - // Return whether this is an invalid token. - bool - is_invalid() const { return this->classification_ == TOKEN_INVALID; } - - // Return whether this is the EOF token. - bool - is_eof() const { return this->classification_ == TOKEN_EOF; } - - // Return the keyword value for a keyword token. - Keyword - keyword() const { - gcc_assert(this->classification_ == TOKEN_KEYWORD); - return this->u_.keyword; - } - - // Return whether this is an identifier. - bool - is_identifier() const { return this->classification_ == TOKEN_IDENTIFIER; } - - // Return the identifier. - const std::string& - identifier() const { - gcc_assert(this->classification_ == TOKEN_IDENTIFIER); - return *this->u_.identifier_value.name; - } - - // Return whether the identifier is exported. - bool - is_identifier_exported() const { - gcc_assert(this->classification_ == TOKEN_IDENTIFIER); - return this->u_.identifier_value.is_exported; - } - - // Return whether this is a string. - bool - is_string() const { - return this->classification_ == TOKEN_STRING; - } - - // Return the value of a string. The returned value is a string of - // UTF-8 characters. - std::string - string_value() const { - gcc_assert(this->classification_ == TOKEN_STRING); - return *this->u_.string_value; - } - - // Return the value of a character constant. - const mpz_t* - character_value() const { - gcc_assert(this->classification_ == TOKEN_CHARACTER); - return &this->u_.integer_value; - } - - // Return the value of an integer. - const mpz_t* - integer_value() const { - gcc_assert(this->classification_ == TOKEN_INTEGER); - return &this->u_.integer_value; - } - - // Return the value of a float. - const mpfr_t* - float_value() const { - gcc_assert(this->classification_ == TOKEN_FLOAT); - return &this->u_.float_value; - } - - // Return the value of an imaginary number. - const mpfr_t* - imaginary_value() const { - gcc_assert(this->classification_ == TOKEN_IMAGINARY); - return &this->u_.float_value; - } - - // Return the operator value for an operator token. - Operator - op() const { - gcc_assert(this->classification_ == TOKEN_OPERATOR); - return this->u_.op; - } - - // Return whether this token is KEYWORD. - bool - is_keyword(Keyword keyword) const { - return (this->classification_ == TOKEN_KEYWORD && this->u_.keyword == keyword); - } - - // Return whether this token is OP. - bool - is_op(Operator op) const { return this->classification_ == TOKEN_OPERATOR && this->u_.op == op; } - - // Print the token for debugging. - void - print(FILE*) const; - - private: - // Private constructor used by make_..._token functions above. - Token(Classification, Location); - - // Clear the token. - void - clear(); - - // The token classification. - Classification classification_; - union { - // The keyword value for TOKEN_KEYWORD. - Keyword keyword; - // The token value for TOKEN_IDENTIFIER. - struct - { - // The name of the identifier. This has been mangled to only - // include ASCII characters. - std::string* name; - // Whether this name should be exported. This is true if the - // first letter in the name is upper case. - bool is_exported; - } identifier_value; - // The string value for TOKEN_STRING. - std::string* string_value; - // The token value for TOKEN_CHARACTER or TOKEN_INTEGER. - mpz_t integer_value; - // The token value for TOKEN_FLOAT or TOKEN_IMAGINARY. - mpfr_t float_value; - // The token value for TOKEN_OPERATOR or the keyword value - Operator op; - } u_; - // The source location. - Location location_; -}; - -#endif // RUST_TOKEN_H \ No newline at end of file diff --git a/gcc/rust/test2/rustfrontend/rust.cc b/gcc/rust/test2/rustfrontend/rust.cc deleted file mode 100644 index 989c992..0000000 --- a/gcc/rust/test2/rustfrontend/rust.cc +++ /dev/null @@ -1,179 +0,0 @@ -// rust.cc - Rust frontend main file for GCC - -// copyright, etc. - -#include "rust-system.h" - -#include "rust-c.h" -#include "rust-diagnostics.h" - -#include "rs-backend.h" -#include "rustrust.h" -#include "rs-lex.h" -#include "rs-parse.h" - -// The data structures we build to represent the file. -static Gorust* rustrust; -// replace with rdot or something else? - -// Create the main IR data structure. -RUST_EXTERN_C void rust_create_rustrust(const struct rust_create_rustrust_args* args) { - rust_assert(::rustrust == NULL); - ::rustrust = new Gorust(args->backend, args->linemap, args->int_type_size, args->pointer_size); - - if (args->pkgpath != NULL) - ::rustrust->set_pkgpath(args->pkgpath); - else if (args->prefix != NULL) - ::rustrust->set_prefix(args->prefix); - - if (args->relative_import_path != NULL) - ::rustrust->set_relative_import_path(args->relative_import_path); - ::rustrust->set_check_divide_by_zero(args->check_divide_by_zero); - ::rustrust->set_check_divide_overflow(args->check_divide_overflow); - if (args->compiling_runtime) - ::rustrust->set_compiling_runtime(args->compiling_runtime); - if (args->c_header != NULL) - ::rustrust->set_c_header(args->c_header); - ::rustrust->set_debug_escape_level(args->debug_escape_level); - if (args->debug_escape_hash != NULL) - ::rustrust->set_debug_escape_hash(args->debug_escape_hash); - ::rustrust->set_nil_check_size_threshold(args->nil_check_size_threshold); - if (args->debug_optimization) - ::rustrust->set_debug_optimization(args->debug_optimization); -} - -// Parse the input files. -RUST_EXTERN_C void grs_parse_input_files(const char** filenames, unsigned int filename_count, - bool only_check_syntax, bool) { - rust_assert(filename_count > 0); - - Lex::Linknames all_linknames; - for (unsigned int i = 0; i < filename_count; ++i) { - if (i > 0) - ::rustrust->clear_file_scope(); - - const char* filename = filenames[i]; - FILE* file; - if (strcmp(filename, "-") == 0) - file = stdin; - else { - file = fopen(filename, "r"); - if (file == NULL) - rust_fatal_error(Linemap::unknown_location(), - "cannot open %s: %m", - filename); - } - - Lex lexer(filename, file, ::rustrust->linemap()); - - Parse parse(&lexer, ::rustrust); - parse.program(); - - if (strcmp(filename, "-") != 0) - fclose(file); - - Lex::Linknames* linknames = lexer.get_and_clear_linknames(); - if (linknames != NULL) { - if (!::rustrust->current_file_imported_unsafe()) { - for (Lex::Linknames::const_iterator p = linknames->begin(); - p != linknames->end(); - ++p) - rust_error_at(p->second.loc, - ("//rust:linkname only allowed in Go files that " - "import \"unsafe\"")); - } - all_linknames.insert(linknames->begin(), linknames->end()); - } - } - - ::rustrust->clear_file_scope(); - - // If the global predeclared names are referenced but not defined, - // define them now. - ::rustrust->define_global_names(); - - // Apply any rust:linkname directives. - for (Lex::Linknames::const_iterator p = all_linknames.begin(); - p != all_linknames.end(); - ++p) - ::rustrust->add_linkname(p->first, p->second.is_exported, p->second.ext_name, p->second.loc); - - // Finalize method lists and build stub methods for named types. - ::rustrust->finalize_methods(); - - // Check that functions have a terminating statement. - ::rustrust->check_return_statements(); - - // Now that we have seen all the names, lower the parse tree into a - // form which is easier to use. - ::rustrust->lower_parse_tree(); - - // At this point we have handled all inline functions, so we no - // longer need the linemap. - ::rustrust->linemap()->stop(); - - // Create function descriptors as needed. - ::rustrust->create_function_descriptors(); - - // Now that we have seen all the names, verify that types are - // correct. - ::rustrust->verify_types(); - - // Work out types of unspecified constants and variables. - ::rustrust->determine_types(); - - // Check types and issue errors as appropriate. - ::rustrust->check_types(); - - if (only_check_syntax) - return; - - // Make implicit type conversions explicit. - ::rustrust->add_conversions(); - - // Analyze the program flow for escape information. - ::rustrust->analyze_escape(); - - // Export global identifiers as appropriate. - ::rustrust->do_exports(); - - // Use temporary variables to force order of evaluation. - ::rustrust->order_evaluations(); - - // Turn short-cut operators (&&, ||) into explicit if statements. - ::rustrust->remove_shortcuts(); - - // Convert named types to backend representation. - ::rustrust->convert_named_types(); - - // Build thunks for functions which call recover. - ::rustrust->build_recover_thunks(); - - // Convert complicated rust and defer statements into simpler ones. - ::rustrust->simplify_thunk_statements(); - - // Write out queued up functions for hash and comparison of types. - ::rustrust->write_specific_type_functions(); - - // Add write barriers. - ::rustrust->add_write_barriers(); - - // Flatten the parse tree. - ::rustrust->flatten(); - - // Reclaim memory of escape analysis Nodes. - ::rustrust->reclaim_escape_nodes(); - - // Dump ast, use filename[0] as the base name - ::rustrust->dump_ast(filenames[0]); -} - -// Write out globals. -RUST_EXTERN_C void rust_write_globals() { - return ::rustrust->write_globals(); -} - -// Return the global IR structure. This is used by some of the langhooks to pass to other code. -Rustrust* rust_get_rustrust() { - return ::rustrust; -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/Make-lang.in b/gcc/rust/test3-tiny/Make-lang.in deleted file mode 100644 index 500960c..0000000 --- a/gcc/rust/test3-tiny/Make-lang.in +++ /dev/null @@ -1,226 +0,0 @@ -# Make-lang.in -- Top level -*- makefile -*- fragment for GCC Rust frontend. - -# Copyright (C) 2009-2013 Free Software Foundation, Inc. - -# This file is part of GCC. - -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# This file provides the language dependent support in the main Makefile. - -#RUST_EXES = rust - -# Use strict warnings for this front end. -rust-warn = $(STRICT_WARN) - -# Installation name. Useful for cross compilers and used during install. -GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)') -GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)') - -# Define the names for selecting rust in LANGUAGES. -rust: gccrs$(exeext) grs1$(exeext) - -# Tell GNU make to ignore files by these names if they exist. -.PHONY: rust - -# removed GRS_CFLAGS from here - -# removed object files from here -#rs-lexer.o: $(srcdir)/rust/rs-lexer.l rs-parser.o -# $(FLEX) --outfile=lex.rs.c $(srcdir)/rust/rs-lexer.l -# $(COMPILER) $(GRS_CFLAGS) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -# $(LDFLAGS) -c -o $@ lex.rs.c -# etc. for parser, etc. - -# For compiler driver creation. -#rsspec.o: $(srcdir)/rust/rsspec.cc $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \ -# $(CONFIG_H) opts.h -# (SHLIB='$(SHLIB)'; \ -# $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \ -# $(INCLUDES) $(srcdir)/rust/rsspec.cc) - -# Create the compiler driver gccrs. -# A compiler driver is the program that interprets command argument and can be called from the command -# line - e.g. gcc or g++, and not cc1, which is the actual compiler -GCCRS_D_OBJS = \ - $(GCC_OBJS) \ - rust/rsspec.o \ - $(END) - -gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) - +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ - $(EXTRA_GCC_LIBS) $(LIBS) - -# List of host object files used by the rust language - files for translation from the parse tree -# to GENERIC -# The compiler proper, not driver -GRS_OBJS = \ - rust/rust-lang.o \ - rust/rust-token.o \ - rust/rust-lex.o \ - rust/rust-parse.o \ - rust/rust-scope.o \ - rust/rust-misc-convert.o \ - $(END) -# removed object files from here - -# The compiler itself is called grs1 -grs1$(exeext): attribs.o $(GRS_OBJS) $(BACKEND) $(LIBDEPS) - +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - attribs.o $(GRS_OBJS) $(BACKEND) $(LIBS) $(BACKENDLIBS) - -# Build hooks. - -# Copies its dependencies into the source directory. This generally should be used for generated files -# such as Bison output files which are not version-controlled, but should be included in any release -# tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’ -# was specified as a configure option. -rust.srcextra: - -rust.all.cross: - -# idk what this does but someone used it -rust.start.encap: gccrs$(exeext) -rust.rest.encap: - -# Build generated man pages for the front end from Texinfo manuals (see Man Page Generation), in the -# build directory. This target is only called if the necessary tools are available, but should ignore -# errors so as not to stop the build if errors occur; man pages are optional and the tools involved -# may be installed in a broken way. -rust.man: - -# Copies its dependencies into the source directory. These targets will be executed during a bootstrap -# if ‘--enable-generated-files-in-srcdir’ was specified as a configure option. -rust.srcman: - -# Clean hooks. - -rust.mostlyclean: -# cd $(srcdir)/rust; rm -f *.o y.tab.h y.tab.c lex.yy.c - -rust.clean: rust.mostlyclean - -# Builds an etags TAGS file in the language subdirectory in the source tree. -#rust.tags: force -# cd $(srcdir)/rust; etags -o TAGS.sub *.y *.l *.cc *.h; \ -# etags --include TAGS.sub --include ../TAGS.sub - -# Build documentation hooks. - -# Build info documentation for the front end, in the build directory. This target is only called by -# ‘make bootstrap’ if a suitable version of makeinfo is available, so does not need to check for this, -# and should fail if an error occurs. -rust.info: - -rust.srcinfo: - -# Build DVI documentation for the front end, in the build directory. This should be done using -# $(TEXI2DVI), with appropriate -I arguments pointing to directories of included files. -rust.dvi: - -# Build PDF documentation for the front end, in the build directory. This should be done using -# $(TEXI2PDF), with appropriate -I arguments pointing to directories of included files. -rust.pdf: - -doc/rust.info: -doc/rust.dvi: -doc/rust.pdf: - -# Build HTML documentation for the front end, in the build directory. -rust.html: - -# Install hooks. - -# Install everything that is part of the front end, apart from the compiler executables listed in -# compilers in config-lang.in. -rust.install-common: installdirs -# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) -# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext) -# $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) -# if test -f $(DESTDIR)$(bindir)$(GCCRS_TARGET_INSTALL_NAME)$(exeext); then \ -# :; \ -# else \ -# cd $(DESTDIR)$(bindir) && \ -# $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ -# fi - -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ - ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext) ); \ - -# Install headers needed for plugins. -rust.install-plugin: - -# Uninstall files installed by installing the compiler. This is currently documented not to be -# supported, so the hook need not do anything. -rust.uninstall: -# -rm -rf $(DESTDIR)/$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - -rm -f gccrs$(exeext) grs1$(exeext) - -rm -f $(GRS_OBJS) -# ^those two are a maybe - -# No rust-specific selftests -selftest-rust: - -# Install info documentation for the front end, if it is present in the source directory. This target -# should have dependencies on info files that should be installed. -rust.install-info: - -rust.install-pdf: - -# Install man pages for the front end. This target should ignore errors. -rust.install-man: - -# Stage hooks: -# The toplevel makefile has already created stage?/rust at this point. -# Used for handling bootstrap - -rust.stage1: stage1-start - -mv rust/*$(objext) stage1/rust -rust.stage2: stage2-start - -mv rust/*$(objext) stage2/rust -rust.stage3: stage3-start - -mv rust/*$(objext) stage3/rust -rust.stage4: stage4-start - -mv rust/*$(objext) stage4/rust -rust.stageprofile: stageprofile-start - -mv rust/*$(objext) stageprofile/rust -rust.stagefeedback: stagefeedback-start - -mv rust/*$(objext) stagefeedback/rust - -#config.status: rust/config-lang.in - -#CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ -# -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" - -# cross-folder includes - add new folders later -RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse - -# add files that require cross-folder includes - currently rust-lang.o, rust-lex.o -CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) -CFLAGS-rust/rust-lex.o += $(RUST_INCLUDES) -CFLAGS-rust/rust-parse.o += $(RUST_INCLUDES) - -# build all rust/lex files in rust folder, add cross-folder includes -rust/%.o: rust/lex/%.cc - $(COMPILE) $(RUST_INCLUDES) $< - $(POSTCOMPILE) - -# build all rust/parse files in rust folder, add cross-folder includes -rust/%.o: rust/parse/%.cc - $(COMPILE) $(RUST_INCLUDES) $< - $(POSTCOMPILE) \ No newline at end of file diff --git a/gcc/rust/test3-tiny/config-lang.in b/gcc/rust/test3-tiny/config-lang.in deleted file mode 100644 index 823f626..0000000 --- a/gcc/rust/test3-tiny/config-lang.in +++ /dev/null @@ -1,49 +0,0 @@ -# config-lang.in -- Top level configure fragment for gcc Rust frontend. - -# Copyright (C) 2013 Free Software Foundation, Inc. - -# This file is part of GCC. - -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# Configure looks for the existence of this file to auto-config each language. -# We define several parameters used by configure: -# -# language - name of language as it would appear in $(LANGUAGES) -# compilers - value to add to $(COMPILERS) -# diff_excludes - files to ignore when building diffs between two versions. - -language="rust" - -# Space-separated list of compiler executables that will be run by the driver. The names here will -# each end with ‘\$(exeext)’. -compilers="grs1\$(exeext)" - -# Do not build by default. -build_by_default="no" - -# Lists (space-separated) language front ends other than C that this front end requires to be -# enabled (with the names given being their language settings). -lang_requires_boot_languages=c++ - -# Lists (space-separated) targets in the top level Makefile to build the runtime libraries -# for this language, such as target-libobjc. -target_libs="" - -# Space-separated list of files that should be scanned by gengtype.c to generate the garbage -# collection tables and routines for this language. This excludes the files that are common to all -# front ends. -# gtfiles="\$(srcdir)/rust/rs-lang.c \$(srcdir)/rust/rdot-impl.h" -gtfiles="\$(srcdir)/rust/rust-lang.cc" diff --git a/gcc/rust/test3-tiny/lang-specs.h b/gcc/rust/test3-tiny/lang-specs.h deleted file mode 100644 index c36a9e7..0000000 --- a/gcc/rust/test3-tiny/lang-specs.h +++ /dev/null @@ -1,30 +0,0 @@ -/* This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -// describes Rust front-end to GCC driver - -/* tells GCC to invoke Rust frontend on .rs files, gives instructions on - other programs to be run, such as assembler, etc. - In this, it has grs1 as the actual compiler and whatever */ -/* This is the contribution to the `default_compilers' array in gcc.c - for the Rust language. */ -{".rs", "@rs", 0, 1, 0}, -/*{"@rs", "grs1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", - 0, 1, 0},*/ -{"@rs", "grs1 %i %{!Q:-quiet} %(cc1_options) %{!fsyntax-only:%(invoke_as)}", - 0, 1, 0}, - -// "May take a while" to write this file - refer to other language lang-specs.h \ No newline at end of file diff --git a/gcc/rust/test3-tiny/lex/rust-lex.cc b/gcc/rust/test3-tiny/lex/rust-lex.cc deleted file mode 100644 index e620b84..0000000 --- a/gcc/rust/test3-tiny/lex/rust-lex.cc +++ /dev/null @@ -1,314 +0,0 @@ -#include "rust-lex.h" - -#include "diagnostic.h" // for error_at -#include "safe-ctype.h" - -namespace Rust { - Lexer::Lexer(const char* filename, FILE* input) : - input(input), current_line(1), current_column(1), line_map(0), input_source(input), - input_queue(input_source), token_source(this), token_queue(token_source) { - // inform line_table that file is being entered and is in line 1 - line_map - = ::linemap_add(::line_table, ::LC_ENTER, /* sysp */ 0, filename, /* current_line */ 1); - } - - Lexer::~Lexer() { - ::linemap_add(::line_table, ::LC_LEAVE, /* sysp */ 0, /* filename */ NULL, /* to_line */ 0); - } - - location_t Lexer::get_current_location() { - return ::linemap_position_for_column(::line_table, current_column); - } - - int Lexer::peek_input(int n) { - return input_queue.peek(n); - } - - int Lexer::peek_input() { - return peek_input(0); - } - - void Lexer::skip_input(int n) { - input_queue.skip(n); - } - - void Lexer::skip_input() { - skip_input(0); - } - - const_TokenPtr Lexer::peek_token(int n) { - return token_queue.peek(n); - } - - const_TokenPtr Lexer::peek_token() { - return peek_token(0); - } - - void Lexer::skip_token(int n) { - token_queue.skip(n); - } - - void Lexer::skip_token() { - skip_token(0); - } - - /* shitty anonymous namespace that can only be accessed inside the compilation unit - used for - * classify_keyword - * Binary search in sorted array of keywords created with x-macros. */ - namespace { - const std::string keyword_index[] = { -#define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(name, keyword) keyword, - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - TokenId keyword_keys[] = { -#define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(name, keyword) name, - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - const int num_keywords = sizeof(keyword_index) / sizeof(*keyword_index); - } - - TokenId Lexer::classify_keyword(const std::string& str) { - const std::string* last = keyword_index + num_keywords; - const std::string* idx = std::lower_bound(keyword_index, last, str); - - if (idx == last || str != *idx) { - return IDENTIFIER; - } else { - return keyword_keys[idx - keyword_index]; - } - } - - TokenPtr Lexer::build_token() { - // loop to go through multiple characters to build a single token - while (true) { - location_t loc = get_current_location(); - int current_char = peek_input(); - skip_input(); - - // return end of file token if end of file - if (current_char == EOF) { - return Token::make(END_OF_FILE, loc); - } - - // if not end of file, start tokenising - switch (current_char) { - // ignore whitespace characters for tokens but continue updating location - case '\n': // newline - current_line++; - current_column = 1; - // tell line_table that new line starts - linemap_line_start(::line_table, current_line, max_column_hint); - continue; - case ' ': // space - current_column++; - continue; - case '\t': // tab - // width of a tab is not well-defined, assume 8 spaces - current_column += 8; - continue; - - // punctuation - actual tokens - case '=': - current_column++; - return Token::make(EQUAL, loc); - case '(': - current_column++; - return Token::make(LEFT_PAREN, loc); - case '-': - current_column++; - return Token::make(MINUS, loc); - case '+': - current_column++; - return Token::make(PLUS, loc); - case ')': - current_column++; - return Token::make(RIGHT_PAREN, loc); - case ';': - current_column++; - return Token::make(SEMICOLON, loc); - case '*': - current_column++; - return Token::make(ASTERISK, loc); - /*case ',': - current_column++; - return Token::make(COMMA, loc);*/ - case '/': - current_column++; - return Token::make(SLASH, loc); - case '%': - current_column++; - return Token::make(PERCENT, loc); - /*case '[': - current_column++; - return Token::make(LEFT_SQUARE, loc); - case ']': - current_column++; - return Token::make(RIGHT_SQUARE, loc);*/ - // dodgily implemented peeking for some operators - case '<': - if (peek_input() == '=') { - skip_input(); - current_column += 2; - - return Token::make(SMALLER_OR_EQUAL, loc); - } else { - current_column++; - return Token::make(SMALLER, loc); - } - break; - case '>': - if (peek_input() == '=') { - skip_input(); - current_column += 2; - - return Token::make(GREATER_OR_EQUAL, loc); - } else { - current_column++; - return Token::make(GREATER, loc); - } - case ':': - if (peek_input() == '=') { - skip_input(); - current_column += 2; - - return Token::make(ASSIG, loc); - } else { - current_column++; - return Token::make(COLON, loc); - } - case '!': - if (peek_input() == '=') { - skip_input(); - current_column += 2; - - return Token::make(DIFFERENT, loc); - } - - // bad comment implementation - case '#': // single-line comment - current_column++; - current_char = peek_input(); - // basically ignore until line finishes - while (current_char != '\n') { - skip_input(); - current_column++; // not used - current_char = peek_input(); - } - - continue; - break; - - case '[': - current_column++; - return Token::make(LEFT_SQUARE, loc); - case ']': - current_column++; - return Token::make(RIGHT_SQUARE, loc); - case '.': - if (!ISDIGIT(peek_input())) { - // Only if followed by a non-number - current_column++; - return Token::make(DOT, loc); - } - } - - // find identifiers and keywords - if (ISALPHA(current_char) - || current_char == '_') { // is alphanumeric or _ (maybe just letters) - std::string str; - str.reserve(16); // default - str += current_char; - - int length = 1; - current_char = peek_input(); - // loop through entire name - while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - TokenId keyword = classify_keyword(str); - if (keyword == IDENTIFIER) { - return Token::make_identifier(loc, str); - } else { - return Token::make(keyword, loc); - } - } - - // identify literals - // int or float literals - if (ISDIGIT(current_char) || current_char == '.') { - std::string str; - str.reserve(16); // some sensible default - str += current_char; - - bool is_real = (current_char == '.'); - - int length = 1; - current_char = peek_input(); - while (ISDIGIT(current_char) || (!is_real && current_char == '.')) { - length++; - - is_real = is_real || (current_char == '.'); - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - if (is_real) { - return Token::make_float(loc, str); - } else { - return Token::make_int(loc, str); - } - } - - // string literals - if (current_char == '"') { - std::string str; - str.reserve(16); // some sensible default - - int length = 1; - current_char = peek_input(); - while (current_char != '\n' && current_char != '"') { - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - if (current_char == '\n') { - error_at(get_current_location(), "unended string literal"); - } else if (current_char == '"') { - skip_input(); - } else { - gcc_unreachable(); - } - - return Token::make_string(loc, str); - } - - // didn't match anything so error - error_at(loc, "unexpected character '%x'", current_char); - current_column++; - } - } -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/lex/rust-lex.h b/gcc/rust/test3-tiny/lex/rust-lex.h deleted file mode 100644 index 4d0bdbb..0000000 --- a/gcc/rust/test3-tiny/lex/rust-lex.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef RUST_LEX_H -#define RUST_LEX_H - -#include "rust-buffered-queue.h" -#include "rust-token.h" - -namespace Rust { - class Lexer { - private: - // Request new location_t for current column in line_table - location_t get_current_location(); - - // Skips the current input char. - void skip_input(); - // Advances current input char to n + 1 chars ahead of current position. - void skip_input(int n); - - // Returns char n chars ahead of current position. - int peek_input(); - // Peeks the current char. - int peek_input(int n); - - // Classifies keyword (i.e. gets id for keyword). - TokenId classify_keyword(const std::string& str); - - // Builds a token from the input queue. - TokenPtr build_token(); - - public: - // Construct lexer with input file and filename provided - Lexer(const char* filename, FILE* input); - ~Lexer(); - - // Returns token n tokens ahead of current position. - const_TokenPtr peek_token(int n); - // Peeks the current token. - const_TokenPtr peek_token(); - - // Advances current token to n + 1 tokens ahead of current position. - void skip_token(int n); - // Skips the current token. - void skip_token(); - - private: - // File for use as input. - FILE* input; - - // Current line number. - int current_line; - // Current column number. - int current_column; - // Line map. - const struct line_map* line_map; - - // Max column number that can be quickly allocated - higher may require allocating new linemap - static const int max_column_hint = 80; - - // Input source wrapper thing. - struct InputSource { - // Input source file. - FILE* input; - - // Create new input source from file. - InputSource(FILE* input) : input(input) {} - - // Overload operator () to return next char from input stream. - int operator()() { - return fgetc(input); - } - }; - - // The input source for the lexer. - InputSource input_source; - // Input file queue. - buffered_queue input_queue; - - // Token source wrapper thing. - struct TokenSource { - // The lexer object that will use this TokenSource. - Lexer* lexer; - - // Create a new TokenSource with given lexer. - TokenSource(Lexer* parLexer) : lexer(parLexer) {} - - // Overload operator () to build token in lexer. - TokenPtr operator()() { - return lexer->build_token(); - } - }; - - // The token source for the lexer. - TokenSource token_source; - // Token stream queue. - buffered_queue, TokenSource> token_queue; - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3-tiny/lex/rust-token.cc b/gcc/rust/test3-tiny/lex/rust-token.cc deleted file mode 100644 index 1a4fe38..0000000 --- a/gcc/rust/test3-tiny/lex/rust-token.cc +++ /dev/null @@ -1,33 +0,0 @@ -#include "rust-token.h" - -namespace Rust { - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id) { - switch (id) { -#define RS_TOKEN(name, descr) \ - case name: \ - return descr; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - default: - gcc_unreachable(); - } - } - - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id) { - switch (id) { -#define RS_TOKEN(name, _) \ - case name: \ - return #name; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - default: - gcc_unreachable(); - } - } -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/lex/rust-token.h b/gcc/rust/test3-tiny/lex/rust-token.h deleted file mode 100644 index 68c8d63..0000000 --- a/gcc/rust/test3-tiny/lex/rust-token.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef RUST_TOKEN_H -#define RUST_TOKEN_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "input.h" -// order: config, system, coretypes, input - -#include -#include // as shared_ptr is not available in std memory in c++03 - -namespace Rust { -// RS_TOKEN(name, description) -// RS_TOKEN_KEYWORD(name, identifier) -// -// Keep RS_TOKEN_KEYWORD sorted - -// TODO: change to actual rust tokens -#define RS_TOKEN_LIST \ - RS_TOKEN(FIRST_TOKEN, "") \ - RS_TOKEN(END_OF_FILE, "end of file") \ - RS_TOKEN(ASSIG, ":=") \ - RS_TOKEN(ASTERISK, "*") \ - RS_TOKEN(COLON, ":") \ - RS_TOKEN(DIFFERENT, "!=") \ - RS_TOKEN(EQUAL, "=") \ - RS_TOKEN(LEFT_PAREN, "(") \ - RS_TOKEN(MINUS, "-") \ - RS_TOKEN(PLUS, "+") \ - RS_TOKEN(RIGHT_PAREN, ")") \ - RS_TOKEN(SEMICOLON, ";") \ - RS_TOKEN(SLASH, "/") \ - RS_TOKEN(PERCENT, "%") \ - RS_TOKEN(GREATER, ">") \ - RS_TOKEN(GREATER_OR_EQUAL, ">=") \ - RS_TOKEN(SMALLER, "<") \ - RS_TOKEN(SMALLER_OR_EQUAL, "<=") \ - RS_TOKEN(IDENTIFIER, "identifier") \ - RS_TOKEN(INT_LITERAL, "integer literal") \ - RS_TOKEN(FLOAT_LITERAL, "float literal") \ - RS_TOKEN(STRING_LITERAL, "string literal") \ - RS_TOKEN(LEFT_SQUARE, "[") \ - RS_TOKEN(RIGHT_SQUARE, "]") \ - RS_TOKEN(DOT, ".") \ - \ - RS_TOKEN_KEYWORD(AND, "and") \ - RS_TOKEN_KEYWORD(BOOL, "bool") \ - RS_TOKEN_KEYWORD(DO, "do") \ - RS_TOKEN_KEYWORD(ELSE, "else") \ - RS_TOKEN_KEYWORD(END, "end") \ - RS_TOKEN_KEYWORD(FALSE_LITERAL, "false") \ - RS_TOKEN_KEYWORD(FLOAT, "float") \ - RS_TOKEN_KEYWORD(FOR, "for") \ - RS_TOKEN_KEYWORD(IF, "if") \ - RS_TOKEN_KEYWORD(INT, "int") \ - RS_TOKEN_KEYWORD(NOT, "not") \ - RS_TOKEN_KEYWORD(OR, "or") \ - RS_TOKEN_KEYWORD(READ, "read") \ - RS_TOKEN_KEYWORD(RECORD, "record") \ - RS_TOKEN_KEYWORD(THEN, "then") \ - RS_TOKEN_KEYWORD(TO, "to") \ - RS_TOKEN_KEYWORD(TRUE_LITERAL, "true") \ - RS_TOKEN_KEYWORD(TYPE, "type") \ - RS_TOKEN_KEYWORD(VAR, "var") \ - RS_TOKEN_KEYWORD(WHILE, "while") \ - RS_TOKEN_KEYWORD(WRITE, "write") \ - \ - RS_TOKEN(LAST_TOKEN, "") - - // Contains all token types. Crappy implementation via x-macros. - enum TokenId { -#define RS_TOKEN(name, _) name, -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - // dodgy "TokenPtr" declaration with Token forward declaration - class Token; - // A smart pointer (shared_ptr) to Token. - typedef std::tr1::shared_ptr TokenPtr; - // A smart pointer (shared_ptr) to a constant Token. - typedef std::tr1::shared_ptr const_TokenPtr; - - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id); - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id); - - // Represents a single token. Create using factory static methods. - class Token { - private: - // Token kind. - TokenId token_id; - // Token location. - location_t locus; - // Associated text (if any) of token. - std::string* str; - - // Token constructor from token id and location. Has a null string. - Token(TokenId token_id, location_t location) : - token_id(token_id), locus(location), str(NULL) {} - - // Token constructor from token id, location, and a string. - Token(TokenId token_id, location_t location, const std::string& paramStr) : - token_id(token_id), locus(location), str(new std::string(paramStr)) {} - - // No default initialiser. - Token(); - // Do not copy/assign tokens. - Token(const Token&); - Token& operator=(const Token&); - - public: - ~Token() { - delete str; - } - - // Makes and returns a new TokenPtr (with null string). - static TokenPtr make(TokenId token_id, location_t locus) { - return TokenPtr(new Token(token_id, locus)); - } - - // Makes and returns a new TokenPtr of type IDENTIFIER. - static TokenPtr make_identifier(location_t locus, const std::string& str) { - return TokenPtr(new Token(IDENTIFIER, locus, str)); - } - - // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int(location_t locus, const std::string& str) { - return TokenPtr(new Token(INT_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float(location_t locus, const std::string& str) { - return TokenPtr(new Token(FLOAT_LITERAL, locus, str)); - } - - static TokenPtr make_string(location_t locus, const std::string& str) { - return TokenPtr(new Token(STRING_LITERAL, locus, str)); - } - - // Gets id of the token. - TokenId get_id() const { - return token_id; - } - - // Gets location of the token. - location_t get_locus() const { - return locus; - } - - // Gets string description of the token. - const std::string& get_str() const { - gcc_assert(str != NULL); - return *str; - } - - // diagnostics - const char* get_token_description() const { - return Rust::get_token_description(token_id); - } - - // debugging - const char* token_id_to_str() const { - return Rust::token_id_to_str(token_id); - } - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-misc-convert.cc b/gcc/rust/test3-tiny/parse/rust-misc-convert.cc deleted file mode 100644 index a38f0c4..0000000 --- a/gcc/rust/test3-tiny/parse/rust-misc-convert.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -#include "fold-const.h" -#include "convert.h" -// order: config, system, coretypes, tree, fold-const, convert - -// Required by some generic routines. Converts expression of value expr to type type. -tree convert(tree type, tree expr) { - if (type == error_mark_node || expr == error_mark_node || TREE_TYPE(expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE(expr)) - return expr; - - if (TYPE_MAIN_VARIANT(type) == TYPE_MAIN_VARIANT(TREE_TYPE(expr))) - return fold_convert(type, expr); - - switch (TREE_CODE(type)) { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert(type, expr); - case INTEGER_TYPE: - return fold(convert_to_integer(type, expr)); - case POINTER_TYPE: - return fold(convert_to_pointer(type, expr)); - case REAL_TYPE: - return fold(convert_to_real(type, expr)); - case COMPLEX_TYPE: - return fold(convert_to_complex(type, expr)); - default: - break; - } - - gcc_unreachable(); -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-parse.cc b/gcc/rust/test3-tiny/parse/rust-parse.cc deleted file mode 100644 index ec9c212..0000000 --- a/gcc/rust/test3-tiny/parse/rust-parse.cc +++ /dev/null @@ -1,1806 +0,0 @@ -#include "rust-parse.h" - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "tree-iterator.h" -#include "input.h" -#include "diagnostic.h" -#include "stringpool.h" -#include "cgraph.h" -#include "gimplify.h" -#include "gimple-expr.h" -#include "convert.h" -#include "print-tree.h" -#include "stor-layout.h" -#include "fold-const.h" -/* order: config, system, coretypes, target, tree, tree-iterator, input, diagnostic, stringpool, - * cgraph, gimplify, gimple-expr, convert, print-tree, stor-layout, fold-const */ -// probably don't need all these - -#include // for std::find - -/* parsing notes: - * kinds of "syntactic units" used: - * - statement: expresses an action to be carried out (executed), e.g.: - * function calls - * goto - * return - * (maybe) variable definition - * blocks (apparently) - as in {} - * control structures - if, while, do-while, switch - * cannot return a result and are executed only for side effects - * distinction may not exist in rust entirely due to functional influence of lots of things being - * expressions - * - * - expression: stuff that evaluates to a value, e.g.: - * 2 + 3 - * y * 6 - * - * - variable definition (maybe - if not a statement), e.g.: - * y = x + 2 */ - -namespace Rust { - // Left binding powers of operations. - enum binding_powers { - // Highest priority - LBP_HIGHEST = 100, - - LBP_DOT = 90, - - LBP_ARRAY_REF = 80, - - LBP_UNARY_PLUS = 50, // Used only when the null denotation is + - LBP_UNARY_MINUS = LBP_UNARY_PLUS, // Used only when the null denotation is - - - LBP_MUL = 40, - LBP_DIV = LBP_MUL, - LBP_MOD = LBP_MUL, - - LBP_PLUS = 30, - LBP_MINUS = LBP_PLUS, - - LBP_EQUAL = 20, - LBP_DIFFERENT = LBP_EQUAL, - LBP_SMALLER_THAN = LBP_EQUAL, - LBP_SMALLER_EQUAL = LBP_EQUAL, - LBP_GREATER_THAN = LBP_EQUAL, - LBP_GREATER_EQUAL = LBP_EQUAL, - - LBP_LOGICAL_AND = 10, - LBP_LOGICAL_OR = LBP_LOGICAL_AND, - LBP_LOGICAL_NOT = LBP_LOGICAL_AND, - - // lowest priority - LBP_LOWEST = 0, - }; - - // Checks if Tree has a string type (tree code pointer_type and tree variant char node). - bool is_string_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - - // ensure main variant of pointee is char_type_node (i.e. type is char*) - return type.get_tree_code() == POINTER_TYPE - && TYPE_MAIN_VARIANT(TREE_TYPE(type.get_tree())) == char_type_node; - } - - // Checks if Tree has array type. - bool is_array_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - return type.get_tree_code() == ARRAY_TYPE; - } - - // Checks if Tree has record type. - bool is_record_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - return type.get_tree_code() == RECORD_TYPE; - } - - // Gets left binding power for specified token. - int Parser::left_binding_power(const_TokenPtr token) { - switch (token->get_id()) { - case DOT: - return LBP_DOT; - - case LEFT_SQUARE: - return LBP_ARRAY_REF; - - case ASTERISK: - return LBP_MUL; - case SLASH: - return LBP_DIV; - case PERCENT: - return LBP_MOD; - - case PLUS: - return LBP_PLUS; - case MINUS: - return LBP_MINUS; - - case EQUAL: - return LBP_EQUAL; - case DIFFERENT: - return LBP_DIFFERENT; - case GREATER: - return LBP_GREATER_THAN; - case GREATER_OR_EQUAL: - return LBP_GREATER_EQUAL; - case SMALLER: - return LBP_SMALLER_THAN; - case SMALLER_OR_EQUAL: - return LBP_SMALLER_EQUAL; - - case OR: - return LBP_LOGICAL_OR; - case AND: - return LBP_LOGICAL_AND; - case NOT: - return LBP_LOGICAL_NOT; - - // anything that can't appear in an infix position is given lowest priority - default: - return LBP_LOWEST; - } - } - - TreeStmtList& Parser::get_current_stmt_list() { - return stack_stmt_list.back(); - } - - // Parse statement sequence? - void Parser::parse_statement_seq(bool (Parser::*done)()) { - // Parse statements until done and append to the current stmt list - while (!(this->*done)()) { - // get stmt tree for parsed statement - Tree stmt = parse_statement(); - // append each stmt tree to current stmt list - get_current_stmt_list().append(stmt); - } - } - - // Returns true when current token is EOF. - bool Parser::done_end_of_file() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == END_OF_FILE); - } - - // Entry point - parse entire program (in file) from here. - void Parser::parse_program() { - // Built type of main "int (int, char**)" - tree main_fndecl_type_param[] - = { integer_type_node, build_pointer_type(build_pointer_type(char_type_node)) }; - tree main_fndecl_type - = build_function_type_array(integer_type_node, 2, main_fndecl_type_param); - // Create function declaration "int main(int, char**)" - main_fndecl = build_fn_decl("main", main_fndecl_type); - - // Enter top-level scope. - enter_scope(); - // program -> statement* - parse_statement_seq(&Parser::done_end_of_file); - // Append "return 0;" - tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); - // create decl_context of resdecl for main function (local variable of main function) - DECL_CONTEXT(resdecl) = main_fndecl; - DECL_RESULT(main_fndecl) = resdecl; - tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), - build_int_cst_type(integer_type_node, 0)); - tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); - - get_current_stmt_list().append(return_stmt); - - // Leave top-level scope, get its binding expression and its main block - TreeSymbolMapping main_tree_scope = leave_scope(); - Tree main_block = main_tree_scope.block; - - // Finish main function - BLOCK_SUPERCONTEXT(main_block.get_tree()) = main_fndecl; - DECL_INITIAL(main_fndecl) = main_block.get_tree(); - DECL_SAVED_TREE(main_fndecl) = main_tree_scope.bind_expr.get_tree(); - - // Main function is not external - DECL_EXTERNAL(main_fndecl) = 0; - // Preserve main function - DECL_PRESERVE_P(main_fndecl) = 1; - - // Convert from GENERIC to GIMPLE - gimplify_function_tree(main_fndecl); - - // Insert it into the graph (queue for compilation?) - cgraph_node::finalize_function(main_fndecl, true); - - main_fndecl = NULL_TREE; - } - - // Parses a statement. Selects how to parse based on token id. - Tree Parser::parse_statement() { - /* - statement -> variable_declaration - | assignment_statement - | if_statement - | while_statement - | for_statement - | read_statement - | write_statement - */ - // peek current token - const_TokenPtr t = lexer.peek_token(); - - // call method to parse statement if recognised - switch (t->get_id()) { - case VAR: - return parse_variable_declaration(); - break; - case TYPE: - return parse_type_declaration(); - break; - case IF: - return parse_if_statement(); - break; - case WHILE: - return parse_while_statement(); - break; - case FOR: - return parse_for_statement(); - break; - case READ: - return parse_read_statement(); - break; - case WRITE: - return parse_write_statement(); - break; - case IDENTIFIER: - return parse_assignment_statement(); - break; - default: - // if not recognised, error with unexpected token and attempt resume - unexpected_token(t); - skip_after_semicolon(); - return Tree::error(); - break; - } - } - - // "Unexpected token" panic mode - flags gcc error at unexpected token - void Parser::unexpected_token(const_TokenPtr t) { - ::error_at(t->get_locus(), "unexpected %s\n", t->get_token_description()); - } - - // Crappy "error recovery" performed after error by skipping tokens until a semi-colon is found - void Parser::skip_after_semicolon() { - const_TokenPtr t = lexer.peek_token(); - - while (t->get_id() != END_OF_FILE && t->get_id() != SEMICOLON) { - lexer.skip_token(); - t = lexer.peek_token(); - } - - if (t->get_id() == SEMICOLON) - lexer.skip_token(); - } - - // Parses a variable declaration statement. - Tree Parser::parse_variable_declaration() { - // skip initial var keyword - if (!skip_token(VAR)) { - skip_after_semicolon(); - return Tree::error(); - } - - // keep identifier token as used later - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip colon - if (!skip_token(COLON)) { - skip_after_semicolon(); - return Tree::error(); - } - - // parse the actual type of the variable - Tree type_tree = parse_type(); - - if (type_tree.is_error()) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip the semicolon - skip_token(SEMICOLON); - - // check if current mapping of the scope already contains a mapping for identifier - if (scope.get_current_mapping().get(identifier->get_str())) { - // create error if this is true - error_at(identifier->get_locus(), "name %s already declared in this scope", - identifier->get_str().c_str()); - return Tree::error(); - } - - // create a new symbol using the given identifier - SymbolPtr sym(new Symbol(VARIABLE, identifier->get_str())); - // put new symbol into scope mapping - scope.get_current_mapping().insert(sym); - - // create GENERIC tree for variable declaration - Tree decl = build_decl(identifier->get_locus(), VAR_DECL, - get_identifier(sym->get_name().c_str()), type_tree.get_tree()); - // set decl_context of decl to main function (make it local variable of main function) - DECL_CONTEXT(decl.get_tree()) = main_fndecl; - - // keep VAR_DECL tree in top list of stack_var_decl_chain stack for block purposes - gcc_assert(!stack_var_decl_chain.empty()); - stack_var_decl_chain.back().append(decl); - - // associate new symbol with VAR_DECL tree - sym->set_tree_decl(decl); - - Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); - - return stmt; - } - - /* Checks if current token has inputted id - skips it and returns true if so, diagnoses an error - * and returns false otherwise. */ - bool Parser::skip_token(TokenId token_id) { - return expect_token(token_id) != const_TokenPtr(); - } - - /* Checks the current token - if id is same as expected, skips and returns it, otherwise diagnoses - * error and returns null. */ - const_TokenPtr Parser::expect_token(TokenId token_id) { - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() == token_id) { - lexer.skip_token(); - return t; - } else { - error_at(t->get_locus(), "expecting %s but %s found!\n", get_token_description(token_id), - t->get_token_description()); - - return const_TokenPtr(); - } - } - - // Parses type in variable declaration. - Tree Parser::parse_type() { - const_TokenPtr t = lexer.peek_token(); - - Tree type; - - switch (t->get_id()) { - case INT: - lexer.skip_token(); - type = integer_type_node; - break; - case FLOAT: - lexer.skip_token(); - type = float_type_node; - break; - case BOOL: - lexer.skip_token(); - type = boolean_type_node; - break; - case IDENTIFIER: { - SymbolPtr s = query_type(t->get_str(), t->get_locus()); - lexer.skip_token(); - - if (s == NULL) - type = Tree::error(); - else { - type = TREE_TYPE(s->get_tree_decl().get_tree()); - } - } break; - case RECORD: - type = parse_record(); - break; - default: - unexpected_token(t); - return Tree::error(); - break; - } - - // start parsing index ranges: list of expression pairs (lower and upper indexes of array) - typedef std::vector > Dimensions; - Dimensions dimensions; - - t = lexer.peek_token(); - while (t->get_id() == LEFT_PAREN || t->get_id() == LEFT_SQUARE) { - lexer.skip_token(); - - // array bounds - Tree lower_bound, upper_bound; - - if (t->get_id() == LEFT_SQUARE) { - // for array of form [e] - Tree size = parse_integer_expression(); - skip_token(RIGHT_SQUARE); - - lower_bound = Tree(build_int_cst_type(integer_type_node, 0), size.get_locus()); - - // set upper to e - 1 - upper_bound = build_tree(MINUS_EXPR, size.get_locus(), integer_type_node, size, - build_int_cst(integer_type_node, 1)); - } else if (t->get_id() == LEFT_PAREN) { - // for array of form [e0:e1] - // parse e0 - lower_bound = parse_integer_expression(); - skip_token(COLON); - - // parse e1 - upper_bound = parse_integer_expression(); - skip_token(RIGHT_PAREN); - } else { - gcc_unreachable(); - } - - dimensions.push_back(std::make_pair(lower_bound, upper_bound)); - t = lexer.peek_token(); - } - - // start building array type - // transverse list in reverse order - for (Dimensions::reverse_iterator it = dimensions.rbegin(); it != dimensions.rend(); it++) { - // fold lower and upper expressions (simplify expressions if possible) - it->first = Tree(fold(it->first.get_tree()), it->first.get_locus()); - it->second = Tree(fold(it->second.get_tree()), it->second.get_locus()); - - if (!type.is_error()) { - // build GCC range type using lower and upper - Tree range_type - = build_range_type(integer_type_node, it->first.get_tree(), it->second.get_tree()); - // build array type - type = build_array_type(type.get_tree(), range_type.get_tree()); - } - } - - return type; - } - - // Parses an if statement. Probably important to study as it seems complex. - Tree Parser::parse_if_statement() { - // skip if statement token - if (!skip_token(IF)) { - skip_after_end(); - return Tree::error(); - } - - // parse expression in statement body - Tree expr = parse_boolean_expression(); - - // skip the "THEN" after expression - skip_token(THEN); - - // enter new block scope - enter_scope(); - // parse statement sequence? inside if body. Finish at "end if" or "else" - parse_statement_seq(&Parser::done_end_or_else); - - TreeSymbolMapping then_tree_scope = leave_scope(); - Tree then_stmt = then_tree_scope.bind_expr; - - Tree else_stmt; - const_TokenPtr tok = lexer.peek_token(); - // if there is an else, parse statement seq inside its body too - if (tok->get_id() == ELSE) { - // Consume 'else' - skip_token(ELSE); - - // enter block scope - enter_scope(); - parse_statement_seq(&Parser::done_end); - TreeSymbolMapping else_tree_scope = leave_scope(); - else_stmt = else_tree_scope.bind_expr; - - // Consume 'end' - skip_token(END); - } else if (tok->get_id() == END) { - // Consume 'end' - skip_token(END); - } else { - unexpected_token(tok); - return Tree::error(); - } - - // build GENERIC if statement node. - return build_if_statement(expr, then_stmt, else_stmt); - } - - // Builds an if statement tree. - Tree Parser::build_if_statement(Tree bool_expr, Tree then_part, Tree else_part) { - if (bool_expr.is_error()) - return bool_expr; - - // create then label declaration tree - Tree then_label_decl = build_label_decl("then", then_part.get_locus()); - - // create else label declaration if it exists - Tree else_label_decl; - if (!else_part.is_null()) - else_label_decl = build_label_decl("else", else_part.get_locus()); - - // create endif label declaration - Tree endif_label_decl = build_label_decl("end_if", then_part.get_locus()); - - // create goto expressions for entering "if" branch, "else" branch, and code after if block - Tree goto_then - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, then_label_decl); - Tree goto_endif - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, endif_label_decl); - - Tree goto_else_or_endif; - if (!else_part.is_null()) - goto_else_or_endif - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, else_label_decl); - else - goto_else_or_endif = goto_endif; - - // create statement list for if statement which will have required statements appended - TreeStmtList stmt_list; - - // create conditional branch expression and append to stmt_list - Tree cond_expr = build_tree( - COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, goto_then, goto_else_or_endif); - stmt_list.append(cond_expr); - - // define location related to "then" part and append to stmt_list - Tree then_label_expr - = build_tree(LABEL_EXPR, then_part.get_locus(), void_type_node, then_label_decl); - stmt_list.append(then_label_expr); - - // append parameter "then_part" to statement list - stmt_list.append(then_part); - - // if else part exists, append a goto endif - if (!else_part.is_null()) { - // Make sure after then part has been executed we go to the end if - stmt_list.append(goto_endif); - - // define location of else label, append it, and append else_part parameter tree - Tree else_label_expr - = build_tree(LABEL_EXPR, else_part.get_locus(), void_type_node, else_label_decl); - stmt_list.append(else_label_expr); - stmt_list.append(else_part); - // do not need to jump to endif as handled implicitly here - } - - // define label for endif, append to statement list - Tree endif_label_expr - = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, endif_label_decl); - stmt_list.append(endif_label_expr); - - // return the statement list in tree form - return stmt_list.get_tree(); - } - - // Builds a GENERIC tree LABEL_DECL (represents a label, as in a "goto" label). - Tree Parser::build_label_decl(const char* name, location_t loc) { - tree t = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node); - - gcc_assert(main_fndecl != NULL_TREE); - DECL_CONTEXT(t) = main_fndecl; - - return t; - } - - // Skips all tokens until EOF. - void Parser::skip_after_end() { - const_TokenPtr t = lexer.peek_token(); - - while (t->get_id() != END_OF_FILE && t->get_id() != END) { - lexer.skip_token(); - t = lexer.peek_token(); - } - - if (t->get_id() == END) { - lexer.skip_token(); - } - } - - // Pratt parser impl of parse_expression. - Tree Parser::parse_expression(int right_binding_power) { - const_TokenPtr current_token = lexer.peek_token(); - lexer.skip_token(); - - Tree expr = null_denotation(current_token); - - if (expr.is_error()) { - return Tree::error(); - } - - // stop parsing if find lower priority token - parse higher priority first - while (right_binding_power < left_binding_power(lexer.peek_token())) { - current_token = lexer.peek_token(); - lexer.skip_token(); - - expr = left_denotation(current_token, expr); - if (expr.is_error()) - return Tree::error(); - } - - return expr; - } - - // Parse an expression with lowest left binding power. - Tree Parser::parse_expression() { - return parse_expression(LBP_LOWEST); - } - - // Parses a boolean expression (basically parses expression and ensures boolean result). - Tree Parser::parse_boolean_expression() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_type() != boolean_type_node) { - error_at(expr.get_locus(), "expected expression of boolean type but its type is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return expr; - } - - // Parses an integer expression (basically parses expression and ensures integer result). - Tree Parser::parse_integer_expression() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_type() != integer_type_node) { - error_at(expr.get_locus(), "expected expression of integer type but its type is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return expr; - } - - // Determines action to take when finding token at beginning of expression. - Tree Parser::null_denotation(const_TokenPtr tok) { - // note: tok is previous character in input stream, not current one, as parse_expression - // skips it before passing it in - - /* as a Pratt parser (which works by decomposing expressions into a null denotation and then a - * left denotation), null denotations handle primaries and unary operands */ - - switch (tok->get_id()) { - case IDENTIFIER: { - // when encountering identifier, lookup in scope - SymbolPtr s = scope.lookup(tok->get_str()); - if (s == NULL) { - error_at(tok->get_locus(), "variable '%s' not declared in the current scope", - tok->get_str().c_str()); - - return Tree::error(); - } - // expression is just its VAR_DECL that was stored in the Symbol at declaration - return Tree(s->get_tree_decl(), tok->get_locus()); - } - case INT_LITERAL: - // we should check the range, but ignore for now - // literal itself encodes value, so token's text has to be interpreted as int. use - // atoi for this - return Tree(build_int_cst_type(integer_type_node, atoi(tok->get_str().c_str())), - tok->get_locus()); - case FLOAT_LITERAL: { - REAL_VALUE_TYPE float_value; - // invoke real_from_string3 to get float value representation from string - real_from_string3(&float_value, tok->get_str().c_str(), TYPE_MODE(float_type_node)); - // this is because machine-dependent - - // create actual tree with that built constant value - return Tree(build_real(float_type_node, float_value), tok->get_locus()); - } - case STRING_LITERAL: { - // get c string from token - std::string str = tok->get_str(); - const char* c_str = str.c_str(); - - // use GCC's build_string_literal (with null terminator) to create tree - return Tree(build_string_literal(strlen(c_str) + 1, c_str), tok->get_locus()); - } - case TRUE_LITERAL: { - // construct tree with code INTEGER_CST and value 1 but with boolean_type_node - return Tree(build_int_cst_type(boolean_type_node, 1), tok->get_locus()); - break; - } - case FALSE_LITERAL: { - return Tree(build_int_cst_type(boolean_type_node, 0), tok->get_locus()); - break; - } - case LEFT_PAREN: { // have to parse whole expression if inside brackets - /* recursively invoke parse_expression with lowest priority possible as it it were - * a top-level expression. */ - Tree expr = parse_expression(); - tok = lexer.peek_token(); - - // end of expression must be a close-bracket - if (tok->get_id() != RIGHT_PAREN) - error_at( - tok->get_locus(), "expecting ')' but %s found\n", tok->get_token_description()); - else - lexer.skip_token(); - - return Tree(expr, tok->get_locus()); - } - case PLUS: { // unary plus operator - // invoke parse_expression recursively with appropriate priority, etc. for below - Tree expr = parse_expression(LBP_UNARY_PLUS); - - if (expr.is_error()) - return Tree::error(); - // can only apply to integer and float expressions - if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary plus must be int or float but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return Tree(expr, tok->get_locus()); - } - case MINUS: { // unary minus - Tree expr = parse_expression(LBP_UNARY_MINUS); - - if (expr.is_error()) - return Tree::error(); - // can only apply to integer and float expressions - if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary minus must be int or float but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - // create NEGATE_EXPR tree, which computes negation of operand - expr = build_tree(NEGATE_EXPR, tok->get_locus(), expr.get_type(), expr); - return expr; - } - case NOT: { // logical not - Tree expr = parse_expression(LBP_LOGICAL_NOT); - - if (expr.is_error()) - return Tree::error(); - // can only apply to boolean expressions - if (expr.get_type() != boolean_type_node) { - error_at(tok->get_locus(), - "operand of logical not must be a boolean but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - // create TRUTH_NOT_EXPR tree, which computes logical negation of operand - expr = build_tree(TRUTH_NOT_EXPR, tok->get_locus(), boolean_type_node, expr); - return expr; - } - default: - unexpected_token(tok); - return Tree::error(); - } - } - - /* Called for each token that can appear in infix (between) position. Can be operators or other - * punctuation. - * Returns a function pointer to member function that implements the left denotation for the token - * given. */ - Tree Parser::left_denotation(const_TokenPtr tok, Tree left) { - BinaryHandler binary_handler = get_binary_handler(tok->get_id()); - if (binary_handler == NULL) { - unexpected_token(tok); - return Tree::error(); - } - - return (this->*binary_handler)(tok, left); - } - - // Gets method for handling binary operation parsing for specific token type. - Parser::BinaryHandler Parser::get_binary_handler(TokenId id) { - switch (id) { -#define BINARY_HANDLER(name, token_id) \ - case token_id: \ - return &Parser::binary_##name; - BINARY_HANDLER_LIST -#undef BINARY_HANDLER - default: - return NULL; - } - } - - /* Returns the type of the binary operation. May also modify input trees if types do not match, - * e.g. change a float and int to two floats in addition. */ - Tree Parser::coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right) { - Tree left_type = left->get_type(); - Tree right_type = right->get_type(); - - // return error if either types are invalid - if (left_type.is_error() || right_type.is_error()) - return Tree::error(); - - // good, easy, no type conversion required - if (left_type == right_type) { - if (left_type == integer_type_node || left_type == float_type_node) { - return left_type; - } - // dodgy type coercion happening if types don't match but are both numerical - } else if ((left_type == integer_type_node && right_type == float_type_node) - || (left_type == float_type_node && right_type == integer_type_node)) { - // rebuild one tree as float - if (left_type == integer_type_node) { - *left = build_tree(FLOAT_EXPR, left->get_locus(), float_type_node, left->get_tree()); - } else { - *right - = build_tree(FLOAT_EXPR, right->get_locus(), float_type_node, right->get_tree()); - } - - return float_type_node; - } - - // unhandled - e.g. int + boolean - error_at(tok->get_locus(), "invalid operands of type %s and %s for operator %s", - print_type(left_type), print_type(right_type), tok->get_token_description()); - return Tree::error(); - } - - // Verifies that both left and right trees are boolean-type nodes. - bool Parser::check_logical_operands(const_TokenPtr tok, Tree left, Tree right) { - // ensure both operands are boolean types - if (left.get_type() != boolean_type_node || right.get_type() != boolean_type_node) { - error_at(tok->get_locus(), - "operands of operator %s must be boolean but they are %s and %s\n", - tok->get_token_description(), print_type(left.get_type()), - print_type(right.get_type())); - - return false; - } - - return true; - } - - // Implementation of addition expression parsing. - Tree Parser::binary_plus(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code PLUS_EXPR to represent binary addition - return build_tree(PLUS_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of subtraction expression parsing. - Tree Parser::binary_minus(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code MINUS_EXPR to represent binary subtraction - return build_tree(MINUS_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of multiplication expression parsing. - Tree Parser::binary_mult(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code MULT_EXPR to represent binary multiplication - return build_tree(MULT_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of divison expression parsing. - Tree Parser::binary_div(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_DIV); - if (right.is_error()) - return Tree::error(); - - // if integer division, create C-like truncated division expression tree - if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { - return build_tree(TRUNC_DIV_EXPR, tok->get_locus(), integer_type_node, left, right); - } else { - // floating-point division - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - gcc_assert(tree_type == float_type_node); - - return build_tree(RDIV_EXPR, tok->get_locus(), tree_type, left, right); - } - } - - // Implementation of modulo expression parsing. - Tree Parser::binary_mod(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_MOD); - if (right.is_error()) - return Tree::error(); - - // if integer modulo, create truncated modulo expression - if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { - return build_tree(TRUNC_MOD_EXPR, tok->get_locus(), integer_type_node, left, right); - } else { - // no floating-point modulo - return Tree::error(); - } - } - - // Implementation of binary equal comparison relational operator parsing. - Tree Parser::binary_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(EQ_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary different comparison relational operator parsing. - Tree Parser::binary_different(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_DIFFERENT); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(NE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary smaller than comparison relational operator parsing. - Tree Parser::binary_smaller_than(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_SMALLER_THAN); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(LT_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary greater than comparison relational operator parsing. - Tree Parser::binary_greater_than(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_GREATER_THAN); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(GT_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary smaller than or equal to comparison relational operator parsing. - Tree Parser::binary_smaller_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_SMALLER_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(LE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary greater than or equal to comparison relational operator parsing. - Tree Parser::binary_greater_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_GREATER_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(GE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary "and" logical operator parsing. - Tree Parser::binary_logical_and(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_LOGICAL_AND); - if (right.is_error()) - return Tree::error(); - - if (!check_logical_operands(tok, left, right)) - return Tree::error(); - - return build_tree(TRUTH_ANDIF_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary "or" logical operator parsing. - Tree Parser::binary_logical_or(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_LOGICAL_OR); - if (right.is_error()) - return Tree::error(); - - if (!check_logical_operands(tok, left, right)) - return Tree::error(); - - return build_tree(TRUTH_ORIF_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary array reference ([) operator parsing; - Tree Parser::binary_array_ref(const_TokenPtr tok, Tree left) { - // parse integer expression inside square brackets (array index) - Tree right = parse_integer_expression(); - if (right.is_error()) - return Tree::error(); - - // array close token - if (!skip_token(RIGHT_SQUARE)) - return Tree::error(); - - // verify left operand has array type - if (!is_array_type(left.get_type())) { - error_at(left.get_locus(), "does not have array type"); - return Tree::error(); - } - - // compute type of array element - Tree element_type = TREE_TYPE(left.get_type().get_tree()); - - // build GENERIC tree ARRAY_REF that represents array access - return build_tree(ARRAY_REF, tok->get_locus(), element_type, left, right, Tree(), Tree()); - } - - // Parses a binary field access on a record. - Tree Parser::binary_field_ref(const_TokenPtr tok, Tree left) { - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) - return Tree::error(); - - // ensure left expression has record type - if (!is_record_type(left.get_type())) { - error_at(left.get_locus(), "does not have record type"); - return Tree::error(); - } - - // traverse each FIELD_DECL chaining through TREE_CHAIN - // list of fields in record type is available through TYPE_FIELDS - Tree field_decl = TYPE_FIELDS(left.get_type().get_tree()); - while (!field_decl.is_null()) { - // FIELD_DECL has a DECL_NAME containing an IDENTIFIER_POINTER to get field name - Tree decl_name = DECL_NAME(field_decl.get_tree()); - const char* field_name = IDENTIFIER_POINTER(decl_name.get_tree()); - - if (field_name == identifier->get_str()) - break; - - field_decl = TREE_CHAIN(field_decl.get_tree()); - } - - // if can't find a field with given name, this is an error - if (field_decl.is_null()) { - error_at(left.get_locus(), "record type does not have a field named '%s'", - identifier->get_str().c_str()); - return Tree::error(); - } - - // build COMPONENT_REF tree using left tree (record type) and appropriate FIELD_DECL - return build_tree(COMPONENT_REF, tok->get_locus(), TREE_TYPE(field_decl.get_tree()), left, - field_decl, Tree()); - } - - // Parse variable assignment statement. This is not the same as variable declaration. - Tree Parser::parse_assignment_statement() { - Tree variable = parse_lhs_assignment_expression(); - - if (variable.is_error()) - return Tree::error(); - - const_TokenPtr assig_tok = expect_token(ASSIG); - if (assig_tok == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip assignment token and parse expression - const_TokenPtr first_of_expr = lexer.peek_token(); - - Tree expr = parse_expression(); - if (expr.is_error()) - return Tree::error(); - - // skip semicolon token - skip_token(SEMICOLON); - - // enforce rule that rhs of assignment has to have same type as declared lhs type - if (variable.get_type() != expr.get_type()) { - // diagnostic - error_at(first_of_expr->get_locus(), - "cannot assign value of type %s to a variable of type %s", print_type(expr.get_type()), - print_type(variable.get_type())); - - return Tree::error(); - } - - Tree assig_expr - = build_tree(MODIFY_EXPR, assig_tok->get_locus(), void_type_node, variable, expr); - return assig_expr; - } - - // Print human-readable name for type. - const char* Parser::print_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - - if (type == void_type_node) - return "void"; - else if (type == integer_type_node) - return "int"; - else if (type == float_type_node) - return "float"; - else if (is_string_type(type)) - return "string"; - else if (type == boolean_type_node) - return "boolean"; - else - return "<>"; - } - - // Returns address to function declaration of printf. - Tree Parser::get_printf_addr() { - // only run if printf_fn is null to avoid making repeated function declarations - if (printf_fn.is_null()) { - // build const char* type (printf fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type as vararg function - tree fndecl_type - = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree printf_fn_decl = build_fn_decl("printf", fndecl_type); - // mark as external - DECL_EXTERNAL(printf_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), printf_fn_decl); - } - - return printf_fn; - } - - // Returns address to function declaration of puts. - Tree Parser::get_puts_addr() { - if (puts_fn.is_null()) { - // build const char* type (puts fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type - tree fndecl_type = build_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree puts_fn_decl = build_fn_decl("puts", fndecl_type); - // mark as external - DECL_EXTERNAL(puts_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - puts_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), puts_fn_decl); - } - - return puts_fn; - } - - // Returns address to function declaration of scanf. - Tree Parser::get_scanf_addr() { - // only run if scanf_fn is null to avoid making repeated function declarations - if (scanf_fn.is_null()) { - // build const char* type (scanf fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type as vararg function - tree fndecl_type - = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree scanf_fn_decl = build_fn_decl("scanf", fndecl_type); - // mark as external - DECL_EXTERNAL(scanf_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - scanf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), scanf_fn_decl); - } - - return scanf_fn; - } - - // Parses a "write statement". - Tree Parser::parse_write_statement() { - // write_statement -> "write" expression ";" - - if (!skip_token(WRITE)) { - skip_after_semicolon(); - return Tree::error(); - } - - const_TokenPtr first_of_expr = lexer.peek_token(); - Tree expr = parse_expression(); - - skip_token(SEMICOLON); - - if (expr.is_error()) - return Tree::error(); - - // enable printing of value of expression - if (expr.get_type() == integer_type_node) { - // printf("%d\n", expr) - // build format string for integer (also add null terminator) and integer expression - const char* format_integer = "%d\n"; - tree args[] - = { build_string_literal(strlen(format_integer) + 1, format_integer), expr.get_tree() }; - - // used as trees do not allow calling a FUNCTIONAL_DECL directly - Tree printf_fn = get_printf_addr(); - - // build call to print function (printf_fn), in which two arguments in args are passed - // first argument is format string - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); - - return stmt; - } else if (expr.get_type() == float_type_node) { - // printf("%f\n" (double)expr) - // have to convert float to double - const char* format_float = "%f\n"; - tree args[] = { build_string_literal(strlen(format_float) + 1, format_float), - convert(double_type_node, expr.get_tree()) }; - - Tree printf_fn = get_printf_addr(); - - // build call, etc. - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); - - return stmt; - } else if (is_string_type(expr.get_type())) { - // Alternatively we could use printf('%s\n', expr) instead of puts(expr) - tree args[] = { expr.get_tree() }; - - Tree puts_fn = get_puts_addr(); - - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, puts_fn.get_tree(), 1, args); - - return stmt; - } else { - // no more valid types - error_at(first_of_expr->get_locus(), "value of type %s is not a valid write operand", - print_type(expr.get_type())); - return Tree::error(); - } - - gcc_unreachable(); - } - - // Enters new scope (like block scope or whatever). - void Parser::enter_scope() { - // push new symbol mapping - scope.push_scope(); - - TreeStmtList stmt_list; - // Used as stack for statements. - stack_stmt_list.push_back(stmt_list); - - // Used as stack of var decls. - stack_var_decl_chain.push_back(TreeChain()); - // Used as stack for blocks. - stack_block_chain.push_back(BlockChain()); - } - - // Leaves current scope (as defined by blocks - like block scope). - Parser::TreeSymbolMapping Parser::leave_scope() { - // Get current list of statements and pop them from stack of statement lists - TreeStmtList current_stmt_list = get_current_stmt_list(); - stack_stmt_list.pop_back(); - - // Get current list of var decls and pop them from stack of var decl lists - TreeChain var_decl_chain = stack_var_decl_chain.back(); - stack_var_decl_chain.pop_back(); - - // Get current list of blocks and pop them from stack of block lists - BlockChain subblocks = stack_block_chain.back(); - stack_block_chain.pop_back(); - - // Create a new block from var decls and subblocks - tree new_block = build_block(var_decl_chain.first.get_tree(), subblocks.first.get_tree(), - /* supercontext */ NULL_TREE, /* chain */ NULL_TREE); - - // Add the new block to the current chain of blocks (if any) - if (!stack_block_chain.empty()) { - stack_block_chain.back().append(new_block); - } - - // Set the subblocks to have the new block as their parent - for (tree it = subblocks.first.get_tree(); it != NULL_TREE; it = BLOCK_CHAIN(it)) - BLOCK_SUPERCONTEXT(it) = new_block; - // Do it this way because of double-linkage - - // Create BIND_EXPR from decl chain, stmt list, and new block - tree bind_expr = build3(BIND_EXPR, void_type_node, var_decl_chain.first.get_tree(), - current_stmt_list.get_tree(), new_block); - - // create, basically, a tuple of bind_expr and new_block - TreeSymbolMapping tree_scope; - tree_scope.bind_expr = bind_expr; - tree_scope.block = new_block; - - // pop symbol mapping - scope.pop_scope(); - - return tree_scope; - } - - // Parses the "read" statement. - Tree Parser::parse_read_statement() { - if (!skip_token(READ)) { - skip_after_semicolon(); - return Tree::error(); - } - - const_TokenPtr first_of_expr = lexer.peek_token(); - Tree expr = parse_expression_naming_variable(); - - skip_token(SEMICOLON); - - if (expr.is_error()) - return Tree::error(); - - // force variable name instead of manually looking up identifier token - /* if (expr.get_tree_code() != VAR_DECL) { - error_at(first_of_expr->get_locus(), "invalid expression in read statement"); - return Tree::error(); - }*/ - // not used anymore due to parse_expression_naming_variable - - // Variable must be addressable (variable needs address computed) - TREE_ADDRESSABLE(expr.get_tree()) = 1; - - // determine appropriate format string - const char* format = NULL; - if (expr.get_type() == integer_type_node) { - format = "%d"; - } else if (expr.get_type() == float_type_node) { - format = "%f"; - } else { - error_at(first_of_expr->get_locus(), "variable of type %s is not a valid read operand", - print_type(expr.get_type())); - return Tree::error(); - } - - // build args for scanf - tree args[] = { build_string_literal(strlen(format) + 1, format), - build_tree(ADDR_EXPR, first_of_expr->get_locus(), - build_pointer_type(expr.get_type().get_tree()), expr) - .get_tree() }; - - // get scanf address - Tree scanf_fn = get_scanf_addr(); - - // create tree to call scanf - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, scanf_fn.get_tree(), 2, args); - - return stmt; - } - - // Parses a while statement. - Tree Parser::parse_while_statement() { - if (!skip_token(WHILE)) { - skip_after_end(); - return Tree::error(); - } - - // parse while's conditional expression - Tree expr = parse_boolean_expression(); - if (!skip_token(DO)) { - skip_after_end(); - return Tree::error(); - } - - // enter loop body scope - enter_scope(); - parse_statement_seq(&Parser::done_end); - TreeSymbolMapping while_body_tree_scope = leave_scope(); - - Tree while_body_stmt = while_body_tree_scope.bind_expr; - - skip_token(END); - - // build while statement tree - return build_while_statement(expr, while_body_stmt); - } - - // Builds a while statement tree. - Tree Parser::build_while_statement(Tree bool_expr, Tree while_body) { - if (bool_expr.is_error()) - return Tree::error(); - - TreeStmtList stmt_list; - - // build label decl for while condition check - Tree while_check_label_decl = build_label_decl("while_check", bool_expr.get_locus()); - - // build label expr for while condition check and add to statement list - Tree while_check_label_expr - = build_tree(LABEL_EXPR, bool_expr.get_locus(), void_type_node, while_check_label_decl); - stmt_list.append(while_check_label_expr); - - // build label decl for loop body and end of loop - Tree while_body_label_decl = build_label_decl("while_body", while_body.get_locus()); - Tree end_of_while_label_decl = build_label_decl("end_of_while", UNKNOWN_LOCATION); - - // add cond_expr tree that evaluates condition expression and branches to correct label - Tree cond_expr = build_tree(COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, - build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, while_body_label_decl), - build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, end_of_while_label_decl)); - stmt_list.append(cond_expr); - - // define location of label for body of loop and append to while body - Tree while_body_label_expr - = build_tree(LABEL_EXPR, while_body.get_locus(), void_type_node, while_body_label_decl); - stmt_list.append(while_body_label_expr); - - stmt_list.append(while_body); - - // branch back to condition check (as it is a loop) - Tree goto_check - = build_tree(GOTO_EXPR, UNKNOWN_LOCATION, void_type_node, while_check_label_decl); - stmt_list.append(goto_check); - - // define location of label for end of the while loop - Tree end_of_while_label_expr - = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, end_of_while_label_decl); - stmt_list.append(end_of_while_label_expr); - - return stmt_list.get_tree(); - } - - // Parse a for statement. - Tree Parser::parse_for_statement() { - // for -> for := to do end - if (!skip_token(FOR)) { - skip_after_end(); - return Tree::error(); - } - - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_end(); - return Tree::error(); - } - - if (!skip_token(ASSIG)) { - skip_after_end(); - return Tree::error(); - } - - // parse lower bound expression - Tree lower_bound = parse_integer_expression(); - - if (!skip_token(TO)) { - skip_after_end(); - return Tree::error(); - } - - // parse upper bound expression - Tree upper_bound = parse_integer_expression(); - - if (!skip_token(DO)) { - skip_after_end(); - return Tree::error(); - } - - // enter loop body scope and parse internal statements - enter_scope(); - parse_statement_seq(&Parser::done_end); - - TreeSymbolMapping for_body_tree_scope = leave_scope(); - Tree for_body_stmt = for_body_tree_scope.bind_expr; - - skip_token(END); - - // Induction variable ("loop counter" variable) handling - SymbolPtr ind_var = query_integer_variable(identifier->get_str(), identifier->get_locus()); - - // build for statement - return build_for_statement(ind_var, lower_bound, upper_bound, for_body_stmt); - } - - // Builds a for statement tree (piggybacks on while statement tree building). - Tree Parser::build_for_statement( - SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list) { - if (ind_var == NULL) - return Tree::error(); - Tree ind_var_decl = ind_var->get_tree_decl(); - - // lower - if (lower_bound.is_error()) - return Tree::error(); - - // upper - if (upper_bound.is_error()) - return Tree::error(); - - // ind_var = lower - TreeStmtList stmt_list; - - // initialise induction variable with value of lower bound and append to stmt_list - Tree init_ind_var - = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, lower_bound); - stmt_list.append(init_ind_var); - - // define condition ind_var <= upper for use in while loop - Tree while_condition = build_tree( - LE_EXPR, upper_bound.get_locus(), boolean_type_node, ind_var_decl, upper_bound); - - // simulate incrementing ind_var - Tree incr_ind_var = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, - build_tree(PLUS_EXPR, UNKNOWN_LOCATION, integer_type_node, ind_var_decl, - build_int_cst_type(integer_type_node, 1))); - - // Wrap as stmt list - TreeStmtList for_stmt_list = for_body_stmt_list; - for_stmt_list.append(incr_ind_var); - - // construct associated while statement and append to stmt_list - Tree while_stmt = build_while_statement(while_condition, for_stmt_list.get_tree()); - stmt_list.append(while_stmt); - - // return entire stmt_list - return stmt_list.get_tree(); - } - - // Gets type (as in typedef) of name in current scope. - SymbolPtr Parser::query_type(const std::string& name, location_t loc) { - SymbolPtr sym = scope.lookup(name); - if (sym == NULL) { - error_at(loc, "type '%s' not declared in the current scope", name.c_str()); - } else if (sym->get_kind() != TYPENAME) { - error_at(loc, "name '%s' is not a type", name.c_str()); - sym = SymbolPtr(); - } - - return sym; - } - - // Get variable of name in current scope. - SymbolPtr Parser::query_variable(const std::string& name, location_t loc) { - SymbolPtr sym = scope.lookup(name); - if (sym == NULL) { - error_at(loc, "variable '%s' not declared in the current scope", name.c_str()); - } else if (sym->get_kind() != VARIABLE) { - error_at(loc, "name '%s' is not a variable", name.c_str()); - sym = SymbolPtr(); - } - return sym; - } - - // Gets variable of name in current scope and ensures it has integer type. - SymbolPtr Parser::query_integer_variable(const std::string& name, location_t loc) { - SymbolPtr sym = query_variable(name, loc); - if (sym != NULL) { - Tree var_decl = sym->get_tree_decl(); - gcc_assert(!var_decl.is_null()); - - if (var_decl.get_type() != integer_type_node) { - error_at(loc, "variable '%s' does not have integer type", name.c_str()); - sym = SymbolPtr(); - } - } - - return sym; - } - - // Returns true if the next token is END, ELSE, or EOF; - bool Parser::done_end_or_else() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == END || t->get_id() == ELSE || t->get_id() == END_OF_FILE); - } - - // Returns true if the next token is END or EOF. - bool Parser::done_end() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == END || t->get_id() == END_OF_FILE); - } - - // Parses expression and ensures it is a variable declaration or array reference. - Tree Parser::parse_expression_naming_variable() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_tree_code() != VAR_DECL && expr.get_tree_code() != ARRAY_REF - && expr.get_tree_code() != COMPONENT_REF) { - error_at(expr.get_locus(), "does not designate a variable, array element or field"); - return Tree::error(); - } - - return expr; - } - - // Parses expression and ensures it is an assignment expression? - Tree Parser::parse_lhs_assignment_expression() { - return parse_expression_naming_variable(); - } - - // Parses type (as in typedef) declaration statement. - Tree Parser::parse_type_declaration() { - // type_declaration -> "type" identifier ":" type ";" - if (!skip_token(TYPE)) { - skip_after_semicolon(); - return Tree::error(); - } - - // get identifier - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip colon - if (!skip_token(COLON)) { - skip_after_semicolon(); - return Tree::error(); - } - - // get type of expression - Tree type_tree = parse_type(); - - if (type_tree.is_error()) { - skip_after_semicolon(); - return Tree::error(); - } - - skip_token(SEMICOLON); - - // ensure not already delcared in scope - if (scope.get_current_mapping().get(identifier->get_str())) { - error_at(identifier->get_locus(), "name '%s' already declared in this scope", - identifier->get_str().c_str()); - } - - // create new symbol for typedef and put in mapping for current scope - SymbolPtr sym(new Symbol(TYPENAME, identifier->get_str())); - scope.get_current_mapping().insert(sym); - - // build typedef tree - Tree decl = build_decl(identifier->get_locus(), TYPE_DECL, - get_identifier(sym->get_name().c_str()), type_tree.get_tree()); - DECL_CONTEXT(decl.get_tree()) = main_fndecl; - - // add type declaration to variable declaration stack - gcc_assert(!stack_var_decl_chain.empty()); - stack_var_decl_chain.back().append(decl); - - // set symbol's declaration tree to declaration tree - sym->set_tree_decl(decl); - - // build declaration statement for tree - Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); - - return stmt; - } - - // Parses a record type field declaration. - Tree Parser::parse_field_declaration(std::vector& field_names) { - // identifier ':' type ';' - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - skip_token(COLON); - - Tree type = parse_type(); - - skip_token(SEMICOLON); - - if (type.is_error()) - return Tree::error(); - - // pass vector of fields to avoid repeated field names - error if they exist - if (std::find(field_names.begin(), field_names.end(), identifier->get_str()) - != field_names.end()) { - error_at(identifier->get_locus(), "repeated field name"); - return Tree::error(); - } - - field_names.push_back(identifier->get_str()); - - // create GENERIC FIELD_DECL tree with name of tree and type - Tree field_decl = build_decl(identifier->get_locus(), FIELD_DECL, - get_identifier(identifier->get_str().c_str()), type.get_tree()); - // required for read statement to work on fields - TREE_ADDRESSABLE(field_decl.get_tree()) = 1; - - return field_decl; - } - - // Parses a record. - Tree Parser::parse_record() { - // "record" field-decl* "end" - const_TokenPtr record_tok = expect_token(RECORD); - if (record_tok == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // create empty record type tree - Tree record_type = make_node(RECORD_TYPE); - Tree field_list, field_last; - std::vector field_names; - - // parse field declarations inside record until the end token is found - const_TokenPtr next = lexer.peek_token(); - while (next->get_id() != END) { - Tree field_decl = parse_field_declaration(field_names); - - if (!field_decl.is_error()) { - // set field declaration's decl_context to this record type - DECL_CONTEXT(field_decl.get_tree()) = record_type.get_tree(); - if (field_list.is_null()) - field_list = field_decl; - if (!field_last.is_null()) - // chain fields in record type by using tree_chain - TREE_CHAIN(field_last.get_tree()) = field_decl.get_tree(); - field_last = field_decl; - } - - next = lexer.peek_token(); - } - - skip_token(END); - - // first field sets TYPE_FIELDS attribute of the RECORD_TYPE tree - TYPE_FIELDS(record_type.get_tree()) = field_list.get_tree(); - // request GCC to layout type in memory - layout_type(record_type.get_tree()); - - return record_type; - } -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-parse.h b/gcc/rust/test3-tiny/parse/rust-parse.h deleted file mode 100644 index 60768cf..0000000 --- a/gcc/rust/test3-tiny/parse/rust-parse.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef RUST_PARSE_H -#define RUST_PARSE_H - -#include "rust-lex.h" -//#include "rust-tree.h" -#include "rust-scope.h" - -namespace Rust { - // Parser implementation for gccrs. - class Parser { - private: - void skip_after_semicolon(); - void skip_after_end(); - - bool skip_token(TokenId t); - const_TokenPtr expect_token(TokenId t); - void unexpected_token(const_TokenPtr t); - - // expression parsing - int left_binding_power(const_TokenPtr tok); - Tree null_denotation(const_TokenPtr tok); - Tree left_denotation(const_TokenPtr tok, Tree left); - - Tree parse_expression(int right_binding_power); - - Tree coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right); - bool check_logical_operands(const_TokenPtr tok, Tree left, Tree right); - - Tree get_printf_addr(); - Tree get_puts_addr(); - - Tree get_scanf_addr(); - - Tree build_label_decl(const char* name, location_t loc); - Tree build_if_statement(Tree bool_expr, Tree then_part, Tree else_part); - Tree build_while_statement(Tree bool_expr, Tree while_body); - Tree build_for_statement( - SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list); - - const char* print_type(Tree type); - - TreeStmtList& get_current_stmt_list(); - - void enter_scope(); - - struct TreeSymbolMapping { - Tree bind_expr; - Tree block; - }; - - TreeSymbolMapping leave_scope(); - - SymbolPtr query_type(const std::string& name, location_t loc); - SymbolPtr query_variable(const std::string& name, location_t loc); - SymbolPtr query_integer_variable(const std::string& name, location_t loc); - - void parse_statement_seq(bool (Parser::*done)()); - - bool done_end(); - bool done_end_or_else(); - bool done_end_of_file(); - - typedef Tree (Parser::*BinaryHandler)(const_TokenPtr, Tree); - BinaryHandler get_binary_handler(TokenId id); - - public: - // Construct parser with specified lexer reference. - Parser(Lexer& parLexer) : lexer(parLexer), puts_fn(), printf_fn(), scanf_fn() {} - - // Main entry point for parser. - void parse_program(); - - Tree parse_statement(); - - Tree parse_variable_declaration(); - Tree parse_type_declaration(); - - Tree parse_type(); - Tree parse_record(); - Tree parse_field_declaration(std::vector& field_names); - - Tree parse_assignment_statement(); - Tree parse_if_statement(); - Tree parse_while_statement(); - Tree parse_for_statement(); - Tree parse_read_statement(); - Tree parse_write_statement(); - - Tree parse_expression(); - Tree parse_expression_naming_variable(); - Tree parse_lhs_assignment_expression(); - Tree parse_boolean_expression(); - Tree parse_integer_expression(); - - private: - // The lexer associated with the parser. - Lexer& lexer; - // The current scope. - Scope scope; - - // The simulated "main" function inside which the entire program lies. - tree main_fndecl; - - // Address to function declaration of printf. - Tree printf_fn; - // Address to function declaration of puts. - Tree puts_fn; - // Address to function declaration of scanf. - Tree scanf_fn; - - // The statement stack. - std::vector stack_stmt_list; - // The VAR_DECL stack. - std::vector stack_var_decl_chain; - - // The block stack. - std::vector stack_block_chain; - -// x-macro list for binary operators - only defined here to be inside Parser class -#define BINARY_HANDLER_LIST \ - BINARY_HANDLER(plus, PLUS) \ - BINARY_HANDLER(minus, MINUS) \ - BINARY_HANDLER(mult, ASTERISK) \ - BINARY_HANDLER(div, SLASH) \ - BINARY_HANDLER(mod, PERCENT) \ - \ - BINARY_HANDLER(equal, EQUAL) \ - BINARY_HANDLER(different, DIFFERENT) \ - BINARY_HANDLER(smaller_than, SMALLER) \ - BINARY_HANDLER(smaller_equal, SMALLER_OR_EQUAL) \ - BINARY_HANDLER(greater_than, GREATER) \ - BINARY_HANDLER(greater_equal, GREATER_OR_EQUAL) \ - \ - BINARY_HANDLER(logical_and, AND) \ - BINARY_HANDLER(logical_or, OR) \ - \ - BINARY_HANDLER(array_ref, LEFT_SQUARE) \ - \ - BINARY_HANDLER(field_ref, DOT) - -// create declarations for binary op handling -#define BINARY_HANDLER(name, _) \ - Tree binary_##name(const_TokenPtr tok, Tree left); - BINARY_HANDLER_LIST -#undef BINARY_HANDLER - }; -} - -#endif // RUST_PARSE_H \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-scope.cc b/gcc/rust/test3-tiny/parse/rust-scope.cc deleted file mode 100644 index d38a078..0000000 --- a/gcc/rust/test3-tiny/parse/rust-scope.cc +++ /dev/null @@ -1,43 +0,0 @@ -#include "rust-scope.h" - -#include // for std::make_pair - -namespace Rust { - Scope::Scope() {} - - void SymbolMapping::insert(SymbolPtr s) { - gcc_assert(s != NULL); - std::pair p = map.insert(std::make_pair(s->get_name(), s)); - - gcc_assert(p.second); - } - - SymbolPtr SymbolMapping::get(const std::string& str) const { - Map::const_iterator it = map.find(str); - if (it != map.end()) { - return it->second; - } - - return SymbolPtr(); - } - - SymbolPtr Scope::lookup(const std::string& str) { - // Traverse stack from top (end of MapStack) to bottom, so use reverse_iterator. - for (MapStack::reverse_iterator map = map_stack.rbegin(); map != map_stack.rend(); map++) { - if (SymbolPtr sym = map->get(str)) { - return sym; - } - } - - return SymbolPtr(); - } - - void Scope::push_scope() { - map_stack.push_back(SymbolMapping()); - } - - void Scope::pop_scope() { - gcc_assert(!map_stack.empty()); - map_stack.pop_back(); - } -} \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-scope.h b/gcc/rust/test3-tiny/parse/rust-scope.h deleted file mode 100644 index 1d1f6e2..0000000 --- a/gcc/rust/test3-tiny/parse/rust-scope.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef RUST_SCOPE_H -#define RUST_SCOPE_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -// order: config, system, coretypes, tree -// may not all be required - -#include -#include -#include // as shared_ptr is not available in std memory in c++03 -#include - -#include "rust-tree.h" - -// maybe split out scope into Symbol, SymbolMapping, and Scope headers - -namespace Rust { - // Kinds of symbols. - enum SymbolKind { INVALID, VARIABLE, TYPENAME }; - - // A symbol used for identifiers, etc. - struct Symbol { - public: - // Constructs a new symbol of name with no declaration tree set. - Symbol(SymbolKind kind, const std::string& name_) : - kind(kind), name(name_), decl(error_mark_node) { - gcc_assert(name.size() > 0); - } - - // Gets symbol's kind. - SymbolKind get_kind() const { - return kind; - } - - // Gets symbol's name. - std::string get_name() const { - return name; - } - - // Sets symbol's declaration tree. - void set_tree_decl(Tree decl_) { - // Ensure declaration tree is a variable or type declaration. - gcc_assert((decl_.get_tree_code() == VAR_DECL) || (decl_.get_tree_code() == TYPE_DECL)); - decl = decl_; - } - - // Gets tree with the location of variable declaration. - Tree get_tree_decl() const { - return decl; - } - - private: - // Symbol's kind. - SymbolKind kind; - // Symbol's name. - std::string name; - // Symbol's declaration tree. - Tree decl; - - // Note: in other languages, other info about symbols would also be kept, e.g. "kind" - // Also would be able to store more than just variable declaration trees. - }; - - // Symbol shared pointer. - typedef std::tr1::shared_ptr SymbolPtr; - // Const symbol shared pointer (i.e. to const Symbol). - typedef std::tr1::shared_ptr const_SymbolPtr; - - // Map of strings (identifiers) to SymbolPtrs - struct SymbolMapping { - public: - // Inserts a new Symbol into the map using its name as the key. Also checks name is unique. - void insert(SymbolPtr s); - // Returns the mapped Symbol for the given string. May return a null Symbol. - SymbolPtr get(const std::string& str) const; - - private: - typedef std::map Map; - // SymbolMapping's map. - Map map; - }; - - // Scope class that holds mapping in it. - class Scope { - public: - // Gets current mapping (created in last push that hasn't been popped yet). - SymbolMapping& get_current_mapping() { - gcc_assert(!map_stack.empty()); - return map_stack.back(); - } - - // Create new mapping. - void push_scope(); - // Get rid of mapping? - void pop_scope(); - - Scope(); - - // Get the last mapping for a given string (or null if no such mapping exists). - SymbolPtr lookup(const std::string& str); - - private: - typedef std::vector MapStack; - // Scope's MapStack. - MapStack map_stack; - }; -} - -#endif // RUST_SCOPE_H \ No newline at end of file diff --git a/gcc/rust/test3-tiny/parse/rust-tree.h b/gcc/rust/test3-tiny/parse/rust-tree.h deleted file mode 100644 index 6318a50..0000000 --- a/gcc/rust/test3-tiny/parse/rust-tree.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef RUST_TREE_H -#define RUST_TREE_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -#include "tree-iterator.h" -#include "input.h" -// order: config, system, coretypes, tree, tree-iterator, input -// may not need all of them - -namespace Rust { - // Wrapper around tree to keep location and tree in one data structure. - struct Tree { - public: - Tree() : t(NULL_TREE), loc(UNKNOWN_LOCATION) {} - Tree(tree t_) : t(t_), loc(EXPR_LOCATION(t)) {} - Tree(tree t_, location_t loc_) : t(t_), loc(loc_) {} - Tree(Tree t_, location_t loc_) : t(t_.get_tree()), loc(loc_) {} - - // Get tree's location_t. - location_t get_locus() const { - return loc; - } - - // Sets tree's location_t. - void set_locus(location_t loc_) { - loc = loc_; - } - - // Gets tree's tree in GCC form. - tree get_tree() const { - return t; - } - - // Gets tree's GCC tree code. - tree_code get_tree_code() const { - return TREE_CODE(t); - } - - // Sets tree's GCC tree. - void set_tree(tree t_) { - t = t_; - } - - // Returns if tree is an error node? - bool is_error() const { - return error_operand_p(t); - } - - // Returns whether tree node is null. - bool is_null() { - return t == NULL_TREE; - } - - // Creates an error Tree. - static Tree error() { - return Tree(error_mark_node); - } - - // Gets tree's GCC type. - Tree get_type() const { - return TREE_TYPE(t); - } - - private: - // The tree object's gcc tree representation. - tree t; - // The tree's location. - location_t loc; - }; - - // Comparison by identity as tree is a pointer. - inline bool operator==(Tree t1, Tree t2) { - return t1.get_tree() == t2.get_tree(); - } - inline bool operator!=(Tree t1, Tree t2) { - return !(t1 == t2); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1) { - return build1_loc(loc, tc, type.get_tree(), t1.get_tree()); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2) { - return build2_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree()); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3) { - return build3_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree()); - } - - inline Tree build_tree( - tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4) { - return build4_loc( - loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), t4.get_tree()); - } - - inline Tree build_tree( - tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4, Tree t5) { - return build5_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), - t4.get_tree(), t5.get_tree()); - } - - // Wrapper around STATEMENT_LIST, used to represent lists of statements. Adapter for TREE_LIST. - struct TreeStmtList { - public: - // Create new statement list from nothing. - TreeStmtList() : list(alloc_stmt_list()) {} - // Create new statement list from given tree. - TreeStmtList(Tree param_tree) : list(param_tree.get_tree()) {} - - // Append to statement list. - void append(Tree param_tree) { - append_to_statement_list(param_tree.get_tree(), &list); - } - - // Get the statement list. - tree get_tree() const { - return list; - } - - private: - // The statement list. - tree list; - }; - - // TODO: Check if already exists in GCC - template - struct TreeChainBase { - Tree first; - Tree last; - - TreeChainBase() : first(), last() {} - - void append(Tree t) { - gcc_assert(!t.is_null()); - if (first.is_null()) { - first = last = t; - } else { - Append()(last, t); - last = t; - } - } - }; - - struct tree_chain_append { - void operator()(Tree t, Tree a) { - TREE_CHAIN(t.get_tree()) = a.get_tree(); - } - }; - - // Single-linked list implemented with trees. Used for VAR_DECLs. - struct TreeChain : TreeChainBase {}; - - struct block_chain_append { - void operator()(Tree t, Tree a) { - BLOCK_CHAIN(t.get_tree()) = a.get_tree(); - } - }; - - // Single-linked list implemented with trees. Used for chains of blocks. - struct BlockChain : TreeChainBase {}; -} - -#endif // RUST_TREE_H \ No newline at end of file diff --git a/gcc/rust/test3-tiny/rsspec.cc b/gcc/rust/test3-tiny/rsspec.cc deleted file mode 100644 index 69a14ad..0000000 --- a/gcc/rust/test3-tiny/rsspec.cc +++ /dev/null @@ -1,354 +0,0 @@ -/* Specific flags and argument handling of the Rust front-end. - -This file is part of GCC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -/* #include "config.h" -#include "coretypes.h" -#include "gcc.h" -#include "opts.h" -#include "system.h" - -#include "intl.h" -#include "tm.h" - -#ifndef MATH_LIBRARY -#define MATH_LIBRARY "m" -#endif - -#ifndef RUST_LIBRARY -#define RUST_LIBRARY "grust" -#endif*/ - -/* The original argument list and related info is copied here. */ -/* static unsigned int grs_xargc; -static const struct cl_decoded_option* grs_x_decoded_options; -static void append_arg(const struct cl_decoded_option*);*/ - -/* The new argument list will be built here. */ -/* static unsigned int grs_newargc; -static struct cl_decoded_option* grs_new_decoded_options;*/ - -/* Return whether strings S1 and S2 are both NULL or both the same string. */ -/* static bool strings_same(const char* s1, const char* s2) { - return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0); -}*/ - -/* Return whether decoded option structures OPT1 and OPT2 are the same. */ -/* static bool options_same(const struct cl_decoded_option* opt1, const struct cl_decoded_option* opt2) { - return (opt1->opt_index == opt2->opt_index && strings_same(opt1->arg, opt2->arg) - && strings_same(opt1->orig_option_with_args_text, opt2->orig_option_with_args_text) - && strings_same(opt1->canonical_option[0], opt2->canonical_option[0]) - && strings_same(opt1->canonical_option[1], opt2->canonical_option[1]) - && strings_same(opt1->canonical_option[2], opt2->canonical_option[2]) - && strings_same(opt1->canonical_option[3], opt2->canonical_option[3]) - && (opt1->canonical_option_num_elements == opt2->canonical_option_num_elements) - && opt1->value == opt2->value && opt1->errors == opt2->errors); -}*/ - -/* Append another argument to the list being built. As long as it is identical to the corresponding - * arg in the original list, just increment the new arg count. Otherwise allocate a new list, etc. */ -/* static void append_arg(const struct cl_decoded_option* arg) { - static unsigned int newargsize; - -#if 0 - fprintf (stderr, "`%s'\n", arg); -#endif - - if (grs_new_decoded_options == grs_x_decoded_options && grs_newargc < grs_xargc - && options_same(arg, &grs_x_decoded_options[grs_newargc])) { - ++grs_newargc; - return; // Nothing new here. - } - - if (grs_new_decoded_options == grs_x_decoded_options) { // Make new arglist. - unsigned int i; - - newargsize = (grs_xargc << 2) + 20; // This should handle all. - grs_new_decoded_options = XNEWVEC(struct cl_decoded_option, newargsize); - - // Copy what has been done so far. - for (i = 0; i < grs_newargc; ++i) - grs_new_decoded_options[i] = grs_x_decoded_options[i]; - } - - if (grs_newargc == newargsize) - fatal_error("overflowed output arg list for %qs", arg->orig_option_with_args_text); - - grs_new_decoded_options[grs_newargc++] = *arg; -}*/ - -/* Append an option described by OPT_INDEX, ARG and VALUE to the list being built. */ -/* static void append_option(size_t opt_index, const char* arg, int value) { - struct cl_decoded_option decoded; - - generate_option(opt_index, arg, value, CL_DRIVER, &decoded); - append_arg(&decoded); -}*/ - -/* Append a librust argument to the list being built. If FORCE_STATIC, ensure the library is linked - * statically. */ -/* static void add_arg_libgrust(bool force_static ATTRIBUTE_UNUSED) { -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option(OPT_Wl_, "-Bstatic", 1); -#endif - append_option(OPT_l, RUST_LIBRARY, 1); -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option(OPT_Wl_, "-Bdynamic", 1); -#endif -}*/ - -/* Modeled closely of gcc/fortran/gfortranspec.c */ -// Presumably this is the "compiler driver", which runs the compiler -// Handle calling the compiler (i.e. options, libraries to use) -// Used to change flags before passing them to the driver -void lang_specific_driver(struct cl_decoded_option** /* in_decoded_options*/, - unsigned int* /* in_decoded_options_count*/, int* /* in_added_libraries*/) { - /* unsigned int i = 0; - unsigned int argc = *in_decoded_options_count; // argument list count - struct cl_decoded_option* decoded_options = *in_decoded_options; // argument list - - int verbose = 0;*/ - - /* This will be NULL if we encounter a situation where we should not - link in libf2c. */ - // const char* library = RUST_LIBRARY; - - /* 0 => -xnone in effect. - 1 => -xfoo in effect. */ - // int saw_speclang = 0; - - /* 0 => initial/reset state - 1 => last arg was -l - 2 => last two args were -l -lm. */ - // int saw_library = 0; - - // By default, we throw on the math library if we have one. - // int need_math = (MATH_LIBRARY[0] != '\0'); - - // Whether we should link a static libgrsthon. - // int static_lib = 0; - - // Whether we need to link statically. - // int static_linking = 0; - - // The number of input and output files in the incoming arg list. - // int n_infiles = 0; - // int n_outfiles = 0; - -/* #if 0 - fprintf (stderr, "Incoming:"); - for( i=0; i. - append_option(OPT_l, MATH_LIBRARY, 1); - -saw_library = 0; - -if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) { - append_arg(&decoded_options[i]); // "-" == Standard input. - continue; -} - -if (decoded_options[i].opt_index == OPT_x) { - // Track input language. - const char* lang = decoded_options[i].arg; - saw_speclang = (strcmp(lang, "none") != 0); -} -append_arg(&decoded_options[i]); -continue; -} - -// A filename/library, not an option. - -if (saw_speclang) -saw_library = 0; // -xfoo currently active. -else { // -lfoo or filename. -if (decoded_options[i].opt_index == OPT_l - && strcmp(decoded_options[i].arg, MATH_LIBRARY) == 0) { - if (saw_library == 1) - saw_library = 2; // -l -lm. - else - add_arg_libgrust(static_lib && !static_linking); -} else if (decoded_options[i].opt_index == OPT_l - && strcmp(decoded_options[i].arg, RUST_LIBRARY) == 0) { - saw_library = 1; // -l. - add_arg_libgrust(static_lib && !static_linking); - continue; -} else { // Other library, or filename. - if (saw_library == 1 && need_math) - append_option(OPT_l, MATH_LIBRARY, 1); - saw_library = 0; -} -} -append_arg(&decoded_options[i]); -}*/ - - // Append `-lrust -lm' as necessary. - - /* if (library) { // Doing a link and no -nostdlib. - if (saw_speclang) - append_option(OPT_x, "none", 1); - - switch (saw_library) { - case 0: - add_arg_libgrust(static_lib && !static_linking); - // Fall through. - case 1: - if (need_math) - append_option(OPT_l, MATH_LIBRARY, 1); - default: - break; - } - }*/ - - /* #ifdef ENABLE_SHARED_LIBGCC - if (library) { - unsigned int i; - - for (i = 1; i < grs_newargc; i++) - if (grs_new_decoded_options[i].opt_index == OPT_static_libgcc - || grs_new_decoded_options[i].opt_index == OPT_static) - break; - - if (i == grs_newargc) - append_option(OPT_shared_libgcc, NULL, 1); - } - - #endif*/ - - /* if (verbose && grs_new_decoded_options != grs_x_decoded_options) { - fprintf(stderr, _("Driving:")); - for (i = 0; i < grs_newargc; i++) - fprintf(stderr, " %s", grs_new_decoded_options[i].orig_option_with_args_text); - fprintf(stderr, "\n"); - } - - *in_decoded_options_count = grs_newargc; - *in_decoded_options = grs_new_decoded_options;*/ -} - -/* Called before linking - can be used to do some extra steps and abort if they fail. Returns 0 on - * success and -1 on failure. */ -int lang_specific_pre_link(void) { - // Not used for rust - return 0; -} - -/* Number of extra output files that lang_specific_pre_link may generate. Used to add extra outfiles - * to linking step. */ -int lang_specific_extra_outfiles = 0; // not used for rust diff --git a/gcc/rust/test3-tiny/rust-buffered-queue.h b/gcc/rust/test3-tiny/rust-buffered-queue.h deleted file mode 100644 index bfd36be..0000000 --- a/gcc/rust/test3-tiny/rust-buffered-queue.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef RUST_BUFFERED_QUEUE_H -#define RUST_BUFFERED_QUEUE_H - -#include - -#include "config.h" -#include "system.h" -// order: config, system - -namespace Rust { - // Buffered queue implementation. Items are of type T, queue source is of type Source. - template - class buffered_queue { - public: - // Construct empty queue from Source& src. - buffered_queue(Source& src) : source(src), start(0), end(0), buffer() {} - - // Returns token at position start + n (i.e. n tokens ahead). - T peek(int n) { - // n should not be behind - gcc_assert(n >= 0); - - int num_queued_items = end - start; - int num_items_required = n + 1; - - // if required items go past end of queue, add them to queue - if (num_items_required > num_queued_items) { - int num_items_to_read = num_items_required - num_queued_items; - - // if queue length + extra items is larger than buffer size, expand buffer - if (end + num_items_to_read > (int)buffer.size()) { - // Resize the buffer by 1.5x - int new_size = (buffer.size() + num_items_to_read); - new_size += (new_size >> 1); - - // create new queue buffer with new size - std::vector new_queue(new_size); - std::copy(buffer.begin() + start, buffer.begin() + end, new_queue.begin()); - start = 0; - end = num_queued_items; - - // swap member buffer and new queue buffer - std::swap(buffer, new_queue); - - // validate that buffer is large enough now - gcc_assert(end + num_queued_items < (int)buffer.size()); - } - - // iterate through buffer and invoke operator () on source on values past original end - for (int i = 0; i < num_items_to_read; i++) { - buffer[end + i] = source(); - } - - // move end based on additional items added - end += num_items_to_read; - } - - gcc_assert(0 <= start); - gcc_assert(start <= end); - gcc_assert(end <= (int)buffer.size()); - - gcc_assert(start + n < end); - - // return value at start + n in buffer - return buffer[start + n]; - } - - // Advances start by n (+ 1)?. - void skip(int n) { - // Call peek to ensure requested n is actually in queue. - peek(n); - - // Clear values from start to n (inclusive). - for (int i = 0; i < (n + 1); i++) { - // Clear value at index - buffer[start + i] = T(); - } - - // Move start forward by n + 1; - start += (n + 1); - - // Ensure start is not impossible somehow - gcc_assert(0 <= start); - gcc_assert(start <= end); - - // Compact buffer if empty - if (start == end) { - start = end = 0; - } - } - - private: - // Source of tokens for queue - Source& source; - - // Begin of range in buffer, inclusive - int start; - // End of range in buffer, exclusive - int end; - - // Queue buffer - std::vector buffer; - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3-tiny/rust-lang.cc b/gcc/rust/test3-tiny/rust-lang.cc deleted file mode 100644 index d8f85ca..0000000 --- a/gcc/rust/test3-tiny/rust-lang.cc +++ /dev/null @@ -1,262 +0,0 @@ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "gimple-expr.h" -#include "diagnostic.h" -#include "opts.h" -#include "fold-const.h" -#include "gimplify.h" -#include "stor-layout.h" -#include "debug.h" -#include "convert.h" -#include "langhooks.h" -#include "langhooks-def.h" -#include "common/common-target.h" -// note: header files must be in this order or else forward declarations don't work properly. Kinda -// dumb system, but have to live with it. clang-format seems to mess it up -/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic, opts, fold-const, - * gimplify, stor-layout, debug, convert, langhooks, langhooks-def, common-target */ - -#include "rust-parse.h" - -// Language-dependent contents of a type. GTY() mark used for garbage collector. -struct GTY(()) lang_type { - char dummy; -}; - -// Language-dependent contents of a decl. -struct GTY(()) lang_decl { - char dummy; -}; - -// Language-dependent contents of an identifier. This must include a tree_identifier. -struct GTY(()) lang_identifier { - struct tree_identifier common; -}; - -// The resulting tree type. -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next( - "CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " - "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node { - union tree_node GTY((tag("0"), desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; -}; - -// We don't use language_function. -struct GTY(()) language_function { - int dummy; -}; - -/* Language hooks. */ - -/* Initial lang hook called (possibly), used for initialisation. - * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, and - * build_common_builtin_nodes, as well as set global variable void_list_node. */ -static bool grs_langhook_init(void) { - /* Something to do with this: - This allows the code in d-builtins.cc to not have to worry about - converting (C signed char *) to (D char *) for string arguments of - built-in functions. The parameter (signed_char = false) specifies - whether char is signed. */ - build_common_tree_nodes(false); - - // Creates a new TREE_LIST node with purpose NULL_TREE and value void_type_node - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - // Builds built-ins for middle-end after all front-end built-ins are already instantiated - build_common_builtin_nodes(); - - // mpfr_set_default_prec(128); - // using_eh_for_cleanups(); - - // rdot_init(); - return true; -} - -// Parses a single file with filename filename. -static void grs_parse_file(const char* filename) { - FILE* file = fopen(filename, "r"); - - if (file == NULL) { - fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); - } - - // parse file here - // create lexer - Rust::Lexer lex(filename, file); - Rust::Parser parser(lex); - - parser.parse_program(); - - /* Rust::const_TokenPtr tok = lex.peek_token(); - // do shit until EOF - while (true) { - bool has_text = tok->get_id() == Rust::IDENTIFIER || tok->get_id() == Rust::INT_LITERAL - || tok->get_id() == Rust::FLOAT_LITERAL - || tok->get_id() == Rust::STRING_LITERAL; - - location_t loc = tok->get_locus(); - - fprintf(stderr, "\n", tok->token_id_to_str(), - has_text ? (std::string(", text=") + tok->get_str()).c_str() : "", LOCATION_FILE(loc), - LOCATION_LINE(loc), LOCATION_COLUMN(loc)); - - if (tok->get_id() == Rust::END_OF_FILE) - break; - - lex.skip_token(); - tok = lex.peek_token(); - }*/ - - fclose(file); -} - -/* Actual main entry point for front-end. Called by langhook to parse files. - * May move to a different compilation unit if frontend gets too big. */ -static void grs_parse_files(int num_files, const char** files) { - for (int i = 0; i < num_files; i++) { - grs_parse_file(files[i]); - } -} - -/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and - * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. - * This function must create a complete parse tree in a global var, and then return. - * - * Some consider this the "start of compilation". */ -static void grs_langhook_parse_file(void) { - fprintf(stderr, "Nothing happens yet \n"); - - grs_parse_files(num_in_fnames, in_fnames); -} - -static tree grs_langhook_type_for_mode(machine_mode mode, int unsignedp) { - if (mode == TYPE_MODE(float_type_node)) - return float_type_node; - - if (mode == TYPE_MODE(double_type_node)) - return double_type_node; - - // don't know what this means but assume it has something to do with weird precisions - if (mode == TYPE_MODE(intQI_type_node)) - return unsignedp ? unsigned_intQI_type_node : intQI_type_node; - if (mode == TYPE_MODE(intHI_type_node)) - return unsignedp ? unsigned_intHI_type_node : intHI_type_node; - if (mode == TYPE_MODE(intSI_type_node)) - return unsignedp ? unsigned_intSI_type_node : intSI_type_node; - if (mode == TYPE_MODE(intDI_type_node)) - return unsignedp ? unsigned_intDI_type_node : intDI_type_node; - if (mode == TYPE_MODE(intTI_type_node)) - return unsignedp ? unsigned_intTI_type_node : intTI_type_node; - - if (mode == TYPE_MODE(integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - - if (mode == TYPE_MODE(long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - - if (mode == TYPE_MODE(long_long_integer_type_node)) - return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; - - if (COMPLEX_MODE_P(mode)) { - if (mode == TYPE_MODE(complex_float_type_node)) - return complex_float_type_node; - if (mode == TYPE_MODE(complex_double_type_node)) - return complex_double_type_node; - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) - return complex_integer_type_node; - } - /* gcc_unreachable */ - return NULL; -} - -static tree grs_langhook_type_for_size( - unsigned int bits ATTRIBUTE_UNUSED, int unsignedp ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL_TREE; -} - -// Record a builtin function. We just ignore builtin functions. -static tree grs_langhook_builtin_function(tree decl ATTRIBUTE_UNUSED) { - return decl; -} - -static bool grs_langhook_global_bindings_p(void) { - // return current_function_decl == NULL_TREE; - //gcc_unreachable(); - //return true; - return false; -} - -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL; -} - -static tree grs_langhook_getdecls(void) { - // gcc_unreachable(); - return NULL; -} - -/* Create an expression whose value is that of EXPR, - converted to type TYPE. The TREE_TYPE of the value - is always TYPE. This function implements all reasonable - conversions; callers should filter out those that are - not permitted by the language being compiled. */ -/* tree convert(tree type, tree expr) { // not implemented yet - seems to be needed for compilation - return NULL; -}*/ -// implemented in rust-misc-convert.cc - -/* The language hooks data structure. This is the main interface between the GCC front-end - * and the GCC middle-end/back-end. A list of language hooks could be found in - * /langhooks.h - */ -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -//#undef LANG_HOOKS_OPTION_LANG_MASK -//#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -//#undef LANG_HOOKS_HANDLE_OPTION -//#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -//#undef LANG_HOOKS_WRITE_GLOBALS -//#undef LANG_HOOKS_GIMPLIFY_EXPR -//#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT grs_langhook_init -//#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask -//#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct -//#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option -//#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -/* Main lang-hook, apparently. Finds input file names in global vars in_fnames and num_in_fnames - * From this, frontend can take over and do actual parsing and initial compilation. - * This hook must create a complete parse tree in a global var, and then return. */ -#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl -#define LANG_HOOKS_GETDECLS grs_langhook_getdecls -//#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals -//#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr -//#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality - -// Expands all LANG_HOOKS_x of GCC -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -// These are for GCC's garbage collector to work properly or something -#include "gt-rust-rust-lang.h" -#include "gtype-rust.h" \ No newline at end of file diff --git a/gcc/rust/test3/Make-lang.in b/gcc/rust/test3/Make-lang.in deleted file mode 100644 index 36d908c..0000000 --- a/gcc/rust/test3/Make-lang.in +++ /dev/null @@ -1,240 +0,0 @@ -# Make-lang.in -- Top level -*- makefile -*- fragment for GCC Rust frontend. - -# Copyright (C) 2009-2013 Free Software Foundation, Inc. - -# This file is part of GCC. - -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# This file provides the language dependent support in the main Makefile. - -#RUST_EXES = rust - -# Use strict warnings for this front end. -rust-warn = $(STRICT_WARN) - -# Installation name. Useful for cross compilers and used during install. -GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)') -GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)') - -# Define the names for selecting rust in LANGUAGES. -rust: gccrs$(exeext) grs1$(exeext) - -# Tell GNU make to ignore files by these names if they exist. -.PHONY: rust - -# removed GRS_CFLAGS from here - -# removed object files from here -#rs-lexer.o: $(srcdir)/rust/rs-lexer.l rs-parser.o -# $(FLEX) --outfile=lex.rs.c $(srcdir)/rust/rs-lexer.l -# $(COMPILER) $(GRS_CFLAGS) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -# $(LDFLAGS) -c -o $@ lex.rs.c -# etc. for parser, etc. - -# For compiler driver creation. -#rsspec.o: $(srcdir)/rust/rsspec.cc $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \ -# $(CONFIG_H) opts.h -# (SHLIB='$(SHLIB)'; \ -# $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \ -# $(INCLUDES) $(srcdir)/rust/rsspec.cc) - -# Create the compiler driver gccrs. -# A compiler driver is the program that interprets command argument and can be called from the command -# line - e.g. gcc or g++, and not cc1, which is the actual compiler - -# Create driver objects -GCCRS_D_OBJS = \ - $(GCC_OBJS) \ - rust/rsspec.o \ - $(END) - -gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) - +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ - $(EXTRA_GCC_LIBS) $(LIBS) - -# List of host object files used by the rust language - files for translation from the parse tree -# to GENERIC -# The compiler proper, not driver -GRS_OBJS = \ - rust/rust-lang.o \ - rust/rust-token.o \ - rust/rust-lex.o \ - rust/rust-parse.o \ - rust/rust-scope.o \ - rust/rust-misc-convert.o \ - rust/rust-ast-full-test.o \ - rust/rust-session-manager.o \ - $(END) -# removed object files from here - -# The compiler itself is called grs1 -grs1$(exeext): $(GRS_OBJS) attribs.o $(BACKEND) $(LIBDEPS) - +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GRS_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) - -# Build hooks. - -# Copies its dependencies into the source directory. This generally should be used for generated files -# such as Bison output files which are not version-controlled, but should be included in any release -# tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’ -# was specified as a configure option. -rust.srcextra: - -rust.all.cross: - -# idk what this does but someone used it -rust.start.encap: gccrs$(exeext) -rust.rest.encap: - -# Build generated man pages for the front end from Texinfo manuals (see Man Page Generation), in the -# build directory. This target is only called if the necessary tools are available, but should ignore -# errors so as not to stop the build if errors occur; man pages are optional and the tools involved -# may be installed in a broken way. -rust.man: - -# Copies its dependencies into the source directory. These targets will be executed during a bootstrap -# if ‘--enable-generated-files-in-srcdir’ was specified as a configure option. -rust.srcman: - -# Clean hooks. - -rust.mostlyclean: -# cd $(srcdir)/rust; rm -f *.o y.tab.h y.tab.c lex.yy.c - -rust.clean: rust.mostlyclean - -# Builds an etags TAGS file in the language subdirectory in the source tree. -# TODO: add more directories if I add more -rust.tags: force - cd $(srcdir)/rust; \ - etags -o TAGS.sub *.y *.l *.cc *.h ast/*.h ast/*.cc lex/*.h lex/*.cc parse/*.h parse/*.cc; \ - etags --include TAGS.sub --include ../TAGS.sub - -# Build documentation hooks. - -# Build info documentation for the front end, in the build directory. This target is only called by -# ‘make bootstrap’ if a suitable version of makeinfo is available, so does not need to check for this, -# and should fail if an error occurs. -rust.info: - -rust.srcinfo: - -# Build DVI documentation for the front end, in the build directory. This should be done using -# $(TEXI2DVI), with appropriate -I arguments pointing to directories of included files. -rust.dvi: - -# Build PDF documentation for the front end, in the build directory. This should be done using -# $(TEXI2PDF), with appropriate -I arguments pointing to directories of included files. -rust.pdf: - -doc/rust.info: -doc/rust.dvi: -doc/rust.pdf: - -# Build HTML documentation for the front end, in the build directory. -rust.html: - -# Install hooks. - -# Install everything that is part of the front end, apart from the compiler executables listed in -# compilers in config-lang.in. -rust.install-common: installdirs -# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) -# -rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext) -# $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) -# if test -f $(DESTDIR)$(bindir)$(GCCRS_TARGET_INSTALL_NAME)$(exeext); then \ -# :; \ -# else \ -# cd $(DESTDIR)$(bindir) && \ -# $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ -# fi - -rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - $(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext); \ - ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext) ); \ - -# Install headers needed for plugins. -rust.install-plugin: - -# Uninstall files installed by installing the compiler. This is currently documented not to be -# supported, so the hook need not do anything. -rust.uninstall: -# -rm -rf $(DESTDIR)/$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext) - -rm -f gccrs$(exeext) grs1$(exeext) - -rm -f $(GRS_OBJS) -# ^those two are a maybe - -# No rust-specific selftests -selftest-rust: - -# Install info documentation for the front end, if it is present in the source directory. This target -# should have dependencies on info files that should be installed. -rust.install-info: - -rust.install-pdf: - -# Install man pages for the front end. This target should ignore errors. -rust.install-man: - -# Stage hooks: -# The toplevel makefile has already created stage?/rust at this point. -# Used for handling bootstrap - -rust.stage1: stage1-start - -mv rust/*$(objext) stage1/rust -rust.stage2: stage2-start - -mv rust/*$(objext) stage2/rust -rust.stage3: stage3-start - -mv rust/*$(objext) stage3/rust -rust.stage4: stage4-start - -mv rust/*$(objext) stage4/rust -rust.stageprofile: stageprofile-start - -mv rust/*$(objext) stageprofile/rust -rust.stagefeedback: stagefeedback-start - -mv rust/*$(objext) stagefeedback/rust - -#config.status: rust/config-lang.in - -#CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ -# -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" - -# cross-folder includes - add new folders later -RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse -I $(srcdir)/rust/ast - -# add files that require cross-folder includes - currently rust-lang.o, rust-lex.o -CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) -CFLAGS-rust/rust-lex.o += $(RUST_INCLUDES) -CFLAGS-rust/rust-parse.o += $(RUST_INCLUDES) -CFLAGS-rust/rust-session-manager.o += $(RUST_INCLUDES) - -# TODO: possibly find a way to ensure C++11 compilation level here? - -# build all rust/lex files in rust folder, add cross-folder includes -rust/%.o: rust/lex/%.cc - $(COMPILE) $(RUST_INCLUDES) $< - $(POSTCOMPILE) - -# build all rust/parse files in rust folder, add cross-folder includes -rust/%.o: rust/parse/%.cc - $(COMPILE) $(RUST_INCLUDES) $< - $(POSTCOMPILE) - -# build rust/ast files in rust folder -rust/%.o: rust/ast/%.cc - $(COMPILE) $(RUST_INCLUDES) $< - $(POSTCOMPILE) \ No newline at end of file diff --git a/gcc/rust/test3/ast/clone-test.h b/gcc/rust/test3/ast/clone-test.h deleted file mode 100644 index 0c71c82..0000000 --- a/gcc/rust/test3/ast/clone-test.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef CLONE_TEST_H -#define CLONE_TEST_H -// Potential fancy deep cloning test for use with unique_ptr - -// disable by default -#if 0 -#include - -namespace clone_code { - template - class abstract_method {}; - - template - class virtual_inherit_from : virtual public T { - using T::T; - }; - - template - class clone_inherit : public Bases... { - public: - virtual ~clone_inherit() = default; - - std::unique_ptr clone() const { - return std::unique_ptr(static_cast(this->clone_impl())); - } - - protected: - private: - virtual clone_inherit* clone_impl() const override { - return new Derived(static_cast(*this)); - } - }; - - template - class clone_inherit, Bases...> : public Bases... { - public: - virtual ~clone_inherit() = default; - - std::unique_ptr clone() const { - return std::unique_ptr(static_cast(this->clone_impl())); - } - - protected: - private: - virtual clone_inherit* clone_impl() const = 0; - }; - - template - class clone_inherit { - public: - virtual ~clone_inherit() = default; - - std::unique_ptr clone() const { - return std::unique_ptr(static_cast(this->clone_impl())); - } - - private: - virtual clone_inherit* clone_impl() const override { - return new Derived(static_cast(*this)); - } - }; - - template - class clone_inherit > { - public: - virtual ~clone_inherit() = default; - - std::unique_ptr clone() const { - return std::unique_ptr(static_cast(this->clone_impl())); - } - - private: - virtual clone_inherit* clone_impl() const = 0; - }; -} - -namespace user_code { - using namespace clone_code; - - class cloneable : public clone_inherit > {}; - - class foo : public clone_inherit, virtual_inherit_from > {}; - - class bar : public clone_inherit, virtual_inherit_from > {}; - - class concrete : public clone_inherit {}; -} -#endif - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast-containers.h b/gcc/rust/test3/ast/rust-ast-containers.h deleted file mode 100644 index 81b0187..0000000 --- a/gcc/rust/test3/ast/rust-ast-containers.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef RUST_AST_CONTAINERS_H -#define RUST_AST_CONTAINERS_H -// crappy redefined AST maybe. may move - -/* This is mainly the "logical", more "abstract" representation of the code, while the "AST" itself is - * more high-level and matches the language better. */ - -// this is now deprecated and replaced with the proper AST -#error "rust-ast-containers.h was included by accident. Don't use." - -namespace Rust { - namespace AST { - struct Module { - public: - }; - - struct Crate { - public: - Module root_module; - }; - - // replace with rust-types.h version - struct AttributeList { - public: - //::std::vector attribs; - }; - - // replace with rust-types.h version - struct Visibility {}; - - /*enum VisibilityType { - Private, - PublicFull, - PublicInPath, - PublicCrate, - PublicSuper, - PublicSelfModule - }; - - // Represents visibility - maybe make into an enum or union or something - struct Visibility { - }; - - */ - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast-full-decls.h b/gcc/rust/test3/ast/rust-ast-full-decls.h deleted file mode 100644 index a76a599..0000000 --- a/gcc/rust/test3/ast/rust-ast-full-decls.h +++ /dev/null @@ -1,265 +0,0 @@ -#ifndef RUST_AST_FULL_DECLS_H -#define RUST_AST_FULL_DECLS_H -// Forward declarations for all AST classes. Useful for not having to include all definitions. - -namespace Rust { - namespace AST { - // rust-ast.h - class AttrInput; - class TokenTree; - class MacroMatch; - class Token; - struct Literal; - class DelimTokenTree; - class PathSegment; - class SimplePathSegment; - class SimplePath; - struct Attribute; - class MetaItemInner; - class AttrInputMetaItemContainer; - class MetaItem; - class Stmt; - class Item; - class Expr; - class ExprWithoutBlock; - class IdentifierExpr; - class Pattern; - class Type; - class TypeNoBounds; - class TypeParamBound; - class Lifetime; - class GenericParam; - class LifetimeParam; - class MacroItem; - class TraitItem; - class InherentImplItem; - class TraitImplItem; - class MacroInvocationSemi; - struct Crate; - class PathExpr; - - // rust-path.h - class PathIdentSegment; - struct GenericArgsBinding; - struct GenericArgs; - class PathExprSegment; - class PathPattern; - class PathInExpression; - class TypePathSegment; - class TypePathSegmentGeneric; - struct TypePathFunction; - class TypePathSegmentFunction; - class TypePath; - struct QualifiedPathType; - class QualifiedPathInExpression; - class QualifiedPathInType; - - // rust-expr.h - class ExprWithBlock; - class LiteralExpr; - class AttrInputLiteral; - class MetaItemLitExpr; - class MetaItemPathLit; - class OperatorExpr; - class BorrowExpr; - class DereferenceExpr; - class ErrorPropagationExpr; - class NegationExpr; - class ArithmeticOrLogicalExpr; - class ComparisonExpr; - class LazyBooleanExpr; - class TypeCastExpr; - class AssignmentExpr; - class CompoundAssignmentExpr; - class GroupedExpr; - class ArrayElems; - class ArrayElemsValues; - class ArrayElemsCopied; - class ArrayExpr; - class ArrayIndexExpr; - class TupleExpr; - class TupleIndexExpr; - class StructExpr; - class StructExprStruct; - struct StructBase; - class StructExprField; - class StructExprFieldIdentifier; - class StructExprFieldWithVal; - class StructExprFieldIdentifierValue; - class StructExprFieldIndexValue; - class StructExprStructFields; - class StructExprStructBase; - class StructExprTuple; - class StructExprUnit; - class EnumVariantExpr; - class EnumExprField; - class EnumExprFieldIdentifier; - class EnumExprFieldWithVal; - class EnumExprFieldIdentifierValue; - class EnumExprFieldIndexValue; - class EnumExprStruct; - class EnumExprTuple; - class EnumExprFieldless; - class CallExpr; - class MethodCallExpr; - class FieldAccessExpr; - struct ClosureParam; - class ClosureExpr; - class ClosureExprInner; - class BlockExpr; - class ClosureExprInnerTyped; - class ContinueExpr; - class BreakExpr; - class RangeExpr; - class RangeFromToExpr; - class RangeFromExpr; - class RangeToExpr; - class RangeFullExpr; - class RangeFromToInclExpr; - class RangeToInclExpr; - class ReturnExpr; - class UnsafeBlockExpr; - class LoopLabel; - class BaseLoopExpr; - class LoopExpr; - class WhileLoopExpr; - class WhileLetLoopExpr; - class ForLoopExpr; - class IfExpr; - class IfExprConseqElse; - class IfExprConseqIf; - class IfLetExpr; - class IfExprConseqIfLet; - class IfLetExprConseqElse; - class IfLetExprConseqIf; - class IfLetExprConseqIfLet; - struct MatchArm; - class MatchCase; - class MatchCaseBlockExpr; - class MatchCaseExpr; - class MatchExpr; - class AwaitExpr; - class AsyncBlockExpr; - - // rust-stmt.h - class EmptyStmt; - class LetStmt; - class ExprStmt; - class ExprStmtWithoutBlock; - class ExprStmtWithBlock; - - // rust-item.h - class TypeParam; - class WhereClauseItem; - class LifetimeWhereClauseItem; - class TypeBoundWhereClauseItem; - struct WhereClause; - struct SelfParam; - struct FunctionQualifiers; - struct FunctionParam; - struct Visibility; - class Method; - class VisItem; - class Module; - class ModuleBodied; - class ModuleNoBody; - class ExternCrate; - class UseTree; - class UseTreeGlob; - class UseTreeList; - class UseTreeRebind; - class UseDeclaration; - class Function; - class TypeAlias; - class Struct; - struct StructField; - class StructStruct; - struct TupleField; - class TupleStruct; - class EnumItem; - class EnumItemTuple; - class EnumItemStruct; - class EnumItemDiscriminant; - class Enum; - class Union; - class ConstantItem; - class StaticItem; - struct TraitFunctionDecl; - class TraitItemFunc; - struct TraitMethodDecl; - class TraitItemMethod; - class TraitItemConst; - class TraitItemType; - class Trait; - class Impl; - class InherentImpl; - class TraitImpl; - class ExternalItem; - class ExternalStaticItem; - struct NamedFunctionParam; - class ExternalFunctionItem; - class ExternBlock; - - // rust-macro.h - class MacroMatchFragment; - class MacroMatchRepetition; - class MacroMatcher; - struct MacroTranscriber; - struct MacroRule; - class MacroRulesDefinition; - class MacroInvocation; - class MetaItemPath; - class MetaItemSeq; - class MetaWord; - class MetaNameValueStr; - class MetaListPaths; - class MetaListNameValueStr; - - // rust-pattern.h - class LiteralPattern; - class IdentifierPattern; - class WildcardPattern; - class RangePatternBound; - class RangePatternBoundLiteral; - class RangePatternBoundPath; - class RangePatternBoundQualPath; - class RangePattern; - class ReferencePattern; - struct StructPatternEtc; - class StructPatternField; - class StructPatternFieldTuplePat; - class StructPatternFieldIdentPat; - class StructPatternFieldIdent; - struct StructPatternElements; - class StructPattern; - class TupleStructItems; - class TupleStructItemsNoRange; - class TupleStructItemsRange; - class TupleStructPattern; - class TuplePatternItems; - class TuplePatternItemsMultiple; - class TuplePatternItemsRanged; - class TuplePattern; - class GroupedPattern; - class SlicePattern; - - // rust-type.h - class TraitBound; - class ImplTraitType; - class TraitObjectType; - class ParenthesisedType; - class ImplTraitTypeOneBound; - class TraitObjectTypeOneBound; - class TupleType; - class NeverType; - class RawPointerType; - class ReferenceType; - class ArrayType; - class SliceType; - class InferredType; - struct MaybeNamedParam; - class BareFunctionType; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast-full-test.cc b/gcc/rust/test3/ast/rust-ast-full-test.cc deleted file mode 100644 index 6eb48cc..0000000 --- a/gcc/rust/test3/ast/rust-ast-full-test.cc +++ /dev/null @@ -1,4610 +0,0 @@ -#include "rust-ast-full.h" -#include "diagnostic.h" - -#include "rust-ast-visitor.h" - -#include "rust-session-manager.h" - -/* Compilation unit used for various AST-related functions that would make the headers too long if - * they were defined inline and don't receive any benefits from being defined inline because they are - * virtual. Also used for various other stuff. */ - -namespace Rust { - namespace AST { - // Gets a string in a certain delim type. - ::std::string get_string_in_delims(::std::string str_input, DelimType delim_type) { - switch (delim_type) { - case PARENS: - return "(" + str_input + ")"; - case SQUARE: - return "[" + str_input + "]"; - case CURLY: - return "{" + str_input + "}"; - default: - return "ERROR-MARK-STRING (delims)"; - } - gcc_unreachable(); - } - - // Converts a frag spec enum item to a string form. - ::std::string frag_spec_to_str(MacroFragSpec frag_spec) { - switch (frag_spec) { - case BLOCK: - return "block"; - case EXPR: - return "expr"; - case IDENT: - return "ident"; - case ITEM: - return "item"; - case LIFETIME: - return "lifetime"; - case LITERAL: - return "literal"; - case META: - return "meta"; - case PAT: - return "pat"; - case PATH: - return "path"; - case STMT: - return "stmt"; - case TT: - return "tt"; - case TY: - return "ty"; - case VIS: - return "vis"; - case INVALID: - return "INVALID_FRAG_SPEC"; - default: - return "ERROR_MARK_STRING - unknown frag spec"; - } - } - - ::std::string Crate::as_string() const { - fprintf(stderr, "beginning crate recursive as-string\n"); - - ::std::string str("Crate: "); - // add utf8bom and shebang - if (has_utf8bom) { - str += "\n has utf8bom"; - } - if (has_shebang) { - str += "\n has shebang"; - } - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - // items - str += "\n items: "; - if (items.empty()) { - str += "none"; - } else { - for (const auto& item : items) { - // DEBUG: null pointer check - if (item == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer item in crate."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + item->as_string(); - } - } - - return str + "\n"; - } - - ::std::string Attribute::as_string() const { - ::std::string path_str = path.as_string(); - if (attr_input == NULL) { - return path_str; - } else { - return path_str + attr_input->as_string(); - } - } - - ::std::string DelimTokenTree::as_string() const { - ::std::string start_delim; - ::std::string end_delim; - switch (delim_type) { - case PARENS: - start_delim = "("; - end_delim = ")"; - break; - case SQUARE: - start_delim = "["; - end_delim = "]"; - break; - case CURLY: - start_delim = "{"; - end_delim = "}"; - break; - default: - // error - return ""; - } - ::std::string str = start_delim; - if (token_trees.empty()) { - str += "none"; - } else { - for (const auto& tree : token_trees) { - // DEBUG: null pointer check - if (tree == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "token tree in delim token tree."); - return "NULL_POINTER_MARK"; - } - - str += tree->as_string() + ", "; - } - } - str += end_delim; - - return str; - } - - ::std::string Token::as_string() const { - /* FIXME: only works when not identifier or literal or whatever, i.e. when doesn't store - * string value */ - // return get_token_description(token_id); - - // maybe fixed - stores everything as string though, so storage-inefficient - return str; - } - - ::std::string SimplePathSegment::as_string() const { - return segment_name; - } - - ::std::string SimplePath::as_string() const { - ::std::string path; - if (has_opening_scope_resolution) { - path = "::"; - } - - // crappy hack because doing proper for loop would be more code - bool first_time = true; - for (const auto& segment : segments) { - if (first_time) { - path += segment.as_string(); - first_time = false; - } else { - path += "::" + segment.as_string(); - } - - // DEBUG: remove later. Checks for path error. - if (segment.is_error()) { - fprintf(stderr, - "segment in path is error - this should've been filtered out. first segment " - "was '%s' \n", - segments.at(0).as_string().c_str()); - } - } - - return path; - } - - ::std::string Visibility::as_string() const { - switch (public_vis_type) { - case NONE: - return ::std::string("pub"); - case CRATE: - return ::std::string("ub(crate)"); - case SELF: - return ::std::string("pub(self)"); - case SUPER: - return ::std::string("pub(super)"); - case IN_PATH: - return ::std::string("pub(in ") + in_path.as_string() + ::std::string(")"); - default: - gcc_unreachable(); - } - } - - // Creates a string that reflects the visibility stored. - ::std::string VisItem::as_string() const { - // FIXME: can't do formatting on string to make identation occur. - ::std::string str = Item::as_string(); - - if (has_visibility()) { - str = visibility.as_string() + " "; - } - - return str; - } - - // Creates a string that reflects the outer attributes stored. - ::std::string Item::as_string() const { - ::std::string str; - - if (!outer_attrs.empty()) { - for (const auto& attr : outer_attrs) { - str += attr.as_string() + "\n"; - } - } - - return str; - } - - ::std::string Module::as_string() const { - ::std::string vis_item = VisItem::as_string(); - - return vis_item + "mod " + module_name; - } - - ::std::string ModuleBodied::as_string() const { - // get module string for "[vis] mod [name]" - ::std::string str = Module::as_string(); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - // items - str += "\n items: "; - if (items.empty()) { - str += "none"; - } else { - for (const auto& item : items) { - // DEBUG: null pointer check - if (item == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer item in crate."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + item->as_string(); - } - } - - return str + "\n"; - } - - ::std::string ModuleNoBody::as_string() const { - ::std::string str = Module::as_string(); - - str += "\n no body (reference to external file)"; - - return str + "\n"; - } - - ::std::string StaticItem::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "static"; - - if (has_mut) { - str += " mut"; - } - - str += name; - - // DEBUG: null pointer check - if (type == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer type in static item."); - return "NULL_POINTER_MARK"; - } - str += "\n Type: " + type->as_string(); - - // DEBUG: null pointer check - if (expr == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer expr in static item."); - return "NULL_POINTER_MARK"; - } - str += "\n Expression: " + expr->as_string(); - - return str + "\n"; - } - - ::std::string ExternCrate::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "extern crate " + referenced_crate; - - if (has_as_clause()) { - str += " as " + as_clause_name; - } - - return str; - } - - ::std::string TupleStruct::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "struct " + struct_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in enum."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - // tuple fields - str += "\n Tuple fields: "; - if (fields.empty()) { - str += "none"; - } else { - for (const auto& field : fields) { - str += "\n " + field.as_string(); - } - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string ConstantItem::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "const " + identifier; - - // DEBUG: null pointer check - if (type == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer type in const item."); - return "NULL_POINTER_MARK"; - } - str += "\n Type: " + type->as_string(); - - // DEBUG: null pointer check - if (const_expr == NULL) { - fprintf(stderr, - "something really terrible has gone wrong - null pointer expr in const item."); - return "NULL_POINTER_MARK"; - } - str += "\n Expression: " + const_expr->as_string(); - - return str + "\n"; - } - - ::std::string InherentImpl::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "impl "; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in inherent impl."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Type: " + trait_type->as_string(); - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - // inherent impl items - str += "\n Inherent impl items: "; - if (!has_impl_items()) { - str += "none"; - } else { - for (const auto& item : impl_items) { - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string Method::as_string() const { - ::std::string str("Method: \n "); - - str += vis.as_string() + " " + qualifiers.as_string(); - - str += " fn " + method_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in method."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Self param: " + self_param.as_string(); - - str += "\n Function params: "; - if (function_params.empty()) { - str += "none"; - } else { - for (const auto& param : function_params) { - str += "\n " + param.as_string(); - } - } - - str += "\n Return type: "; - if (has_return_type()) { - str += return_type->as_string(); - } else { - str += "none (void)"; - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - str += "\n Block expr (body): \n "; - str += expr->as_string(); - - return str; - } - - ::std::string StructStruct::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "struct " + struct_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in enum."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - // struct fields - str += "\n Struct fields: "; - if (is_unit) { - str += "none (unit)"; - } else if (fields.empty()) { - str += "none (non-unit)"; - } else { - for (const auto& field : fields) { - str += "\n " + field.as_string(); - } - } - - return str; - } - - ::std::string UseDeclaration::as_string() const { - ::std::string str = VisItem::as_string(); - - // DEBUG: null pointer check - if (use_tree == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer use tree in " - "use declaration."); - return "NULL_POINTER_MARK"; - } - - str += "use " + use_tree->as_string(); - - return str; - } - - ::std::string UseTreeGlob::as_string() const { - switch (glob_type) { - case NO_PATH: - return "*"; - case GLOBAL: - return "::*"; - case PATH_PREFIXED: { - ::std::string path_str = path.as_string(); - return path_str + "::*"; - } - default: - // some kind of error - return "ERROR-PATH"; - } - gcc_unreachable(); - } - - ::std::string UseTreeList::as_string() const { - ::std::string path_str; - switch (path_type) { - case NO_PATH: - path_str = "{"; - break; - case GLOBAL: - path_str = "::{"; - break; - case PATH_PREFIXED: { - path_str = path.as_string() + "::{"; - break; - } - default: - // some kind of error - return "ERROR-PATH-LIST"; - } - - if (has_trees()) { - for (const auto& tree : trees) { - // DEBUG: null pointer check - if (tree == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "tree in use tree list."); - return "NULL_POINTER_MARK"; - } - - path_str += tree->as_string() + ", "; - } - } else { - path_str += "none"; - } - - return path_str + "}"; - } - - ::std::string UseTreeRebind::as_string() const { - ::std::string path_str = path.as_string(); - - switch (bind_type) { - case NONE: - // nothing to add, just path - break; - case IDENTIFIER: - path_str += " as " + identifier; - break; - case WILDCARD: - path_str += " as _"; - break; - default: - // error - return "ERROR-PATH-REBIND"; - } - - return path_str; - } - - ::std::string Enum::as_string() const { - ::std::string str = VisItem::as_string(); - str += enum_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in enum."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - // items - str += "\n Items: "; - if (items.empty()) { - str += "none"; - } else { - for (const auto& item : items) { - // DEBUG: null pointer check - if (item == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "enum item in enum."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string Trait::as_string() const { - ::std::string str = VisItem::as_string(); - - if (has_unsafe) { - str += "unsafe "; - } - - str += "trait " + name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in trait."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Type param bounds: "; - if (!has_type_param_bounds()) { - str += "none"; - } else { - for (const auto& bound : type_param_bounds) { - // DEBUG: null pointer check - if (bound == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "type param bound in trait."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + bound->as_string(); - } - } - - str += "\n Where clause: "; - if (!has_where_clause()) { - str += "none"; - } else { - str += where_clause.as_string(); - } - - str += "\n Trait items: "; - if (!has_trait_items()) { - str += "none"; - } else { - for (const auto& item : trait_items) { - // DEBUG: null pointer check - if (item == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "trait item in trait."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string Union::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "union " + union_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in union."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - // struct fields - str += "\n Struct fields (variants): "; - if (variants.empty()) { - str += "none"; - } else { - for (const auto& field : variants) { - str += "\n " + field.as_string(); - } - } - - return str; - } - - ::std::string Function::as_string() const { - ::std::string str = VisItem::as_string() + "Function: "; - ::std::string qualifiers_str = "Qualifiers: " + qualifiers.as_string(); - - ::std::string generic_params_str("Generic params: "); - if (has_generics()) { - for (const auto& generic_param : generic_params) { - // DEBUG: null pointer check - if (generic_param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in function item."); - return "NULL_POINTER_MARK"; - } - - generic_params_str += generic_param->as_string() + ", "; - } - } else { - generic_params_str += "none"; - } - - ::std::string function_params_str("Function params: "); - if (has_function_params()) { - for (const auto& param : function_params) { - function_params_str += param.as_string() + ", "; - } - } else { - function_params_str += "none"; - } - - ::std::string return_type_str("Return type: "); - if (has_function_return_type()) { - // DEBUG: null pointer check - if (return_type == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer return " - "type in function."); - return "NULL_POINTER_MARK"; - } - - return_type_str += return_type->as_string(); - } else { - return_type_str += "none (void)"; - } - - ::std::string where_clause_str("Where clause: "); - if (has_where_clause()) { - where_clause_str += where_clause.as_string(); - } else { - where_clause_str += "none"; - } - - // DEBUG: null pointer check - if (function_body == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer function " - "body in function."); - return "NULL_POINTER_MARK"; - } - ::std::string body_str = "Body: " + function_body->as_string(); - - str += "\n " + qualifiers_str + "\n " + generic_params_str + "\n " - + function_params_str + "\n " + return_type_str + "\n " + where_clause_str - + "\n " + body_str; - - return str; - } - - ::std::string WhereClause::as_string() const { - // just print where clause items, don't mention "where" or "where clause" - ::std::string str; - - if (where_clause_items.empty()) { - str = "none"; - } else { - for (const auto& item : where_clause_items) { - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string BlockExpr::as_string() const { - ::std::string str = "BlockExpr: "; - - // get outer attributes - str += "\n " + Expr::as_string(); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - // statements - str += "\n statements: "; - if (statements.empty()) { - str += "none"; - } else { - for (const auto& stmt : statements) { - // DEBUG: null pointer check - if (stmt == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "stmt in block expr."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + stmt->as_string(); - } - } - - // final expression - str += "\n final expression: "; - if (expr == NULL) { - str += "none"; - } else { - str += "\n " + expr->as_string(); - } - - return str; - } - - ::std::string TraitImpl::as_string() const { - ::std::string str = VisItem::as_string(); - - if (has_unsafe) { - str += "unsafe "; - } - - str += "impl "; - - // generic params - str += "\n Generic params: "; - if (!has_generics()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - str += "\n " + param->as_string(); - } - } - - str += "\n Has exclam: "; - if (has_exclam) { - str += "true"; - } else { - str += "false"; - } - - str += "\n TypePath (to trait): " + trait_path.as_string(); - - str += "\n Type (struct to impl on): " + trait_type->as_string(); - - str += "\n Where clause: "; - if (!has_where_clause()) { - str += "none"; - } else { - str += where_clause.as_string(); - } - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n trait impl items: "; - if (!has_impl_items()) { - str += "none"; - } else { - for (const auto& item : impl_items) { - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string TypeAlias::as_string() const { - ::std::string str = VisItem::as_string(); - - str += " " + new_type_name; - - // generic params - str += "\n Generic params: "; - if (!has_generics()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - str += param->as_string() + ", "; - } - } - - str += "\n Where clause: "; - if (!has_where_clause()) { - str += "none"; - } else { - str += where_clause.as_string(); - } - - str += "\n Type: " + existing_type->as_string(); - - return str; - } - - ::std::string MacroInvocationSemi::as_string() const { - // get outer attrs - ::std::string str = MacroItem::as_string(); - - str += "\n" + path.as_string() + "!"; - - ::std::string tok_trees; - if (token_trees.empty()) { - tok_trees = "none"; - } else { - for (const auto& tree : token_trees) { - // DEBUG: null pointer check - if (tree == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "token tree in macro invocation semi."); - return "NULL_POINTER_MARK"; - } - - tok_trees += tree->as_string() + ", "; - } - } - - return str + get_string_in_delims(::std::move(tok_trees), delim_type); - } - - ::std::string ExternBlock::as_string() const { - ::std::string str = VisItem::as_string(); - - str += "extern "; - if (has_abi()) { - str += "\"" + abi + "\" "; - } - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n external items: "; - if (!has_extern_items()) { - str += "none"; - } else { - for (const auto& item : extern_items) { - str += "\n " + item->as_string(); - } - } - - return str; - } - - ::std::string MacroRule::as_string() const { - ::std::string str("Macro rule: "); - - str += "\n Matcher: \n "; - str += matcher.as_string(); - - str += "\n Transcriber: \n "; - str += transcriber.as_string(); - - return str; - } - - ::std::string MacroRulesDefinition::as_string() const { - ::std::string str("macro_rules!"); - - str += rule_name; - - str += "\n Macro rules: "; - if (rules.empty()) { - str += "none"; - } else { - for (const auto& rule : rules) { - str += "\n " + rule.as_string(); - } - } - - str += "\n Delim type: "; - switch (delim_type) { - case PARENS: - str += "parentheses"; - break; - case SQUARE: - str += "square"; - break; - case CURLY: - str += "curly"; - break; - default: - return "ERROR_MARK_STRING - delim type in macro invocation"; - } - - return str; - } - - ::std::string MacroInvocation::as_string() const { - return path.as_string() + "!" + token_tree.as_string(); - } - - ::std::string PathInExpression::as_string() const { - ::std::string str; - - if (has_opening_scope_resolution) { - str = "::"; - } - - return str + PathPattern::as_string(); - } - - ::std::string ExprStmtWithBlock::as_string() const { - ::std::string str("ExprStmtWithBlock: \n "); - - if (expr == NULL) { - str += "none (this should not happen and is an error)"; - } else { - str += expr->as_string(); - } - - return str; - } - - ::std::string ClosureParam::as_string() const { - ::std::string str(pattern->as_string()); - - if (has_type_given()) { - str += " : " + type->as_string(); - } - - return str; - } - - ::std::string ClosureExpr::as_string() const { - ::std::string str("ClosureExpr:\n Has move: "); - if (has_move) { - str += "true"; - } else { - str += "false"; - } - - str += "\n Params: "; - if (params.empty()) { - str += "none"; - } else { - for (const auto& param : params) { - str += "\n " + param.as_string(); - } - } - - return str; - } - - ::std::string ClosureExprInnerTyped::as_string() const { - ::std::string str = ClosureExpr::as_string(); - - str += "\n Return type: " + return_type->as_string(); - - str += "\n Body: " + expr->as_string(); - - return str; - } - - ::std::string PathPattern::as_string() const { - ::std::string str; - - for (const auto& segment : segments) { - str += segment.as_string() + "::"; - } - - // basically a hack - remove last two characters of string (remove final ::) - str.erase(str.length() - 2); - - return str; - } - - ::std::string QualifiedPathType::as_string() const { - ::std::string str("<"); - str += type_to_invoke_on->as_string(); - - if (has_as_clause()) { - str += " as " + trait_path.as_string(); - } - - return str + ">"; - } - - ::std::string QualifiedPathInExpression::as_string() const { - return path_type.as_string() + "::" + PathPattern::as_string(); - } - - ::std::string BorrowExpr::as_string() const { - ::std::string str("&"); - - if (double_borrow) { - str += "&"; - } - - if (is_mut) { - str += "mut "; - } - - str += main_or_left_expr->as_string(); - - return str; - } - - ::std::string ReturnExpr::as_string() const { - ::std::string str("return "); - - if (has_return_expr()) { - str += return_expr->as_string(); - } - - return str; - } - - ::std::string GroupedExpr::as_string() const { - ::std::string str("Grouped expr:"); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n Expr in parens: " + expr_in_parens->as_string(); - - return str; - } - - ::std::string RangeToExpr::as_string() const { - return ".." + to->as_string(); - } - - ::std::string ContinueExpr::as_string() const { - ::std::string str("continue "); - - if (has_label()) { - str += label.as_string(); - } - - return str; - } - - ::std::string NegationExpr::as_string() const { - ::std::string str; - - switch (negation_type) { - case NEGATE: - str = "-"; - break; - case NOT: - str = "!"; - break; - default: - return "ERROR_MARK_STRING - negation expr"; - } - - str += main_or_left_expr->as_string(); - - return str; - } - - ::std::string RangeFromExpr::as_string() const { - return from->as_string() + ".."; - } - - ::std::string RangeFullExpr::as_string() const { - return ".."; - } - - ::std::string ArrayIndexExpr::as_string() const { - return array_expr->as_string() + "[" + index_expr->as_string() + "]"; - } - - ::std::string AssignmentExpr::as_string() const { - ::std::string str("AssignmentExpr: "); - - if (main_or_left_expr == NULL || right_expr == NULL) { - str += "error (either or both expressions are null)"; - } else { - // left expr - str += "\n left: " + main_or_left_expr->as_string(); - - // right expr - str += "\n right: " + right_expr->as_string(); - } - - return str; - } - - ::std::string AsyncBlockExpr::as_string() const { - ::std::string str = "AsyncBlockExpr: "; - - // get outer attributes - str += "\n " + Expr::as_string(); - - str += "\n Has move: "; - str += has_move ? "true" : "false"; - - return str + "\n" + block_expr->as_string(); - } - - ::std::string ComparisonExpr::as_string() const { - ::std::string str(main_or_left_expr->as_string()); - - switch (expr_type) { - case EQUAL: - str += " == "; - break; - case NOT_EQUAL: - str += " != "; - break; - case GREATER_THAN: - str += " > "; - break; - case LESS_THAN: - str += " < "; - break; - case GREATER_OR_EQUAL: - str += " >= "; - break; - case LESS_OR_EQUAL: - str += " <= "; - break; - default: - return "ERROR_MARK_STRING - comparison expr"; - } - - str += right_expr->as_string(); - - return str; - } - - ::std::string MethodCallExpr::as_string() const { - ::std::string str("MethodCallExpr: \n Object (receiver) expr: "); - - str += receiver->as_string(); - - str += "\n Method path segment: \n"; - - str += method_name.as_string(); - - str += "\n Call params:"; - if (params.empty()) { - str += "none"; - } else { - for (const auto& param : params) { - if (param == NULL) { - return "ERROR_MARK_STRING - method call expr param is null"; - } - - str += "\n " + param->as_string(); - } - } - - return str; - } - - ::std::string TupleIndexExpr::as_string() const { - return tuple_expr->as_string() + "." + ::std::to_string(tuple_index); - } - - ::std::string DereferenceExpr::as_string() const { - return "*" + main_or_left_expr->as_string(); - } - - ::std::string FieldAccessExpr::as_string() const { - return receiver->as_string() + "." + field; - } - - ::std::string LazyBooleanExpr::as_string() const { - ::std::string str(main_or_left_expr->as_string()); - - switch (expr_type) { - case LOGICAL_OR: - str += " || "; - break; - case LOGICAL_AND: - str += " && "; - break; - default: - return "ERROR_MARK_STRING - lazy boolean expr out of bounds"; - } - - str += right_expr->as_string(); - - return str; - } - - ::std::string RangeFromToExpr::as_string() const { - return from->as_string() + ".." + to->as_string(); - } - - ::std::string RangeToInclExpr::as_string() const { - return "..=" + to->as_string(); - } - - ::std::string UnsafeBlockExpr::as_string() const { - ::std::string str = "UnsafeBlockExpr: "; - - // get outer attributes - str += "\n " + Expr::as_string(); - - return str + "\n" + expr->as_string(); - } - - ::std::string ClosureExprInner::as_string() const { - ::std::string str = ClosureExpr::as_string(); - - str += "\n Expression: " + closure_inner->as_string(); - - return str; - } - - ::std::string IfExpr::as_string() const { - ::std::string str("IfExpr: "); - - str += "\n Condition expr: " + condition->as_string(); - - str += "\n If block expr: " + if_block->as_string(); - - return str; - } - - ::std::string IfExprConseqElse::as_string() const { - ::std::string str = IfExpr::as_string(); - - str += "\n Else block expr: " + else_block->as_string(); - - return str; - } - - ::std::string IfExprConseqIf::as_string() const { - ::std::string str = IfExpr::as_string(); - - str += "\n Else if expr: \n " + if_expr->as_string(); - - return str; - } - - ::std::string IfExprConseqIfLet::as_string() const { - ::std::string str = IfExpr::as_string(); - - str += "\n Else if let expr: \n " + if_let_expr->as_string(); - - return str; - } - - ::std::string IfLetExpr::as_string() const { - ::std::string str("IfLetExpr: "); - - str += "\n Condition match arm patterns: "; - if (match_arm_patterns.empty()) { - str += "none"; - } else { - for (const auto& pattern : match_arm_patterns) { - str += "\n " + pattern->as_string(); - } - } - - str += "\n Scrutinee expr: " + value->as_string(); - - str += "\n If let block expr: " + if_block->as_string(); - - return str; - } - - ::std::string IfLetExprConseqElse::as_string() const { - ::std::string str = IfLetExpr::as_string(); - - str += "\n Else block expr: " + else_block->as_string(); - - return str; - } - - ::std::string IfLetExprConseqIf::as_string() const { - ::std::string str = IfLetExpr::as_string(); - - str += "\n Else if expr: \n " + if_expr->as_string(); - - return str; - } - - ::std::string IfLetExprConseqIfLet::as_string() const { - ::std::string str = IfLetExpr::as_string(); - - str += "\n Else if let expr: \n " + if_let_expr->as_string(); - - return str; - } - - ::std::string RangeFromToInclExpr::as_string() const { - return from->as_string() + "..=" + to->as_string(); - } - - ::std::string ErrorPropagationExpr::as_string() const { - return main_or_left_expr->as_string() + "?"; - } - - ::std::string CompoundAssignmentExpr::as_string() const { - ::std::string operator_str; - operator_str.reserve(1); - - // get operator string - switch (expr_type) { - case ADD: - operator_str = "+"; - break; - case SUBTRACT: - operator_str = "-"; - break; - case MULTIPLY: - operator_str = "*"; - break; - case DIVIDE: - operator_str = "/"; - break; - case MODULUS: - operator_str = "%"; - break; - case BITWISE_AND: - operator_str = "&"; - break; - case BITWISE_OR: - operator_str = "|"; - break; - case BITWISE_XOR: - operator_str = "^"; - break; - case LEFT_SHIFT: - operator_str = "<<"; - break; - case RIGHT_SHIFT: - operator_str = ">>"; - break; - default: - operator_str = "invalid operator. wtf"; - break; - } - - operator_str += "="; - - ::std::string str("CompoundAssignmentExpr: "); - if (main_or_left_expr == NULL || right_expr == NULL) { - str += "error. this is probably a parsing failure."; - } else { - str += "\n left: " + main_or_left_expr->as_string(); - str += "\n right: " + right_expr->as_string(); - str += "\n operator: " + operator_str; - } - - return str; - } - - ::std::string ArithmeticOrLogicalExpr::as_string() const { - ::std::string operator_str; - operator_str.reserve(1); - - // get operator string - switch (expr_type) { - case ADD: - operator_str = "+"; - break; - case SUBTRACT: - operator_str = "-"; - break; - case MULTIPLY: - operator_str = "*"; - break; - case DIVIDE: - operator_str = "/"; - break; - case MODULUS: - operator_str = "%"; - break; - case BITWISE_AND: - operator_str = "&"; - break; - case BITWISE_OR: - operator_str = "|"; - break; - case BITWISE_XOR: - operator_str = "^"; - break; - case LEFT_SHIFT: - operator_str = "<<"; - break; - case RIGHT_SHIFT: - operator_str = ">>"; - break; - default: - operator_str = "invalid operator. wtf"; - break; - } - - ::std::string str("ArithmeticOrLogicalExpr: "); - if (main_or_left_expr == NULL || right_expr == NULL) { - str += "error. this is probably a parsing failure."; - } else { - str += "\n left: " + main_or_left_expr->as_string(); - str += "\n right: " + right_expr->as_string(); - str += "\n operator: " + operator_str; - } - - return str; - } - - ::std::string CallExpr::as_string() const { - ::std::string str("CallExpr: \n Function expr: "); - - str += function->as_string(); - - str += "\n Call params:"; - if (!has_params()) { - str += "none"; - } else { - for (const auto& param : params) { - if (param == NULL) { - return "ERROR_MARK_STRING - call expr param is null"; - } - - str += "\n " + param->as_string(); - } - } - - return str; - } - - ::std::string WhileLoopExpr::as_string() const { - ::std::string str("WhileLoopExpr: "); - - str += "\n Label: "; - if (!has_loop_label()) { - str += "none"; - } else { - str += loop_label.as_string(); - } - - str += "\n Conditional expr: " + condition->as_string(); - - str += "\n Loop block: " + loop_block->as_string(); - - return str; - } - - ::std::string WhileLetLoopExpr::as_string() const { - ::std::string str("WhileLetLoopExpr: "); - - str += "\n Label: "; - if (!has_loop_label()) { - str += "none"; - } else { - str += loop_label.as_string(); - } - - str += "\n Match arm patterns: "; - if (match_arm_patterns.empty()) { - str += "none"; - } else { - for (const auto& pattern : match_arm_patterns) { - str += "\n " + pattern->as_string(); - } - } - - str += "\n Scrutinee expr: " + condition->as_string(); - - str += "\n Loop block: " + loop_block->as_string(); - - return str; - } - - ::std::string LoopExpr::as_string() const { - ::std::string str("LoopExpr: (infinite loop)"); - - str += "\n Label: "; - if (!has_loop_label()) { - str += "none"; - } else { - str += loop_label.as_string(); - } - - str += "\n Loop block: " + loop_block->as_string(); - - return str; - } - - ::std::string ArrayExpr::as_string() const { - ::std::string str("ArrayExpr:"); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n Array elems: "; - if (!has_array_elems()) { - str += "none"; - } else { - str += internal_elements->as_string(); - } - - return str; - } - - ::std::string AwaitExpr::as_string() const { - return awaited_expr->as_string() + ".await"; - } - - ::std::string BreakExpr::as_string() const { - ::std::string str("break "); - - if (has_label()) { - str += label.as_string() + " "; - } - - if (has_break_expr()) { - str += break_expr->as_string(); - } - - return str; - } - - ::std::string LoopLabel::as_string() const { - return label.as_string() + ": (label) "; - } - - ::std::string MatchArm::as_string() const { - // outer attributes - ::std::string str = "Outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\nPatterns: "; - if (match_arm_patterns.empty()) { - str += "none"; - } else { - for (const auto& pattern : match_arm_patterns) { - str += "\n " + pattern->as_string(); - } - } - - str += "\nGuard expr: "; - if (!has_match_arm_guard()) { - str += "none"; - } else { - str += guard_expr->as_string(); - } - - return str; - } - - ::std::string MatchCase::as_string() const { - ::std::string str("MatchCase: (match arm) "); - - str += "\n Match arm matcher: \n" + arm.as_string(); - - return str; - } - - ::std::string MatchCaseBlockExpr::as_string() const { - ::std::string str = MatchCase::as_string(); - - str += "\n Block expr: " + block_expr->as_string(); - - return str; - } - - ::std::string MatchCaseExpr::as_string() const { - ::std::string str = MatchCase::as_string(); - - str += "\n Expr: " + expr->as_string(); - - return str; - } - - ::std::string MatchExpr::as_string() const { - ::std::string str("MatchExpr:"); - - str += "\n Scrutinee expr: " + branch_value->as_string(); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - // match arms - str += "\n Match arms: "; - if (match_arms.empty()) { - str += "none"; - } else { - for (const auto& arm : match_arms) { - str += "\n " + arm->as_string(); - } - } - - return str; - } - - ::std::string TupleExpr::as_string() const { - ::std::string str("TupleExpr:"); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n Tuple elements: "; - if (tuple_elems.empty()) { - str += "none"; - } else { - for (const auto& elem : tuple_elems) { - str += "\n " + elem->as_string(); - } - } - - return str; - } - - ::std::string ExprStmtWithoutBlock::as_string() const { - ::std::string str("ExprStmtWithoutBlock: \n "); - - if (expr == NULL) { - str += "none (this shouldn't happen and is probably an error)"; - } else { - str += expr->as_string(); - } - - return str; - } - - ::std::string FunctionParam::as_string() const { - return param_name->as_string() + " : " + type->as_string(); - } - - ::std::string FunctionQualifiers::as_string() const { - ::std::string str; - - switch (const_status) { - case NONE: - // do nothing - break; - case CONST: - str += "const "; - break; - case ASYNC: - str += "async "; - break; - default: - return "ERROR_MARK_STRING: async-const status failure"; - } - - if (has_unsafe) { - str += "unsafe "; - } - - if (has_extern) { - str += "extern"; - if (extern_abi != "") { - str += " \"" + extern_abi + "\""; - } - } - - return str; - } - - ::std::string TraitBound::as_string() const { - ::std::string str("TraitBound:"); - - str += "\n Has opening question mark: "; - if (opening_question_mark) { - str += "true"; - } else { - str += "false"; - } - - str += "\n For lifetimes: "; - if (!has_for_lifetimes()) { - str += "none"; - } else { - for (const auto& lifetime : for_lifetimes) { - str += "\n " + lifetime.as_string(); - } - } - - str += "\n Type path: " + type_path.as_string(); - - return str; - } - - ::std::string MacroMatcher::as_string() const { - ::std::string str("Macro matcher: "); - - str += "\n Delim type: "; - - switch (delim_type) { - case PARENS: - str += "parentheses"; - break; - case SQUARE: - str += "square"; - break; - case CURLY: - str += "curly"; - break; - default: - return "ERROR_MARK_STRING - macro matcher delim"; - } - - str += "\n Matches: "; - - if (matches.empty()) { - str += "none"; - } else { - for (const auto& match : matches) { - str += "\n " + match->as_string(); - } - } - - return str; - } - - ::std::string LifetimeParam::as_string() const { - ::std::string str("LifetimeParam: "); - - str += "\n Outer attribute: "; - if (!has_outer_attribute()) { - str += "none"; - } else { - str += outer_attr.as_string(); - } - - str += "\n Lifetime: " + lifetime.as_string(); - - str += "\n Lifetime bounds: "; - if (!has_lifetime_bounds()) { - str += "none"; - } else { - for (const auto& bound : lifetime_bounds) { - str += "\n " + bound.as_string(); - } - } - - return str; - } - - ::std::string MacroMatchFragment::as_string() const { - return "$" + ident + ": " + frag_spec_to_str(frag_spec); - } - - ::std::string QualifiedPathInType::as_string() const { - ::std::string str = path_type.as_string(); - - for (const auto& segment : segments) { - str += "::" + segment->as_string(); - } - - return str; - } - - ::std::string MacroMatchRepetition::as_string() const { - ::std::string str("Macro match repetition: "); - - str += "\n Matches: "; - if (matches.empty()) { - str += "none"; - } else { - for (const auto& match : matches) { - str += "\n " + match->as_string(); - } - } - - str += "\n Sep: "; - if (!has_sep()) { - str += "none"; - } else { - str += sep->as_string(); - } - - str += "\n Op: "; - switch (op) { - case ASTERISK: - str += "*"; - break; - case PLUS: - str += "+"; - break; - case QUESTION_MARK: - str += "?"; - break; - case NONE: - str += "no op? shouldn't be allowed"; - break; - default: - return "ERROR_MARK_STRING - unknown op in macro match repetition"; - } - - return str; - } - - ::std::string Lifetime::as_string() const { - if (is_error()) { - return "error lifetime"; - } - - switch (lifetime_type) { - case NAMED: - return "'" + lifetime_name; - case STATIC: - return "'static"; - case WILDCARD: - return "'_"; - default: - return "ERROR-MARK-STRING: lifetime type failure"; - } - } - - ::std::string TypePath::as_string() const { - ::std::string str; - - if (has_opening_scope_resolution) { - str = "::"; - } - - for (const auto& segment : segments) { - str += segment->as_string() + "::"; - } - - // kinda hack - remove last 2 '::' characters - str.erase(str.length() - 2); - - return str; - } - - ::std::string TypeParam::as_string() const { - ::std::string str("TypeParam: "); - - str += "\n Outer attribute: "; - if (!has_outer_attribute()) { - str += "none"; - } else { - str += outer_attr.as_string(); - } - - str += "\n Identifier: " + type_representation; - - str += "\n Type param bounds: "; - if (!has_type_param_bounds()) { - str += "none"; - } else { - for (const auto& bound : type_param_bounds) { - str += "\n " + bound->as_string(); - } - } - - str += "\n Type: "; - if (!has_type()) { - str += "none"; - } else { - str += type->as_string(); - } - - return str; - } - - SimplePath PathPattern::convert_to_simple_path(bool with_opening_scope_resolution) const { - if (!has_segments()) { - return SimplePath::create_empty(); - } - - // create vector of reserved size (to minimise reallocations) - ::std::vector simple_segments; - simple_segments.reserve(segments.size()); - - for (const auto& segment : segments) { - // return empty path if doesn't meet simple path segment requirements - if (segment.is_error() || segment.has_generic_args() - || segment.as_string() == "Self") { - return SimplePath::create_empty(); - } - - // create segment and add to vector - ::std::string segment_str = segment.as_string(); - simple_segments.push_back( - SimplePathSegment(::std::move(segment_str), segment.get_locus())); - } - - // kind of a HACK to get locus depending on opening scope resolution - location_t locus = UNKNOWN_LOCATION; - if (with_opening_scope_resolution) { - locus = simple_segments[0].get_locus() - 2; // minus 2 chars for :: - } else { - locus = simple_segments[0].get_locus(); - } - - return SimplePath(::std::move(simple_segments), with_opening_scope_resolution, locus); - } - - SimplePath TypePath::as_simple_path() const { - if (segments.empty()) { - return SimplePath::create_empty(); - } - - // create vector of reserved size (to minimise reallocations) - ::std::vector simple_segments; - simple_segments.reserve(segments.size()); - - for (const auto& segment : segments) { - // return empty path if doesn't meet simple path segment requirements - if (segment == NULL || segment->is_error() || !segment->is_ident_only() - || segment->as_string() == "Self") { - return SimplePath::create_empty(); - } - - // create segment and add to vector - ::std::string segment_str = segment->as_string(); - simple_segments.push_back( - SimplePathSegment(::std::move(segment_str), segment->get_locus())); - } - - return SimplePath(::std::move(simple_segments), has_opening_scope_resolution, locus); - } - - ::std::string PathExprSegment::as_string() const { - ::std::string ident_str = segment_name.as_string(); - if (has_generic_args()) { - ident_str += "::<" + generic_args.as_string() + ">"; - } - - return ident_str; - } - - ::std::string GenericArgs::as_string() const { - ::std::string args; - - // lifetime args - if (!lifetime_args.empty()) { - for (const auto& lifetime_arg : lifetime_args) { - args += lifetime_arg.as_string() + ", "; - } - } - - // type args - if (!type_args.empty()) { - for (const auto& type_arg : type_args) { - args += type_arg->as_string() + ", "; - } - } - - // binding args - if (!binding_args.empty()) { - for (const auto& binding_arg : binding_args) { - args += binding_arg.as_string() + ", "; - } - } - - return args; - } - - ::std::string GenericArgsBinding::as_string() const { - return identifier + " = " + type->as_string(); - } - - ::std::string ForLoopExpr::as_string() const { - ::std::string str("ForLoopExpr: "); - - str += "\n Label: "; - if (!has_loop_label()) { - str += "none"; - } else { - str += loop_label.as_string(); - } - - str += "\n Pattern: " + pattern->as_string(); - - str += "\n Iterator expr: " + iterator_expr->as_string(); - - str += "\n Loop block: " + loop_block->as_string(); - - return str; - } - - ::std::string RangePattern::as_string() const { - if (has_ellipsis_syntax) { - return lower->as_string() + "..." + upper->as_string(); - } else { - return lower->as_string() + "..=" + upper->as_string(); - } - } - - ::std::string RangePatternBoundLiteral::as_string() const { - ::std::string str; - - if (has_minus) { - str += "-"; - } - - str += literal.as_string(); - - return str; - } - - ::std::string SlicePattern::as_string() const { - ::std::string str("SlicePattern: "); - - for (const auto& pattern : items) { - str += "\n " + pattern->as_string(); - } - - return str; - } - - ::std::string TuplePatternItemsMultiple::as_string() const { - ::std::string str; - - for (const auto& pattern : patterns) { - str += "\n " + pattern->as_string(); - } - - return str; - } - - ::std::string TuplePatternItemsRanged::as_string() const { - ::std::string str; - - str += "\n Lower patterns: "; - if (lower_patterns.empty()) { - str += "none"; - } else { - for (const auto& lower : lower_patterns) { - str += "\n " + lower->as_string(); - } - } - - str += "\n Upper patterns: "; - if (upper_patterns.empty()) { - str += "none"; - } else { - for (const auto& upper : upper_patterns) { - str += "\n " + upper->as_string(); - } - } - - return str; - } - - ::std::string TuplePattern::as_string() const { - return "TuplePattern: " + items->as_string(); - } - - ::std::string StructPatternField::as_string() const { - // outer attributes - ::std::string str("Outer attributes: "); - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - return str; - } - - ::std::string StructPatternFieldIdent::as_string() const { - ::std::string str = StructPatternField::as_string(); - - str += "\n"; - - if (has_ref) { - str += "ref "; - } - - if (has_mut) { - str += "mut "; - } - - str += ident; - - return str; - } - - ::std::string StructPatternFieldTuplePat::as_string() const { - ::std::string str = StructPatternField::as_string(); - - str += "\n"; - - str += ::std::to_string(index) + " : " + tuple_pattern->as_string(); - - return str; - } - - ::std::string StructPatternFieldIdentPat::as_string() const { - ::std::string str = StructPatternField::as_string(); - - str += "\n"; - - str += ident + " : " + ident_pattern->as_string(); - - return str; - } - - ::std::string StructPatternElements::as_string() const { - ::std::string str("\n Fields: "); - - if (!has_struct_pattern_fields()) { - str += "none"; - } else { - for (const auto& field : fields) { - str += "\n " + field->as_string(); - } - } - - str += "\n Etc: "; - if (has_struct_pattern_etc) { - str += "true"; - } else { - str += "false"; - } - - return str; - } - - ::std::string StructPattern::as_string() const { - ::std::string str("StructPattern: \n Path: "); - - str += path.as_string(); - - str += "\n Struct pattern elems: "; - if (!has_struct_pattern_elems()) { - str += "none"; - } else { - str += elems.as_string(); - } - - return str; - } - - ::std::string LiteralPattern::as_string() const { - ::std::string str; - - if (has_minus) { - str += "-"; - } - - return str + lit.as_string(); - } - - ::std::string ReferencePattern::as_string() const { - ::std::string str("&"); - - if (has_two_amps) { - str += "&"; - } - - if (is_mut) { - str += "mut "; - } - - str += pattern->as_string(); - - return str; - } - - ::std::string IdentifierPattern::as_string() const { - ::std::string str; - - if (is_ref) { - str += "ref "; - } - - if (is_mut) { - str += "mut "; - } - - str += variable_ident; - - if (has_pattern_to_bind()) { - str += " @ " + to_bind->as_string(); - } - - return str; - } - - ::std::string TupleStructItemsNoRange::as_string() const { - ::std::string str; - - for (const auto& pattern : patterns) { - str += "\n " + pattern->as_string(); - } - - return str; - } - - ::std::string TupleStructItemsRange::as_string() const { - ::std::string str("\n Lower patterns: "); - - if (lower_patterns.empty()) { - str += "none"; - } else { - for (const auto& lower : lower_patterns) { - str += "\n " + lower->as_string(); - } - } - - str += "\n Upper patterns: "; - if (upper_patterns.empty()) { - str += "none"; - } else { - for (const auto& upper : upper_patterns) { - str += "\n " + upper->as_string(); - } - } - - return str; - } - - ::std::string TupleStructPattern::as_string() const { - ::std::string str("TupleStructPattern: \n Path: "); - - str += path.as_string(); - - str += "\n Tuple struct items: " + items->as_string(); - - return str; - } - - ::std::string LetStmt::as_string() const { - // outer attributes - ::std::string str = "Outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\nlet " + variables_pattern->as_string(); - - if (has_type()) { - str += " : " + type->as_string(); - } - - if (has_init_expr()) { - str += " = " + init_expr->as_string(); - } - - return str; - } - - // Used to get outer attributes for expressions. - ::std::string Expr::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - return str; - } - - // hopefully definition here will prevent circular dependency issue - TraitBound* TypePath::to_trait_bound(bool in_parens) const { - // create clone FIXME is this required? or is copy constructor automatically called? - TypePath copy(*this); - return new TraitBound(::std::move(copy), in_parens); - } - - ::std::string InferredType::as_string() const { - return "_ (inferred)"; - } - - ::std::string TypeCastExpr::as_string() const { - return main_or_left_expr->as_string() + " as " + type_to_convert_to->as_string(); - } - - ::std::string ImplTraitType::as_string() const { - ::std::string str("ImplTraitType: \n TypeParamBounds: "); - - if (type_param_bounds.empty()) { - str += "none"; - } else { - for (const auto& bound : type_param_bounds) { - str += "\n " + bound->as_string(); - } - } - - return str; - } - - ::std::string ReferenceType::as_string() const { - ::std::string str("&"); - - if (has_lifetime()) { - str += lifetime.as_string() + " "; - } - - if (has_mut) { - str += "mut "; - } - - str += type->as_string(); - - return str; - } - - ::std::string RawPointerType::as_string() const { - ::std::string str("*"); - - switch (pointer_type) { - case MUT: - str += "mut "; - break; - case CONST: - str += "const "; - break; - default: - return "ERROR_MARK_STRING - unknown pointer type in raw pointer type"; - } - - str += type->as_string(); - - return str; - } - - ::std::string TraitObjectType::as_string() const { - ::std::string str("TraitObjectType: \n Has dyn dispatch: "); - - if (has_dyn) { - str += "true"; - } else { - str += "false"; - } - - str += "\n TypeParamBounds: "; - if (type_param_bounds.empty()) { - str += "none"; - } else { - for (const auto& bound : type_param_bounds) { - str += "\n " + bound->as_string(); - } - } - - return str; - } - - ::std::string BareFunctionType::as_string() const { - ::std::string str("BareFunctionType: \n For lifetimes: "); - - if (!has_for_lifetimes()) { - str += "none"; - } else { - for (const auto& for_lifetime : for_lifetimes) { - str += "\n " + for_lifetime.as_string(); - } - } - - str += "\n Qualifiers: " + function_qualifiers.as_string(); - - str += "\n Params: "; - if (params.empty()) { - str += "none"; - } else { - for (const auto& param : params) { - str += "\n " + param.as_string(); - } - } - - str += "\n Is variadic: "; - if (is_variadic) { - str += "true"; - } else { - str += "false"; - } - - str += "\n Return type: "; - if (!has_return_type()) { - str += "none (void)"; - } else { - str += return_type->as_string(); - } - - return str; - } - - ::std::string ImplTraitTypeOneBound::as_string() const { - ::std::string str("ImplTraitTypeOneBound: \n TraitBound: "); - - return str + trait_bound.as_string(); - } - - ::std::string TypePathSegmentGeneric::as_string() const { - return TypePathSegment::as_string() + "<" + generic_args.as_string() + ">"; - } - - ::std::string TraitObjectTypeOneBound::as_string() const { - ::std::string str("TraitObjectTypeOneBound: \n Has dyn dispatch: "); - - if (has_dyn) { - str += "true"; - } else { - str += "false"; - } - - str += "\n TraitBound: " + trait_bound.as_string(); - - return str; - } - - ::std::string TypePathFunction::as_string() const { - ::std::string str("("); - - if (has_inputs()) { - for (const auto& param : inputs) { - str += param->as_string() + ", "; - } - } - - str += ")"; - - if (has_return_type()) { - str += " -> " + return_type->as_string(); - } - - return str; - } - - ::std::string TypePathSegmentFunction::as_string() const { - return TypePathSegment::as_string() + function_path.as_string(); - } - - ::std::string ArrayType::as_string() const { - return "[" + elem_type->as_string() + "; " + size->as_string() + "]"; - } - - ::std::string SliceType::as_string() const { - return "[" + elem_type->as_string() + "]"; - } - - ::std::string TupleType::as_string() const { - ::std::string str("("); - - if (!is_unit_type()) { - for (const auto& elem : elems) { - str += elem->as_string() + ", "; - } - } - - str += ")"; - - return str; - } - - ::std::string StructExpr::as_string() const { - ::std::string str = ExprWithoutBlock::as_string(); - - str += "\nStructExpr"; - - str += "\n PathInExpr: " + struct_name.as_string(); - - return str; - } - - ::std::string StructExprTuple::as_string() const { - ::std::string str = StructExpr::as_string(); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n Tuple fields: "; - if (exprs.empty()) { - str += "none"; - } else { - for (const auto& field : exprs) { - // debug - null pointer check - if (field == NULL) { - return "ERROR_MARK_STRING - nullptr struct expr tuple field"; - } - - str += "\n " + field->as_string(); - } - } - - return str; - } - - ::std::string StructExprStruct::as_string() const { - ::std::string str("StructExprStruct (or subclass): "); - - str += "\n Path: " + get_struct_name().as_string(); - - // inner attributes - str += "\n inner attributes: "; - if (inner_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "inner attribute" syntax - just the body - for (const auto& attr : inner_attrs) { - str += "\n " + attr.as_string(); - } - } - - return str; - } - - ::std::string StructBase::as_string() const { - if (base_struct != NULL) { - return base_struct->as_string(); - } else { - return "ERROR_MARK_STRING - invalid struct base had as string applied"; - } - } - - ::std::string StructExprFieldWithVal::as_string() const { - // used to get value string - return value->as_string(); - } - - ::std::string StructExprFieldIdentifierValue::as_string() const { - return field_name + " : " + StructExprFieldWithVal::as_string(); - } - - ::std::string StructExprFieldIndexValue::as_string() const { - return ::std::to_string(index) + " : " + StructExprFieldWithVal::as_string(); - } - - ::std::string StructExprStructFields::as_string() const { - ::std::string str = StructExprStruct::as_string(); - - str += "\n Fields: "; - if (fields.empty()) { - str += "none"; - } else { - for (const auto& field : fields) { - str += "\n " + field->as_string(); - } - } - - str += "\n Struct base: "; - if (!has_struct_base()) { - str += "none"; - } else { - str += struct_base.as_string(); - } - - return str; - } - - ::std::string EnumItem::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n" + variant_name; - - return str; - } - - ::std::string EnumItemTuple::as_string() const { - ::std::string str = EnumItem::as_string(); - - // add tuple opening parens - str += "("; - - // tuple fields - if (has_tuple_fields()) { - for (const auto& field : tuple_fields) { - str += field.as_string() + ", "; - } - } - - // add tuple closing parens - str += ")"; - - return str; - } - - ::std::string TupleField::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - if (has_visibility()) { - str += "\n" + visibility.as_string(); - } - - str += " " + field_type->as_string(); - - return str; - } - - ::std::string EnumItemStruct::as_string() const { - ::std::string str = EnumItem::as_string(); - - // add struct opening parens - str += "{"; - - // tuple fields - if (has_struct_fields()) { - for (const auto& field : struct_fields) { - str += field.as_string() + ", "; - } - } - - // add struct closing parens - str += "}"; - - return str; - } - - ::std::string StructField::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - if (has_visibility()) { - str += "\n" + visibility.as_string(); - } - - str += " " + field_name + " : " + field_type->as_string(); - - return str; - } - - ::std::string EnumItemDiscriminant::as_string() const { - ::std::string str = EnumItem::as_string(); - - // add equal and expression - str += " = " + expression->as_string(); - - return str; - } - - ::std::string ExternalItem::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - // start visibility on new line and with a space - str += "\n" + visibility.as_string() + " "; - - return str; - } - - ::std::string ExternalStaticItem::as_string() const { - ::std::string str = ExternalItem::as_string(); - - str += "static "; - - if (has_mut) { - str += "mut "; - } - - // add name - str += get_item_name(); - - // add type on new line - str += "\n Type: " + item_type->as_string(); - - return str; - } - - ::std::string ExternalFunctionItem::as_string() const { - ::std::string str = ExternalItem::as_string(); - - str += "fn "; - - // add name - str += get_item_name(); - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in external function item."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - // function params - str += "\n Function params: "; - if (function_params.empty()) { - str += "none"; - } else { - for (const auto& param : function_params) { - str += "\n " + param.as_string(); - } - if (has_variadics) { - str += "\n .. (variadic)"; - } - } - - // add type on new line - str += "\n (return) Type: " + return_type->as_string(); - - // where clause - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string NamedFunctionParam::as_string() const { - ::std::string str = name; - - str += "\n Type: " + param_type->as_string(); - - return str; - } - - /*::std::string TraitItem::as_string() const { - // outer attributes - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - return str; - }*/ - - ::std::string TraitItemFunc::as_string() const { - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n" + decl.as_string(); - - str += "\n Definition (block expr): "; - if (has_definition()) { - str += block_expr->as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string TraitFunctionDecl::as_string() const { - ::std::string str = qualifiers.as_string() + "fn " + function_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in trait function decl."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Function params: "; - if (has_params()) { - for (const auto& param : function_params) { - str += "\n " + param.as_string(); - } - } else { - str += "none"; - } - - str += "\n Return type: "; - if (has_return_type()) { - str += return_type->as_string(); - } else { - str += "none (void)"; - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string TraitItemMethod::as_string() const { - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\n" + decl.as_string(); - - str += "\n Definition (block expr): "; - if (has_definition()) { - str += block_expr->as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string TraitMethodDecl::as_string() const { - ::std::string str = qualifiers.as_string() + "fn " + function_name; - - // generic params - str += "\n Generic params: "; - if (generic_params.empty()) { - str += "none"; - } else { - for (const auto& param : generic_params) { - // DEBUG: null pointer check - if (param == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "generic param in trait function decl."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + param->as_string(); - } - } - - str += "\n Self param: " + self_param.as_string(); - - str += "\n Function params: "; - if (has_params()) { - for (const auto& param : function_params) { - str += "\n " + param.as_string(); - } - } else { - str += "none"; - } - - str += "\n Return type: "; - if (has_return_type()) { - str += return_type->as_string(); - } else { - str += "none (void)"; - } - - str += "\n Where clause: "; - if (has_where_clause()) { - str += where_clause.as_string(); - } else { - str += "none"; - } - - return str; - } - - ::std::string TraitItemConst::as_string() const { - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\nconst " + name + " : " + type->as_string(); - - if (has_expression()) { - str += " = " + expr->as_string(); - } - - return str; - } - - ::std::string TraitItemType::as_string() const { - ::std::string str = "outer attributes: "; - if (outer_attrs.empty()) { - str += "none"; - } else { - // note that this does not print them with "outer attribute" syntax - just the body - for (const auto& attr : outer_attrs) { - str += "\n " + attr.as_string(); - } - } - - str += "\ntype " + name; - - str += "\n Type param bounds: "; - if (!has_type_param_bounds()) { - str += "none"; - } else { - for (const auto& bound : type_param_bounds) { - // DEBUG: null pointer check - if (bound == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "type param bound in trait item type."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + bound->as_string(); - } - } - - return str; - } - - ::std::string SelfParam::as_string() const { - if (is_error()) { - return "error"; - } else { - if (has_type()) { - // type (i.e. not ref, no lifetime) - ::std::string str; - - if (is_mut) { - str += "mut "; - } - - str += "self : "; - - str += type->as_string(); - - return str; - } else if (has_lifetime()) { - // ref and lifetime - ::std::string str = "&" + lifetime.as_string() + " "; - - if (is_mut) { - str += "mut "; - } - - str += "self"; - - return str; - } else if (has_ref) { - // ref with no lifetime - ::std::string str = "&"; - - if (is_mut) { - str += " mut "; - } - - str += "self"; - - return str; - } else { - // no ref, no type - ::std::string str; - - if (is_mut) { - str += "mut "; - } - - str += "self"; - - return str; - } - } - } - - ::std::string ArrayElemsCopied::as_string() const { - return elem_to_copy->as_string() + "; " + num_copies->as_string(); - } - - ::std::string LifetimeWhereClauseItem::as_string() const { - ::std::string str("Lifetime: "); - - str += lifetime.as_string(); - - str += "\nLifetime bounds: "; - - for (const auto& bound : lifetime_bounds) { - str += "\n " + bound.as_string(); - } - - return str; - } - - ::std::string TypeBoundWhereClauseItem::as_string() const { - ::std::string str("For lifetimes: "); - - if (!has_for_lifetimes()) { - str += "none"; - } else { - for (const auto& for_lifetime : for_lifetimes) { - str += "\n " + for_lifetime.as_string(); - } - } - - str += "\nType: " + bound_type->as_string(); - - str += "\nType param bounds bounds: "; - - for (const auto& bound : type_param_bounds) { - // debug null pointer check - if (bound == NULL) { - return "NULL_POINTER_MARK - type param bounds"; - } - - str += "\n " + bound->as_string(); - } - - return str; - } - - ::std::string ArrayElemsValues::as_string() const { - ::std::string str; - - for (const auto& expr : values) { - // DEBUG: null pointer check - if (expr == NULL) { - fprintf(stderr, "something really terrible has gone wrong - null pointer " - "expr in array elems values."); - return "NULL_POINTER_MARK"; - } - - str += "\n " + expr->as_string(); - } - - return str; - } - - ::std::string MaybeNamedParam::as_string() const { - ::std::string str; - - switch (param_kind) { - case UNNAMED: - break; - case IDENTIFIER: - str = name + " : "; - break; - case WILDCARD: - str = "_ : "; - break; - default: - return "ERROR_MARK_STRING - maybe named param unrecognised param kind"; - } - - str += param_type->as_string(); - - return str; - } - - ::std::string MetaItemSeq::as_string() const { - ::std::string path_str = path.as_string() + "("; - - for (const auto& item : seq) { - path_str += item->as_string() + ", "; - } - - return path_str + ")"; - } - - ::std::string MetaListPaths::as_string() const { - ::std::string str = ident + "("; - - for (const auto& path : paths) { - str += path.as_string() + ", "; - } - - return str + ")"; - } - - ::std::string MetaListNameValueStr::as_string() const { - ::std::string str = ident + "("; - - for (const auto& elem : strs) { - str += elem.as_string() + ", "; - } - - return str + ")"; - } - - ::std::string AttrInputMetaItemContainer::as_string() const { - ::std::string str = "("; - - for (const auto& item : items) { - str += item->as_string() + ", "; - } - - return str + ")"; - } - - // Override that calls the function recursively on all items contained within the module. - void ModuleBodied::add_crate_name(::std::vector< ::std::string>& names) const { - /* TODO: test whether module has been 'cfg'-ed out to determine whether to exclude it - * from search */ - - for (const auto& item : items) { - item->add_crate_name(names); - } - } - - void Attribute::parse_attr_to_meta_item() { - // only parse if has attribute input - if (!has_attr_input()) { - return; - } - - ::std::unique_ptr converted_input(attr_input->parse_to_meta_item()); - - if (converted_input != NULL) { - attr_input = ::std::move(converted_input); - } - } - - AttrInput* DelimTokenTree::parse_to_meta_item() const { - // must have token trees - if (token_trees.empty()) { - return NULL; - } - - // assume top-level delim token tree in attribute - convert all nested ones to token - // stream - ::std::vector< ::std::unique_ptr > token_stream = to_token_stream(); - - // TODO: replace this with a specialised converter that the token stream is moved into - /*int i = 0; - ::std::vector< ::std::unique_ptr > meta_items( - parse_meta_item_seq(token_stream, i));*/ - // something like: - MacroParser parser(::std::move(token_stream)); - ::std::vector< ::std::unique_ptr > meta_items( - parser.parse_meta_item_seq()); - - return new AttrInputMetaItemContainer(::std::move(meta_items)); - } - - ::std::unique_ptr MacroParser::parse_meta_item_inner() { - // if first tok not identifier, not a "special" case one - if (peek_token()->get_id() != IDENTIFIER) { - switch (peek_token()->get_id()) { - case CHAR_LITERAL: - case STRING_LITERAL: - case BYTE_CHAR_LITERAL: - case BYTE_STRING_LITERAL: - case INT_LITERAL: - case FLOAT_LITERAL: - case TRUE_LITERAL: - case FALSE_LITERAL: - // stream_pos++; - return parse_meta_item_lit(); - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { - return parse_path_meta_item(); - } - default: - error_at(peek_token()->get_locus(), "unrecognised token '%s' in meta item", - get_token_description(peek_token()->get_id())); - return NULL; - } - } - - // else, check for path - if (peek_token(1)->get_id() == SCOPE_RESOLUTION) { - // path - return parse_path_meta_item(); - } - - Identifier ident = peek_token()->as_string(); - if (is_end_meta_item_tok(peek_token(1)->get_id())) { - // meta word syntax - skip_token(); - return ::std::unique_ptr(new MetaWord(::std::move(ident))); - } - - if (peek_token(1)->get_id() == EQUAL) { - // maybe meta name value str syntax - check next 2 tokens - if (peek_token(2)->get_id() == STRING_LITERAL - && is_end_meta_item_tok(peek_token(3)->get_id())) { - // meta name value str syntax - ::std::string value = peek_token(2)->as_string(); - - skip_token(2); - - return ::std::unique_ptr( - new MetaNameValueStr(::std::move(ident), ::std::move(value))); - } else { - // just interpret as path-based meta item - return parse_path_meta_item(); - } - } - - if (peek_token(1)->get_id() != LEFT_PAREN) { - error_at(peek_token(1)->get_locus(), - "unexpected token '%s' after identifier in attribute", - get_token_description(peek_token(1)->get_id())); - return NULL; - } - - // HACK: parse parenthesised sequence, and then try conversions to other stuff - ::std::vector< ::std::unique_ptr > meta_items = parse_meta_item_seq(); - - // pass for meta name value str - ::std::vector meta_name_value_str_items; - for (const auto& item : meta_items) { - ::std::unique_ptr converted_item(item->to_meta_name_value_str()); - if (converted_item == NULL) { - meta_name_value_str_items.clear(); - break; - } - meta_name_value_str_items.push_back(::std::move(*converted_item)); - } - // if valid, return this - if (!meta_name_value_str_items.empty()) { - return ::std::unique_ptr(new MetaListNameValueStr( - ::std::move(ident), ::std::move(meta_name_value_str_items))); - } - - // pass for meta list idents - /*::std::vector ident_items; - for (const auto& item : meta_items) { - ::std::unique_ptr converted_ident(item->to_ident_item()); - if (converted_ident == NULL) { - ident_items.clear(); - break; - } - ident_items.push_back(::std::move(*converted_ident)); - } - // if valid return this - if (!ident_items.empty()) { - return ::std::unique_ptr(new MetaListIdents(::std::move(ident), - ::std::move(ident_items))); - }*/ - // as currently no meta list ident, currently no path. may change in future - - // pass for meta list paths - ::std::vector path_items; - for (const auto& item : meta_items) { - SimplePath converted_path(item->to_path_item()); - if (converted_path.is_empty()) { - path_items.clear(); - break; - } - path_items.push_back(::std::move(converted_path)); - } - if (!path_items.empty()) { - return ::std::unique_ptr( - new MetaListPaths(::std::move(ident), ::std::move(path_items))); - } - - error_at(UNKNOWN_LOCATION, "failed to parse any meta item inner"); - return NULL; - } - - bool MacroParser::is_end_meta_item_tok(TokenId id) const { - return id == COMMA || id == RIGHT_PAREN; - } - - ::std::unique_ptr MacroParser::parse_path_meta_item() { - SimplePath path = parse_simple_path(); - if (path.is_empty()) { - error_at(peek_token()->get_locus(), "failed to parse simple path in attribute"); - return NULL; - } - - switch (peek_token()->get_id()) { - case LEFT_PAREN: { - ::std::vector< ::std::unique_ptr > meta_items - = parse_meta_item_seq(); - - return ::std::unique_ptr( - new MetaItemSeq(::std::move(path), ::std::move(meta_items))); - } - case EQUAL: { - skip_token(); - - location_t locus = peek_token()->get_locus(); - Literal lit = parse_literal(); - if (lit.is_error()) { - error_at(peek_token()->get_locus(), "failed to parse literal in attribute"); - return NULL; - } - LiteralExpr expr(::std::move(lit), locus); - // stream_pos++; - // shouldn't be required anymore due to parsing literal actually skipping the - // token - return ::std::unique_ptr( - new MetaItemPathLit(::std::move(path), ::std::move(expr))); - } - case COMMA: - // just simple path - return ::std::unique_ptr(new MetaItemPath(::std::move(path))); - default: - error_at(peek_token()->get_locus(), "unrecognised token '%s' in meta item", - get_token_description(peek_token()->get_id())); - return NULL; - } - } - - // Parses a parenthesised sequence of meta item inners. Parentheses are required here. - ::std::vector< ::std::unique_ptr > MacroParser::parse_meta_item_seq() { - if (stream_pos != 0) { - // warning? - fprintf(stderr, "WARNING: stream pos for parse_meta_item_seq is not 0!\n"); - } - - // int i = 0; - int vec_length = token_stream.size(); - ::std::vector< ::std::unique_ptr > meta_items; - - if (peek_token()->get_id() != LEFT_PAREN) { - error_at(peek_token()->get_locus(), "missing left paren in delim token tree"); - return {}; - } - skip_token(); - - while (stream_pos < vec_length && peek_token()->get_id() != RIGHT_PAREN) { - ::std::unique_ptr inner = parse_meta_item_inner(); - if (inner == NULL) { - error_at( - peek_token()->get_locus(), "failed to parse inner meta item in attribute"); - return {}; - } - meta_items.push_back(::std::move(inner)); - - if (peek_token()->get_id() != COMMA) { - break; - } - skip_token(); - } - - if (peek_token()->get_id() != RIGHT_PAREN) { - error_at(peek_token()->get_locus(), "missing right paren in delim token tree"); - return {}; - } - skip_token(); - - return meta_items; - } - - // Collects any nested token trees into a flat token stream, suitable for parsing. - ::std::vector< ::std::unique_ptr > DelimTokenTree::to_token_stream() const { - ::std::vector< ::std::unique_ptr > tokens; - - // simulate presence of delimiters - tokens.push_back(::std::unique_ptr( - new Token(LEFT_PAREN, UNKNOWN_LOCATION, "", CORETYPE_UNKNOWN))); - - for (const auto& tree : token_trees) { - ::std::vector< ::std::unique_ptr > stream = tree->to_token_stream(); - - tokens.insert(tokens.end(), ::std::make_move_iterator(stream.begin()), - ::std::make_move_iterator(stream.end())); - } - - tokens.push_back(::std::unique_ptr( - new Token(RIGHT_PAREN, UNKNOWN_LOCATION, "", CORETYPE_UNKNOWN))); - - tokens.shrink_to_fit(); - - return tokens; - } - - Literal MacroParser::parse_literal() { - const ::std::unique_ptr& tok = peek_token(); - switch (tok->get_id()) { - case CHAR_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::CHAR); - case STRING_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::STRING); - case BYTE_CHAR_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::BYTE); - case BYTE_STRING_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::BYTE_STRING); - case INT_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::INT); - case FLOAT_LITERAL: - skip_token(); - return Literal(tok->as_string(), Literal::FLOAT); - case TRUE_LITERAL: - skip_token(); - return Literal("true", Literal::BOOL); - case FALSE_LITERAL: - skip_token(); - return Literal("false", Literal::BOOL); - default: - error_at(tok->get_locus(), "expected literal - found '%s'", - get_token_description(tok->get_id())); - return Literal::create_error(); - } - } - - SimplePath MacroParser::parse_simple_path() { - bool has_opening_scope_res = false; - if (peek_token()->get_id() == SCOPE_RESOLUTION) { - has_opening_scope_res = true; - skip_token(); - } - - ::std::vector segments; - - SimplePathSegment segment = parse_simple_path_segment(); - if (segment.is_error()) { - error_at(peek_token()->get_locus(), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty(); - } - segments.push_back(::std::move(segment)); - - while (peek_token()->get_id() == SCOPE_RESOLUTION) { - skip_token(); - - SimplePathSegment segment = parse_simple_path_segment(); - if (segment.is_error()) { - error_at(peek_token()->get_locus(), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty(); - } - segments.push_back(::std::move(segment)); - } - segments.shrink_to_fit(); - - return SimplePath(::std::move(segments), has_opening_scope_res); - } - - SimplePathSegment MacroParser::parse_simple_path_segment() { - const ::std::unique_ptr& tok = peek_token(); - switch (tok->get_id()) { - case IDENTIFIER: - skip_token(); - return SimplePathSegment(tok->as_string(), tok->get_locus()); - case SUPER: - skip_token(); - return SimplePathSegment("super", tok->get_locus()); - case SELF: - skip_token(); - return SimplePathSegment("self", tok->get_locus()); - case CRATE: - skip_token(); - return SimplePathSegment("crate", tok->get_locus()); - case DOLLAR_SIGN: - if (peek_token(1)->get_id() == CRATE) { - skip_token(1); - return SimplePathSegment("$crate", tok->get_locus()); - } - gcc_fallthrough(); - default: - error_at(tok->get_locus(), "unexpected token '%s' in simple path segment", - get_token_description(tok->get_id())); - return SimplePathSegment::create_error(); - } - } - - ::std::unique_ptr MacroParser::parse_meta_item_lit() { - location_t locus = peek_token()->get_locus(); - LiteralExpr lit_expr(parse_literal(), locus); - return ::std::unique_ptr(new MetaItemLitExpr(::std::move(lit_expr))); - } - - bool AttrInputMetaItemContainer::check_cfg_predicate(const Session& session) const { - // cfg value of container is purely based on cfg of each inner item - all must be true - for (const auto& inner_item : items) { - if (!inner_item->check_cfg_predicate(session)) { - return false; - } - } - - /* TODO: as far as I can tell, there should only be a single element to check here, so - * ensure there is only a single element in items too? */ - - return true; - } - - bool MetaItemLitExpr::check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const { - // as far as I can tell, a literal expr can never be a valid cfg body, so false - return false; - } - - bool MetaListNameValueStr::check_cfg_predicate(const Session& session) const { - if (ident == "all") { - for (const auto& str : strs) { - if (!str.check_cfg_predicate(session)) { - return false; - } - } - return true; - } else if (ident == "any") { - for (const auto& str : strs) { - if (str.check_cfg_predicate(session)) { - return true; - } - } - return false; - } else if (ident == "not") { - if (strs.size() != 1) { - // HACK: convert vector platform-dependent size_type to string to use in printf - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaListNameValueStr with ident of " - "'not' because there are '%s' elements, not '1'", - ::std::to_string(strs.size()).c_str()); - return false; - } - - return !strs[0].check_cfg_predicate(session); - } else { - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaListNameValueStr with ident of " - "'%s' - ident must be 'all' or 'any'", - ident.c_str()); - return false; - } - } - - bool MetaListPaths::check_cfg_predicate(const Session& session) const { - if (ident == "all") { - for (const auto& path : paths) { - if (!check_path_exists_in_cfg(session, path)) { - return false; - } - } - return true; - } else if (ident == "any") { - for (const auto& path : paths) { - if (check_path_exists_in_cfg(session, path)) { - return true; - } - } - return false; - } else if (ident == "not") { - if (paths.size() != 1) { - // HACK: convert vector platform-dependent size_type to string to use in printf - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaListPaths with ident of 'not' " - "because there are '%s' elements, not '1'", - ::std::to_string(paths.size()).c_str()); - return false; - } - - return !check_path_exists_in_cfg(session, paths[0]); - } else { - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaListNameValueStr with ident of " - "'%s' - ident must be 'all' or 'any'", - ident.c_str()); - return false; - } - } - - bool MetaListPaths::check_path_exists_in_cfg( - const Session& session, const SimplePath& path) const { - auto it = session.options.target_data.features.find(path.as_string()); - if (it != session.options.target_data.features.end()) { - return true; - } - return false; - } - - bool MetaItemSeq::check_cfg_predicate(const Session& session) const { - if (path.as_string() == "all") { - for (const auto& item : seq) { - if (!item->check_cfg_predicate(session)) { - return false; - } - } - return true; - } else if (path.as_string() == "any") { - for (const auto& item : seq) { - if (item->check_cfg_predicate(session)) { - return true; - } - } - return false; - } else if (path.as_string() == "not") { - if (seq.size() != 1) { - // HACK: convert vector platform-dependent size_type to string to use in printf - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaItemSeq with ident of 'not' " - "because there are '%s' elements, not '1'", - ::std::to_string(seq.size()).c_str()); - return false; - } - - return !seq[0]->check_cfg_predicate(session); - } else { - error_at(UNKNOWN_LOCATION, - "cfg predicate could not be checked for MetaItemSeq with path of " - "'%s' - path must be 'all' or 'any'", - path.as_string().c_str()); - return false; - } - } - - bool MetaWord::check_cfg_predicate(const Session& session) const { - auto it = session.options.target_data.features.find(ident); - if (it != session.options.target_data.features.end()) { - return true; - } - return false; - } - - bool MetaItemPath::check_cfg_predicate(const Session& session) const { - /* Strictly speaking, this should always be false, but maybe do check relating to - * SimplePath being identifier. Currently, it would return true if path as identifier - * existed, and if the path in string form existed (though this shouldn't occur). */ - auto it = session.options.target_data.features.find(path.as_string()); - if (it != session.options.target_data.features.end()) { - return true; - } - return false; - } - - bool MetaNameValueStr::check_cfg_predicate(const Session& session) const { - auto it = session.options.target_data.features.find(ident); - if (it != session.options.target_data.features.end()) { - // value must also be the same, not just the name existing - if (str == it->second) { - return true; - } - } - return false; - } - - bool MetaItemPathLit::check_cfg_predicate(const Session& session) const { - auto it = session.options.target_data.features.find(path.as_string()); - if (it != session.options.target_data.features.end()) { - // value must also be the same, not just the name existing - if (lit.as_string() == it->second) { - return true; - } - } - return false; - } - - ::std::vector< ::std::unique_ptr > Token::to_token_stream() const { - // initialisation list doesn't work as it needs copy constructor, so have to do this - ::std::vector< ::std::unique_ptr > dummy_vector; - dummy_vector.reserve(1); - dummy_vector.push_back(::std::unique_ptr(clone_token_impl())); - return dummy_vector; - } - - /* Visitor implementations - these are short but inlining can't happen anyway due to virtual - * functions and I didn't want to make the ast header includes any longer than they already - * are. */ - - void Token::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void DelimTokenTree::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IdentifierExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Lifetime::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LifetimeParam::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroInvocationSemi::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void PathInExpression::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypePathSegment::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypePathSegmentGeneric::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypePathSegmentFunction::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypePath::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void QualifiedPathInExpression::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void QualifiedPathInType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LiteralExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void AttrInputLiteral::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaItemLitExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaItemPathLit::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void BorrowExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void DereferenceExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ErrorPropagationExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void NegationExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArithmeticOrLogicalExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ComparisonExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LazyBooleanExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypeCastExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void AssignmentExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void CompoundAssignmentExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void GroupedExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArrayElemsValues::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArrayElemsCopied::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArrayExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArrayIndexExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleIndexExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprStruct::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprFieldIdentifier::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprFieldIdentifierValue::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprFieldIndexValue::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprStructFields::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprStructBase::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprTuple::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructExprUnit::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprFieldIdentifier::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprFieldIdentifierValue::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprFieldIndexValue::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprStruct::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprTuple::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumExprFieldless::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void CallExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MethodCallExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void FieldAccessExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ClosureExprInner::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void BlockExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ClosureExprInnerTyped::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ContinueExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void BreakExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeFromToExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeFromExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeToExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeFullExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeFromToInclExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangeToInclExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ReturnExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void UnsafeBlockExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LoopExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void WhileLoopExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void WhileLetLoopExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ForLoopExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfExprConseqElse::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfExprConseqIf::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfExprConseqIfLet::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfLetExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfLetExprConseqElse::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfLetExprConseqIf::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IfLetExprConseqIfLet::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MatchCaseBlockExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MatchCaseExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MatchExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void AwaitExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void AsyncBlockExpr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypeParam::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LifetimeWhereClauseItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypeBoundWhereClauseItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Method::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ModuleBodied::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ModuleNoBody::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExternCrate::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void UseTreeGlob::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void UseTreeList::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void UseTreeRebind::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void UseDeclaration::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Function::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TypeAlias::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructStruct::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleStruct::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumItemTuple::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumItemStruct::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EnumItemDiscriminant::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Enum::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Union::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ConstantItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StaticItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitItemFunc::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitItemMethod::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitItemConst::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitItemType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void Trait::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void InherentImpl::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitImpl::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExternalStaticItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExternalFunctionItem::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExternBlock::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroMatchFragment::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroMatchRepetition::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroMatcher::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroRulesDefinition::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MacroInvocation::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LiteralPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void IdentifierPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void WildcardPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangePatternBoundLiteral::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangePatternBoundPath::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangePatternBoundQualPath::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RangePattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ReferencePattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructPatternFieldTuplePat::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructPatternFieldIdentPat::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructPatternFieldIdent::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void StructPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleStructItemsNoRange::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleStructItemsRange::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleStructPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TuplePatternItemsMultiple::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TuplePatternItemsRanged::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TuplePattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void GroupedPattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void SlicePattern::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void EmptyStmt::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void LetStmt::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExprStmtWithoutBlock::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ExprStmtWithBlock::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitBound::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ImplTraitType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitObjectType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ParenthesisedType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ImplTraitTypeOneBound::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TraitObjectTypeOneBound::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void TupleType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void NeverType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void RawPointerType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ReferenceType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void ArrayType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void SliceType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void InferredType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void BareFunctionType::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaItemSeq::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaItemPath::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaListPaths::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaNameValueStr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaListNameValueStr::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void AttrInputMetaItemContainer::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - - void MetaWord::accept_vis(ASTVisitor& vis) { - vis.visit(*this); - } - } -} \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast-full.h b/gcc/rust/test3/ast/rust-ast-full.h deleted file mode 100644 index 5378236..0000000 --- a/gcc/rust/test3/ast/rust-ast-full.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef RUST_AST_FULL_H -#define RUST_AST_FULL_H -// Use as a fast way of including all aspects of the AST (i.e. all headers) -#include "rust-ast.h" -#include "rust-expr.h" -#include "rust-item.h" -#include "rust-path.h" -#include "rust-pattern.h" -#include "rust-stmt.h" -#include "rust-type.h" -#include "rust-macro.h" - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast-visitor.h b/gcc/rust/test3/ast/rust-ast-visitor.h deleted file mode 100644 index b8e92c2..0000000 --- a/gcc/rust/test3/ast/rust-ast-visitor.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef RUST_AST_VISITOR_H -#define RUST_AST_VISITOR_H -// Visitor base for AST - -// full include not required - only forward decls -#include "rust-ast-full-decls.h" - -namespace Rust { - namespace AST { - // Pure abstract class that provides an interface for accessing different classes of the AST. - class ASTVisitor { - public: - // only concrete class overloads are required - - // rust-ast.h - //virtual void visit(AttrInput& attr_input) = 0; - //virtual void visit(TokenTree& token_tree) = 0; - //virtual void visit(MacroMatch& macro_match) = 0; - virtual void visit(Token& tok) = 0; - virtual void visit(DelimTokenTree& delim_tok_tree) = 0; - virtual void visit(AttrInputMetaItemContainer& input) = 0; - //virtual void visit(MetaItem& meta_item) = 0; - //virtual void visit(Stmt& stmt) = 0; - //virtual void visit(Expr& expr) = 0; - virtual void visit(IdentifierExpr& ident_expr) = 0; - //virtual void visit(Pattern& pattern) = 0; - //virtual void visit(Type& type) = 0; - //virtual void visit(TypeParamBound& type_param_bound) = 0; - virtual void visit(Lifetime& lifetime) = 0; - //virtual void visit(GenericParam& generic_param) = 0; - virtual void visit(LifetimeParam& lifetime_param) = 0; - //virtual void visit(TraitItem& trait_item) = 0; - //virtual void visit(InherentImplItem& inherent_impl_item) = 0; - //virtual void visit(TraitImplItem& trait_impl_item) = 0; - virtual void visit(MacroInvocationSemi& macro) = 0; - - // rust-path.h - virtual void visit(PathInExpression& path) = 0; - virtual void visit(TypePathSegment& segment) = 0; - virtual void visit(TypePathSegmentGeneric& segment) = 0; - virtual void visit(TypePathSegmentFunction& segment) = 0; - virtual void visit(TypePath& path) = 0; - virtual void visit(QualifiedPathInExpression& path) = 0; - virtual void visit(QualifiedPathInType& path) = 0; - - // rust-expr.h - virtual void visit(LiteralExpr& expr) = 0; - virtual void visit(AttrInputLiteral& attr_input) = 0; - virtual void visit(MetaItemLitExpr& meta_item) = 0; - virtual void visit(MetaItemPathLit& meta_item) = 0; - virtual void visit(BorrowExpr& expr) = 0; - virtual void visit(DereferenceExpr& expr) = 0; - virtual void visit(ErrorPropagationExpr& expr) = 0; - virtual void visit(NegationExpr& expr) = 0; - virtual void visit(ArithmeticOrLogicalExpr& expr) = 0; - virtual void visit(ComparisonExpr& expr) = 0; - virtual void visit(LazyBooleanExpr& expr) = 0; - virtual void visit(TypeCastExpr& expr) = 0; - virtual void visit(AssignmentExpr& expr) = 0; - virtual void visit(CompoundAssignmentExpr& expr) = 0; - virtual void visit(GroupedExpr& expr) = 0; - //virtual void visit(ArrayElems& elems) = 0; - virtual void visit(ArrayElemsValues& elems) = 0; - virtual void visit(ArrayElemsCopied& elems) = 0; - virtual void visit(ArrayExpr& expr) = 0; - virtual void visit(ArrayIndexExpr& expr) = 0; - virtual void visit(TupleExpr& expr) = 0; - virtual void visit(TupleIndexExpr& expr) = 0; - virtual void visit(StructExprStruct& expr) = 0; - //virtual void visit(StructExprField& field) = 0; - virtual void visit(StructExprFieldIdentifier& field) = 0; - virtual void visit(StructExprFieldIdentifierValue& field) = 0; - virtual void visit(StructExprFieldIndexValue& field) = 0; - virtual void visit(StructExprStructFields& expr) = 0; - virtual void visit(StructExprStructBase& expr) = 0; - virtual void visit(StructExprTuple& expr) = 0; - virtual void visit(StructExprUnit& expr) = 0; - //virtual void visit(EnumExprField& field) = 0; - virtual void visit(EnumExprFieldIdentifier& field) = 0; - virtual void visit(EnumExprFieldIdentifierValue& field) = 0; - virtual void visit(EnumExprFieldIndexValue& field) = 0; - virtual void visit(EnumExprStruct& expr) = 0; - virtual void visit(EnumExprTuple& expr) = 0; - virtual void visit(EnumExprFieldless& expr) = 0; - virtual void visit(CallExpr& expr) = 0; - virtual void visit(MethodCallExpr& expr) = 0; - virtual void visit(FieldAccessExpr& expr) = 0; - virtual void visit(ClosureExprInner& expr) = 0; - virtual void visit(BlockExpr& expr) = 0; - virtual void visit(ClosureExprInnerTyped& expr) = 0; - virtual void visit(ContinueExpr& expr) = 0; - virtual void visit(BreakExpr& expr) = 0; - virtual void visit(RangeFromToExpr& expr) = 0; - virtual void visit(RangeFromExpr& expr) = 0; - virtual void visit(RangeToExpr& expr) = 0; - virtual void visit(RangeFullExpr& expr) = 0; - virtual void visit(RangeFromToInclExpr& expr) = 0; - virtual void visit(RangeToInclExpr& expr) = 0; - virtual void visit(ReturnExpr& expr) = 0; - virtual void visit(UnsafeBlockExpr& expr) = 0; - virtual void visit(LoopExpr& expr) = 0; - virtual void visit(WhileLoopExpr& expr) = 0; - virtual void visit(WhileLetLoopExpr& expr) = 0; - virtual void visit(ForLoopExpr& expr) = 0; - virtual void visit(IfExpr& expr) = 0; - virtual void visit(IfExprConseqElse& expr) = 0; - virtual void visit(IfExprConseqIf& expr) = 0; - virtual void visit(IfExprConseqIfLet& expr) = 0; - virtual void visit(IfLetExpr& expr) = 0; - virtual void visit(IfLetExprConseqElse& expr) = 0; - virtual void visit(IfLetExprConseqIf& expr) = 0; - virtual void visit(IfLetExprConseqIfLet& expr) = 0; - //virtual void visit(MatchCase& match_case) = 0; - virtual void visit(MatchCaseBlockExpr& match_case) = 0; - virtual void visit(MatchCaseExpr& match_case) = 0; - virtual void visit(MatchExpr& expr) = 0; - virtual void visit(AwaitExpr& expr) = 0; - virtual void visit(AsyncBlockExpr& expr) = 0; - - // rust-item.h - virtual void visit(TypeParam& param) = 0; - //virtual void visit(WhereClauseItem& item) = 0; - virtual void visit(LifetimeWhereClauseItem& item) = 0; - virtual void visit(TypeBoundWhereClauseItem& item) = 0; - virtual void visit(Method& method) = 0; - virtual void visit(ModuleBodied& module) = 0; - virtual void visit(ModuleNoBody& module) = 0; - virtual void visit(ExternCrate& crate) = 0; - //virtual void visit(UseTree& use_tree) = 0; - virtual void visit(UseTreeGlob& use_tree) = 0; - virtual void visit(UseTreeList& use_tree) = 0; - virtual void visit(UseTreeRebind& use_tree) = 0; - virtual void visit(UseDeclaration& use_decl) = 0; - virtual void visit(Function& function) = 0; - virtual void visit(TypeAlias& type_alias) = 0; - virtual void visit(StructStruct& struct_item) = 0; - virtual void visit(TupleStruct& tuple_struct) = 0; - virtual void visit(EnumItem& item) = 0; - virtual void visit(EnumItemTuple& item) = 0; - virtual void visit(EnumItemStruct& item) = 0; - virtual void visit(EnumItemDiscriminant& item) = 0; - virtual void visit(Enum& enum_item) = 0; - virtual void visit(Union& union_item) = 0; - virtual void visit(ConstantItem& const_item) = 0; - virtual void visit(StaticItem& static_item) = 0; - virtual void visit(TraitItemFunc& item) = 0; - virtual void visit(TraitItemMethod& item) = 0; - virtual void visit(TraitItemConst& item) = 0; - virtual void visit(TraitItemType& item) = 0; - virtual void visit(Trait& trait) = 0; - virtual void visit(InherentImpl& impl) = 0; - virtual void visit(TraitImpl& impl) = 0; - //virtual void visit(ExternalItem& item) = 0; - virtual void visit(ExternalStaticItem& item) = 0; - virtual void visit(ExternalFunctionItem& item) = 0; - virtual void visit(ExternBlock& block) = 0; - - // rust-macro.h - virtual void visit(MacroMatchFragment& match) = 0; - virtual void visit(MacroMatchRepetition& match) = 0; - virtual void visit(MacroMatcher& matcher) = 0; - virtual void visit(MacroRulesDefinition& rules_def) = 0; - virtual void visit(MacroInvocation& macro_invoc) = 0; - virtual void visit(MetaItemPath& meta_item) = 0; - virtual void visit(MetaItemSeq& meta_item) = 0; - virtual void visit(MetaWord& meta_item) = 0; - virtual void visit(MetaNameValueStr& meta_item) = 0; - virtual void visit(MetaListPaths& meta_item) = 0; - virtual void visit(MetaListNameValueStr& meta_item) = 0; - - // rust-pattern.h - virtual void visit(LiteralPattern& pattern) = 0; - virtual void visit(IdentifierPattern& pattern) = 0; - virtual void visit(WildcardPattern& pattern) = 0; - //virtual void visit(RangePatternBound& bound) = 0; - virtual void visit(RangePatternBoundLiteral& bound) = 0; - virtual void visit(RangePatternBoundPath& bound) = 0; - virtual void visit(RangePatternBoundQualPath& bound) = 0; - virtual void visit(RangePattern& pattern) = 0; - virtual void visit(ReferencePattern& pattern) = 0; - //virtual void visit(StructPatternField& field) = 0; - virtual void visit(StructPatternFieldTuplePat& field) = 0; - virtual void visit(StructPatternFieldIdentPat& field) = 0; - virtual void visit(StructPatternFieldIdent& field) = 0; - virtual void visit(StructPattern& pattern) = 0; - //virtual void visit(TupleStructItems& tuple_items) = 0; - virtual void visit(TupleStructItemsNoRange& tuple_items) = 0; - virtual void visit(TupleStructItemsRange& tuple_items) = 0; - virtual void visit(TupleStructPattern& pattern) = 0; - //virtual void visit(TuplePatternItems& tuple_items) = 0; - virtual void visit(TuplePatternItemsMultiple& tuple_items) = 0; - virtual void visit(TuplePatternItemsRanged& tuple_items) = 0; - virtual void visit(TuplePattern& pattern) = 0; - virtual void visit(GroupedPattern& pattern) = 0; - virtual void visit(SlicePattern& pattern) = 0; - - // rust-stmt.h - virtual void visit(EmptyStmt& stmt) = 0; - virtual void visit(LetStmt& stmt) = 0; - virtual void visit(ExprStmtWithoutBlock& stmt) = 0; - virtual void visit(ExprStmtWithBlock& stmt) = 0; - - // rust-type.h - virtual void visit(TraitBound& bound) = 0; - virtual void visit(ImplTraitType& type) = 0; - virtual void visit(TraitObjectType& type) = 0; - virtual void visit(ParenthesisedType& type) = 0; - virtual void visit(ImplTraitTypeOneBound& type) = 0; - virtual void visit(TraitObjectTypeOneBound& type) = 0; - virtual void visit(TupleType& type) = 0; - virtual void visit(NeverType& type) = 0; - virtual void visit(RawPointerType& type) = 0; - virtual void visit(ReferenceType& type) = 0; - virtual void visit(ArrayType& type) = 0; - virtual void visit(SliceType& type) = 0; - virtual void visit(InferredType& type) = 0; - virtual void visit(BareFunctionType& type) = 0; - - // TODO: rust-cond-compilation.h visiting? not currently used - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-ast.h b/gcc/rust/test3/ast/rust-ast.h deleted file mode 100644 index fb0cd23..0000000 --- a/gcc/rust/test3/ast/rust-ast.h +++ /dev/null @@ -1,1376 +0,0 @@ -#ifndef RUST_AST_BASE_H -#define RUST_AST_BASE_H -// Base for AST used in gccrs, basically required by all specific ast things - -// GCC imports -#include "config.h" -//#define INCLUDE_UNIQUE_PTR -// should allow including the gcc emulation of std::unique_ptr -#include "system.h" -#include "coretypes.h" // order: config, INCLUDE, system, coretypes - -// STL imports -#include -#include -// with C++11, now can use actual std::unique_ptr -#include - -// gccrs imports -// required for AST::Token -#include "rust-token.h" - -namespace Rust { - // TODO: remove typedefs and make actual types for these - // typedef int location_t; - // typedef ::std::string SimplePath; - typedef ::std::string Identifier; - typedef int TupleIndex; - - struct Session; - - namespace AST { - // foward decl: ast visitor - class ASTVisitor; - - // Delimiter types - used in macros and whatever. - enum DelimType { PARENS, SQUARE, CURLY }; - - // Base AST node object - TODO is this really required or useful? Where to draw line? - /*class Node { - public: - // Gets node's location_t. - location_t get_locus() const { - return loc; - } - - // Sets node's location_t. - void set_locus(location_t loc_) { - loc = loc_; - } - - // Get node output as a string. Pure virtual. - virtual ::std::string as_string() const = 0; - - virtual ~Node() {} - - // TODO: constructor including location_t? Make all derived classes have location_t? - - private: - // The node's location. - location_t loc; - };*/ - // decided to not have node as a "node" would never need to be stored - - // Attribute body - abstract base class - class AttrInput { - public: - virtual ~AttrInput() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_attr_input() const { - return ::std::unique_ptr(clone_attr_input_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - virtual bool check_cfg_predicate(const Session& session) const = 0; - - // Parse attribute input to meta item, if possible - virtual AttrInput* parse_to_meta_item() const { - return NULL; - } - - protected: - // pure virtual clone implementation - virtual AttrInput* clone_attr_input_impl() const = 0; - }; - - // forward decl for use in token tree method - class Token; - - // A tree of tokens (or a single token) - abstract base class - class TokenTree { - public: - virtual ~TokenTree() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_token_tree() const { - return ::std::unique_ptr(clone_token_tree_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - /* Converts token tree to a flat token stream. Tokens must be pointer to avoid mutual - * dependency with Token. */ - virtual ::std::vector< ::std::unique_ptr > to_token_stream() const = 0; - - protected: - // pure virtual clone implementation - virtual TokenTree* clone_token_tree_impl() const = 0; - }; - - // Abstract base class for a macro match - class MacroMatch { - public: - virtual ~MacroMatch() {} - - virtual ::std::string as_string() const = 0; - - // Unique pointer custom clone function - ::std::unique_ptr clone_macro_match() const { - return ::std::unique_ptr(clone_macro_match_impl()); - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual MacroMatch* clone_macro_match_impl() const = 0; - }; - - // A token is a kind of token tree (except delimiter tokens) - class Token - : public TokenTree - , public MacroMatch { - // A token is a kind of token tree (except delimiter tokens) - // A token is a kind of MacroMatch (except $ and delimiter tokens) - // TODO: improve member variables - current ones are the same as lexer token - // Token kind. - TokenId token_id; - // Token location. - location_t locus; - // Associated text (if any) of token. - std::string str; - // Token type hint (if any). - PrimitiveCoreType type_hint; - - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_token() const { - return ::std::unique_ptr(clone_token_impl()); - } - - // constructor from general text - avoid using if lexer const_TokenPtr is available - Token( - TokenId token_id, location_t locus, ::std::string str, PrimitiveCoreType type_hint) : - token_id(token_id), - locus(locus), str(::std::move(str)), type_hint(type_hint) {} - - // Constructor from lexer const_TokenPtr - /* TODO: find workaround for std::string being NULL - probably have to introduce new - * method in lexer Token, or maybe make conversion method there*/ - Token(const_TokenPtr lexer_token_ptr) : - token_id(lexer_token_ptr->get_id()), locus(lexer_token_ptr->get_locus()), str(""), - type_hint(lexer_token_ptr->get_type_hint()) { - // FIXME: change to "should have str" later? - if (lexer_token_ptr->has_str()) { - str = lexer_token_ptr->get_str(); - - // DEBUG - fprintf(stderr, "ast token created with str '%s'\n", str.c_str()); - } else { - // FIXME: is this returning correct thing? - str = lexer_token_ptr->get_token_description(); - - // DEBUG - fprintf(stderr, "ast token created with string '%s'\n", str.c_str()); - } - - // DEBUG - if (lexer_token_ptr->should_have_str() && !lexer_token_ptr->has_str()) { - fprintf(stderr, "BAD: for token '%s', should have string but does not!\n", - lexer_token_ptr->get_token_description()); - } - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // Return copy of itself but in token stream form. - virtual ::std::vector< ::std::unique_ptr > to_token_stream() const OVERRIDE; - - TokenId get_id() const { - return token_id; - } - - location_t get_locus() const { - return locus; - } - - protected: - // No virtual for now as not polymorphic but can be in future - /*virtual*/ Token* clone_token_impl() const { - return new Token(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Token* clone_token_tree_impl() const OVERRIDE { - return new Token(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Token* clone_macro_match_impl() const OVERRIDE { - return new Token(*this); - } - }; - - // A literal - value with a type. Used in LiteralExpr and LiteralPattern. - struct Literal { - public: - enum LitType { - CHAR, - STRING, - RAW_STRING, - BYTE, - BYTE_STRING, - RAW_BYTE_STRING, - INT, - FLOAT, - BOOL - }; - - private: - // TODO: maybe make subclasses of each type of literal with their typed values (or - // generics) - ::std::string value_as_string; - LitType type; - - public: - ::std::string as_string() const { - return value_as_string; - } - - inline LitType get_lit_type() const { - return type; - } - - Literal(::std::string value_as_string, LitType type) : - value_as_string(::std::move(value_as_string)), type(type) {} - - static Literal create_error() { - return Literal("", CHAR); - } - - // Returns whether literal is in an invalid state. - bool is_error() const { - return value_as_string == ""; - } - }; - - // A token tree with delimiters - class DelimTokenTree - : public TokenTree - , public AttrInput { - DelimType delim_type; - ::std::vector< ::std::unique_ptr > token_trees; - - location_t locus; - - // TODO: move all the "parse" functions into a separate class that has the token stream - // reference - will be cleaner Parse a meta item inner. - //::std::unique_ptr parse_meta_item_inner(const ::std::vector< - //::std::unique_ptr >& token_stream, int& i) const; SimplePath - // parse_simple_path(const ::std::vector< ::std::unique_ptr >& token_stream, int& i) - // const; SimplePathSegment parse_simple_path_segment(const ::std::vector< - // ::std::unique_ptr >& token_stream, int& i) const; - //::std::unique_ptr parse_meta_item_lit(const ::std::unique_ptr& - //tok) const; - //::std::vector< ::std::unique_ptr > parse_meta_item_seq(const - //::std::vector< ::std::unique_ptr >& token_stream, int& i) const; Literal - // parse_literal(const ::std::unique_ptr& tok) const; - //::std::unique_ptr parse_path_meta_item(const ::std::vector< - //::std::unique_ptr >& token_stream, int& i) const; bool - // is_end_meta_item_tok(TokenId tok) const; - - protected: - // Use covariance to implement clone function as returning a DelimTokenTree object - virtual DelimTokenTree* clone_attr_input_impl() const OVERRIDE { - return new DelimTokenTree(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual DelimTokenTree* clone_token_tree_impl() const OVERRIDE { - return new DelimTokenTree(*this); - } - - public: - DelimTokenTree(DelimType delim_type, - ::std::vector< ::std::unique_ptr > token_trees - = ::std::vector< ::std::unique_ptr >(), - location_t locus = UNKNOWN_LOCATION) : - delim_type(delim_type), - token_trees(::std::move(token_trees)), locus(locus) {} - - // Copy constructor with vector clone - DelimTokenTree(DelimTokenTree const& other) : - delim_type(other.delim_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - } - - // overloaded assignment operator with vector clone - DelimTokenTree& operator=(DelimTokenTree const& other) { - delim_type = other.delim_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - - return *this; - } - - // move constructors - DelimTokenTree(DelimTokenTree&& other) = default; - DelimTokenTree& operator=(DelimTokenTree&& other) = default; - - static DelimTokenTree create_empty() { - return DelimTokenTree(PARENS); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { - // this should never be called - should be converted first - return false; - } - - virtual AttrInput* parse_to_meta_item() const OVERRIDE; - - virtual ::std::vector< ::std::unique_ptr > to_token_stream() const OVERRIDE; - }; - - // Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to be defined - class AttrInputLiteral; - - // TODO: move applicable stuff into here or just don't include it because nothing uses it - // A segment of a path (maybe) - class PathSegment { - public: - virtual ~PathSegment() {} - - virtual ::std::string as_string() const = 0; - - // TODO: add visitor here? - }; - - // A segment of a simple path without generic or type arguments - class SimplePathSegment : public PathSegment { - ::std::string segment_name; - location_t locus; - - // only allow identifiers, "super", "self", "crate", or "$crate" - public: - // TODO: put checks in constructor to enforce this rule? - SimplePathSegment(::std::string segment_name, location_t locus = UNKNOWN_LOCATION) : - segment_name(::std::move(segment_name)), locus(locus) {} - - // Returns whether simple path segment is in an invalid state (currently, if empty). - inline bool is_error() const { - return segment_name.empty(); - } - - // Creates an error SimplePathSegment - static SimplePathSegment create_error() { - return SimplePathSegment(::std::string("")); - } - - ::std::string as_string() const; - - inline location_t get_locus() const { - return locus; - } - - // TODO: visitor pattern? - }; - - // A simple path without generic or type arguments - class SimplePath { - bool has_opening_scope_resolution; - ::std::vector segments; - location_t locus; - - public: - // Constructor - SimplePath(::std::vector path_segments, - bool has_opening_scope_resolution = false, location_t locus = UNKNOWN_LOCATION) : - has_opening_scope_resolution(has_opening_scope_resolution), - segments(::std::move(path_segments)), locus(locus) {} - - // Creates an empty SimplePath. - static SimplePath create_empty() { - return SimplePath(::std::vector()); - } - - // Returns whether the SimplePath is empty, i.e. has path segments. - inline bool is_empty() const { - return segments.empty(); - } - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - // does this need visitor if not polymorphic? probably not - - // path-to-string comparison operator - bool operator==(const ::std::string& rhs) { - return !has_opening_scope_resolution && segments.size() == 1 - && segments[0].as_string() == rhs; - } - - /* Creates a single-segment SimplePath from a string. This will not check to ensure that - * this is a valid identifier in path, so be careful. Also, this will have no location - * data. - * TODO have checks? */ - static SimplePath from_str(::std::string str) { - ::std::vector single_segments - = { AST::SimplePathSegment(::std::move(str)) }; - return SimplePath(::std::move(single_segments)); - } - }; - - // aka Attr - // Attribute AST representation - struct Attribute { - private: - SimplePath path; - - // bool has_attr_input; - // AttrInput* attr_input; - ::std::unique_ptr attr_input; - - location_t locus; - - // TODO: maybe a variable storing whether attr input is parsed or not - - public: - // Returns whether Attribute has AttrInput - inline bool has_attr_input() const { - return attr_input != NULL; - } - - // Constructor has pointer AttrInput for polymorphism reasons - Attribute(SimplePath path, ::std::unique_ptr input, - location_t locus = UNKNOWN_LOCATION) : - path(::std::move(path)), - attr_input(::std::move(input)), locus(locus) {} - - // Copy constructor must deep copy attr_input as unique pointer - Attribute(Attribute const& other) : path(other.path), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.attr_input != NULL) { - attr_input = other.attr_input->clone_attr_input(); - } - } - - // default destructor - ~Attribute() = default; - - // overload assignment operator to use custom clone method - Attribute& operator=(Attribute const& other) { - path = other.path; - locus = other.locus; - // guard to protect from null pointer dereference - if (other.attr_input != NULL) { - attr_input = other.attr_input->clone_attr_input(); - } - - return *this; - } - - // default move semantics - Attribute(Attribute&& other) = default; - Attribute& operator=(Attribute&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr clone_attribute() const { - return ::std::unique_ptr(clone_attribute_impl()); - } - - /*~Attribute() { - delete attr_input; - }*/ - - // Creates an empty attribute (which is invalid) - static Attribute create_empty() { - return Attribute(SimplePath::create_empty(), NULL); - } - - // Returns whether the attribute is considered an "empty" attribute. - inline bool is_empty() const { - return attr_input == NULL && path.is_empty(); - } - - /* e.g.: - #![crate_type = "lib"] - #[test] - #[cfg(target_os = "linux")] - #[allow(non_camel_case_types)] - #![allow(unused_variables)] - */ - - // Full built-in attribute list: - /* cfg - * cfg_attr - * test - * ignore - * should_panic - * derive - * macro_export - * macro_use - * proc_macro - * proc_macro_derive - * proc_macro_attribute - * allow - * warn - * deny - * forbid - * deprecated - * must_use - * link - * link_name - * no_link - * repr - * crate_type - * no_main - * export_name - * link_section - * no_mangle - * used - * crate_name - * inline - * cold - * no_builtins - * target_feature - * doc - * no_std - * no_implicit_prelude - * path - * recursion_limit - * type_length_limit - * panic_handler - * global_allocator - * windows_subsystem - * feature */ - - ::std::string as_string() const; - - // TODO: does this require visitor pattern as not polymorphic? - - // Maybe change to const-reference in future - SimplePath get_path() const { - return path; - } - - // Call to parse attribute body to meta item syntax. - void parse_attr_to_meta_item(); - - // Determines whether cfg predicate is true and item with attribute should not be - // stripped. - bool check_cfg_predicate(const Session& session) { - // assume that cfg predicate actually can exist, i.e. attribute has cfg or cfg_attr - // path - - if (!has_attr_input()) { - return false; - } - - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item(); - // can't be const because of this anyway - - return attr_input->check_cfg_predicate(session); - } - - protected: - // not virtual as currently no subclasses of Attribute, but could be in future - /*virtual*/ Attribute* clone_attribute_impl() const { - return new Attribute(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MetaNameValueStr; - - // abstract base meta item inner class - class MetaItemInner { - protected: - // pure virtual as MetaItemInner - virtual MetaItemInner* clone_meta_item_inner_impl() const = 0; - - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_meta_item_inner() const { - return ::std::unique_ptr(clone_meta_item_inner_impl()); - } - - virtual ~MetaItemInner() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - // HACK: used to simplify parsing - creates a copy of that type, or returns null - virtual MetaNameValueStr* to_meta_name_value_str() const { - return NULL; - } - - // HACK: used to simplify parsing - same thing - virtual SimplePath to_path_item() const { - return SimplePath::create_empty(); - } - - virtual bool check_cfg_predicate(const Session& session) const = 0; - }; - - // Container used to store MetaItems as AttrInput (bridge-ish kinda thing) - class AttrInputMetaItemContainer : public AttrInput { - ::std::vector< ::std::unique_ptr > items; - - public: - AttrInputMetaItemContainer(::std::vector< ::std::unique_ptr > items) : - items(::std::move(items)) {} - - // copy constructor with vector clone - AttrInputMetaItemContainer(const AttrInputMetaItemContainer& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_meta_item_inner()); - } - } - - // no destructor definition required - - // copy assignment operator with vector clone - AttrInputMetaItemContainer& operator=(const AttrInputMetaItemContainer& other) { - AttrInput::operator=(other); - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_meta_item_inner()); - } - - return *this; - } - - // default move constructors - AttrInputMetaItemContainer(AttrInputMetaItemContainer&& other) = default; - AttrInputMetaItemContainer& operator=(AttrInputMetaItemContainer&& other) = default; - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual AttrInputMetaItemContainer* clone_attr_input_impl() const OVERRIDE { - return new AttrInputMetaItemContainer(*this); - } - }; - - // abstract base meta item class - class MetaItem : public MetaItemInner {}; - - // Forward decl - defined in rust-expr.h - class MetaItemLitExpr; - - // Forward decl - defined in rust-expr.h - class MetaItemPathLit; - - // Forward decl - defined in rust-macro.h - class MetaItemPath; - - // Forward decl - defined in rust-macro.h - class MetaItemSeq; - - // Forward decl - defined in rust-macro.h - class MetaWord; - - // Forward decl - defined in rust-macro.h - class MetaListPaths; - - // Forward decl - defined in rust-macro.h - struct MetaListNameValueStr; - - /* Base statement abstract class. Note that most "statements" are not allowed in top-level - * module scope - only a subclass of statements called "items" are. */ - class Stmt { - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_stmt() const { - return ::std::unique_ptr(clone_stmt_impl()); - } - - virtual ~Stmt() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual Stmt* clone_stmt_impl() const = 0; - }; - - // Rust "item" AST node (declaration of top-level/module-level allowed stuff) - class Item : public Stmt { - ::std::vector outer_attrs; - - // TODO: should outer attrs be defined here or in each derived class? - - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_item() const { - return ::std::unique_ptr(clone_item_impl()); - } - - ::std::string as_string() const; - - // Adds crate names to the vector passed by reference, if it can (polymorphism). - virtual void add_crate_name(::std::vector< ::std::string>& names ATTRIBUTE_UNUSED) const { - } - - protected: - // Constructor - Item(::std::vector outer_attribs = ::std::vector()) : - outer_attrs(::std::move(outer_attribs)) {} - - // Clone function implementation as pure virtual method - virtual Item* clone_item_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making statement clone - * return item clone. Hopefully won't affect performance too much. */ - virtual Item* clone_stmt_impl() const OVERRIDE { - return clone_item_impl(); - } - }; - - // forward decl of ExprWithoutBlock - class ExprWithoutBlock; - - // Base expression AST node - abstract - class Expr { - // TODO: move outer attribute data to derived classes? - ::std::vector outer_attrs; - - public: - inline const ::std::vector& get_outer_attrs() const { - return outer_attrs; - } - - // Unique pointer custom clone function - ::std::unique_ptr clone_expr() const { - return ::std::unique_ptr(clone_expr_impl()); - } - - /* TODO: public methods that could be useful: - * - get_type() - returns type of expression. set_type() may also be useful for some? - * - evaluate() - evaluates expression if constant? can_evaluate()? */ - - // HACK: downcasting without dynamic_cast (if possible) via polymorphism - overrided in - // subclasses of ExprWithoutBlock - virtual ExprWithoutBlock* as_expr_without_block() const { - // DEBUG - fprintf(stderr, "clone expr without block returns null and has not been overriden\n"); - - return NULL; - } - - // TODO: make pure virtual if move out outer attributes to derived classes - virtual ::std::string as_string() const; - - virtual ~Expr() {} - - // HACK: slow way of getting location from base expression through virtual methods. - virtual location_t get_locus_slow() const { - return UNKNOWN_LOCATION; - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Constructor - Expr(::std::vector outer_attribs = ::std::vector()) : - outer_attrs(::std::move(outer_attribs)) {} - - // Clone function implementation as pure virtual method - virtual Expr* clone_expr_impl() const = 0; - - // TODO: think of less hacky way to implement this kind of thing - // Sets outer attributes. - void set_outer_attrs(::std::vector outer_attrs_to_set) { - outer_attrs = ::std::move(outer_attrs_to_set); - } - }; - - // AST node for an expression without an accompanying block - abstract - class ExprWithoutBlock : public Expr { - protected: - // Constructor - ExprWithoutBlock(::std::vector outer_attribs = ::std::vector()) : - Expr(::std::move(outer_attribs)) {} - - // pure virtual clone implementation - virtual ExprWithoutBlock* clone_expr_without_block_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making expr clone - * return exprwithoutblock clone. Hopefully won't affect performance too much. */ - virtual ExprWithoutBlock* clone_expr_impl() const OVERRIDE { - return clone_expr_without_block_impl(); - } - - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_expr_without_block() const { - return ::std::unique_ptr(clone_expr_without_block_impl()); - } - - // downcasting hack from expr to use pratt parsing with parse_expr_without_block - virtual ExprWithoutBlock* as_expr_without_block() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to call the impl for clone expr without block\n"); - - return clone_expr_without_block_impl(); - } - }; - - // HACK: IdentifierExpr, delete when figure out identifier vs expr problem in Pratt parser - // Alternatively, identifiers could just be represented as single-segment paths - class IdentifierExpr : public ExprWithoutBlock { - Identifier ident; - - location_t locus; - - public: - IdentifierExpr(Identifier ident, location_t locus = UNKNOWN_LOCATION, - ::std::vector outer_attrs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attrs)), - ident(::std::move(ident)), locus(locus) {} - - ::std::string as_string() const OVERRIDE { - return ident; - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone method implementation - virtual IdentifierExpr* clone_expr_without_block_impl() const OVERRIDE { - return new IdentifierExpr(*this); - } - }; - - // Pattern base AST node - class Pattern { - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_pattern() const { - return ::std::unique_ptr(clone_pattern_impl()); - } - - // possible virtual methods: is_refutable() - - virtual ~Pattern() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone pattern implementation as pure virtual method - virtual Pattern* clone_pattern_impl() const = 0; - }; - - // forward decl for Type - class TraitBound; - - // Base class for types as represented in AST - abstract - class Type { - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_type() const { - return ::std::unique_ptr(clone_type_impl()); - } - - // virtual destructor - virtual ~Type() {} - - virtual ::std::string as_string() const = 0; - - // HACK: convert to trait bound. Virtual method overriden by classes that enable this. - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const { - return NULL; - } - // as pointer, shouldn't require definition beforehand, only forward declaration. - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual Type* clone_type_impl() const = 0; - }; - - // A type without parentheses? - abstract - class TypeNoBounds : public Type { - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_type_no_bounds() const { - return ::std::unique_ptr(clone_type_no_bounds_impl()); - } - - protected: - // Clone function implementation as pure virtual method - virtual TypeNoBounds* clone_type_no_bounds_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making type clone - * return typenobounds clone. Hopefully won't affect performance too much. */ - virtual TypeNoBounds* clone_type_impl() const OVERRIDE { - return clone_type_no_bounds_impl(); - } - }; - - // Abstract base class representing a type param bound - Lifetime and TraitBound extends it - class TypeParamBound { - public: - virtual ~TypeParamBound() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_type_param_bound() const { - return ::std::unique_ptr(clone_type_param_bound_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual TypeParamBound* clone_type_param_bound_impl() const = 0; - }; - - // Represents a lifetime (and is also a kind of type param bound) - class Lifetime : public TypeParamBound { - public: - enum LifetimeType { - NAMED, // corresponds to LIFETIME_OR_LABEL - STATIC, // corresponds to 'static - WILDCARD // corresponds to '_ - }; - - private: - LifetimeType lifetime_type; - - // TODO: LIFETIME_OR_LABEL (aka lifetime token) is only field - // find way of enclosing token or something - ::std::string lifetime_name; - // only applies for NAMED lifetime_type - - location_t locus; - - public: - // Constructor - Lifetime(LifetimeType type, ::std::string name = ::std::string(), - location_t locus = UNKNOWN_LOCATION) : - lifetime_type(type), - lifetime_name(::std::move(name)), locus(locus) {} - - // Creates an "error" lifetime. - static Lifetime error() { - return Lifetime(NAMED, ::std::string("")); - } - - // Returns true if the lifetime is in an error state. - inline bool is_error() const { - return lifetime_type == NAMED && lifetime_name.empty(); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Lifetime* clone_type_param_bound_impl() const OVERRIDE { - return new Lifetime(*this); - } - }; - - // Base generic parameter in AST. Abstract - can be represented by a Lifetime or Type param - class GenericParam { - public: - virtual ~GenericParam() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_generic_param() const { - return ::std::unique_ptr(clone_generic_param_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual GenericParam* clone_generic_param_impl() const = 0; - }; - - // A lifetime generic parameter (as opposed to a type generic parameter) - class LifetimeParam : public GenericParam { - Lifetime lifetime; - - // bool has_lifetime_bounds; - // LifetimeBounds lifetime_bounds; - ::std::vector lifetime_bounds; // inlined LifetimeBounds - - // bool has_outer_attribute; - //::std::unique_ptr outer_attr; - Attribute outer_attr; - - location_t locus; - - public: - // Returns whether the lifetime param has any lifetime bounds. - inline bool has_lifetime_bounds() const { - return !lifetime_bounds.empty(); - } - - // Returns whether the lifetime param has an outer attribute. - inline bool has_outer_attribute() const { - return !outer_attr.is_empty(); - } - - // Creates an error state lifetime param. - static LifetimeParam create_error() { - return LifetimeParam(Lifetime::error()); - } - - // Returns whether the lifetime param is in an error state. - inline bool is_error() const { - return lifetime.is_error(); - } - - // Constructor - LifetimeParam(Lifetime lifetime, location_t locus = UNKNOWN_LOCATION, - ::std::vector lifetime_bounds = ::std::vector(), - Attribute outer_attr = Attribute::create_empty()) : - lifetime(::std::move(lifetime)), - lifetime_bounds(::std::move(lifetime_bounds)), outer_attr(::std::move(outer_attr)), - locus(locus) {} - - // TODO: remove copy and assignment operator definitions - not required - - // Copy constructor with clone - LifetimeParam(LifetimeParam const& other) : - lifetime(other.lifetime), lifetime_bounds(other.lifetime_bounds), - outer_attr(other.outer_attr), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone attribute - LifetimeParam& operator=(LifetimeParam const& other) { - lifetime = other.lifetime; - lifetime_bounds = other.lifetime_bounds; - outer_attr = other.outer_attr; - locus = other.locus; - - return *this; - } - - // move constructors - LifetimeParam(LifetimeParam&& other) = default; - LifetimeParam& operator=(LifetimeParam&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LifetimeParam* clone_generic_param_impl() const OVERRIDE { - return new LifetimeParam(*this); - } - }; - - // A macro item AST node - potentially abstract base class - class MacroItem : public Item { - /*public: - ::std::string as_string() const;*/ - protected: - MacroItem(::std::vector outer_attribs) : Item(::std::move(outer_attribs)) {} - }; - - // Item used in trait declarations - abstract base class - class TraitItem { - // bool has_outer_attrs; - // TODO: remove and rely on virtual functions and VisItem-derived attributes? - //::std::vector outer_attrs; - - // NOTE: all children should have outer attributes - - protected: - // Constructor - /*TraitItem(::std::vector outer_attrs = ::std::vector()) : - outer_attrs(::std::move(outer_attrs)) {}*/ - - // Clone function implementation as pure virtual method - virtual TraitItem* clone_trait_item_impl() const = 0; - - public: - virtual ~TraitItem() {} - - // Returns whether TraitItem has outer attributes. - /*inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - }*/ - - // Unique pointer custom clone function - ::std::unique_ptr clone_trait_item() const { - return ::std::unique_ptr(clone_trait_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Abstract base class for items used within an inherent impl block (the impl name {} one) - class InherentImplItem { - protected: - // Clone function implementation as pure virtual method - virtual InherentImplItem* clone_inherent_impl_item_impl() const = 0; - - public: - virtual ~InherentImplItem() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_inherent_impl_item() const { - return ::std::unique_ptr(clone_inherent_impl_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Abstract base class for items used in a trait impl - class TraitImplItem { - protected: - virtual TraitImplItem* clone_trait_impl_item_impl() const = 0; - - public: - virtual ~TraitImplItem(){}; - - // Unique pointer custom clone function - ::std::unique_ptr clone_trait_impl_item() const { - return ::std::unique_ptr(clone_trait_impl_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // A macro invocation item (or statement) AST node (i.e. semi-coloned macro invocation) - class MacroInvocationSemi - : public MacroItem - , public TraitItem - , public InherentImplItem - , public TraitImplItem - /*, public Statement*/ { - // already inherits from statement indirectly via item as item is a subclass of statement - SimplePath path; - // all delim types except curly must have invocation end with a semicolon - DelimType delim_type; - //::std::vector token_trees; - ::std::vector< ::std::unique_ptr > token_trees; - - location_t locus; - - public: - ::std::string as_string() const; - - MacroInvocationSemi(SimplePath macro_path, DelimType delim_type, - ::std::vector< ::std::unique_ptr > token_trees, - ::std::vector outer_attribs, location_t locus) : - MacroItem(::std::move(outer_attribs)), - path(::std::move(macro_path)), delim_type(delim_type), - token_trees(::std::move(token_trees)), locus(locus) {} - /* TODO: possible issue with Item and TraitItem hierarchies both having outer attributes - * - storage inefficiency at least. - * Best current idea is to make Item preferred and have TraitItem get virtual functions - * for attributes or something. - * Or just redo the "composition" approach, but then this prevents polymorphism and would - * entail redoing quite a bit of the parser. */ - - // Copy constructor with vector clone - MacroInvocationSemi(MacroInvocationSemi const& other) : - MacroItem(other), TraitItem(other), InherentImplItem(other), TraitImplItem(other), - path(other.path), delim_type(other.delim_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - } - - // Overloaded assignment operator to vector clone - MacroInvocationSemi& operator=(MacroInvocationSemi const& other) { - MacroItem::operator=(other); - TraitItem::operator=(other); - InherentImplItem::operator=(other); - TraitImplItem::operator=(other); - path = other.path; - delim_type = other.delim_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - - return *this; - } - - // Move constructors - MacroInvocationSemi(MacroInvocationSemi&& other) = default; - MacroInvocationSemi& operator=(MacroInvocationSemi&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_inherent_impl_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_trait_impl_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // FIXME: remove if item impl virtual override works properly - // Use covariance to implement clone function as returning this object rather than base - /*virtual MacroInvocationSemi* clone_statement_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - }*/ - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_trait_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - }; - - // A crate AST object - holds all the data for a single compilation unit - struct Crate { - bool has_utf8bom; - bool has_shebang; - - ::std::vector inner_attrs; - //::std::vector items; - // dodgy spacing required here - // TODO: is it better to have a vector of items here or a module (implicit top-level one)? - ::std::vector< ::std::unique_ptr > items; - - public: - // Constructor - Crate(::std::vector< ::std::unique_ptr > items, - ::std::vector inner_attrs, bool has_utf8bom = false, - bool has_shebang = false) : - has_utf8bom(has_utf8bom), - has_shebang(has_shebang), inner_attrs(::std::move(inner_attrs)), - items(::std::move(items)) {} - - // Copy constructor with vector clone - Crate(Crate const& other) : - has_utf8bom(other.has_utf8bom), has_shebang(other.has_shebang), - inner_attrs(other.inner_attrs) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - } - - ~Crate() = default; - - // Overloaded assignment operator with vector clone - Crate& operator=(Crate const& other) { - inner_attrs = other.inner_attrs; - has_shebang = other.has_shebang; - has_utf8bom = other.has_utf8bom; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - - return *this; - } - - // Move constructors - Crate(Crate&& other) = default; - Crate& operator=(Crate&& other) = default; - - // Get crate representation as string (e.g. for debugging). - ::std::string as_string() const; - }; - - // Base path expression AST node - abstract - class PathExpr : public ExprWithoutBlock { - protected: - PathExpr(::std::vector outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)) {} - - public: - // TODO: think of a better and less hacky way to allow this - - // Replaces the outer attributes of this path expression with the given outer attributes. - void replace_outer_attrs(::std::vector outer_attrs) { - set_outer_attrs(::std::move(outer_attrs)); - } - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-cond-compilation.h b/gcc/rust/test3/ast/rust-cond-compilation.h deleted file mode 100644 index 4fa6a0b..0000000 --- a/gcc/rust/test3/ast/rust-cond-compilation.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef RUST_AST_CONDCOMPILATION -#define RUST_AST_CONDCOMPILATION -// Conditional compilation-related AST stuff - -#include "rust-ast.h" - -namespace Rust { - namespace AST { - // Base conditional compilation configuration predicate thing - abstract - class ConfigurationPredicate { - public: - virtual ~ConfigurationPredicate() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_configuration_predicate() const { - return ::std::unique_ptr( - clone_configuration_predicate_impl()); - } - - // not sure if I'll use this but here anyway - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate* clone_configuration_predicate_impl() const = 0; - }; - - // A configuration option - true if option is set, false if option is not set. - class ConfigurationOption : public ConfigurationPredicate { - Identifier option_name; - - // bool has_string_literal_option_body; - ::std::string option_value; // technically a string or raw string literal - - public: - // Returns whether the configuration option has a "value" part of the key-value pair. - inline bool has_option_value() const { - return !option_value.empty(); - } - - // Key-value pair constructor - ConfigurationOption(Identifier option_name, ::std::string option_value) : - option_name(option_name), option_value(option_value) {} - - // Name-only constructor - ConfigurationOption(Identifier option_name) : option_name(option_name) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationOption* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationOption(*this); - } - }; - - // TODO: inline - struct ConfigurationPredicateList { - ::std::vector< ::std::unique_ptr > predicate_list; - }; - - // Predicate that returns true if all of the supplied predicates return true. - class ConfigurationAll : public ConfigurationPredicate { - ::std::vector< ::std::unique_ptr > predicate_list; // inlined form - - public: - ConfigurationAll( - ::std::vector< ::std::unique_ptr > predicate_list) : - predicate_list(predicate_list) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationAll* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationAll(*this); - } - }; - - // Predicate that returns true if any of the supplied predicates are true. - class ConfigurationAny : public ConfigurationPredicate { - ::std::vector< ::std::unique_ptr > predicate_list; // inlined form - - public: - ConfigurationAny( - ::std::vector< ::std::unique_ptr > predicate_list) : - predicate_list(predicate_list) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationAny* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationAny(*this); - } - }; - - // Predicate that produces the negation of a supplied other configuration predicate. - class ConfigurationNot : public ConfigurationPredicate { - ::std::unique_ptr config_to_negate; - - public: - ConfigurationNot(ConfigurationPredicate* config_to_negate) : - config_to_negate(config_to_negate) {} - - // Copy constructor with clone - ConfigurationNot(ConfigurationNot const& other) : - config_to_negate(other.config_to_negate->clone_configuration_predicate()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ConfigurationNot& operator=(ConfigurationNot const& other) { - config_to_negate = other.config_to_negate->clone_configuration_predicate(); - - return *this; - } - - // move constructors - ConfigurationNot(ConfigurationNot&& other) = default; - ConfigurationNot& operator=(ConfigurationNot&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationNot* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationNot(*this); - } - }; - - // TODO: relationship to other attributes? - class CfgAttribute { - ::std::unique_ptr config_to_include; - - public: - CfgAttribute(ConfigurationPredicate* config_to_include) : - config_to_include(config_to_include) {} - - // Copy constructor with clone - CfgAttribute(CfgAttribute const& other) : - config_to_include(other.config_to_include->clone_configuration_predicate()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - CfgAttribute& operator=(CfgAttribute const& other) { - config_to_include = other.config_to_include->clone_configuration_predicate(); - - return *this; - } - - // move constructors - CfgAttribute(CfgAttribute&& other) = default; - CfgAttribute& operator=(CfgAttribute&& other) = default; - }; - /* TODO: ok, best thing to do would be eliminating this class, making Attribute has a "is_cfg()" - * method, and having attribute path as "cfg" and AttrInput as ConfigurationPredicate (so make - * ConfigurationPredicate a subclass of AttrInput?). Would need special handling in parser, however. */ - - // TODO: inline - struct CfgAttrs { - ::std::vector cfg_attrs; - }; - - // TODO: relationship to other attributes? - class CfgAttrAttribute { - ::std::unique_ptr config_to_include; - ::std::vector cfg_attrs; - - public: - CfgAttrAttribute( - ConfigurationPredicate* config_to_include, ::std::vector cfg_attrs) : - config_to_include(config_to_include), - cfg_attrs(cfg_attrs) {} - - // Copy constructor with clone - CfgAttrAttribute(CfgAttrAttribute const& other) : - config_to_include(other.config_to_include->clone_configuration_predicate()), - cfg_attrs(cfg_attrs) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - CfgAttrAttribute& operator=(CfgAttrAttribute const& other) { - config_to_include = other.config_to_include->clone_configuration_predicate(); - cfg_attrs = other.cfg_attrs; - - return *this; - } - - // move constructors - CfgAttrAttribute(CfgAttrAttribute&& other) = default; - CfgAttrAttribute& operator=(CfgAttrAttribute&& other) = default; - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-expr.h b/gcc/rust/test3/ast/rust-expr.h deleted file mode 100644 index 1842da9..0000000 --- a/gcc/rust/test3/ast/rust-expr.h +++ /dev/null @@ -1,4614 +0,0 @@ -#ifndef RUST_AST_EXPR_H -#define RUST_AST_EXPR_H - -#include "rust-ast.h" -#include "rust-path.h" - -namespace Rust { - namespace AST { - /* TODO: if GCC moves to C++17 or allows boost, replace some boolean "has_whatever" pairs with - * optional types (std::optional or boost::optional)? */ - - // forward decls: defined in rust-path.h, rust-type.h, rust-pattern.h, and rust-stmt.h - /*class PathInExpression; - class QualifiedPathInExpression; - class PathExprSegment;*/ // decls no longer required as "rust-path.h" is included - /*class Type; - class TypeNoBounds; - class Lifetime; - class Pattern; - class Statement;*/ // decls no longer required as definitions moved to rust-ast.h - - // Decl as definition moved to rust-ast.h - class ExprWithoutBlock; - - // AST node for an expression with an accompanying block - abstract - class ExprWithBlock : public Expr { - // TODO: should this mean that a BlockExpr should be a member variable? - protected: - ExprWithBlock(::std::vector outer_attrs = ::std::vector()) : - Expr(::std::move(outer_attrs)) {} - - // pure virtual clone implementation - virtual ExprWithBlock* clone_expr_with_block_impl() const = 0; - - // prevent having to define multiple clone expressions - virtual ExprWithBlock* clone_expr_impl() const OVERRIDE { - return clone_expr_with_block_impl(); - } - - public: - // Unique pointer custom clone function - ::std::unique_ptr clone_expr_with_block() const { - return ::std::unique_ptr(clone_expr_with_block_impl()); - } - }; - - // Literals? Or literal base? - class LiteralExpr : public ExprWithoutBlock { - /*public: - enum LitType { - CHAR, - STRING, - RAW_STRING, - BYTE, - BYTE_STRING, - RAW_BYTE_STRING, - INT, - FLOAT, - BOOL - }; - - private: - // TODO: maybe make subclasses of each type of literal with their typed values (or - // generics) - ::std::string value_as_string; - LitType type;*/ - // moved to Literal - Literal literal; - - location_t locus; - - public: - ::std::string as_string() const { - return literal.as_string(); - } - - inline Literal::LitType get_lit_type() const { - return literal.get_lit_type(); - } - - LiteralExpr(::std::string value_as_string, Literal::LitType type, location_t locus, - ::std::vector outer_attrs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attrs)), - literal(::std::move(value_as_string), type), locus(locus) {} - - LiteralExpr(Literal literal, location_t locus, - ::std::vector outer_attrs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attrs)), - literal(::std::move(literal)), locus(locus) {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_literal_expr() const { - return ::std::unique_ptr(clone_literal_expr_impl()); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralExpr* clone_expr_impl() const OVERRIDE { - return new LiteralExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralExpr* clone_expr_without_block_impl() const OVERRIDE { - return new LiteralExpr(*this); - } - - // not virtual as currently no subclasses of LiteralExpr, but could be in future - /*virtual*/ LiteralExpr* clone_literal_expr_impl() const { - return new LiteralExpr(*this); - } - }; - - // Literal expression attribute body (non-macro attribute) - class AttrInputLiteral : public AttrInput { - // Literal expression WITHOUT SUFFIX - // LiteralExpr* literal_expr; - //::std::unique_ptr literal_expr; - LiteralExpr literal_expr; // as not using polymorphic behaviour, doesn't require pointer - // TODO: will require pointer if LiteralExpr is changed to have subclassing - - // TODO: should this store location data? - - public: - AttrInputLiteral(LiteralExpr lit_expr) : literal_expr(::std::move(lit_expr)) {} - /*~AttrInputLiteral() { - delete literal_expr; - }*/ - - ::std::string as_string() const { - return " = " + literal_expr.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // this can never be a cfg predicate - cfg and cfg_attr require a token-tree cfg - virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { - // TODO: ensure this is true - // DEBUG - fprintf( - stderr, "check_cfg_predicate call went to AttrInputLiteral - should not happen?\n"); - - return false; - } - - protected: - // Use covariance to implement clone function as returning an AttrInputLiteral object - virtual AttrInputLiteral* clone_attr_input_impl() const OVERRIDE { - return new AttrInputLiteral(*this); - } - }; - - // literal expr only meta item inner - TODO possibly replace with inheritance of LiteralExpr - // itself? - class MetaItemLitExpr : public MetaItemInner { - LiteralExpr lit_expr; - - public: - MetaItemLitExpr(LiteralExpr lit_expr) : lit_expr(::std::move(lit_expr)) {} - - ::std::string as_string() const OVERRIDE { - return lit_expr.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemLitExpr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemLitExpr(*this); - } - }; - - // more generic meta item "path = lit" form - class MetaItemPathLit : public MetaItem { - SimplePath path; - LiteralExpr lit; - - public: - MetaItemPathLit(SimplePath path, LiteralExpr lit_expr) : - path(::std::move(path)), lit(::std::move(lit_expr)) {} - - ::std::string as_string() const OVERRIDE { - return path.as_string() + " = " + lit.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - // TODO: return true if "ident" is defined and value of it is "lit", return false otherwise - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemPathLit* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemPathLit(*this); - } - }; - - // AST node for a non-qualified path expression - FIXME: should this be inheritance instead? - /*class PathExprNonQual : public PathExpr { - PathInExpression path; - - public: - ::std::string as_string() const { - return path.as_string(); - } - - PathExprNonQual(PathInExpression path, ::std::vector outer_attribs) : - PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprNonQual* clone_expr_impl() const OVERRIDE { - return new PathExprNonQual(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprNonQual* clone_expr_without_block_impl() const OVERRIDE { - return new PathExprNonQual(*this); - } - };*/ - // converted to inheritance - - // AST node for a qualified path expression - FIXME: should this be inheritance instead? - /*class PathExprQual : public PathExpr { - QualifiedPathInExpression path; - - public: - ::std::string as_string() const { - return path.as_string(); - } - - PathExprQual(QualifiedPathInExpression path, ::std::vector outer_attribs) : - PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprQual* clone_expr_impl() const OVERRIDE { - return new PathExprQual(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprQual* clone_expr_without_block_impl() const OVERRIDE { - return new PathExprQual(*this); - } - };*/ - // replaced with inheritance - - // Represents an expression using unary or binary operators as AST node. Can be overloaded. - class OperatorExpr : public ExprWithoutBlock { - // TODO: create binary and unary operator subclasses? - - location_t locus; - - protected: - // Variable must be protected to allow derived classes to use it as a first class citizen - // Expr* main_or_left_expr; - ::std::unique_ptr main_or_left_expr; - - // Constructor (only for initialisation of expr purposes) - OperatorExpr(::std::unique_ptr main_or_left_expr, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - locus(locus), main_or_left_expr(::std::move(main_or_left_expr)) {} - - // Copy constructor (only for initialisation of expr purposes) - OperatorExpr(OperatorExpr const& other) : - ExprWithoutBlock(other), - locus(other.locus) /*, main_or_left_expr(other.main_or_left_expr->clone_expr())*/ { - // DEBUG: moved main_or_left_expr into body - move back later - - if (other.main_or_left_expr == NULL) { - fprintf(stderr, "other operator expr's main_or_left_expr is null!\n"); - } - - fprintf(stderr, - "called operator expr copy constructor - about to clone main_or_left_expr\n"); - main_or_left_expr = other.main_or_left_expr->clone_expr(); - fprintf(stderr, "successfully cloned main_or_left_expr\n"); - // this occurred successfully, so something else must be the issue - } - - // Overload assignment operator to deep copy expr - OperatorExpr& operator=(OperatorExpr const& other) { - ExprWithoutBlock::operator=(other); - main_or_left_expr = other.main_or_left_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - OperatorExpr(OperatorExpr&& other) = default; - OperatorExpr& operator=(OperatorExpr&& other) = default; - - public: - /*virtual ~OperatorExpr() { - delete main_or_left_expr; - }*/ - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be overloaded. - class BorrowExpr : public OperatorExpr { - bool is_mut; - bool double_borrow; - - public: - ::std::string as_string() const; - - BorrowExpr(::std::unique_ptr borrow_lvalue, bool is_mut_borrow, - bool is_double_borrow, ::std::vector outer_attribs, location_t locus) : - OperatorExpr(::std::move(borrow_lvalue), ::std::move(outer_attribs), locus), - is_mut(is_mut_borrow), double_borrow(is_double_borrow) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BorrowExpr* clone_expr_impl() const OVERRIDE { - return new BorrowExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BorrowExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on borrowexpr\n"); - - return new BorrowExpr(*this); - } - }; - - // Unary prefix * deference operator - class DereferenceExpr : public OperatorExpr { - public: - ::std::string as_string() const; - - // Constructor calls OperatorExpr's protected constructor - DereferenceExpr(::std::unique_ptr deref_lvalue, - ::std::vector outer_attribs, location_t locus) : - OperatorExpr(::std::move(deref_lvalue), ::std::move(outer_attribs), locus) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual DereferenceExpr* clone_expr_impl() const OVERRIDE { - return new DereferenceExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual DereferenceExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on dereferenceexpr\n"); - - return new DereferenceExpr(*this); - } - }; - - // Unary postfix ? error propogation operator. Cannot be overloaded. - class ErrorPropagationExpr : public OperatorExpr { - public: - ::std::string as_string() const; - - // Constructor calls OperatorExpr's protected constructor - ErrorPropagationExpr(::std::unique_ptr potential_error_value, - ::std::vector outer_attribs, location_t locus) : - OperatorExpr(::std::move(potential_error_value), ::std::move(outer_attribs), locus) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ErrorPropagationExpr* clone_expr_impl() const OVERRIDE { - return new ErrorPropagationExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ErrorPropagationExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on errorpropagationexpr\n"); - - return new ErrorPropagationExpr(*this); - } - }; - - // Unary prefix - or ! negation or NOT operators. - class NegationExpr : public OperatorExpr { - public: - enum NegationType { NEGATE, NOT }; - - private: - // Note: overload negation via std::ops::Neg and not via std::ops::Not - // Negation only works for signed integer and floating-point types, NOT only works for - // boolean and integer types (via bitwise NOT) - NegationType negation_type; - - public: - ::std::string as_string() const; - - inline NegationType get_negation_type() const { - return negation_type; - } - - // Constructor calls OperatorExpr's protected constructor - NegationExpr(::std::unique_ptr negated_value, NegationType negation_kind, - ::std::vector outer_attribs, location_t locus) : - OperatorExpr(::std::move(negated_value), ::std::move(outer_attribs), locus), - negation_type(negation_kind) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual NegationExpr* clone_expr_impl() const OVERRIDE { - return new NegationExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual NegationExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on negationexpr\n"); - - return new NegationExpr(*this); - } - }; - - // Infix binary operators. +, -, *, /, %, &, |, ^, <<, >> - class ArithmeticOrLogicalExpr : public OperatorExpr { - public: - enum ExprType { - ADD, // std::ops::Add - SUBTRACT, // std::ops::Sub - MULTIPLY, // std::ops::Mul - DIVIDE, // std::ops::Div - MODULUS, // std::ops::Rem - BITWISE_AND, // std::ops::BitAnd - BITWISE_OR, // std::ops::BitOr - BITWISE_XOR, // std::ops::BitXor - LEFT_SHIFT, // std::ops::Shl - RIGHT_SHIFT // std::ops::Shr - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr right_expr; - - public: - /*~ArithmeticOrLogicalExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Constructor calls OperatorExpr's protected constructor - ArithmeticOrLogicalExpr(::std::unique_ptr left_value, - ::std::unique_ptr right_value, ExprType expr_kind, location_t locus) : - OperatorExpr(::std::move(left_value), ::std::vector(), locus), - expr_type(expr_kind), right_expr(::std::move(right_value)) {} - // outer attributes not allowed - - // Copy constructor - probably required due to unique pointer - ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator - ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - - return *this; - } - - // move constructors - ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr&& other) = default; - ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArithmeticOrLogicalExpr* clone_expr_impl() const OVERRIDE { - return new ArithmeticOrLogicalExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArithmeticOrLogicalExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf( - stderr, "called clone_expr_without_block_impl() on arithmeticorlogicalexpr\n"); - - return new ArithmeticOrLogicalExpr(*this); - } - }; - - // Infix binary comparison operators. ==, !=, <, <=, >, >= - class ComparisonExpr : public OperatorExpr { - public: - enum ExprType { - EQUAL, // std::cmp::PartialEq::eq - NOT_EQUAL, // std::cmp::PartialEq::ne - GREATER_THAN, // std::cmp::PartialEq::gt - LESS_THAN, // std::cmp::PartialEq::lt - GREATER_OR_EQUAL, // std::cmp::PartialEq::ge - LESS_OR_EQUAL // std::cmp::PartialEq::le - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr right_expr; - - public: - /*~ComparisonExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Constructor requires pointers for polymorphism - ComparisonExpr(::std::unique_ptr left_value, ::std::unique_ptr right_value, - ExprType comparison_kind, location_t locus) : - OperatorExpr(::std::move(left_value), ::std::vector(), locus), - expr_type(comparison_kind), right_expr(::std::move(right_value)) {} - // outer attributes not allowed - - // Copy constructor also calls OperatorExpr's protected constructor - ComparisonExpr(ComparisonExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - ComparisonExpr& operator=(ComparisonExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ComparisonExpr(ComparisonExpr&& other) = default; - ComparisonExpr& operator=(ComparisonExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) maybe? - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ComparisonExpr* clone_expr_impl() const OVERRIDE { - return new ComparisonExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ComparisonExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on comparisonexpr\n"); - - return new ComparisonExpr(*this); - } - }; - - // Infix binary lazy boolean logical operators && and ||. - class LazyBooleanExpr : public OperatorExpr { - public: - enum ExprType { LOGICAL_OR, LOGICAL_AND }; - - private: - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr right_expr; - - public: - /*~LazyBooleanExpr() { - delete right_expr; - }*/ - - // Constructor calls OperatorExpr's protected constructor - LazyBooleanExpr(::std::unique_ptr left_bool_expr, - ::std::unique_ptr right_bool_expr, ExprType expr_kind, location_t locus) : - OperatorExpr(::std::move(left_bool_expr), ::std::vector(), locus), - expr_type(expr_kind), right_expr(::std::move(right_bool_expr)) {} - // outer attributes not allowed - - // Copy constructor also calls OperatorExpr's protected constructor - LazyBooleanExpr(LazyBooleanExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - LazyBooleanExpr& operator=(LazyBooleanExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - - return *this; - } - - // move constructors - LazyBooleanExpr(LazyBooleanExpr&& other) = default; - LazyBooleanExpr& operator=(LazyBooleanExpr&& other) = default; - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LazyBooleanExpr* clone_expr_impl() const OVERRIDE { - return new LazyBooleanExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LazyBooleanExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on lazybooleanexpr\n"); - - return new LazyBooleanExpr(*this); - } - }; - - // Binary infix "as" cast expression. - class TypeCastExpr : public OperatorExpr { - // TypeNoBounds type_to_convert_to; - ::std::unique_ptr type_to_convert_to; - - // Note: only certain type casts allowed, outlined in reference - public: - ::std::string as_string() const; - - // Constructor requires calling protected constructor of OperatorExpr - TypeCastExpr(::std::unique_ptr expr_to_cast, - ::std::unique_ptr type_to_cast_to, location_t locus) : - OperatorExpr(::std::move(expr_to_cast), ::std::vector(), locus), - type_to_convert_to(::std::move(type_to_cast_to)) {} - // outer attributes not allowed - - // Copy constructor also requires calling protected constructor - TypeCastExpr(TypeCastExpr const& other) : - OperatorExpr(other), - type_to_convert_to(other.type_to_convert_to->clone_type_no_bounds()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - TypeCastExpr& operator=(TypeCastExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds(); - - return *this; - } - - // move constructors as not supported in c++03 - TypeCastExpr(TypeCastExpr&& other) = default; - TypeCastExpr& operator=(TypeCastExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TypeCastExpr* clone_expr_impl() const OVERRIDE { - return new TypeCastExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TypeCastExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on typecastexpr\n"); - - return new TypeCastExpr(*this); - } - }; - - // Binary assignment expression. - class AssignmentExpr : public OperatorExpr { - // Expr* right_expr; - ::std::unique_ptr right_expr; - - public: - /*~AssignmentExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - // Call OperatorExpr constructor to initialise left_expr - AssignmentExpr(::std::unique_ptr value_to_assign_to, - ::std::unique_ptr value_to_assign, location_t locus) : - OperatorExpr(::std::move(value_to_assign_to), ::std::vector(), locus), - right_expr(::std::move(value_to_assign)) {} - // outer attributes not allowed - - // Call OperatorExpr constructor in copy constructor, as well as clone - AssignmentExpr(AssignmentExpr const& other) : - OperatorExpr(other) /*, right_expr(other.right_expr->clone_expr())*/ { - // DEBUG: moved cloning right expr into body - fprintf(stderr, - "assignment expr copy constructor successfully cloned base operator expr\n"); - if (other.right_expr == NULL) { - fprintf(stderr, "other expr's right expr (in assignment) is null!!!"); - } - fprintf(stderr, "test other's right expr as string: %s\n", - other.right_expr->as_string().c_str()); - // apparently, despite not being null, cloning still fails - right_expr = other.right_expr->clone_expr(); - fprintf(stderr, "assignment expr copy constructor successfully cloned right expr\n"); - - // DEBUG - fprintf(stderr, "assignment expr copy constructor called successfully\n"); - } - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr right_expr - AssignmentExpr& operator=(AssignmentExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - AssignmentExpr(AssignmentExpr&& other) = default; - AssignmentExpr& operator=(AssignmentExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AssignmentExpr* clone_expr_impl() const OVERRIDE { - return new AssignmentExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual AssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on assignmentexpr\n"); - - return new AssignmentExpr(*this); - } - }; - - // Binary infix compound assignment (arithmetic or logic then assignment) expressions. - class CompoundAssignmentExpr : public OperatorExpr { - public: - enum ExprType { - ADD, // std::ops::AddAssign - SUBTRACT, // std::ops::SubAssign - MULTIPLY, // std::ops::MulAssign - DIVIDE, // std::ops::DivAssign - MODULUS, // std::ops::RemAssign - BITWISE_AND, // std::ops::BitAndAssign - BITWISE_OR, // std::ops::BitOrAssign - BITWISE_XOR, // std::ops::BitXorAssign - LEFT_SHIFT, // std::ops::ShlAssign - RIGHT_SHIFT // std::ops::ShrAssign - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr right_expr; - - public: - /*~CompoundAssignmentExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Use pointers in constructor to enable polymorphism - CompoundAssignmentExpr(::std::unique_ptr value_to_assign_to, - ::std::unique_ptr value_to_assign, ExprType expr_kind, location_t locus) : - OperatorExpr(::std::move(value_to_assign_to), ::std::vector(), locus), - expr_type(expr_kind), right_expr(::std::move(value_to_assign)) {} - // outer attributes not allowed - - // Have clone in copy constructor - CompoundAssignmentExpr(CompoundAssignmentExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - CompoundAssignmentExpr& operator=(CompoundAssignmentExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - CompoundAssignmentExpr(CompoundAssignmentExpr&& other) = default; - CompoundAssignmentExpr& operator=(CompoundAssignmentExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual CompoundAssignmentExpr* clone_expr_impl() const OVERRIDE { - return new CompoundAssignmentExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual CompoundAssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on compoundassignmentexpr\n"); - - return new CompoundAssignmentExpr(*this); - } - }; - - // Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) - class GroupedExpr : public ExprWithoutBlock { - ::std::vector inner_attrs; - // Expr* expr_in_parens; - ::std::unique_ptr expr_in_parens; - - location_t locus; - - public: - /*~GroupedExpr() { - delete expr_in_parens; - }*/ - - ::std::string as_string() const; - - inline ::std::vector get_inner_attrs() const { - return inner_attrs; - } - - GroupedExpr(::std::unique_ptr parenthesised_expr, - ::std::vector inner_attribs, ::std::vector outer_attribs, - location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), - expr_in_parens(::std::move(parenthesised_expr)), locus(locus) {} - - // Copy constructor includes clone for expr_in_parens - GroupedExpr(GroupedExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), - expr_in_parens(other.expr_in_parens->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone expr_in_parens - GroupedExpr& operator=(GroupedExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - expr_in_parens = other.expr_in_parens->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - GroupedExpr(GroupedExpr&& other) = default; - GroupedExpr& operator=(GroupedExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedExpr* clone_expr_impl() const OVERRIDE { - return new GroupedExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedExpr* clone_expr_without_block_impl() const OVERRIDE { - return new GroupedExpr(*this); - } - }; - - // Base array initialisation internal element representation thing (abstract) - // aka ArrayElements - class ArrayElems { - public: - virtual ~ArrayElems() {} - - // Unique pointer custom clone ArrayElems function - ::std::unique_ptr clone_array_elems() const { - return ::std::unique_ptr(clone_array_elems_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual ArrayElems* clone_array_elems_impl() const = 0; - }; - - // Value array elements - class ArrayElemsValues : public ArrayElems { - //::std::vector values; - ::std::vector< ::std::unique_ptr > values; - - // TODO: should this store location data? - - public: - /*inline ::std::vector< ::std::unique_ptr > get_values() const { - return values; - }*/ - - ArrayElemsValues(::std::vector< ::std::unique_ptr > elems) : - values(::std::move(elems)) {} - - // copy constructor with vector clone - ArrayElemsValues(ArrayElemsValues const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - ArrayElemsValues& operator=(ArrayElemsValues const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - ArrayElemsValues(ArrayElemsValues&& other) = default; - ArrayElemsValues& operator=(ArrayElemsValues&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - virtual ArrayElemsValues* clone_array_elems_impl() const OVERRIDE { - return new ArrayElemsValues(*this); - } - }; - - // Copied array element and number of copies - class ArrayElemsCopied : public ArrayElems { - // Expr* elem_to_copy; - ::std::unique_ptr elem_to_copy; - // Expr* num_copies; - ::std::unique_ptr num_copies; - - // TODO: should this store location data? - - public: - /*~ArrayElemsCopied() { - delete num_copies; - delete elem_to_copy; - }*/ - - // Constructor requires pointers for polymorphism - ArrayElemsCopied( - ::std::unique_ptr copied_elem, ::std::unique_ptr copy_amount) : - elem_to_copy(::std::move(copied_elem)), - num_copies(::std::move(copy_amount)) {} - - // Copy constructor required due to unique_ptr - uses custom clone - ArrayElemsCopied(ArrayElemsCopied const& other) : - elem_to_copy(other.elem_to_copy->clone_expr()), - num_copies(other.num_copies->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator for deep copying - ArrayElemsCopied& operator=(ArrayElemsCopied const& other) { - elem_to_copy = other.elem_to_copy->clone_expr(); - num_copies = other.num_copies->clone_expr(); - - return *this; - } - - // move constructors - ArrayElemsCopied(ArrayElemsCopied&& other) = default; - ArrayElemsCopied& operator=(ArrayElemsCopied&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - virtual ArrayElemsCopied* clone_array_elems_impl() const OVERRIDE { - return new ArrayElemsCopied(*this); - } - }; - - // Array definition-ish expression - class ArrayExpr : public ExprWithoutBlock { - ::std::vector inner_attrs; - // ArrayElems internal_elements; - ::std::unique_ptr internal_elements; - - location_t locus; - - public: - ::std::string as_string() const; - - inline ::std::vector get_inner_attrs() const { - return inner_attrs; - } - - // Returns whether array expr has array elems or if it is just empty. - inline bool has_array_elems() const { - return internal_elements != NULL; - } - - // Constructor requires ArrayElems pointer - ArrayExpr(::std::unique_ptr array_elems, - ::std::vector inner_attribs, ::std::vector outer_attribs, - location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), internal_elements(::std::move(array_elems)), - locus(locus) {} - - // Copy constructor requires cloning ArrayElems for polymorphism to hold - ArrayExpr(ArrayExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { - if (other.has_array_elems()) { - internal_elements = other.internal_elements->clone_array_elems(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone internal_elements - ArrayExpr& operator=(ArrayExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - if (other.has_array_elems()) { - internal_elements = other.internal_elements->clone_array_elems(); - } - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ArrayExpr(ArrayExpr&& other) = default; - ArrayExpr& operator=(ArrayExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayExpr* clone_expr_impl() const OVERRIDE { - return new ArrayExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ArrayExpr(*this); - } - }; - - // Aka IndexExpr (also applies to slices) - // Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or - // *std::ops::Index::index_mut(&mut a, b) - // Also apparently deref operations on a will be repeatedly applied to find an implementation - class ArrayIndexExpr : public ExprWithoutBlock { - /*Expr* array_expr; - Expr* index_expr;*/ - ::std::unique_ptr array_expr; - ::std::unique_ptr index_expr; - - location_t locus; - - public: - /*~ArrayIndexExpr() { - delete index_expr; - delete array_expr; - }*/ - - ::std::string as_string() const; - - ArrayIndexExpr(::std::unique_ptr array_expr, - ::std::unique_ptr array_index_expr, ::std::vector outer_attribs, - location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - array_expr(::std::move(array_expr)), index_expr(::std::move(array_index_expr)), - locus(locus) {} - - // Copy constructor requires special cloning due to unique_ptr - ArrayIndexExpr(ArrayIndexExpr const& other) : - ExprWithoutBlock(other), array_expr(other.array_expr->clone_expr()), - index_expr(other.index_expr->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptrs - ArrayIndexExpr& operator=(ArrayIndexExpr const& other) { - ExprWithoutBlock::operator=(other); - array_expr = other.array_expr->clone_expr(); - index_expr = other.index_expr->clone_expr(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - ArrayIndexExpr(ArrayIndexExpr&& other) = default; - ArrayIndexExpr& operator=(ArrayIndexExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayIndexExpr* clone_expr_impl() const OVERRIDE { - return new ArrayIndexExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayIndexExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ArrayIndexExpr(*this); - } - }; - - // AST representation of a tuple - class TupleExpr : public ExprWithoutBlock { - ::std::vector inner_attrs; - - //::std::vector tuple_elems; - ::std::vector< ::std::unique_ptr > tuple_elems; - // replaces (inlined version of) TupleElements - - location_t locus; - - public: - ::std::string as_string() const; - - inline ::std::vector get_inner_attrs() const { - return inner_attrs; - } - - TupleExpr(::std::vector< ::std::unique_ptr > tuple_elements, - ::std::vector inner_attribs, ::std::vector outer_attribs, - location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), tuple_elems(::std::move(tuple_elements)), - locus(locus) {} - - // copy constructor with vector clone - TupleExpr(TupleExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - tuple_elems.reserve(other.tuple_elems.size()); - - for (const auto& e : other.tuple_elems) { - tuple_elems.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator to vector clone - TupleExpr& operator=(TupleExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - tuple_elems.reserve(other.tuple_elems.size()); - - for (const auto& e : other.tuple_elems) { - tuple_elems.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - TupleExpr(TupleExpr&& other) = default; - TupleExpr& operator=(TupleExpr&& other) = default; - - // Note: syntactically, can disambiguate single-element tuple from parens with comma, i.e. - // (0,) rather than (0) - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleExpr* clone_expr_impl() const OVERRIDE { - return new TupleExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleExpr* clone_expr_without_block_impl() const OVERRIDE { - return new TupleExpr(*this); - } - }; - - // aka TupleIndexingExpr - // AST representation of a tuple indexing expression - class TupleIndexExpr : public ExprWithoutBlock { - // Expr* tuple_expr; - ::std::unique_ptr tuple_expr; - // TupleIndex is a decimal int literal with no underscores or suffix - TupleIndex tuple_index; - - location_t locus; - - // i.e. pair.0 - - public: - /*~TupleIndexExpr() { - delete tuple_expr; - }*/ - - ::std::string as_string() const; - - inline TupleIndex get_tuple_index() const { - return tuple_index; - } - - TupleIndexExpr(::std::unique_ptr tuple_expr, TupleIndex index, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - tuple_expr(::std::move(tuple_expr)), tuple_index(index), locus(locus) {} - - // Copy constructor requires a clone for tuple_expr - TupleIndexExpr(TupleIndexExpr const& other) : - ExprWithoutBlock(other), tuple_expr(other.tuple_expr->clone_expr()), - tuple_index(other.tuple_index), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator in order to clone - TupleIndexExpr& operator=(TupleIndexExpr const& other) { - ExprWithoutBlock::operator=(other); - tuple_expr = other.tuple_expr->clone_expr(); - tuple_index = other.tuple_index; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - TupleIndexExpr(TupleIndexExpr&& other) = default; - TupleIndexExpr& operator=(TupleIndexExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleIndexExpr* clone_expr_impl() const OVERRIDE { - return new TupleIndexExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleIndexExpr* clone_expr_without_block_impl() const OVERRIDE { - return new TupleIndexExpr(*this); - } - }; - - // Base struct/tuple/union value creator AST node (abstract) - class StructExpr : public ExprWithoutBlock { - PathInExpression struct_name; - - protected: - // Protected constructor to allow initialising struct_name - StructExpr(PathInExpression struct_path, ::std::vector outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)), struct_name(::std::move(struct_path)) {} - - public: - inline const PathInExpression& get_struct_name() const { - return struct_name; - } - - virtual ::std::string as_string() const; - }; - - // Actual AST node of the struct creator (with no fields). Not abstract! - class StructExprStruct : public StructExpr { - ::std::vector inner_attrs; - - location_t locus; - - public: - ::std::string as_string() const; - - inline ::std::vector get_inner_attrs() const { - return inner_attrs; - } - - // Constructor has to call protected constructor of base class - StructExprStruct(PathInExpression struct_path, ::std::vector inner_attribs, - ::std::vector outer_attribs, location_t locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), locus(locus) {} - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStruct* clone_expr_impl() const OVERRIDE { - return new StructExprStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStruct* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprStruct(*this); - } - }; - - // AST node representing expression used to fill a struct's fields from another struct - struct StructBase { - private: - // Expr* base_struct; - ::std::unique_ptr base_struct; - - // TODO: should this store location data? - - public: - StructBase(::std::unique_ptr base_struct_ptr) : - base_struct(::std::move(base_struct_ptr)) {} - - // Copy constructor requires clone - StructBase(StructBase const& other) { - // HACK: gets around base_struct pointer being null (e.g. if no struct base exists) - if (other.base_struct != NULL) { - other.base_struct->clone_expr(); - } - - // DEBUG: - fprintf(stderr, "struct base copy constructor called successfully\n"); - } - - // Destructor - ~StructBase() = default; - - // Overload assignment operator to clone base_struct - StructBase& operator=(StructBase const& other) { - base_struct = other.base_struct->clone_expr(); - - return *this; - } - - // move constructors - StructBase(StructBase&& other) = default; - StructBase& operator=(StructBase&& other) = default; - - /*~StructBase() { - delete base_struct; - }*/ - - // Returns a null expr-ed StructBase - error state - static StructBase error() { - return StructBase(NULL); - } - - // Returns whether StructBase is in error state - inline bool is_invalid() const { - return base_struct == NULL; - } - - ::std::string as_string() const; - }; - - // Base AST node for a single struct expression field (in struct instance creation) - abstract - class StructExprField { - public: - virtual ~StructExprField() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_struct_expr_field() const { - return ::std::unique_ptr(clone_struct_expr_field_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual StructExprField* clone_struct_expr_field_impl() const = 0; - }; - - // Identifier-only variant of StructExprField AST node - class StructExprFieldIdentifier : public StructExprField { - Identifier field_name; - - // TODO: should this store location data? - - public: - StructExprFieldIdentifier(Identifier field_identifier) : - field_name(::std::move(field_identifier)) {} - - ::std::string as_string() const { - return field_name; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIdentifier* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIdentifier(*this); - } - }; - - // Base AST node for a single struct expression field with an assigned value - abstract - class StructExprFieldWithVal : public StructExprField { - // Expr* value; - ::std::unique_ptr value; - - protected: - StructExprFieldWithVal(::std::unique_ptr field_value) : - value(::std::move(field_value)) {} - - // Copy constructor requires clone - StructExprFieldWithVal(StructExprFieldWithVal const& other) : - value(other.value->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - StructExprFieldWithVal& operator=(StructExprFieldWithVal const& other) { - value = other.value->clone_expr(); - - return *this; - } - - // move constructors - StructExprFieldWithVal(StructExprFieldWithVal&& other) = default; - StructExprFieldWithVal& operator=(StructExprFieldWithVal&& other) = default; - - public: - /*~StructExprFieldWithVal() { - delete value; - }*/ - - ::std::string as_string() const; - }; - - // Identifier and value variant of StructExprField AST node - class StructExprFieldIdentifierValue : public StructExprFieldWithVal { - Identifier field_name; - - // TODO: should this store location data? - - public: - StructExprFieldIdentifierValue( - Identifier field_identifier, ::std::unique_ptr field_value) : - StructExprFieldWithVal(::std::move(field_value)), - field_name(::std::move(field_identifier)) {} - - // copy constructor, destructor, and overloaded assignment operator should carry through - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIdentifierValue* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIdentifierValue(*this); - } - }; - - // Tuple index and value variant of StructExprField AST node - class StructExprFieldIndexValue : public StructExprFieldWithVal { - TupleIndex index; - - // TODO: should this store location data? - - public: - StructExprFieldIndexValue(TupleIndex tuple_index, ::std::unique_ptr field_value) : - StructExprFieldWithVal(::std::move(field_value)), index(tuple_index) {} - - // copy constructor, destructor, and overloaded assignment operator should carry through - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIndexValue* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIndexValue(*this); - } - }; - - // AST node of a struct creator with fields - class StructExprStructFields : public StructExprStruct { - //::std::vector fields; - ::std::vector< ::std::unique_ptr > fields; - - // bool has_struct_base; - StructBase struct_base; - - public: - ::std::string as_string() const; - - inline bool has_struct_base() const { - return !struct_base.is_invalid(); - } - - /*inline ::std::vector< ::std::unique_ptr > get_fields() const { - return fields; - }*/ - - /*inline StructBase get_struct_base() const { - return has_struct_base ? struct_base : StructBase::error(); - }*/ - - // Constructor for StructExprStructFields when no struct base is used - StructExprStructFields(PathInExpression struct_path, - ::std::vector< ::std::unique_ptr > expr_fields, location_t locus, - StructBase base_struct = StructBase::error(), - ::std::vector inner_attribs = ::std::vector(), - ::std::vector outer_attribs = ::std::vector()) : - StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), - ::std::move(outer_attribs), locus), - fields(::std::move(expr_fields)), struct_base(::std::move(base_struct)) {} - - // copy constructor with vector clone - StructExprStructFields(StructExprStructFields const& other) : - StructExprStruct(other), struct_base(other.struct_base) { - // DEBUG - fprintf(stderr, "got past the initialisation list part of copy constructor\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - // DEBUG - fprintf(stderr, "reserved space in fields\n"); - - for (const auto& e : other.fields) { - // DEBUG - fprintf(stderr, "about to clone a field\n"); - - fields.push_back(e->clone_struct_expr_field()); - - // DEBUG - fprintf(stderr, "cloned a field successfully\n"); - } - - // DEBUG - fprintf(stderr, "finished cloning fields\n"); - } - - // overloaded assignment operator with vector clone - StructExprStructFields& operator=(StructExprStructFields const& other) { - StructExprStruct::operator=(other); - struct_base = other.struct_base; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_expr_field()); - } - - return *this; - } - - // move constructors - StructExprStructFields(StructExprStructFields&& other) = default; - StructExprStructFields& operator=(StructExprStructFields&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructFields* clone_expr_impl() const OVERRIDE { - return new StructExprStructFields(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructFields* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called structexprstructfields clone expr without block impl - about " - "to return new structexprstructfields\n"); - - // DEBUG - test creation of a base from this - fprintf(stderr, "about to try to create and allocate structexprstruct \n"); - StructExprStruct* test_DELETE = new StructExprStruct(*this); - delete test_DELETE; - fprintf(stderr, "managed to create and allocate structexprstruct \n"); - // very weird: can create and allocate structexpstruct but not structexprstructfields - - // DEBUG - test creation of a non-returned class from this - fprintf(stderr, - "about to try to create and allocate structexprstructfields (but not return)\n"); - StructExprStructFields* test_DELETE2 = new StructExprStructFields(*this); - delete test_DELETE2; - fprintf(stderr, - "managed to create and allocate structexprstructfields (if not returned) \n"); - // ok this fails. fair enough. - - return new StructExprStructFields(*this); - } - }; - - // AST node of the functional update struct creator - class StructExprStructBase : public StructExprStruct { - StructBase struct_base; - - public: - ::std::string as_string() const; - - /*inline StructBase get_struct_base() const { - return struct_base; - }*/ - - StructExprStructBase(PathInExpression struct_path, StructBase base_struct, - ::std::vector inner_attribs, ::std::vector outer_attribs, - location_t locus) : - StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), - ::std::move(outer_attribs), locus), - struct_base(::std::move(base_struct)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructBase* clone_expr_impl() const OVERRIDE { - return new StructExprStructBase(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructBase* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprStructBase(*this); - } - }; - - // AST node of a tuple struct creator - class StructExprTuple : public StructExpr { - ::std::vector inner_attrs; - //::std::vector exprs; - ::std::vector< ::std::unique_ptr > exprs; - - location_t locus; - - public: - ::std::string as_string() const; - - inline const ::std::vector& get_inner_attrs() const { - return inner_attrs; - } - - /*inline ::std::vector< ::std::unique_ptr > get_exprs() const { - return exprs; - }*/ - - StructExprTuple(PathInExpression struct_path, - ::std::vector< ::std::unique_ptr > tuple_exprs, - ::std::vector inner_attribs, ::std::vector outer_attribs, - location_t locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), exprs(::std::move(tuple_exprs)), locus(locus) { - } - - // copy constructor with vector clone - StructExprTuple(StructExprTuple const& other) : - StructExpr(other), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - exprs.reserve(other.exprs.size()); - - for (const auto& e : other.exprs) { - exprs.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - StructExprTuple& operator=(StructExprTuple const& other) { - StructExpr::operator=(other); - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - exprs.reserve(other.exprs.size()); - - for (const auto& e : other.exprs) { - exprs.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - StructExprTuple(StructExprTuple&& other) = default; - StructExprTuple& operator=(StructExprTuple&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprTuple* clone_expr_impl() const OVERRIDE { - return new StructExprTuple(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprTuple* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprTuple(*this); - } - }; - - // AST node of a "unit" struct creator (no fields and no braces) - class StructExprUnit : public StructExpr { - location_t locus; - - public: - ::std::string as_string() const { - return get_struct_name().as_string(); - // return struct_name.as_string(); - } - - StructExprUnit(PathInExpression struct_path, ::std::vector outer_attribs, - location_t locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - locus(locus) {} - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprUnit* clone_expr_impl() const OVERRIDE { - return new StructExprUnit(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprUnit* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprUnit(*this); - } - }; - - // aka EnumerationVariantExpr - // Base AST node representing creation of an enum variant instance - abstract - class EnumVariantExpr : public ExprWithoutBlock { - PathInExpression enum_variant_path; - - protected: - // Protected constructor for initialising enum_variant_path - EnumVariantExpr( - PathInExpression path_to_enum_variant, ::std::vector outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)), - enum_variant_path(::std::move(path_to_enum_variant)) {} - - public: - // TODO: maybe remove and have string version gotten here directly - inline PathInExpression get_enum_variant_path() const { - return enum_variant_path; - } - }; - - // Base AST node for a single enum expression field (in enum instance creation) - abstract - class EnumExprField { - public: - virtual ~EnumExprField() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_enum_expr_field() const { - return ::std::unique_ptr(clone_enum_expr_field_impl()); - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual EnumExprField* clone_enum_expr_field_impl() const = 0; - }; - - // Identifier-only variant of EnumExprField AST node - class EnumExprFieldIdentifier : public EnumExprField { - Identifier field_name; - - // TODO: should this store location data? - - public: - EnumExprFieldIdentifier(Identifier field_identifier) : - field_name(::std::move(field_identifier)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIdentifier* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIdentifier(*this); - } - }; - - // Base AST node for a single enum expression field with an assigned value - abstract - class EnumExprFieldWithVal : public EnumExprField { - // Expr* value; - ::std::unique_ptr value; - - // TODO: should this store location data? - - protected: - EnumExprFieldWithVal(::std::unique_ptr field_value) : - value(::std::move(field_value)) {} - - // Copy constructor must clone unique_ptr value - EnumExprFieldWithVal(EnumExprFieldWithVal const& other) : - value(other.value->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - EnumExprFieldWithVal& operator=(EnumExprFieldWithVal const& other) { - value = other.value->clone_expr(); - - return *this; - } - - // move constructors - EnumExprFieldWithVal(EnumExprFieldWithVal&& other) = default; - EnumExprFieldWithVal& operator=(EnumExprFieldWithVal&& other) = default; - }; - - // Identifier and value variant of EnumExprField AST node - class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal { - Identifier field_name; - - // TODO: should this store location data? - - public: - EnumExprFieldIdentifierValue(Identifier field_name, ::std::unique_ptr field_value) : - EnumExprFieldWithVal(::std::move(field_value)), field_name(::std::move(field_name)) {} - - // copy constructor, destructor, and assignment operator should not need defining - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIdentifierValue* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIdentifierValue(*this); - } - }; - - // Tuple index and value variant of EnumExprField AST node - class EnumExprFieldIndexValue : public EnumExprFieldWithVal { - TupleIndex index; - // TODO: implement "with val" as a template with EnumExprField as type param? - - // TODO: should this store location data? - - public: - EnumExprFieldIndexValue(TupleIndex field_index, ::std::unique_ptr field_value) : - EnumExprFieldWithVal(::std::move(field_value)), index(field_index) {} - - // copy constructor, destructor, and assignment operator should not need defining - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIndexValue* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIndexValue(*this); - } - }; - - // Struct-like syntax enum variant instance creation AST node - class EnumExprStruct : public EnumVariantExpr { - //::std::vector fields; - ::std::vector< ::std::unique_ptr > fields; - - location_t locus; - - public: - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr > get_fields() const { - return fields; - }*/ - - EnumExprStruct(PathInExpression enum_variant_path, - ::std::vector< ::std::unique_ptr > variant_fields, - ::std::vector outer_attribs, location_t locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - fields(::std::move(variant_fields)), locus(locus) {} - - // copy constructor with vector clone - EnumExprStruct(EnumExprStruct const& other) : EnumVariantExpr(other), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_enum_expr_field()); - } - } - - // overloaded assignment operator with vector clone - EnumExprStruct& operator=(EnumExprStruct const& other) { - EnumVariantExpr::operator=(other); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_enum_expr_field()); - } - - return *this; - } - - // move constructors - EnumExprStruct(EnumExprStruct&& other) = default; - EnumExprStruct& operator=(EnumExprStruct&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprStruct* clone_expr_impl() const OVERRIDE { - return new EnumExprStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprStruct* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprStruct(*this); - } - }; - - // Tuple-like syntax enum variant instance creation AST node - class EnumExprTuple : public EnumVariantExpr { - //::std::vector values; - ::std::vector< ::std::unique_ptr > values; - - location_t locus; - - public: - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr > get_values() const { - return values; - }*/ - - EnumExprTuple(PathInExpression enum_variant_path, - ::std::vector< ::std::unique_ptr > variant_values, - ::std::vector outer_attribs, location_t locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - values(::std::move(variant_values)), locus(locus) {} - - // copy constructor with vector clone - EnumExprTuple(EnumExprTuple const& other) : EnumVariantExpr(other), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - EnumExprTuple& operator=(EnumExprTuple const& other) { - EnumVariantExpr::operator=(other); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - EnumExprTuple(EnumExprTuple&& other) = default; - EnumExprTuple& operator=(EnumExprTuple&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprTuple* clone_expr_impl() const OVERRIDE { - return new EnumExprTuple(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprTuple* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprTuple(*this); - } - }; - - // No-field enum variant instance creation AST node - class EnumExprFieldless : public EnumVariantExpr { - location_t locus; - - public: - ::std::string as_string() const { - // return enum_variant_path.as_string(); - return get_enum_variant_path().as_string(); - } - - EnumExprFieldless(PathInExpression enum_variant_path, - ::std::vector outer_attribs, location_t locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - locus(locus) {} - - // copy constructor, destructor, and assignment operator should not need defining - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldless* clone_expr_impl() const OVERRIDE { - return new EnumExprFieldless(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldless* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprFieldless(*this); - } - }; - - // Function call expression AST node - class CallExpr : public ExprWithoutBlock { - // Expr* function; - ::std::unique_ptr function; - //::std::vector params; // inlined form of CallParams - ::std::vector< ::std::unique_ptr > params; - - location_t locus; - - public: - /*~CallExpr() { - delete function; - }*/ - - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr > get_params() const { - return params; - }*/ - - CallExpr(::std::unique_ptr function_expr, - ::std::vector< ::std::unique_ptr > function_params, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - function(::std::move(function_expr)), params(::std::move(function_params)), - locus(locus) {} - - // copy constructor requires clone - CallExpr(CallExpr const& other) : - ExprWithoutBlock(other), function(other.function->clone_expr()), locus(other.locus) - /*, params(other.params),*/ { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone - CallExpr& operator=(CallExpr const& other) { - ExprWithoutBlock::operator=(other); - function = other.function->clone_expr(); - locus = other.locus; - // params = other.params; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - CallExpr(CallExpr&& other) = default; - CallExpr& operator=(CallExpr&& other) = default; - - // Returns whether function call has parameters. - inline bool has_params() const { - return !params.empty(); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual CallExpr* clone_expr_impl() const OVERRIDE { - return new CallExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual CallExpr* clone_expr_without_block_impl() const OVERRIDE { - return new CallExpr(*this); - } - }; - - // Method call expression AST node - class MethodCallExpr : public ExprWithoutBlock { - // Expr* receiver; - ::std::unique_ptr receiver; - PathExprSegment method_name; - //::std::vector params; // inlined form of CallParams - ::std::vector< ::std::unique_ptr > params; - - location_t locus; - - public: - /*~MethodCallExpr() { - delete receiver; - }*/ - - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr > get_params() const { - return params; - }*/ - - MethodCallExpr(::std::unique_ptr call_receiver, PathExprSegment method_path, - ::std::vector< ::std::unique_ptr > method_params, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - receiver(::std::move(call_receiver)), method_name(::std::move(method_path)), - params(::std::move(method_params)), locus(locus) {} - - // copy constructor required due to cloning - MethodCallExpr(MethodCallExpr const& other) : - ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), - method_name(other.method_name), locus(other.locus) - /*, params(other.params),*/ { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone receiver object - MethodCallExpr& operator=(MethodCallExpr const& other) { - ExprWithoutBlock::operator=(other); - receiver = other.receiver->clone_expr(); - method_name = other.method_name; - locus = other.locus; - // params = other.params; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - MethodCallExpr(MethodCallExpr&& other) = default; - MethodCallExpr& operator=(MethodCallExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MethodCallExpr* clone_expr_impl() const OVERRIDE { - return new MethodCallExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MethodCallExpr* clone_expr_without_block_impl() const OVERRIDE { - return new MethodCallExpr(*this); - } - }; - - // aka FieldExpression - // Struct or union field access expression AST node - class FieldAccessExpr : public ExprWithoutBlock { - // Expr* receiver; - ::std::unique_ptr receiver; - Identifier field; - - location_t locus; - - public: - /*~FieldAccessExpr() { - delete receiver; - }*/ - - ::std::string as_string() const; - - FieldAccessExpr(::std::unique_ptr field_access_receiver, Identifier field_name, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - receiver(::std::move(field_access_receiver)), field(::std::move(field_name)), - locus(locus) {} - - // Copy constructor required due to unique_ptr cloning - FieldAccessExpr(FieldAccessExpr const& other) : - ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), field(other.field), - locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - FieldAccessExpr& operator=(FieldAccessExpr const& other) { - ExprWithoutBlock::operator=(other); - receiver = other.receiver->clone_expr(); - field = other.field; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - FieldAccessExpr(FieldAccessExpr&& other) = default; - FieldAccessExpr& operator=(FieldAccessExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual FieldAccessExpr* clone_expr_impl() const OVERRIDE { - return new FieldAccessExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual FieldAccessExpr* clone_expr_without_block_impl() const OVERRIDE { - return new FieldAccessExpr(*this); - } - }; - - // Closure parameter data structure - struct ClosureParam { - private: - // Pattern pattern; - ::std::unique_ptr pattern; - - // bool has_type_given; - // Type type; - ::std::unique_ptr type; - - // TODO: should this store location data? - - public: - // Returns whether the type of the parameter has been given. - inline bool has_type_given() const { - return type != NULL; - } - - // Constructor for closure parameter - ClosureParam( - ::std::unique_ptr param_pattern, ::std::unique_ptr param_type = NULL) : - pattern(::std::move(param_pattern)), - type(::std::move(param_type)) {} - - // Copy constructor required due to cloning as a result of unique_ptrs - ClosureParam(ClosureParam const& other) : pattern(other.pattern->clone_pattern()) { - // guard to protect from null pointer dereference - if (other.type != NULL) { - type = other.type->clone_type(); - } - } - - ~ClosureParam() = default; - - // Assignment operator must be overloaded to clone as well - ClosureParam& operator=(ClosureParam const& other) { - pattern = other.pattern->clone_pattern(); - type = other.type->clone_type(); - - return *this; - } - - // move constructors - ClosureParam(ClosureParam&& other) = default; - ClosureParam& operator=(ClosureParam&& other) = default; - - // Returns whether closure parameter is in an error state. - inline bool is_error() const { - return pattern == NULL; - } - - // Creates an error state closure parameter. - static ClosureParam create_error() { - return ClosureParam(NULL); - } - - ::std::string as_string() const; - }; - - // Base closure definition expression AST node - abstract - class ClosureExpr : public ExprWithoutBlock { - bool has_move; - ::std::vector params; // may be empty - // also note a double pipe "||" can be used for empty params - does not need a space - - location_t locus; - - protected: - ClosureExpr(::std::vector closure_params, bool has_move, - ::std::vector outer_attribs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - has_move(has_move), params(::std::move(closure_params)), locus(locus) {} - - // Copy constructor, destructor, and assignment operator override should not be needed - public: - virtual ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Represents a non-type-specified closure expression AST node - class ClosureExprInner : public ClosureExpr { - // Expr* closure_inner; - ::std::unique_ptr closure_inner; - - public: - /*~ClosureExprInner() { - delete closure_inner; - }*/ - - ::std::string as_string() const; - - // Constructor for a ClosureExprInner - ClosureExprInner(::std::unique_ptr closure_inner_expr, - ::std::vector closure_params, location_t locus, bool is_move = false, - ::std::vector outer_attribs = ::std::vector()) : - ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), - closure_inner(::std::move(closure_inner_expr)) {} - - // Copy constructor must be defined to allow copying via cloning of unique_ptr - ClosureExprInner(ClosureExprInner const& other) : - ClosureExpr(other), closure_inner(other.closure_inner->clone_expr()) {} - // TODO: ensure that this actually constructs properly - - // Destructor - define here if required - - // Overload assignment operator to clone closure_inner - ClosureExprInner& operator=(ClosureExprInner const& other) { - ClosureExpr::operator=(other); - closure_inner = other.closure_inner->clone_expr(); - // params = other.params; - // has_move = other.has_move; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ClosureExprInner(ClosureExprInner&& other) = default; - ClosureExprInner& operator=(ClosureExprInner&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInner* clone_expr_impl() const OVERRIDE { - return new ClosureExprInner(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInner* clone_expr_without_block_impl() const OVERRIDE { - return new ClosureExprInner(*this); - } - }; - - // Forward decl BlockExpr for ClosureExprInnerTyped - // class BlockExpr; - - // A block AST node - class BlockExpr : public ExprWithBlock { - ::std::vector inner_attrs; - - /*bool has_statements; - Statements statements;*/ - - // bool has_statements; - ::std::vector< ::std::unique_ptr > statements; - // bool has_expr; - ::std::unique_ptr expr; // inlined from Statements - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether the block contains statements. - inline bool has_statements() const { - return !statements.empty(); - } - - // Returns whether the block contains an expression - inline bool has_expr() const { - return expr != NULL; - } - - BlockExpr(::std::vector< ::std::unique_ptr > block_statements, - ::std::unique_ptr block_expr, ::std::vector inner_attribs, - ::std::vector outer_attribs, location_t locus) : - ExprWithBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), statements(::std::move(block_statements)), - expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - BlockExpr(BlockExpr const& other) : - ExprWithBlock(other), /*statements(other.statements),*/ - inner_attrs(other.inner_attrs), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.expr != NULL) { - expr = other.expr->clone_expr_without_block(); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - statements.reserve(other.statements.size()); - - for (const auto& e : other.statements) { - statements.push_back(e->clone_stmt()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone pointer - BlockExpr& operator=(BlockExpr const& other) { - ExprWithBlock::operator=(other); - // statements = other.statements; - expr = other.expr->clone_expr_without_block(); - inner_attrs = other.inner_attrs; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - statements.reserve(other.statements.size()); - - for (const auto& e : other.statements) { - statements.push_back(e->clone_stmt()); - } - - return *this; - } - - // move constructors - BlockExpr(BlockExpr&& other) = default; - BlockExpr& operator=(BlockExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr clone_block_expr() const { - return ::std::unique_ptr(clone_block_expr_impl()); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BlockExpr* clone_expr_impl() const OVERRIDE { - return new BlockExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new BlockExpr(*this); - } - - /* This is the base method as not an abstract class - not virtual but could be in future - * if required. */ - /*virtual*/ BlockExpr* clone_block_expr_impl() const { - return new BlockExpr(*this); - } - }; - - // Represents a type-specified closure expression AST node - class ClosureExprInnerTyped : public ClosureExpr { - // Type return_type; - ::std::unique_ptr return_type; - // BlockExpr* expr; - ::std::unique_ptr expr; // only used because may be polymorphic in future - - public: - /*~ClosureExprInnerTyped() { - delete expr; - }*/ - - ::std::string as_string() const; - - // Constructor potentially with a move - ClosureExprInnerTyped(::std::unique_ptr closure_return_type, - ::std::unique_ptr closure_expr, ::std::vector closure_params, - location_t locus, bool is_move = false, - ::std::vector outer_attribs = ::std::vector()) : - ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), - return_type(::std::move(closure_return_type)), expr(::std::move(closure_expr)) {} - - // Copy constructor requires cloning - ClosureExprInnerTyped(ClosureExprInnerTyped const& other) : - ClosureExpr(other), return_type(other.return_type->clone_type()), - expr(other.expr->clone_block_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptrs - ClosureExprInnerTyped& operator=(ClosureExprInnerTyped const& other) { - ClosureExpr::operator=(other); - return_type = other.return_type->clone_type(); - expr = other.expr->clone_block_expr(); - // params = other.params; - // has_move = other.has_move; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ClosureExprInnerTyped(ClosureExprInnerTyped&& other) = default; - ClosureExprInnerTyped& operator=(ClosureExprInnerTyped&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInnerTyped* clone_expr_impl() const OVERRIDE { - return new ClosureExprInnerTyped(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInnerTyped* clone_expr_without_block_impl() const OVERRIDE { - return new ClosureExprInnerTyped(*this); - } - }; - - // AST node representing continue expression within loops - class ContinueExpr : public ExprWithoutBlock { - // bool has_label; - Lifetime label; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns true if the continue expr has a label. - inline bool has_label() const { - return !label.is_error(); - } - - // Constructor for a ContinueExpr with a label. - ContinueExpr(location_t locus, Lifetime label = Lifetime::error(), - ::std::vector outer_attribs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attribs)), - label(::std::move(label)), locus(locus) {} - - // copy constructor, destructor, and assignment operator should not need defining - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ContinueExpr* clone_expr_impl() const OVERRIDE { - return new ContinueExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ContinueExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ContinueExpr(*this); - } - }; - // TODO: merge "break" and "continue"? Or even merge in "return"? - - // AST node representing break expression within loops - class BreakExpr : public ExprWithoutBlock { - // bool has_label; - Lifetime label; - - // bool has_break_expr; - // Expr* break_expr; // may be uninitialised - ::std::unique_ptr break_expr; - - location_t locus; - - public: - /*~BreakExpr() { - if (has_break_expr) { - delete break_expr; - } - }*/ - - ::std::string as_string() const; - - // Returns whether the break expression has a label or not. - inline bool has_label() const { - return !label.is_error(); - } - - // Returns whether the break expression has an expression used in the break or not. - inline bool has_break_expr() const { - return break_expr != NULL; - } - - // Constructor for a break expression - BreakExpr(location_t locus, Lifetime break_label = Lifetime::error(), - ::std::unique_ptr expr_in_break = NULL, - ::std::vector outer_attribs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attribs)), - label(::std::move(break_label)), break_expr(::std::move(expr_in_break)), locus(locus) {} - - // Copy constructor defined to use clone for unique pointer - BreakExpr(BreakExpr const& other) : - ExprWithoutBlock(other), label(other.label), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.break_expr != NULL) { - break_expr = other.break_expr->clone_expr(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone unique pointer - BreakExpr& operator=(BreakExpr const& other) { - ExprWithoutBlock::operator=(other); - label = other.label; - break_expr = other.break_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - BreakExpr(BreakExpr&& other) = default; - BreakExpr& operator=(BreakExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BreakExpr* clone_expr_impl() const OVERRIDE { - return new BreakExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BreakExpr* clone_expr_without_block_impl() const OVERRIDE { - return new BreakExpr(*this); - } - }; - - // Base range expression AST node object - abstract - class RangeExpr : public ExprWithoutBlock { - location_t locus; - - protected: - // outer attributes not allowed before range expressions - RangeExpr(location_t locus) : - ExprWithoutBlock(::std::vector()), locus(locus) {} - - public: - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Range from (inclusive) and to (exclusive) expression AST node object - // aka RangeExpr; constructs a std::ops::Range object - class RangeFromToExpr : public RangeExpr { - /*Expr* from; - Expr* to;*/ - ::std::unique_ptr from; - ::std::unique_ptr to; - - public: - /*~RangeFromToExpr() { - delete from; - delete to; - }*/ - - ::std::string as_string() const; - - RangeFromToExpr(::std::unique_ptr range_from, ::std::unique_ptr range_to, - location_t locus) : - RangeExpr(locus), - from(::std::move(range_from)), to(::std::move(range_to)) {} - - // Copy constructor with cloning - RangeFromToExpr(RangeFromToExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique pointers - RangeFromToExpr& operator=(RangeFromToExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeFromToExpr(RangeFromToExpr&& other) = default; - RangeFromToExpr& operator=(RangeFromToExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromToExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromToExpr(*this); - } - }; - - // Range from (inclusive) expression AST node object - // constructs a std::ops::RangeFrom object - class RangeFromExpr : public RangeExpr { - // Expr* from; - ::std::unique_ptr from; - - public: - /*~RangeFromExpr() { - delete from; - }*/ - - ::std::string as_string() const; - - RangeFromExpr(::std::unique_ptr range_from, location_t locus) : - RangeExpr(locus), from(::std::move(range_from)) {} - - // Copy constructor with clone - RangeFromExpr(RangeFromExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - RangeFromExpr& operator=(RangeFromExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - - return *this; - } - - // move constructors - RangeFromExpr(RangeFromExpr&& other) = default; - RangeFromExpr& operator=(RangeFromExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromExpr(*this); - } - }; - - // Range to (exclusive) expression AST node object - // constructs a std::ops::RangeTo object - class RangeToExpr : public RangeExpr { - // Expr* to; - ::std::unique_ptr to; - - public: - /*~RangeToExpr() { - delete to; - }*/ - - ::std::string as_string() const; - - // outer attributes not allowed - RangeToExpr(::std::unique_ptr range_to, location_t locus) : - RangeExpr(locus), to(::std::move(range_to)) {} - - // Copy constructor with clone - RangeToExpr(RangeToExpr const& other) : RangeExpr(other), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - RangeToExpr& operator=(RangeToExpr const& other) { - RangeExpr::operator=(other); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeToExpr(RangeToExpr&& other) = default; - RangeToExpr& operator=(RangeToExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToExpr* clone_expr_impl() const OVERRIDE { - return new RangeToExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeToExpr(*this); - } - }; - - // Full range expression AST node object - // constructs a std::ops::RangeFull object - class RangeFullExpr : public RangeExpr { - public: - ::std::string as_string() const; - - RangeFullExpr(location_t locus) : RangeExpr(locus) {} - // outer attributes not allowed - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFullExpr* clone_expr_impl() const OVERRIDE { - return new RangeFullExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFullExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFullExpr(*this); - } - }; - - // Range from (inclusive) and to (inclusive) expression AST node object - // aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object - class RangeFromToInclExpr : public RangeExpr { - /*Expr* from; - Expr* to;*/ - ::std::unique_ptr from; - ::std::unique_ptr to; - - public: - /*~RangeFromToInclExpr() { - delete from; - delete to; - }*/ - - ::std::string as_string() const; - - RangeFromToInclExpr(::std::unique_ptr range_from, ::std::unique_ptr range_to, - location_t locus) : - RangeExpr(locus), - from(::std::move(range_from)), to(::std::move(range_to)) {} - // outer attributes not allowed - - // Copy constructor with clone - RangeFromToInclExpr(RangeFromToInclExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to use clone - RangeFromToInclExpr& operator=(RangeFromToInclExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeFromToInclExpr(RangeFromToInclExpr&& other) = default; - RangeFromToInclExpr& operator=(RangeFromToInclExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToInclExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromToInclExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToInclExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromToInclExpr(*this); - } - }; - - // Range to (inclusive) expression AST node object - // aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object - class RangeToInclExpr : public RangeExpr { - // Expr* to; - ::std::unique_ptr to; - - public: - /*~RangeToInclExpr() { - delete to; - }*/ - - ::std::string as_string() const; - - RangeToInclExpr(::std::unique_ptr range_to, location_t locus) : - RangeExpr(locus), to(::std::move(range_to)) {} - // outer attributes not allowed - - // Copy constructor with clone - RangeToInclExpr(RangeToInclExpr const& other) : - RangeExpr(other), to(other.to->clone_expr()) {} - - // Define destructor here if required - - // Overload assignment operator to clone pointer - RangeToInclExpr& operator=(RangeToInclExpr const& other) { - RangeExpr::operator=(other); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeToInclExpr(RangeToInclExpr&& other) = default; - RangeToInclExpr& operator=(RangeToInclExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToInclExpr* clone_expr_impl() const OVERRIDE { - return new RangeToInclExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToInclExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeToInclExpr(*this); - } - }; - - // Return expression AST node representation - class ReturnExpr : public ExprWithoutBlock { - // bool has_return_expr; - // Expr* return_expr; - ::std::unique_ptr return_expr; - - location_t locus; - - public: - /*~ReturnExpr() { - if (has_return_expr) { - delete return_expr; - } - }*/ - - ::std::string as_string() const; - - // Returns whether the object has an expression returned (i.e. not void return type). - inline bool has_return_expr() const { - return return_expr != NULL; - } - - // Constructor for ReturnExpr. - ReturnExpr(location_t locus, ::std::unique_ptr returned_expr = NULL, - ::std::vector outer_attribs = ::std::vector()) : - ExprWithoutBlock(::std::move(outer_attribs)), - return_expr(::std::move(returned_expr)), locus(locus) {} - - // Copy constructor with clone - ReturnExpr(ReturnExpr const& other) : ExprWithoutBlock(other), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.return_expr != NULL) { - return_expr = other.return_expr->clone_expr(); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone return_expr pointer - ReturnExpr& operator=(ReturnExpr const& other) { - ExprWithoutBlock::operator=(other); - return_expr = other.return_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ReturnExpr(ReturnExpr&& other) = default; - ReturnExpr& operator=(ReturnExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReturnExpr* clone_expr_impl() const OVERRIDE { - return new ReturnExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ReturnExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ReturnExpr(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MacroInvocation; - /*class MacroInvocation : public ExprWithoutBlock { - public: - ::std::string as_string() const; - };*/ - - // An unsafe block AST node - class UnsafeBlockExpr : public ExprWithBlock { - // Or just have it extend BlockExpr - // BlockExpr* expr; - ::std::unique_ptr expr; - - location_t locus; - - public: - /*~UnsafeBlockExpr() { - delete expr; - }*/ - - ::std::string as_string() const; - - UnsafeBlockExpr(::std::unique_ptr block_expr, - ::std::vector outer_attribs, location_t locus) : - ExprWithBlock(::std::move(outer_attribs)), - expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - UnsafeBlockExpr(UnsafeBlockExpr const& other) : - ExprWithBlock(other), expr(other.expr->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - UnsafeBlockExpr& operator=(UnsafeBlockExpr const& other) { - ExprWithBlock::operator=(other); - expr = other.expr->clone_block_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - UnsafeBlockExpr(UnsafeBlockExpr&& other) = default; - UnsafeBlockExpr& operator=(UnsafeBlockExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UnsafeBlockExpr* clone_expr_impl() const OVERRIDE { - return new UnsafeBlockExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual UnsafeBlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new UnsafeBlockExpr(*this); - } - }; - - // Loop label expression AST node used with break and continue expressions - // TODO: inline? - class LoopLabel /*: public Node*/ { - Lifetime label; // or type LIFETIME_OR_LABEL - - location_t locus; - - public: - ::std::string as_string() const; - - LoopLabel(Lifetime loop_label, location_t locus = UNKNOWN_LOCATION) : - label(::std::move(loop_label)), locus(locus) {} - - // Returns whether the LoopLabel is in an error state. - inline bool is_error() const { - return label.is_error(); - } - - // Creates an error state LoopLabel. - static LoopLabel error() { - return LoopLabel(Lifetime::error()); - } - - location_t get_locus() const { - return locus; - } - }; - - // Base loop expression AST node - aka LoopExpr - class BaseLoopExpr : public ExprWithBlock { - protected: - // protected to allow subclasses better use of them - // bool has_loop_label; - LoopLabel loop_label; - - // BlockExpr* loop_block; - ::std::unique_ptr loop_block; - - private: - location_t locus; - - protected: - // Constructor for BaseLoopExpr - BaseLoopExpr(::std::unique_ptr loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector outer_attribs = ::std::vector()) : - ExprWithBlock(::std::move(outer_attribs)), - loop_label(::std::move(loop_label)), loop_block(::std::move(loop_block)), locus(locus) { - } - - // Copy constructor for BaseLoopExpr with clone - BaseLoopExpr(BaseLoopExpr const& other) : - ExprWithBlock(other), loop_label(other.loop_label), - loop_block(other.loop_block->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - BaseLoopExpr& operator=(BaseLoopExpr const& other) { - ExprWithBlock::operator=(other); - loop_block = other.loop_block->clone_block_expr(); - loop_label = other.loop_label; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - BaseLoopExpr(BaseLoopExpr&& other) = default; - BaseLoopExpr& operator=(BaseLoopExpr&& other) = default; - - public: - /*~BaseLoopExpr() { - delete loop_block; - }*/ - - inline bool has_loop_label() const { - return !loop_label.is_error(); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // 'Loop' expression (i.e. the infinite loop) AST node - class LoopExpr : public BaseLoopExpr { - public: - ::std::string as_string() const; - - // Constructor for LoopExpr - LoopExpr(::std::unique_ptr loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector outer_attribs = ::std::vector()) : - BaseLoopExpr(::std::move(loop_block), locus, ::std::move(loop_label), - ::std::move(outer_attribs)) {} - - // copy constructor, destructor, and assignment operator should not need modification - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LoopExpr* clone_expr_impl() const OVERRIDE { - return new LoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new LoopExpr(*this); - } - }; - - // While loop expression AST node (predicate loop) - class WhileLoopExpr : public BaseLoopExpr { - // Expr* condition; - ::std::unique_ptr condition; - - public: - /*~WhileLoopExpr() { - delete condition; - }*/ - - ::std::string as_string() const; - - // Constructor for while loop with loop label - WhileLoopExpr(::std::unique_ptr loop_condition, - ::std::unique_ptr loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector outer_attribs = ::std::vector()) : - BaseLoopExpr( - ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - condition(::std::move(loop_condition)) {} - - // Copy constructor with clone - WhileLoopExpr(WhileLoopExpr const& other) : - BaseLoopExpr(other), condition(other.condition->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - WhileLoopExpr& operator=(WhileLoopExpr const& other) { - BaseLoopExpr::operator=(other); - condition = other.condition->clone_expr(); - // loop_block = other.loop_block->clone_block_expr(); - // loop_label = other.loop_label; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - WhileLoopExpr(WhileLoopExpr&& other) = default; - WhileLoopExpr& operator=(WhileLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLoopExpr* clone_expr_impl() const OVERRIDE { - return new WhileLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new WhileLoopExpr(*this); - } - }; - - // Forward decl MatchArmPatterns - // struct MatchArmPatterns; - - // While let loop expression AST node (predicate pattern loop) - class WhileLetLoopExpr : public BaseLoopExpr { - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined - // Expr* condition; - ::std::unique_ptr condition; - - public: - /*~WhileLetLoopExpr() { - delete condition; - }*/ - - ::std::string as_string() const; - - // Constructor with a loop label - WhileLetLoopExpr(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr condition, ::std::unique_ptr loop_block, - location_t locus, LoopLabel loop_label = LoopLabel::error(), - ::std::vector outer_attribs = ::std::vector()) : - BaseLoopExpr( - ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - match_arm_patterns(::std::move(match_arm_patterns)), condition(::std::move(condition)) { - } - - // Copy constructor with clone - WhileLetLoopExpr(WhileLetLoopExpr const& other) : - BaseLoopExpr(other), /*match_arm_patterns(other.match_arm_patterns),*/ condition( - other.condition->clone_expr()) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone pointers - WhileLetLoopExpr& operator=(WhileLetLoopExpr const& other) { - BaseLoopExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - condition = other.condition->clone_expr(); - // loop_block = other.loop_block->clone_block_expr(); - // loop_label = other.loop_label; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - WhileLetLoopExpr(WhileLetLoopExpr&& other) = default; - WhileLetLoopExpr& operator=(WhileLetLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLetLoopExpr* clone_expr_impl() const OVERRIDE { - return new WhileLetLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLetLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new WhileLetLoopExpr(*this); - } - }; - - // For loop expression AST node (iterator loop) - class ForLoopExpr : public BaseLoopExpr { - // Pattern pattern; - ::std::unique_ptr pattern; - // Expr* iterator_expr; - ::std::unique_ptr iterator_expr; - - public: - /*~ForLoopExpr() { - delete iterator_expr; - }*/ - - ::std::string as_string() const; - - // Constructor with loop label - ForLoopExpr(::std::unique_ptr loop_pattern, - ::std::unique_ptr iterator_expr, ::std::unique_ptr loop_body, - location_t locus, LoopLabel loop_label = LoopLabel::error(), - ::std::vector outer_attribs = ::std::vector()) : - BaseLoopExpr( - ::std::move(loop_body), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - pattern(::std::move(loop_pattern)), iterator_expr(::std::move(iterator_expr)) {} - - // Copy constructor with clone - ForLoopExpr(ForLoopExpr const& other) : - BaseLoopExpr(other), pattern(other.pattern->clone_pattern()), - iterator_expr(other.iterator_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ForLoopExpr& operator=(ForLoopExpr const& other) { - BaseLoopExpr::operator=(other); - pattern = other.pattern->clone_pattern(); - iterator_expr = other.iterator_expr->clone_expr(); - /*loop_block = other.loop_block->clone_block_expr(); - loop_label = other.loop_label; - outer_attrs = other.outer_attrs;*/ - - return *this; - } - - // move constructors - ForLoopExpr(ForLoopExpr&& other) = default; - ForLoopExpr& operator=(ForLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ForLoopExpr* clone_expr_impl() const OVERRIDE { - return new ForLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ForLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new ForLoopExpr(*this); - } - }; - - // forward decl for IfExpr - class IfLetExpr; - - // Base if expression with no "else" or "if let" AST node - class IfExpr : public ExprWithBlock { - /*Expr* condition; - BlockExpr* if_block;*/ - ::std::unique_ptr condition; - ::std::unique_ptr if_block; - /*union { - BlockExpr else_block; - IfExpr* if_expr; - IfLetExpr if_let_expr; - } consequent_block;*/ - - location_t locus; - - public: - /*virtual ~IfExpr() { - delete condition; - delete if_block; - }*/ - - ::std::string as_string() const; - - IfExpr(::std::unique_ptr condition, ::std::unique_ptr if_block, - location_t locus) : - ExprWithBlock(::std::vector()), - condition(::std::move(condition)), if_block(::std::move(if_block)), locus(locus) {} - // outer attributes are never allowed on IfExprs - - // Copy constructor with clone - IfExpr(IfExpr const& other) : - ExprWithBlock(other), condition(other.condition->clone_expr()), - if_block(other.if_block->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone expressions - IfExpr& operator=(IfExpr const& other) { - ExprWithBlock::operator=(other); - condition = other.condition->clone_expr(); - if_block = other.if_block->clone_block_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - IfExpr(IfExpr&& other) = default; - IfExpr& operator=(IfExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr clone_if_expr() const { - return ::std::unique_ptr(clone_if_expr_impl()); - } - - /* Note that multiple "else if"s are handled via nested ASTs rather than a vector of - * else ifs - i.e. not like a switch statement. TODO - is this a better approach? or - * does it not parse correctly and have downsides? */ - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExpr* clone_expr_impl() const OVERRIDE { - return new IfExpr(*this); - } - - // Base clone function but still concrete as concrete base class - virtual IfExpr* clone_if_expr_impl() const { - return new IfExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExpr* clone_expr_with_block_impl() const OVERRIDE { - return new IfExpr(*this); - } - }; - - // If expression with an ending "else" expression AST node (trailing) - class IfExprConseqElse : public IfExpr { - // BlockExpr* else_block; - ::std::unique_ptr else_block; - - public: - /*~IfExprConseqElse() { - delete else_block; - }*/ - - ::std::string as_string() const; - - IfExprConseqElse(::std::unique_ptr condition, ::std::unique_ptr if_block, - ::std::unique_ptr else_block, location_t locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - else_block(::std::move(else_block)) {} - // again, outer attributes not allowed - - // Copy constructor with clone - IfExprConseqElse(IfExprConseqElse const& other) : - IfExpr(other), else_block(other.else_block->clone_block_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator with cloning - IfExprConseqElse& operator=(IfExprConseqElse const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - else_block = other.else_block->clone_block_expr(); - - return *this; - } - - // move constructors - IfExprConseqElse(IfExprConseqElse&& other) = default; - IfExprConseqElse& operator=(IfExprConseqElse&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_expr_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - }; - - // If expression with an ending "else if" expression AST node - class IfExprConseqIf : public IfExpr { - // IfExpr* if_expr; - ::std::unique_ptr if_expr; - - public: - /*~IfExprConseqIf() { - delete if_expr; - }*/ - - ::std::string as_string() const; - - IfExprConseqIf(::std::unique_ptr condition, ::std::unique_ptr if_block, - ::std::unique_ptr conseq_if_expr, location_t locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - if_expr(::std::move(conseq_if_expr)) {} - // outer attributes not allowed - - // Copy constructor with clone - IfExprConseqIf(IfExprConseqIf const& other) : - IfExpr(other), if_expr(other.if_expr->clone_if_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to use clone - IfExprConseqIf& operator=(IfExprConseqIf const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_expr = other.if_expr->clone_if_expr(); - - return *this; - } - - // move constructors - IfExprConseqIf(IfExprConseqIf&& other) = default; - IfExprConseqIf& operator=(IfExprConseqIf&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_expr_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - }; - - // Basic "if let" expression AST node with no else - class IfLetExpr : public ExprWithBlock { - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined - /*Expr* value; - BlockExpr* if_block;*/ - ::std::unique_ptr value; - ::std::unique_ptr if_block; - /*union { - BlockExpr else_block; - IfExpr if_expr; - IfLetExpr* if_let_expr; - } consequent_block;*/ - - location_t locus; - - public: - ::std::string as_string() const; - - IfLetExpr(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr value, ::std::unique_ptr if_block, - location_t locus) : - ExprWithBlock(::std::vector()), - match_arm_patterns(::std::move(match_arm_patterns)), value(::std::move(value)), - if_block(::std::move(if_block)), locus(locus) {} - // outer attributes not allowed on if let exprs either - - // copy constructor with clone - IfLetExpr(IfLetExpr const& other) : - ExprWithBlock(other), - /*match_arm_patterns(other.match_arm_patterns),*/ value(other.value->clone_expr()), - if_block(other.if_block->clone_block_expr()), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - } - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExpr& operator=(IfLetExpr const& other) { - ExprWithBlock::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - value = other.value->clone_expr(); - if_block = other.if_block->clone_block_expr(); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - IfLetExpr(IfLetExpr&& other) = default; - IfLetExpr& operator=(IfLetExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr clone_if_let_expr() const { - return ::std::unique_ptr(clone_if_let_expr_impl()); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExpr* clone_expr_impl() const OVERRIDE { - return new IfLetExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExpr* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExpr(*this); - } - - // Base clone function but still concrete as concrete base class - virtual IfLetExpr* clone_if_let_expr_impl() const { - return new IfLetExpr(*this); - } - }; - - // If expression with an ending "else if let" expression AST node - class IfExprConseqIfLet : public IfExpr { - // IfLetExpr* if_let_expr; - ::std::unique_ptr if_let_expr; - - public: - /*~IfExprIfConseqIfLet() { - delete if_let_expr; - }*/ - - ::std::string as_string() const; - - IfExprConseqIfLet(::std::unique_ptr condition, - ::std::unique_ptr if_block, ::std::unique_ptr conseq_if_let_expr, - location_t locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - if_let_expr(::std::move(conseq_if_let_expr)) {} - // outer attributes not allowed - - // Copy constructor with clone - IfExprConseqIfLet(IfExprConseqIfLet const& other) : - IfExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to use clone - IfExprConseqIfLet& operator=(IfExprConseqIfLet const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_let_expr = other.if_let_expr->clone_if_let_expr(); - - return *this; - } - - // move constructors - IfExprConseqIfLet(IfExprConseqIfLet&& other) = default; - IfExprConseqIfLet& operator=(IfExprConseqIfLet&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_expr_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - }; - - // AST node representing "if let" expression with an "else" expression at the end - class IfLetExprConseqElse : public IfLetExpr { - // BlockExpr* else_block; - ::std::unique_ptr else_block; - - public: - /*~IfLetExprConseqElse() { - delete else_block; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqElse(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr value, ::std::unique_ptr if_block, - ::std::unique_ptr else_block, location_t locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - else_block(::std::move(else_block)) {} - // outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqElse(IfLetExprConseqElse const& other) : - IfLetExpr(other), else_block(other.else_block->clone_block_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqElse& operator=(IfLetExprConseqElse const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - else_block = other.else_block->clone_block_expr(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - IfLetExprConseqElse(IfLetExprConseqElse&& other) = default; - IfLetExprConseqElse& operator=(IfLetExprConseqElse&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - }; - - // AST node representing "if let" expression with an "else if" expression at the end - class IfLetExprConseqIf : public IfLetExpr { - // IfExpr* if_expr; - ::std::unique_ptr if_expr; - - public: - /*~IfLetExprConseqIf() { - delete if_expr; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqIf(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr value, ::std::unique_ptr if_block, - ::std::unique_ptr if_expr, location_t locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - if_expr(::std::move(if_expr)) {} - // again, outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqIf(IfLetExprConseqIf const& other) : - IfLetExpr(other), if_expr(other.if_expr->clone_if_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqIf& operator=(IfLetExprConseqIf const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_expr = other.if_expr->clone_if_expr(); - - return *this; - } - - // move constructors - IfLetExprConseqIf(IfLetExprConseqIf&& other) = default; - IfLetExprConseqIf& operator=(IfLetExprConseqIf&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - }; - - // AST node representing "if let" expression with an "else if let" expression at the end - class IfLetExprConseqIfLet : public IfLetExpr { - // IfLetExpr* if_let_expr; - ::std::unique_ptr if_let_expr; - - public: - /*~IfLetExprConseqIfLet() { - delete if_let_expr; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqIfLet(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr value, ::std::unique_ptr if_block, - ::std::unique_ptr if_let_expr, location_t locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - if_let_expr(::std::move(if_let_expr)) {} - // outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqIfLet(IfLetExprConseqIfLet const& other) : - IfLetExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_let_expr = other.if_let_expr->clone_if_let_expr(); - - return *this; - } - - // move constructors - IfLetExprConseqIfLet(IfLetExprConseqIfLet&& other) = default; - IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - }; - - // Match arm expression - struct MatchArm { - private: - ::std::vector outer_attrs; - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr > match_arm_patterns; // inlined - - // bool has_match_arm_guard; - // Expr* match_arm_guard; // inlined from MatchArmGuard - ::std::unique_ptr guard_expr; - - // TODO: should this store location data? - - public: - /*~MatchArm() { - if (has_match_arm_guard) { - delete match_arm_guard; - } - }*/ - - // Returns whether the MatchArm has a match arm guard expression - inline bool has_match_arm_guard() const { - return guard_expr != NULL; - } - - // Constructor for match arm with a guard expression - MatchArm(::std::vector< ::std::unique_ptr > match_arm_patterns, - ::std::unique_ptr guard_expr = NULL, - ::std::vector outer_attrs = ::std::vector()) : - outer_attrs(::std::move(outer_attrs)), - match_arm_patterns(::std::move(match_arm_patterns)), - guard_expr(::std::move(guard_expr)) {} - - // Copy constructor with clone - MatchArm(MatchArm const& other) : - /*match_arm_patterns(other.match_arm_patterns),*/ outer_attrs(other.outer_attrs) { - // guard to protect from null pointer dereference - if (other.guard_expr != NULL) { - guard_expr = other.guard_expr->clone_expr(); - } - - // DEBUG - fprintf( - stderr, "started copy-constructing match arm (outer attrs, guard expr done)\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - - // DEBUG - fprintf(stderr, "successfully pushed back a match arm pattern\n"); - } - - // DEBUG - fprintf(stderr, "successfully copy-constructed match arm\n"); - } - - ~MatchArm() = default; - - // Overload assignment operator to clone - MatchArm& operator=(MatchArm const& other) { - // match_arm_patterns = other.match_arm_patterns; - outer_attrs = other.outer_attrs; - guard_expr = other.guard_expr->clone_expr(); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - MatchArm(MatchArm&& other) = default; - MatchArm& operator=(MatchArm&& other) = default; - - // Returns whether match arm is in an error state. - inline bool is_error() const { - return match_arm_patterns.empty(); - } - - // Creates a match arm in an error state. - static MatchArm create_error() { - return MatchArm(::std::vector< ::std::unique_ptr >()); - } - - ::std::string as_string() const; - }; - - // Base "match case" for a match expression - abstract - class MatchCase { - MatchArm arm; - - protected: - MatchCase(MatchArm arm) : arm(::std::move(arm)) {} - - // Should not require copy constructor or assignment operator overloading - - // Clone function implementation as pure virtual method - virtual MatchCase* clone_match_case_impl() const = 0; - - public: - virtual ~MatchCase() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_match_case() const { - // DEBUG - fprintf(stderr, "about to call clone match case impl\n"); - - return ::std::unique_ptr(clone_match_case_impl()); - } - - virtual ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Block expression match case - class MatchCaseBlockExpr : public MatchCase { - // BlockExpr* block_expr; - ::std::unique_ptr block_expr; - - // TODO: should this store location data? - - public: - /*~MatchCaseBlockExpr() { - delete block_expr; - }*/ - - MatchCaseBlockExpr(MatchArm arm, ::std::unique_ptr block_expr) : - MatchCase(::std::move(arm)), block_expr(::std::move(block_expr)) {} - - // Copy constructor requires clone - MatchCaseBlockExpr(MatchCaseBlockExpr const& other) : - MatchCase(other), block_expr(other.block_expr->clone_block_expr()) { - // DEBUG - fprintf(stderr, "successfully copy constructed match case expr\n"); - } - - // Destructor - define here if required - - // Overload assignment operator to have clone - MatchCaseBlockExpr& operator=(MatchCaseBlockExpr const& other) { - MatchCase::operator=(other); - block_expr = other.block_expr->clone_block_expr(); - // arm = other.arm; - - return *this; - } - - // move constructors - MatchCaseBlockExpr(MatchCaseBlockExpr&& other) = default; - MatchCaseBlockExpr& operator=(MatchCaseBlockExpr&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchCaseBlockExpr* clone_match_case_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to copy construct match case block expr\n"); - - return new MatchCaseBlockExpr(*this); - } - }; - - // Expression (except block expression) match case - class MatchCaseExpr : public MatchCase { - // Expr* expr; - ::std::unique_ptr expr; - - // TODO: should this store location data? - - public: - /*~MatchCaseExpr() { - delete expr; - }*/ - - MatchCaseExpr(MatchArm arm, ::std::unique_ptr expr) : - MatchCase(::std::move(arm)), expr(::std::move(expr)) {} - - // Copy constructor requires clone - MatchCaseExpr(MatchCaseExpr const& other) : - MatchCase(other), expr(other.expr->clone_expr()) { - // DEBUG - fprintf(stderr, "successfully copy constructed match case expr\n"); - } - - // Destructor - define here if required - - // Overload assignment operator to have clone - MatchCaseExpr& operator=(MatchCaseExpr const& other) { - MatchCase::operator=(other); - expr = other.expr->clone_expr(); - // arm = other.arm; - - return *this; - } - - // move constructors - MatchCaseExpr(MatchCaseExpr&& other) = default; - MatchCaseExpr& operator=(MatchCaseExpr&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchCaseExpr* clone_match_case_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to copy construct match case expr\n"); - if (expr == NULL) { - fprintf( - stderr, "warning: match case expr to be copy constructed has null expr!\n"); - } - - return new MatchCaseExpr(*this); - } - }; - - // Match expression AST node - class MatchExpr : public ExprWithBlock { - // Expr* branch_value; - ::std::unique_ptr branch_value; - ::std::vector inner_attrs; - - // bool has_match_arms; - // MatchArms match_arms; - ::std::vector< ::std::unique_ptr > match_arms; // inlined from MatchArms - - location_t locus; - - public: - /*~MatchExpr() { - delete branch_value; - }*/ - - ::std::string as_string() const; - - // Returns whether the match expression has any match arms. - inline bool has_match_arms() const { - return !match_arms.empty(); - } - - MatchExpr(::std::unique_ptr branch_value, - ::std::vector< ::std::unique_ptr > match_arms, - ::std::vector inner_attrs, ::std::vector outer_attrs, - location_t locus) : - ExprWithBlock(::std::move(outer_attrs)), - branch_value(::std::move(branch_value)), inner_attrs(::std::move(inner_attrs)), - match_arms(::std::move(match_arms)), locus(locus) {} - - // Copy constructor requires clone due to unique_ptr - MatchExpr(MatchExpr const& other) : - ExprWithBlock(other), - branch_value(other.branch_value->clone_expr()), /*match_arms(other.match_arms),*/ - inner_attrs(other.inner_attrs), locus(other.locus) { - fprintf(stderr, "copy constructor for matchexpr called - only match arm vector " - "copying after this\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arms.reserve(other.match_arms.size()); - - fprintf(stderr, "match expr: successfully reserved size\n"); - - for (const auto& e : other.match_arms) { - match_arms.push_back(e->clone_match_case()); - fprintf(stderr, "match expr: successfully pushed back a match case\n"); - } - - fprintf(stderr, "match expr: successfully pushed back all match cases\n"); - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone due to unique_ptr - MatchExpr& operator=(MatchExpr const& other) { - ExprWithBlock::operator=(other); - branch_value = other.branch_value->clone_expr(); - // match_arms = other.match_arms; - inner_attrs = other.inner_attrs; - // outer_attrs = other.outer_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arms.reserve(other.match_arms.size()); - - for (const auto& e : other.match_arms) { - match_arms.push_back(e->clone_match_case()); - } - - return *this; - } - - // move constructors - MatchExpr(MatchExpr&& other) = default; - MatchExpr& operator=(MatchExpr&& other) = default; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchExpr* clone_expr_impl() const OVERRIDE { - return new MatchExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MatchExpr* clone_expr_with_block_impl() const OVERRIDE { - return new MatchExpr(*this); - } - }; - - // Await expression AST node (pseudo-member variable access) - class AwaitExpr : public ExprWithoutBlock { - ::std::unique_ptr awaited_expr; - - location_t locus; - - public: - // TODO: ensure outer attributes are actually allowed - AwaitExpr(::std::unique_ptr awaited_expr, ::std::vector outer_attrs, - location_t locus) : - ExprWithoutBlock(::std::move(outer_attrs)), - awaited_expr(::std::move(awaited_expr)), locus(locus) {} - - // copy constructor with clone - AwaitExpr(AwaitExpr const& other) : - ExprWithoutBlock(other), awaited_expr(other.awaited_expr->clone_expr()), - locus(other.locus) {} - - // destructor - define here if required - - // overloaded assignment operator with clone - AwaitExpr& operator=(AwaitExpr const& other) { - ExprWithoutBlock::operator=(other); - awaited_expr = other.awaited_expr->clone_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - AwaitExpr(AwaitExpr&& other) = default; - AwaitExpr& operator=(AwaitExpr&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AwaitExpr* clone_expr_without_block_impl() const OVERRIDE { - return new AwaitExpr(*this); - } - }; - - // Async block expression AST node (block expr that evaluates to a future) - class AsyncBlockExpr : public ExprWithBlock { - // TODO: should this extend BlockExpr rather than be a composite of it? - bool has_move; - ::std::unique_ptr block_expr; - - location_t locus; - - public: - AsyncBlockExpr(::std::unique_ptr block_expr, bool has_move, - ::std::vector outer_attrs, location_t locus) : - ExprWithBlock(::std::move(outer_attrs)), - has_move(has_move), block_expr(::std::move(block_expr)), locus(locus) {} - - // copy constructor with clone - AsyncBlockExpr(AsyncBlockExpr const& other) : - ExprWithBlock(other), has_move(other.has_move), - block_expr(other.block_expr->clone_block_expr()), locus(other.locus) {} - - // destructor - define if required - - // overloaded assignment operator to clone - AsyncBlockExpr& operator=(AsyncBlockExpr const& other) { - ExprWithBlock::operator=(other); - has_move = other.has_move; - block_expr = other.block_expr->clone_block_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - AsyncBlockExpr(AsyncBlockExpr&& other) = default; - AsyncBlockExpr& operator=(AsyncBlockExpr&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AsyncBlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new AsyncBlockExpr(*this); - } - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-item.h b/gcc/rust/test3/ast/rust-item.h deleted file mode 100644 index c5154f5..0000000 --- a/gcc/rust/test3/ast/rust-item.h +++ /dev/null @@ -1,3385 +0,0 @@ -#ifndef RUST_AST_ITEM_H -#define RUST_AST_ITEM_H - -#include "rust-ast.h" -#include "rust-path.h" - -namespace Rust { - namespace AST { - // forward decls - // struct Lifetime; - // struct LifetimeBounds; - // struct TypeParamBounds; - class BlockExpr; - // class Expr; - // class Type; - class TypePath; - // class Pattern; - class MacroInvocationSemi; - - // TODO: inline? - /*struct AbiName { - ::std::string abi_name; - // Technically is meant to be STRING_LITERAL or RAW_STRING_LITERAL - - public: - // Returns whether abi name is empty, i.e. doesn't exist. - inline bool is_empty() const { - return abi_name.empty(); - } - - AbiName(::std::string name) : abi_name(::std::move(name)) {} - - // Empty AbiName constructor - AbiName() {} - };*/ - - // A type generic parameter (as opposed to a lifetime generic parameter) - class TypeParam : public GenericParam { - // bool has_outer_attribute; - //::std::unique_ptr outer_attr; - Attribute outer_attr; - - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - // bool has_type; - // Type type; - ::std::unique_ptr type; - - location_t locus; - - public: - // Returns whether the type of the type param has been specified. - inline bool has_type() const { - return type != NULL; - } - - // Returns whether the type param has type param bounds. - inline bool has_type_param_bounds() const { - return !type_param_bounds.empty(); - } - - // Returns whether the type param has an outer attribute. - inline bool has_outer_attribute() const { - return !outer_attr.is_empty(); - } - - TypeParam(Identifier type_representation, location_t locus = UNKNOWN_LOCATION, - ::std::vector< ::std::unique_ptr > type_param_bounds - = ::std::vector< ::std::unique_ptr >(), - ::std::unique_ptr type = NULL, Attribute outer_attr = Attribute::create_empty()) : - outer_attr(::std::move(outer_attr)), - type_representation(::std::move(type_representation)), - type_param_bounds(::std::move(type_param_bounds)), type(::std::move(type)), - locus(locus) {} - - // Copy constructor uses clone - TypeParam(TypeParam const& other) : - outer_attr(other.outer_attr), type_representation(other.type_representation), - /*type_param_bounds(other.type_param_bounds),*/ type(other.type->clone_type()), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - TypeParam& operator=(TypeParam const& other) { - type_representation = other.type_representation; - // type_param_bounds = other.type_param_bounds; - type = other.type->clone_type(); - outer_attr = other.outer_attr; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - TypeParam(TypeParam&& other) = default; - TypeParam& operator=(TypeParam&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TypeParam* clone_generic_param_impl() const { - return new TypeParam(*this); - } - }; - - // "where" clause item base. Abstract - use LifetimeWhereClauseItem, TypeBoundWhereClauseItem - class WhereClauseItem { - public: - virtual ~WhereClauseItem() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_where_clause_item() const { - return ::std::unique_ptr(clone_where_clause_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual WhereClauseItem* clone_where_clause_item_impl() const = 0; - }; - - // A lifetime where clause item - class LifetimeWhereClauseItem : public WhereClauseItem { - Lifetime lifetime; - - // LifetimeBounds lifetime_bounds; - ::std::vector lifetime_bounds; // inlined lifetime bounds - - // should this store location info? - - public: - LifetimeWhereClauseItem(Lifetime lifetime, ::std::vector lifetime_bounds) : - lifetime(::std::move(lifetime)), lifetime_bounds(::std::move(lifetime_bounds)) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual LifetimeWhereClauseItem* clone_where_clause_item_impl() const { - return new LifetimeWhereClauseItem(*this); - } - }; - - // A type bound where clause item - class TypeBoundWhereClauseItem : public WhereClauseItem { - // bool has_for_lifetimes; - // LifetimeParams for_lifetimes; - ::std::vector for_lifetimes; // inlined - - // Type bound_type; - ::std::unique_ptr bound_type; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - // should this store location info? - - public: - // Returns whether the item has ForLifetimes - inline bool has_for_lifetimes() const { - return !for_lifetimes.empty(); - } - - // Returns whether the item has type param bounds - inline bool has_type_param_bounds() const { - return !type_param_bounds.empty(); - } - - TypeBoundWhereClauseItem(::std::vector for_lifetimes, - ::std::unique_ptr bound_type, - ::std::vector< ::std::unique_ptr > type_param_bounds) : - for_lifetimes(::std::move(for_lifetimes)), - bound_type(::std::move(bound_type)), type_param_bounds(::std::move(type_param_bounds)) { - } - - // Copy constructor requires clone - TypeBoundWhereClauseItem(TypeBoundWhereClauseItem const& other) : - for_lifetimes(other.for_lifetimes), bound_type(other.bound_type->clone_type()) /*, - type_param_bounds(other.type_param_bounds)*/ - { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone - TypeBoundWhereClauseItem& operator=(TypeBoundWhereClauseItem const& other) { - for_lifetimes = other.for_lifetimes; - bound_type = other.bound_type->clone_type(); - // type_param_bounds = other.type_param_bounds; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - TypeBoundWhereClauseItem(TypeBoundWhereClauseItem&& other) = default; - TypeBoundWhereClauseItem& operator=(TypeBoundWhereClauseItem&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TypeBoundWhereClauseItem* clone_where_clause_item_impl() const { - return new TypeBoundWhereClauseItem(*this); - } - }; - - // A where clause - struct WhereClause { - private: - //::std::vector where_clause_items; - ::std::vector< ::std::unique_ptr > where_clause_items; - - // should this store location info? - - public: - WhereClause(::std::vector< ::std::unique_ptr > where_clause_items) : - where_clause_items(::std::move(where_clause_items)) {} - - // copy constructor with vector clone - WhereClause(WhereClause const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - where_clause_items.reserve(other.where_clause_items.size()); - - for (const auto& e : other.where_clause_items) { - where_clause_items.push_back(e->clone_where_clause_item()); - } - } - - // overloaded assignment operator with vector clone - WhereClause& operator=(WhereClause const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - where_clause_items.reserve(other.where_clause_items.size()); - - for (const auto& e : other.where_clause_items) { - where_clause_items.push_back(e->clone_where_clause_item()); - } - - return *this; - } - - // move constructors - WhereClause(WhereClause&& other) = default; - WhereClause& operator=(WhereClause&& other) = default; - - // Creates a WhereClause with no items. - static WhereClause create_empty() { - return WhereClause(::std::vector< ::std::unique_ptr >()); - } - - // Returns whether the WhereClause has no items. - inline bool is_empty() const { - return where_clause_items.empty(); - } - - ::std::string as_string() const; - }; - - // A self parameter in a method - struct SelfParam { - private: - bool has_ref; - bool is_mut; - // bool has_lifetime; // only possible if also ref - Lifetime lifetime; - - // bool has_type; // only possible if not ref - // Type type; - ::std::unique_ptr type; - - location_t locus; - - // Unrestricted constructor used for error state - SelfParam(Lifetime lifetime, bool has_ref, bool is_mut, Type* type) : - has_ref(has_ref), is_mut(is_mut), lifetime(::std::move(lifetime)), type(type) {} - // this is ok as no outside classes can ever call this - - public: - // Returns whether the self-param has a type field. - inline bool has_type() const { - return type != NULL; - } - - // Returns whether the self-param has a valid lifetime. - inline bool has_lifetime() const { - return !lifetime.is_error(); - } - - // Returns whether the self-param is in an error state. - inline bool is_error() const { - return has_type() && has_lifetime(); - // not having either is not an error - } - - // Creates an error state self-param. - static SelfParam create_error() { - /* HACK: creates a dummy type. Since it's a unique pointer, it should clean it up, but - * it still allocates memory, which is not ideal. */ - return SelfParam(Lifetime(Lifetime::STATIC), false, false, - new QualifiedPathInType(QualifiedPathInType::create_error())); - } - - // Type-based self parameter (not ref, no lifetime) - SelfParam(::std::unique_ptr type, bool is_mut, location_t locus) : - has_ref(false), is_mut(is_mut), lifetime(Lifetime::error()), type(::std::move(type)), - locus(locus) {} - - // Lifetime-based self parameter (is ref, no type) - SelfParam(Lifetime lifetime, bool is_mut, location_t locus) : - /*type(NULL), */ has_ref(true), is_mut(is_mut), lifetime(::std::move(lifetime)), - locus(locus) {} - - // Copy constructor requires clone - SelfParam(SelfParam const& other) : - has_ref(other.has_ref), is_mut(other.is_mut), lifetime(other.lifetime), - type(other.type->clone_type()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to use clone - SelfParam& operator=(SelfParam const& other) { - type = other.type->clone_type(); - is_mut = other.is_mut; - has_ref = other.has_ref; - lifetime = other.lifetime; - locus = other.locus; - - return *this; - } - - // move constructors - SelfParam(SelfParam&& other) = default; - SelfParam& operator=(SelfParam&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - }; - - // Qualifiers for function, i.e. const, unsafe, extern etc. - struct FunctionQualifiers { - public: - // Whether the function is neither const nor async, const only, or async only. - enum AsyncConstStatus { NONE, CONST, ASYNC }; - - private: - AsyncConstStatus const_status; - bool has_unsafe; - bool has_extern; - ::std::string extern_abi; // e.g. extern "C" fn() -> i32 {} - // TODO: maybe ensure that extern_abi only exists if extern exists? - - // should this store location info? - - public: - // Constructor with no extern (and hence no extern abi) - FunctionQualifiers(AsyncConstStatus const_status, bool has_unsafe) : - const_status(const_status), has_unsafe(has_unsafe), has_extern(false), - extern_abi(::std::string("")) {} - - // Constructor with extern abi (and thus extern) - FunctionQualifiers( - AsyncConstStatus const_status, bool has_unsafe, ::std::string extern_abi) : - const_status(const_status), - has_unsafe(has_unsafe), has_extern(true), extern_abi(::std::move(extern_abi)) {} - - // Constructor with all possible options (DON'T HAVE EXTERN_ABI WITHOUT EXTERN!) - FunctionQualifiers(AsyncConstStatus const_status, bool has_unsafe, bool has_extern, - ::std::string extern_abi) : - const_status(const_status), - has_unsafe(has_unsafe), has_extern(has_extern), extern_abi(::std::move(extern_abi)) {} - - ::std::string as_string() const; - }; - - // Forward decl FunctionParams - // struct FunctionParams; - - // A function parameter - struct FunctionParam { - private: - // Pattern* param_name; - ::std::unique_ptr param_name; - // Type type; - ::std::unique_ptr type; - - location_t locus; - - public: - FunctionParam(::std::unique_ptr param_name, ::std::unique_ptr param_type, - location_t locus) : - param_name(::std::move(param_name)), - type(::std::move(param_type)), locus(locus) {} - - // Copy constructor uses clone - FunctionParam(FunctionParam const& other) : - param_name(other.param_name->clone_pattern()), type(other.type->clone_type()), - locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to use clone - FunctionParam& operator=(FunctionParam const& other) { - param_name = other.param_name->clone_pattern(); - type = other.type->clone_type(); - locus = other.locus; - - return *this; - } - - // move constructors - FunctionParam(FunctionParam&& other) = default; - FunctionParam& operator=(FunctionParam&& other) = default; - - // Returns whether FunctionParam is in an invalid state. - inline bool is_error() const { - return param_name == NULL || type == NULL; - } - - // Creates an error FunctionParam. - static FunctionParam create_error() { - return FunctionParam(NULL, NULL, UNKNOWN_LOCATION); - } - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - }; - - // Visibility of item - if the item has it, then it is some form of public - struct Visibility { - public: - enum PublicVisType { NONE, CRATE, SELF, SUPER, IN_PATH }; - - private: - // bool is_pub; - - // if vis is public, one of these - PublicVisType public_vis_type; - - // Only assigned if public_vis_type is IN_PATH - SimplePath in_path; - - // should this store location info? - - public: - // Creates a Visibility - TODO make constructor protected or private? - Visibility(PublicVisType public_vis_type, SimplePath in_path) : - public_vis_type(public_vis_type), in_path(::std::move(in_path)) { - if (public_vis_type != IN_PATH && !in_path.is_empty()) { - // error - invalid state - - // just ignore path if vis type is not that - } - } - - // Returns whether visibility is in an error state. - inline bool is_error() const { - return public_vis_type == IN_PATH && in_path.is_empty(); - } - - // Creates an error visibility. - static Visibility create_error() { - return Visibility(IN_PATH, SimplePath::create_empty()); - } - - // Unique pointer custom clone function - /*::std::unique_ptr clone_visibility() const { - return ::std::unique_ptr(clone_visibility_impl()); - }*/ - - /* TODO: think of a way to only allow valid Visibility states - polymorphism is one - * idea but may be too resource-intensive. */ - - // Creates a public visibility with no further features/arguments. - static Visibility create_public() { - return Visibility(NONE, SimplePath::create_empty()); - } - - // Creates a public visibility with crate-relative paths or whatever. - static Visibility create_crate() { - return Visibility(CRATE, SimplePath::create_empty()); - } - - // Creates a public visibility with self-relative paths or whatever. - static Visibility create_self() { - return Visibility(SELF, SimplePath::create_empty()); - } - - // Creates a public visibility with parent module-relative paths or whatever. - static Visibility create_super() { - return Visibility(SUPER, SimplePath::create_empty()); - } - - // Creates a public visibility with a given path or whatever. - static Visibility create_in_path(SimplePath in_path) { - return Visibility(IN_PATH, ::std::move(in_path)); - } - - ::std::string as_string() const; - - protected: - // Clone function implementation - not currently virtual but may be if polymorphism used - /*virtual*/ Visibility* clone_visibility_impl() const { - return new Visibility(*this); - } - }; - - // A method (function belonging to a type) - class Method - : public InherentImplItem - , public TraitImplItem { - // moved from impl items for consistency - ::std::vector outer_attrs; - Visibility vis; - - FunctionQualifiers qualifiers; - Identifier method_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - SelfParam self_param; - - // bool has_params; - // FunctionParams function_params; - ::std::vector function_params; // inlined - - // bool has_return_type; - // FunctionReturnType return_type; - ::std::unique_ptr return_type; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - // BlockExpr* expr; - ::std::unique_ptr expr; - - location_t locus; - - public: - /*~Method() { - delete expr; - }*/ - - // Returns whether the method is in an error state. - inline bool is_error() const { - return expr == NULL || method_name.empty() || self_param.is_error(); - } - - // Creates an error state method. - static Method create_error() { - return Method("", FunctionQualifiers(FunctionQualifiers::NONE, true), - ::std::vector< ::std::unique_ptr >(), SelfParam::create_error(), - ::std::vector(), NULL, WhereClause::create_empty(), NULL, - Visibility::create_error(), ::std::vector()); - } - - // Returns whether the method has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether the method has parameters. - inline bool has_params() const { - return !function_params.empty(); - } - - // Returns whether the method has a return type (void otherwise). - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether the where clause exists (i.e. has items) - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Returns whether method has a non-default visibility. - inline bool has_visibility() const { - return !vis.is_error(); - } - - // Mega-constructor with all possible fields - Method(Identifier method_name, FunctionQualifiers qualifiers, - ::std::vector< ::std::unique_ptr > generic_params, SelfParam self_param, - ::std::vector function_params, ::std::unique_ptr return_type, - WhereClause where_clause, ::std::unique_ptr function_body, Visibility vis, - ::std::vector outer_attrs, location_t locus = UNKNOWN_LOCATION) : - outer_attrs(::std::move(outer_attrs)), - vis(::std::move(vis)), qualifiers(::std::move(qualifiers)), - method_name(::std::move(method_name)), generic_params(::std::move(generic_params)), - self_param(::std::move(self_param)), function_params(::std::move(function_params)), - return_type(::std::move(return_type)), where_clause(::std::move(where_clause)), - expr(::std::move(function_body)), locus(locus) {} - - // TODO: add constructor with less fields - - // Copy constructor with clone - Method(Method const& other) : - outer_attrs(other.outer_attrs), vis(other.vis), qualifiers(other.qualifiers), - method_name(other.method_name), - /*generic_params(other.generic_params),*/ self_param(other.self_param), - function_params(other.function_params), return_type(other.return_type->clone_type()), - where_clause(other.where_clause), expr(other.expr->clone_block_expr()), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - //~Method() = default; - - // Overloaded assignment operator to clone - Method& operator=(Method const& other) { - method_name = other.method_name; - outer_attrs = other.outer_attrs; - vis = other.vis; - qualifiers = other.qualifiers; - // generic_params = other.generic_params; - self_param = other.self_param; - function_params = other.function_params; - return_type = other.return_type->clone_type(); - where_clause = other.where_clause; - expr = other.expr->clone_block_expr(); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - Method(Method&& other) = default; - Method& operator=(Method&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Method* clone_inherent_impl_item_impl() const OVERRIDE { - return new Method(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Method* clone_trait_impl_item_impl() const OVERRIDE { - return new Method(*this); - } - }; - - // Item that supports visibility - abstract base class - class VisItem : public Item { - Visibility visibility; - - protected: - // Visibility constructor - VisItem(Visibility visibility, - ::std::vector outer_attrs = ::std::vector()) : - Item(::std::move(outer_attrs)), - visibility(::std::move(visibility)) {} - - // Visibility copy constructor - VisItem(VisItem const& other) : Item(other), visibility(other.visibility) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - VisItem& operator=(VisItem const& other) { - Item::operator=(other); - visibility = other.visibility; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - VisItem(VisItem&& other) = default; - VisItem& operator=(VisItem&& other) = default; - - public: - // Does the item have some kind of public visibility (non-default visibility)? - inline bool has_visibility() const { - return !visibility.is_error(); - } - - virtual ::std::string as_string() const; - }; - - // Rust module item - abstract base class - class Module : public VisItem { - Identifier module_name; - - location_t locus; - - protected: - // Protected constructor - Module(Identifier module_name, Visibility visibility, location_t locus, - ::std::vector outer_attrs = ::std::vector()) : - VisItem(::std::move(visibility), ::std::move(outer_attrs)), - module_name(module_name), locus(locus) {} - - public: - virtual ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - }; - - // Module with a body, defined in file - class ModuleBodied : public Module { - // bool has_inner_attrs; - ::std::vector inner_attrs; - // bool has_items; - //::std::vector items; - ::std::vector< ::std::unique_ptr > items; - - public: - virtual ::std::string as_string() const; - - // Returns whether the module has items in its body. - inline bool has_items() const { - return !items.empty(); - } - - // Returns whether the module has any inner attributes. - inline bool has_inner_attrs() const { - return !inner_attrs.empty(); - } - - // Full constructor - ModuleBodied(Identifier name, location_t locus, - ::std::vector< ::std::unique_ptr > items - = ::std::vector< ::std::unique_ptr >(), - Visibility visibility = Visibility::create_error(), - ::std::vector inner_attrs = ::std::vector(), - ::std::vector outer_attrs = ::std::vector()) : - Module(::std::move(name), ::std::move(visibility), locus, ::std::move(outer_attrs)), - inner_attrs(::std::move(inner_attrs)), items(::std::move(items)) {} - - // Copy constructor with vector clone - ModuleBodied(ModuleBodied const& other) : Module(other), inner_attrs(other.inner_attrs) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - } - - // Overloaded assignment operator with vector clone - ModuleBodied& operator=(ModuleBodied const& other) { - Module::operator=(other); - inner_attrs = other.inner_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - - return *this; - } - - // move constructors - ModuleBodied(ModuleBodied&& other) = default; - ModuleBodied& operator=(ModuleBodied&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // Override that runs the function recursively on all items contained within the module. - virtual void add_crate_name(::std::vector< ::std::string>& names) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ModuleBodied* clone_item_impl() const OVERRIDE { - return new ModuleBodied(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual ModuleBodied* clone_statement_impl() const OVERRIDE { - return new ModuleBodied(*this); - }*/ - }; - - // Module without a body, loaded from external file - class ModuleNoBody : public Module { - public: - ::std::string as_string() const; - - // Full constructor - ModuleNoBody(Identifier name, Visibility visibility, ::std::vector outer_attrs, - location_t locus) : - Module(::std::move(name), ::std::move(visibility), locus, ::std::move(outer_attrs)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ModuleNoBody* clone_item_impl() const OVERRIDE { - return new ModuleNoBody(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual ModuleNoBody* clone_statement_impl() const OVERRIDE { - return new ModuleNoBody(*this); - }*/ - }; - - // Rust extern crate declaration AST node - class ExternCrate : public VisItem { - // this is either an identifier or "self", with self parsed to string - ::std::string referenced_crate; - // bool has_as_clause; - // AsClause as_clause; - // this is either an identifier or "_", with _ parsed to string - ::std::string as_clause_name; - - location_t locus; - - /* e.g. - "extern crate foo as _" - "extern crate foo" - "extern crate std as cool_std" */ - public: - ::std::string as_string() const; - - // Returns whether extern crate declaration has an as clause. - inline bool has_as_clause() const { - return !as_clause_name.empty(); - } - - // Returns whether extern crate declaration references the current crate (i.e. self). - inline bool references_self() const { - return referenced_crate == "self"; - } - - // Constructor - ExternCrate(::std::string referenced_crate, Visibility visibility, - ::std::vector outer_attrs, location_t locus, - ::std::string as_clause_name = ::std::string()) : - VisItem(::std::move(visibility), ::std::move(outer_attrs)), - referenced_crate(::std::move(referenced_crate)), - as_clause_name(::std::move(as_clause_name)), locus(locus) {} - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // Override that adds extern crate name in decl to passed list of names. - virtual void add_crate_name(::std::vector< ::std::string>& names) const OVERRIDE { - names.push_back(referenced_crate); - } - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExternCrate* clone_item_impl() const OVERRIDE { - return new ExternCrate(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual ExternCrate* clone_statement_impl() const OVERRIDE { - return new ExternCrate(*this); - }*/ - }; - - // The path-ish thing referred to in a use declaration - abstract base class - class UseTree { - location_t locus; - - public: - virtual ~UseTree() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_use_tree() const { - return ::std::unique_ptr(clone_use_tree_impl()); - } - - virtual ::std::string as_string() const = 0; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual UseTree* clone_use_tree_impl() const = 0; - - UseTree(location_t locus) : locus(locus) {} - }; - - // Use tree with a glob (wildcard) operator - class UseTreeGlob : public UseTree { - public: - enum PathType { NO_PATH, GLOBAL, PATH_PREFIXED }; - - private: - PathType glob_type; - SimplePath path; - - public: - UseTreeGlob(PathType glob_type, SimplePath path, location_t locus) : - UseTree(locus), glob_type(glob_type), path(::std::move(path)) {} - - // Returns whether has path. Should be made redundant by PathType PATH_PREFIXED. - inline bool has_path() const { - return !path.is_empty(); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory methods? - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UseTreeGlob* clone_use_tree_impl() const OVERRIDE { - return new UseTreeGlob(*this); - } - }; - - // Use tree with a list of paths with a common prefix - class UseTreeList : public UseTree { - public: - enum PathType { NO_PATH, GLOBAL, PATH_PREFIXED }; - - private: - PathType path_type; - SimplePath path; - - ::std::vector< ::std::unique_ptr > trees; - - public: - UseTreeList(PathType path_type, SimplePath path, - ::std::vector< ::std::unique_ptr > trees, location_t locus) : - UseTree(locus), - path_type(path_type), path(::std::move(path)), trees(::std::move(trees)) {} - - // copy constructor with vector clone - UseTreeList(UseTreeList const& other) : - UseTree(other), path_type(other.path_type), path(other.path) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - trees.reserve(other.trees.size()); - - for (const auto& e : other.trees) { - trees.push_back(e->clone_use_tree()); - } - } - - // overloaded assignment operator with vector clone - UseTreeList& operator=(UseTreeList const& other) { - UseTree::operator=(other); - path_type = other.path_type; - path = other.path; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - trees.reserve(other.trees.size()); - - for (const auto& e : other.trees) { - trees.push_back(e->clone_use_tree()); - } - - return *this; - } - - // move constructors - UseTreeList(UseTreeList&& other) = default; - UseTreeList& operator=(UseTreeList&& other) = default; - - // Returns whether has path. Should be made redundant by path_type. - inline bool has_path() const { - return !path.is_empty(); - } - - // Returns whether has inner tree elements. - inline bool has_trees() const { - return !trees.empty(); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory methods? - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UseTreeList* clone_use_tree_impl() const OVERRIDE { - return new UseTreeList(*this); - } - }; - - // Use tree where it rebinds the module name as something else - class UseTreeRebind : public UseTree { - public: - enum NewBindType { NONE, IDENTIFIER, WILDCARD }; - - private: - SimplePath path; - - NewBindType bind_type; - Identifier identifier; // only if NewBindType is IDENTIFIER - - public: - UseTreeRebind(NewBindType bind_type, SimplePath path, location_t locus, - Identifier identifier = ::std::string()) : - UseTree(locus), - path(::std::move(path)), bind_type(bind_type), identifier(::std::move(identifier)) {} - - // Returns whether has path (this should always be true). - inline bool has_path() const { - return !path.is_empty(); - } - - // Returns whether has identifier (or, rather, is allowed to). - inline bool has_identifier() const { - return bind_type == IDENTIFIER; - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory methods? - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UseTreeRebind* clone_use_tree_impl() const OVERRIDE { - return new UseTreeRebind(*this); - } - }; - - // Rust use declaration (i.e. for modules) AST node - class UseDeclaration : public VisItem { - ::std::unique_ptr use_tree; - - location_t locus; - - public: - ::std::string as_string() const; - - UseDeclaration(::std::unique_ptr use_tree, Visibility visibility, - ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(visibility), ::std::move(outer_attrs)), - use_tree(::std::move(use_tree)), locus(locus) {} - - // Copy constructor with clone - UseDeclaration(UseDeclaration const& other) : - VisItem(other), use_tree(other.use_tree->clone_use_tree()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - UseDeclaration& operator=(UseDeclaration const& other) { - VisItem::operator=(other); - use_tree = other.use_tree->clone_use_tree(); - // visibility = other.visibility->clone_visibility(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - UseDeclaration(UseDeclaration&& other) = default; - UseDeclaration& operator=(UseDeclaration&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UseDeclaration* clone_item_impl() const OVERRIDE { - return new UseDeclaration(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual UseDeclaration* clone_statement_impl() const OVERRIDE { - return new UseDeclaration(*this); - }*/ - }; - - // Parameters used in a function - TODO inline? - /*struct FunctionParams { - ::std::vector function_params; - };*/ - - // Rust function declaration AST node - class Function - : public VisItem - , public InherentImplItem - , public TraitImplItem { - FunctionQualifiers qualifiers; - - Identifier function_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_function_params; - // FunctionParams function_params; - ::std::vector function_params; // inlined - - // bool has_function_return_type; - // Type return_type; - ::std::unique_ptr return_type; - - // bool has_where_clause; - WhereClause where_clause; - - // BlockExpr* function_body; - ::std::unique_ptr function_body; - - location_t locus; - - public: - /*~Function() { - delete function_body; - }*/ - ::std::string as_string() const; - - // Returns whether function has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether function has regular parameters. - inline bool has_function_params() const { - return !function_params.empty(); - } - - // Returns whether function has return type - if not, it is void. - inline bool has_function_return_type() const { - return return_type != NULL; - } - - // Returns whether function has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Mega-constructor with all possible fields - Function(Identifier function_name, FunctionQualifiers qualifiers, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::vector function_params, ::std::unique_ptr return_type, - WhereClause where_clause, ::std::unique_ptr function_body, Visibility vis, - ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - qualifiers(::std::move(qualifiers)), function_name(::std::move(function_name)), - generic_params(::std::move(generic_params)), - function_params(::std::move(function_params)), return_type(::std::move(return_type)), - where_clause(::std::move(where_clause)), function_body(::std::move(function_body)), - locus(locus) {} - - // TODO: add constructor with less fields - - // Copy constructor with clone - Function(Function const& other) : - VisItem(other), qualifiers(other.qualifiers), function_name(other.function_name), - /*generic_params(other.generic_params),*/ function_params(other.function_params), - return_type(other.return_type->clone_type()), where_clause(other.where_clause), - function_body(other.function_body->clone_block_expr()), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - Function& operator=(Function const& other) { - VisItem::operator=(other); - function_name = other.function_name; - qualifiers = other.qualifiers; - // generic_params = other.generic_params; - function_params = other.function_params; - return_type = other.return_type->clone_type(); - where_clause = other.where_clause; - function_body = other.function_body->clone_block_expr(); - // visibility = other.visibility->clone_visibility(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - Function(Function&& other) = default; - Function& operator=(Function&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Function* clone_item_impl() const OVERRIDE { - return new Function(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Function* clone_inherent_impl_item_impl() const OVERRIDE { - return new Function(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Function* clone_trait_impl_item_impl() const OVERRIDE { - return new Function(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual Function* clone_statement_impl() const OVERRIDE { - return new Function(*this); - }*/ - }; - - // Rust type alias (i.e. typedef) AST node - class TypeAlias - : public VisItem - , public TraitImplItem { - Identifier new_type_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - // Type exiting_type; - ::std::unique_ptr existing_type; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether type alias has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether type alias has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Mega-constructor with all possible fields - TypeAlias(Identifier new_type_name, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, ::std::unique_ptr existing_type, Visibility vis, - ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - new_type_name(::std::move(new_type_name)), generic_params(::std::move(generic_params)), - where_clause(::std::move(where_clause)), existing_type(::std::move(existing_type)), - locus(locus) {} - - // Copy constructor - TypeAlias(TypeAlias const& other) : - VisItem(other), - new_type_name(other.new_type_name), /*generic_params(other.generic_params),*/ - where_clause(other.where_clause), existing_type(other.existing_type->clone_type()), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - TypeAlias& operator=(TypeAlias const& other) { - VisItem::operator=(other); - new_type_name = other.new_type_name; - // generic_params = other.generic_params; - where_clause = other.where_clause; - existing_type = other.existing_type->clone_type(); - // visibility = other.visibility->clone_visibility(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - TypeAlias(TypeAlias&& other) = default; - TypeAlias& operator=(TypeAlias&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TypeAlias* clone_item_impl() const OVERRIDE { - return new TypeAlias(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TypeAlias* clone_trait_impl_item_impl() const OVERRIDE { - return new TypeAlias(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual TypeAlias* clone_statement_impl() const OVERRIDE { - return new TypeAlias(*this); - }*/ - }; - - // Rust base struct declaration AST node - abstract base class - class Struct : public VisItem { - protected: - // protected to enable access by derived classes - allows better as_string - Identifier struct_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - location_t locus; - - public: - // Returns whether struct has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether struct has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - location_t get_locus() const { - return locus; - } - - protected: - Struct(Identifier struct_name, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, Visibility vis, location_t locus, - ::std::vector outer_attrs = ::std::vector()) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - struct_name(::std::move(struct_name)), generic_params(::std::move(generic_params)), - where_clause(::std::move(where_clause)), locus(locus) {} - - // Copy constructor with vector clone - Struct(Struct const& other) : - VisItem(other), struct_name(other.struct_name), where_clause(other.where_clause), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // Overloaded assignment operator with vector clone - Struct& operator=(Struct const& other) { - VisItem::operator=(other); - struct_name = other.struct_name; - where_clause = other.where_clause; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - Struct(Struct&& other) = default; - Struct& operator=(Struct&& other) = default; - }; - - // A single field in a struct - struct StructField { - private: - // bool has_outer_attributes; - ::std::vector outer_attrs; - - // bool has_visibility; - Visibility visibility; - - Identifier field_name; - // Type field_type; - ::std::unique_ptr field_type; - - // should this store location info? - - public: - // Returns whether struct field has any outer attributes. - inline bool has_outer_attributes() const { - return !outer_attrs.empty(); - } - - // Returns whether struct field has a non-private (non-default) visibility. - inline bool has_visibility() const { - return !visibility.is_error(); - } - - StructField(Identifier field_name, ::std::unique_ptr field_type, Visibility vis, - ::std::vector outer_attrs = ::std::vector()) : - outer_attrs(::std::move(outer_attrs)), - visibility(::std::move(vis)), field_name(::std::move(field_name)), - field_type(::std::move(field_type)) {} - - // Copy constructor - StructField(StructField const& other) : - outer_attrs(other.outer_attrs), visibility(other.visibility), - field_name(other.field_name), field_type(other.field_type->clone_type()) {} - - ~StructField() = default; - - // Overloaded assignment operator to clone - StructField& operator=(StructField const& other) { - field_name = other.field_name; - field_type = other.field_type->clone_type(); - visibility = other.visibility; - outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - StructField(StructField&& other) = default; - StructField& operator=(StructField&& other) = default; - - // Returns whether struct field is in an error state. - inline bool is_error() const { - return field_name.empty() && field_type == NULL; - // this should really be an or since neither are allowed - } - - // Creates an error state struct field. - static StructField create_error() { - return StructField(::std::string(""), NULL, Visibility::create_error()); - } - - ::std::string as_string() const; - }; - - // Rust struct declaration with true struct type AST node - class StructStruct : public Struct { - ::std::vector fields; - bool is_unit; - - public: - ::std::string as_string() const; - - // Mega-constructor with all possible fields - StructStruct(::std::vector fields, Identifier struct_name, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, bool is_unit, Visibility vis, - ::std::vector outer_attrs, location_t locus) : - Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), - ::std::move(vis), locus, ::std::move(outer_attrs)), - fields(::std::move(fields)), is_unit(is_unit) {} - - // Unit struct constructor - StructStruct(Identifier struct_name, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, Visibility vis, ::std::vector outer_attrs, - location_t locus) : - Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), - ::std::move(vis), locus, ::std::move(outer_attrs)), - is_unit(true) {} - // TODO: can a unit struct have generic fields? assuming yes for now. - - /* Returns whether the struct is a unit struct - struct defined without fields. This is - * important because it also means an implicit constant of its type is defined. */ - inline bool is_unit_struct() const { - return is_unit; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructStruct* clone_item_impl() const OVERRIDE { - return new StructStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual StructStruct* clone_statement_impl() const OVERRIDE { - return new StructStruct(*this); - }*/ - }; - - // A single field in a tuple - struct TupleField { - private: - // bool has_outer_attributes; - ::std::vector outer_attrs; - - // bool has_visibility; - Visibility visibility; - - // Type field_type; - ::std::unique_ptr field_type; - - // should this store location info? - - public: - // Returns whether tuple field has outer attributes. - inline bool has_outer_attributes() const { - return !outer_attrs.empty(); - } - - // Returns whether tuple field has a non-default visibility (i.e. a public one) - inline bool has_visibility() const { - return !visibility.is_error(); - } - - // Complete constructor - TupleField(::std::unique_ptr field_type, Visibility vis, - ::std::vector outer_attrs = ::std::vector()) : - outer_attrs(::std::move(outer_attrs)), - visibility(::std::move(vis)), field_type(::std::move(field_type)) {} - - // Copy constructor with clone - TupleField(TupleField const& other) : - outer_attrs(other.outer_attrs), visibility(other.visibility), - field_type(other.field_type->clone_type()) {} - - ~TupleField() = default; - - // Overloaded assignment operator to clone - TupleField& operator=(TupleField const& other) { - field_type = other.field_type->clone_type(); - visibility = other.visibility; - outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - TupleField(TupleField&& other) = default; - TupleField& operator=(TupleField&& other) = default; - - // Returns whether tuple field is in an error state. - inline bool is_error() const { - return field_type == NULL; - } - - // Creates an error state tuple field. - static TupleField create_error() { - return TupleField(NULL, Visibility::create_error()); - } - - ::std::string as_string() const; - }; - - // Rust tuple declared using struct keyword AST node - class TupleStruct : public Struct { - ::std::vector fields; - - public: - ::std::string as_string() const; - - // Mega-constructor with all possible fields - TupleStruct(::std::vector fields, Identifier struct_name, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, Visibility vis, ::std::vector outer_attrs, - location_t locus) : - Struct(::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), - ::std::move(vis), locus, ::std::move(outer_attrs)), - fields(::std::move(fields)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStruct* clone_item_impl() const OVERRIDE { - return new TupleStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual TupleStruct* clone_statement_impl() const OVERRIDE { - return new TupleStruct(*this); - }*/ - }; - - // An item used in an "enum" tagged union - not abstract: base represents a name-only enum - class EnumItem { - // bool has_attrs; - ::std::vector outer_attrs; - - Identifier variant_name; - - location_t locus; - - public: - virtual ~EnumItem() {} - - // Returns whether enum item has outer attributes. - inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - } - - EnumItem( - Identifier variant_name, ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - variant_name(::std::move(variant_name)), locus(locus) {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_enum_item() const { - return ::std::unique_ptr(clone_enum_item_impl()); - } - - virtual ::std::string as_string() const; - - // not pure virtual as not abstract - virtual void accept_vis(ASTVisitor& vis); - - protected: - // Clone function implementation as (not pure) virtual method - virtual EnumItem* clone_enum_item_impl() const { - return new EnumItem(*this); - } - }; - - // A tuple item used in an "enum" tagged union - class EnumItemTuple : public EnumItem { - // bool has_tuple_fields; - ::std::vector tuple_fields; - - public: - // Returns whether tuple enum item has tuple fields. - inline bool has_tuple_fields() const { - return !tuple_fields.empty(); - } - - EnumItemTuple(Identifier variant_name, ::std::vector tuple_fields, - ::std::vector outer_attrs, location_t locus) : - EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), - tuple_fields(::std::move(tuple_fields)) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual EnumItemTuple* clone_enum_item_impl() const { - return new EnumItemTuple(*this); - } - }; - - // A struct item used in an "enum" tagged union - class EnumItemStruct : public EnumItem { - // bool has_struct_fields; - ::std::vector struct_fields; - - public: - // Returns whether struct enum item has struct fields. - inline bool has_struct_fields() const { - return !struct_fields.empty(); - } - - EnumItemStruct(Identifier variant_name, ::std::vector struct_fields, - ::std::vector outer_attrs, location_t locus) : - EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), - struct_fields(::std::move(struct_fields)) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual EnumItemStruct* clone_enum_item_impl() const { - return new EnumItemStruct(*this); - } - }; - - // A discriminant (numbered enum) item used in an "enum" tagged union - class EnumItemDiscriminant : public EnumItem { - // Expr* expression; - ::std::unique_ptr expression; - - public: - /*~EnumItemDiscriminant() { - delete expression; - }*/ - - EnumItemDiscriminant(Identifier variant_name, ::std::unique_ptr expr, - ::std::vector outer_attrs, location_t locus) : - EnumItem(::std::move(variant_name), ::std::move(outer_attrs), locus), - expression(::std::move(expr)) {} - - // Copy constructor with clone - EnumItemDiscriminant(EnumItemDiscriminant const& other) : - EnumItem(other), expression(other.expression->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - EnumItemDiscriminant& operator=(EnumItemDiscriminant const& other) { - EnumItem::operator=(other); - expression = other.expression->clone_expr(); - // variant_name = other.variant_name; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - EnumItemDiscriminant(EnumItemDiscriminant&& other) = default; - EnumItemDiscriminant& operator=(EnumItemDiscriminant&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual EnumItemDiscriminant* clone_enum_item_impl() const { - return new EnumItemDiscriminant(*this); - } - }; - - // AST node for Rust "enum" - tagged union - class Enum : public VisItem { - Identifier enum_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - ::std::vector< ::std::unique_ptr > items; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether "enum" has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether "enum" has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - /* Returns whether enum is a "zero-variant" (no possible variant) enum, which cannot be - * instantiated.*/ - inline bool is_zero_variant() const { - return items.empty(); - } - - // Mega-constructor - Enum(Identifier enum_name, Visibility vis, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, ::std::vector< ::std::unique_ptr > items, - ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - enum_name(::std::move(enum_name)), generic_params(::std::move(generic_params)), - where_clause(::std::move(where_clause)), items(::std::move(items)), locus(locus) {} - - // TODO: constructor with less arguments - - // Copy constructor with vector clone - Enum(Enum const& other) : - VisItem(other), enum_name(other.enum_name), where_clause(other.where_clause), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_enum_item()); - } - } - - // Overloaded assignment operator with vector clone - Enum& operator=(Enum const& other) { - VisItem::operator=(other); - enum_name = other.enum_name; - where_clause = other.where_clause; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_enum_item()); - } - - return *this; - } - - // Move constructors - Enum(Enum&& other) = default; - Enum& operator=(Enum&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Enum* clone_item_impl() const OVERRIDE { - return new Enum(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual Enum* clone_statement_impl() const OVERRIDE { - return new Enum(*this); - }*/ - }; - - // Rust untagged union used for C compat AST node - class Union : public VisItem { - Identifier union_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - ::std::vector variants; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether union has generic params. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether union has where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - Union(Identifier union_name, Visibility vis, - ::std::vector< ::std::unique_ptr > generic_params, - WhereClause where_clause, ::std::vector variants, - ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - union_name(::std::move(union_name)), generic_params(::std::move(generic_params)), - where_clause(::std::move(where_clause)), variants(::std::move(variants)), locus(locus) { - } - - // copy constructor with vector clone - Union(Union const& other) : - VisItem(other), union_name(other.union_name), where_clause(other.where_clause), - variants(other.variants), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // overloaded assignment operator with vector clone - Union& operator=(Union const& other) { - VisItem::operator=(other); - union_name = other.union_name; - where_clause = other.where_clause; - variants = other.variants; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - Union(Union&& other) = default; - Union& operator=(Union&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Union* clone_item_impl() const OVERRIDE { - return new Union(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual Union* clone_statement_impl() const OVERRIDE { - return new Union(*this); - }*/ - }; - - // "Constant item" AST node - used for constant, compile-time expressions within module scope - class ConstantItem - : public VisItem - , public InherentImplItem - , public TraitImplItem { - // either has an identifier or "_" - maybe handle in identifier? - // bool identifier_is_underscore; - // if no identifier declared, identifier will be "_" - Identifier identifier; - - // Type type; - ::std::unique_ptr type; - - // Expr* const_expr; - ::std::unique_ptr const_expr; - - location_t locus; - - public: - /*~ConstantItem() { - delete const_expr; - }*/ - - ::std::string as_string() const; - - ConstantItem(Identifier ident, Visibility vis, ::std::unique_ptr type, - ::std::unique_ptr const_expr, ::std::vector outer_attrs, - location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - identifier(::std::move(ident)), type(::std::move(type)), - const_expr(::std::move(const_expr)), locus(locus) {} - - ConstantItem(ConstantItem const& other) : - VisItem(other), identifier(other.identifier), type(other.type->clone_type()), - const_expr(other.const_expr->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - ConstantItem& operator=(ConstantItem const& other) { - VisItem::operator=(other); - identifier = other.identifier; - type = other.type->clone_type(); - const_expr = other.const_expr->clone_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - ConstantItem(ConstantItem&& other) = default; - ConstantItem& operator=(ConstantItem&& other) = default; - - /* Returns whether constant item is an "unnamed" (wildcard underscore used as identifier) - * constant. */ - inline bool is_unnamed() const { - return identifier == ::std::string("_"); - } - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConstantItem* clone_item_impl() const OVERRIDE { - return new ConstantItem(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ConstantItem* clone_inherent_impl_item_impl() const OVERRIDE { - return new ConstantItem(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ConstantItem* clone_trait_impl_item_impl() const OVERRIDE { - return new ConstantItem(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual ConstantItem* clone_statement_impl() const OVERRIDE { - return new ConstantItem(*this); - }*/ - }; - - // Static item AST node - items within module scope with fixed storage duration? - class StaticItem : public VisItem { - bool has_mut; - - Identifier name; - - // Type type; - ::std::unique_ptr type; - - // Expr* expr; - ::std::unique_ptr expr; - - location_t locus; - - public: - /*~StaticItem() { - delete expr; - }*/ - - ::std::string as_string() const; - - StaticItem(Identifier name, bool is_mut, ::std::unique_ptr type, - ::std::unique_ptr expr, Visibility vis, ::std::vector outer_attrs, - location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - has_mut(is_mut), name(::std::move(name)), type(::std::move(type)), - expr(::std::move(expr)), locus(locus) {} - - // Copy constructor with clone - StaticItem(StaticItem const& other) : - VisItem(other), has_mut(other.has_mut), name(other.name), - type(other.type->clone_type()), expr(other.expr->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - StaticItem& operator=(StaticItem const& other) { - VisItem::operator=(other); - name = other.name; - has_mut = other.has_mut; - type = other.type->clone_type(); - expr = other.expr->clone_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - StaticItem(StaticItem&& other) = default; - StaticItem& operator=(StaticItem&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StaticItem* clone_item_impl() const OVERRIDE { - return new StaticItem(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual StaticItem* clone_statement_impl() const OVERRIDE { - return new StaticItem(*this); - }*/ - }; - - // Function declaration in traits - struct TraitFunctionDecl { - private: - // TODO: delete and replace with Function decl item? no as no body in this. - FunctionQualifiers qualifiers; - Identifier function_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_params; - // FunctionParams function_params; - ::std::vector function_params; // inlined - - // bool has_return_type; - // Type return_type; - ::std::unique_ptr return_type; - - // bool has_where_clause; - WhereClause where_clause; - - // should this store location info? - - public: - // Returns whether function decl has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether function decl has regular parameters. - inline bool has_params() const { - return !function_params.empty(); - } - - // Returns whether function has return type (otherwise is void). - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether function has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Mega-constructor - TraitFunctionDecl(Identifier function_name, FunctionQualifiers qualifiers, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::vector function_params, ::std::unique_ptr return_type, - WhereClause where_clause) : - qualifiers(::std::move(qualifiers)), - function_name(::std::move(function_name)), generic_params(::std::move(generic_params)), - function_params(::std::move(function_params)), return_type(::std::move(return_type)), - where_clause(::std::move(where_clause)) {} - - // Copy constructor with clone - TraitFunctionDecl(TraitFunctionDecl const& other) : - qualifiers(other.qualifiers), function_name(other.function_name), - /*generic_params(other.generic_params),*/ function_params(other.function_params), - return_type(other.return_type->clone_type()), where_clause(other.where_clause) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - ~TraitFunctionDecl() = default; - - // Overloaded assignment operator with clone - TraitFunctionDecl& operator=(TraitFunctionDecl const& other) { - function_name = other.function_name; - qualifiers = other.qualifiers; - // generic_params = other.generic_params; - function_params = other.function_params; - return_type = other.return_type->clone_type(); - where_clause = other.where_clause; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - TraitFunctionDecl(TraitFunctionDecl&& other) = default; - TraitFunctionDecl& operator=(TraitFunctionDecl&& other) = default; - - ::std::string as_string() const; - }; - - // Actual trait item function declaration within traits - class TraitItemFunc : public TraitItem { - ::std::vector outer_attrs; - TraitFunctionDecl decl; - // BlockExpr* block_expr; - ::std::unique_ptr block_expr; - - location_t locus; - - public: - /*~TraitItemFunc() { - delete block_expr; - }*/ - - // Returns whether function has a definition or is just a declaration. - inline bool has_definition() const { - return block_expr != NULL; - } - - TraitItemFunc(TraitFunctionDecl decl, ::std::unique_ptr block_expr, - ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - decl(::std::move(decl)), block_expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - TraitItemFunc(TraitItemFunc const& other) : - outer_attrs(other.outer_attrs), - decl(other.decl) /*, block_expr(other.block_expr->clone_block_expr())*/, - locus(other.locus) { - if (other.block_expr != NULL) { - block_expr = other.block_expr->clone_block_expr(); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - TraitItemFunc& operator=(TraitItemFunc const& other) { - TraitItem::operator=(other); - outer_attrs = other.outer_attrs; - decl = other.decl; - locus = other.locus; - if (other.block_expr != NULL) { - block_expr = other.block_expr->clone_block_expr(); - } - - return *this; - } - - // move constructors - TraitItemFunc(TraitItemFunc&& other) = default; - TraitItemFunc& operator=(TraitItemFunc&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitItemFunc* clone_trait_item_impl() const { - return new TraitItemFunc(*this); - } - }; - - // Method declaration within traits - struct TraitMethodDecl { - private: - // TODO: delete and replace with Function decl item? no as no body. - FunctionQualifiers qualifiers; - Identifier function_name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - SelfParam self_param; - - // bool has_params; - // FunctionParams function_params; - ::std::vector function_params; // inlined - - // bool has_return_type; - // Type return_type; - ::std::unique_ptr return_type; - - // bool has_where_clause; - WhereClause where_clause; - - // should this store location info? - - public: - // Returns whether method decl has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether method decl has regular parameters. - inline bool has_params() const { - return !function_params.empty(); - } - - // Returns whether method has return type (otherwise is void). - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether method has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Mega-constructor - TraitMethodDecl(Identifier function_name, FunctionQualifiers qualifiers, - ::std::vector< ::std::unique_ptr > generic_params, SelfParam self_param, - ::std::vector function_params, ::std::unique_ptr return_type, - WhereClause where_clause) : - qualifiers(::std::move(qualifiers)), - function_name(::std::move(function_name)), generic_params(::std::move(generic_params)), - self_param(::std::move(self_param)), function_params(::std::move(function_params)), - return_type(::std::move(return_type)), where_clause(::std::move(where_clause)) {} - - // Copy constructor with clone - TraitMethodDecl(TraitMethodDecl const& other) : - qualifiers(other.qualifiers), function_name(other.function_name), - /*generic_params(other.generic_params),*/ self_param(other.self_param), - function_params(other.function_params), return_type(other.return_type->clone_type()), - where_clause(other.where_clause) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - ~TraitMethodDecl() = default; - - // Overloaded assignment operator with clone - TraitMethodDecl& operator=(TraitMethodDecl const& other) { - function_name = other.function_name; - qualifiers = other.qualifiers; - // generic_params = other.generic_params; - self_param = other.self_param; - function_params = other.function_params; - return_type = other.return_type->clone_type(); - where_clause = other.where_clause; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - TraitMethodDecl(TraitMethodDecl&& other) = default; - TraitMethodDecl& operator=(TraitMethodDecl&& other) = default; - - ::std::string as_string() const; - }; - - // Actual trait item method declaration within traits - class TraitItemMethod : public TraitItem { - ::std::vector outer_attrs; - TraitMethodDecl decl; - // BlockExpr* block_expr; - ::std::unique_ptr block_expr; - - location_t locus; - - public: - /*~TraitItemMethod() { - delete block_expr; - }*/ - - // Returns whether method has a definition or is just a declaration. - inline bool has_definition() const { - return block_expr != NULL; - } - - TraitItemMethod(TraitMethodDecl decl, ::std::unique_ptr block_expr, - ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - decl(::std::move(decl)), block_expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - TraitItemMethod(TraitItemMethod const& other) : - outer_attrs(other.outer_attrs), decl(other.decl), - block_expr(other.block_expr->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - TraitItemMethod& operator=(TraitItemMethod const& other) { - TraitItem::operator=(other); - outer_attrs = other.outer_attrs; - decl = other.decl; - block_expr = other.block_expr->clone_block_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - TraitItemMethod(TraitItemMethod&& other) = default; - TraitItemMethod& operator=(TraitItemMethod&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitItemMethod* clone_trait_item_impl() const { - return new TraitItemMethod(*this); - } - }; - - // Constant item within traits - class TraitItemConst : public TraitItem { - ::std::vector outer_attrs; - Identifier name; - // Type type; - ::std::unique_ptr type; - - // bool has_expression; - // Expr* expr; - ::std::unique_ptr expr; - - location_t locus; - - public: - /*~TraitItemConst() { - delete expr; - }*/ - - // Whether the constant item has an associated expression. - inline bool has_expression() const { - return expr != NULL; - } - - TraitItemConst(Identifier name, ::std::unique_ptr type, - ::std::unique_ptr expr, ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - name(::std::move(name)), type(::std::move(type)), expr(::std::move(expr)), - locus(locus) {} - - // Copy constructor with clones - TraitItemConst(TraitItemConst const& other) : - outer_attrs(other.outer_attrs), name(other.name), type(other.type->clone_type()), - expr(other.expr->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - TraitItemConst& operator=(TraitItemConst const& other) { - TraitItem::operator=(other); - outer_attrs = other.outer_attrs; - name = other.name; - type = other.type->clone_type(); - expr = other.expr->clone_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - TraitItemConst(TraitItemConst&& other) = default; - TraitItemConst& operator=(TraitItemConst&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitItemConst* clone_trait_item_impl() const { - return new TraitItemConst(*this); - } - }; - - // Type items within traits - class TraitItemType : public TraitItem { - ::std::vector outer_attrs; - - Identifier name; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - location_t locus; - - public: - // Returns whether trait item type has type param bounds. - inline bool has_type_param_bounds() const { - return !type_param_bounds.empty(); - } - - TraitItemType(Identifier name, - ::std::vector< ::std::unique_ptr > type_param_bounds, - ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - name(::std::move(name)), type_param_bounds(::std::move(type_param_bounds)), - locus(locus) {} - - // Copy constructor with vector clone - TraitItemType(TraitItemType const& other) : - outer_attrs(other.outer_attrs), name(other.name), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // Overloaded assignment operator with vector clone - TraitItemType& operator=(TraitItemType const& other) { - TraitItem::operator=(other); - outer_attrs = other.outer_attrs; - name = other.name; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // default move constructors - TraitItemType(TraitItemType&& other) = default; - TraitItemType& operator=(TraitItemType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitItemType* clone_trait_item_impl() const { - return new TraitItemType(*this); - } - }; - - // Macro invocation items within traits - TODO is this approach better or is making - // MacroInvocationSemi itself implement TraitItem better? Leaning toward latter. - /*class TraitItemMacroInvoc : public TraitItem { - MacroInvocationSemi macro_invoc; - - public: - TraitItemMacroInvoc( - MacroInvocationSemi macro_invoc, ::std::vector outer_attrs) : - macro_invoc(macro_invoc), - TraitItem(outer_attrs) {} - };*/ - // replaced with MacroInvocationSemi implementing TraitItem - - // Rust trait item declaration AST node - class Trait : public VisItem { - bool has_unsafe; - - Identifier name; - - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - // bool has_where_clause; - WhereClause where_clause; - - // bool has_trait_items; - ::std::vector< ::std::unique_ptr > trait_items; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether trait has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether trait has type parameter bounds. - inline bool has_type_param_bounds() const { - return !type_param_bounds.empty(); - } - - // Returns whether trait has where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Returns whether trait has trait items. - inline bool has_trait_items() const { - return !trait_items.empty(); - } - - // Mega-constructor - Trait(Identifier name, bool is_unsafe, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::vector< ::std::unique_ptr > type_param_bounds, - WhereClause where_clause, ::std::vector< ::std::unique_ptr > trait_items, - Visibility vis, ::std::vector outer_attrs, location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - has_unsafe(is_unsafe), name(::std::move(name)), - generic_params(::std::move(generic_params)), - type_param_bounds(::std::move(type_param_bounds)), - where_clause(::std::move(where_clause)), trait_items(::std::move(trait_items)), - locus(locus) {} - - // Copy constructor with vector clone - Trait(Trait const& other) : - VisItem(other), has_unsafe(other.has_unsafe), name(other.name), - where_clause(other.where_clause), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - // again for type param bounds - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - // again for trait items - trait_items.reserve(other.trait_items.size()); - - for (const auto& e : other.trait_items) { - trait_items.push_back(e->clone_trait_item()); - } - } - - // Overloaded assignment operator with vector clone - Trait& operator=(Trait const& other) { - VisItem::operator=(other); - name = other.name; - has_unsafe = other.has_unsafe; - where_clause = other.where_clause; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - // again for type param bounds - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - // again for trait items - trait_items.reserve(other.trait_items.size()); - - for (const auto& e : other.trait_items) { - trait_items.push_back(e->clone_trait_item()); - } - - return *this; - } - - // default move constructors - Trait(Trait&& other) = default; - Trait& operator=(Trait&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Trait* clone_item_impl() const OVERRIDE { - return new Trait(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual Trait* clone_statement_impl() const OVERRIDE { - return new Trait(*this); - }*/ - }; - - // Implementation item declaration AST node - abstract base class - class Impl : public VisItem { - // must be protected to allow subclasses to access them properly - protected: - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // Type trait_type; - ::std::unique_ptr trait_type; - - // bool has_where_clause; - WhereClause where_clause; - - // bool has_inner_attrs; - ::std::vector inner_attrs; - - private: - // doesn't really need to be protected as write access probably not needed - location_t locus; - - public: - // Returns whether impl has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether impl has where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - // Returns whether impl has inner attributes. - inline bool has_inner_attrs() const { - return !inner_attrs.empty(); - } - - location_t get_locus() const { - return locus; - } - - protected: - // Mega-constructor - Impl(::std::vector< ::std::unique_ptr > generic_params, - ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, - ::std::vector inner_attrs, ::std::vector outer_attrs, - location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - generic_params(::std::move(generic_params)), trait_type(::std::move(trait_type)), - where_clause(::std::move(where_clause)), inner_attrs(::std::move(inner_attrs)), - locus(locus) {} - - // Copy constructor - Impl(Impl const& other) : - VisItem(other), - /*generic_params(other.generic_params),*/ trait_type(other.trait_type->clone_type()), - where_clause(other.where_clause), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // Destructor - define here if required - - // Assignment operator overload with cloning - Impl& operator=(Impl const& other) { - VisItem::operator=(other); - // generic_params = other.generic_params; - trait_type = other.trait_type->clone_type(); - where_clause = other.where_clause; - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - Impl(Impl&& other) = default; - Impl& operator=(Impl&& other) = default; - }; - - // Regular "impl foo" impl block declaration AST node - class InherentImpl : public Impl { - // bool has_impl_items; - ::std::vector< ::std::unique_ptr > impl_items; - - public: - ::std::string as_string() const; - - // Returns whether inherent impl block has inherent impl items. - inline bool has_impl_items() const { - return !impl_items.empty(); - } - - // Mega-constructor - InherentImpl(::std::vector< ::std::unique_ptr > impl_items, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, - ::std::vector inner_attrs, ::std::vector outer_attrs, - location_t locus) : - Impl(::std::move(generic_params), ::std::move(trait_type), ::std::move(where_clause), - ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus), - impl_items(::std::move(impl_items)) {} - - // Copy constructor with vector clone - InherentImpl(InherentImpl const& other) : Impl(other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - impl_items.reserve(other.impl_items.size()); - - for (const auto& e : other.impl_items) { - impl_items.push_back(e->clone_inherent_impl_item()); - } - } - - // Overloaded assignment operator with vector clone - InherentImpl& operator=(InherentImpl const& other) { - Impl::operator=(other); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - impl_items.reserve(other.impl_items.size()); - - for (const auto& e : other.impl_items) { - impl_items.push_back(e->clone_inherent_impl_item()); - } - - return *this; - } - - // default move constructors - InherentImpl(InherentImpl&& other) = default; - InherentImpl& operator=(InherentImpl&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual InherentImpl* clone_item_impl() const OVERRIDE { - return new InherentImpl(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual InherentImpl* clone_statement_impl() const OVERRIDE { - return new InherentImpl(*this); - }*/ - }; - - // The "impl footrait for foo" impl block declaration AST node - class TraitImpl : public Impl { - bool has_unsafe; - - bool has_exclam; - - TypePath trait_path; - - // bool has_impl_items; - ::std::vector< ::std::unique_ptr > impl_items; - - public: - ::std::string as_string() const; - - // Returns whether trait impl has impl items. - inline bool has_impl_items() const { - return !impl_items.empty(); - } - - // Mega-constructor - TraitImpl(TypePath trait_path, bool is_unsafe, bool has_exclam, - ::std::vector< ::std::unique_ptr > impl_items, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, - ::std::vector inner_attrs, ::std::vector outer_attrs, - location_t locus) : - Impl(::std::move(generic_params), ::std::move(trait_type), ::std::move(where_clause), - ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus), - has_unsafe(is_unsafe), has_exclam(has_exclam), trait_path(::std::move(trait_path)), - impl_items(::std::move(impl_items)) {} - - // TODO: constructors with less params - - // Copy constructor with vector clone - TraitImpl(TraitImpl const& other) : - Impl(other), has_unsafe(other.has_unsafe), has_exclam(other.has_exclam), - trait_path(other.trait_path) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - impl_items.reserve(other.impl_items.size()); - - for (const auto& e : other.impl_items) { - impl_items.push_back(e->clone_trait_impl_item()); - } - } - - // Overloaded assignment operator with vector clone - TraitImpl& operator=(TraitImpl const& other) { - Impl::operator=(other); - trait_path = other.trait_path; - has_unsafe = other.has_unsafe; - has_exclam = other.has_exclam; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - impl_items.reserve(other.impl_items.size()); - - for (const auto& e : other.impl_items) { - impl_items.push_back(e->clone_trait_impl_item()); - } - - return *this; - } - - // move constructors - TraitImpl(TraitImpl&& other) = default; - TraitImpl& operator=(TraitImpl&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TraitImpl* clone_item_impl() const OVERRIDE { - return new TraitImpl(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual TraitImpl* clone_statement_impl() const OVERRIDE { - return new TraitImpl(*this); - }*/ - }; - - // Abstract base class for an item used inside an extern block - class ExternalItem { - // bool has_outer_attrs; - ::std::vector outer_attrs; - - // bool has_visibility; - Visibility visibility; - - Identifier item_name; - - location_t locus; - - public: - virtual ~ExternalItem() {} - - // Returns whether item has outer attributes. - inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - } - - // Returns whether item has non-default visibility. - inline bool has_visibility() const { - return !visibility.is_error(); - } - - // Unique pointer custom clone function - ::std::unique_ptr clone_external_item() const { - return ::std::unique_ptr(clone_external_item_impl()); - } - - virtual ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - ExternalItem(Identifier item_name, Visibility vis, ::std::vector outer_attrs, - location_t locus) : - outer_attrs(::std::move(outer_attrs)), - visibility(::std::move(vis)), item_name(::std::move(item_name)), locus(locus) {} - - // Copy constructor - ExternalItem(ExternalItem const& other) : - outer_attrs(other.outer_attrs), visibility(other.visibility), - item_name(other.item_name), locus(other.locus) {} - - // Overloaded assignment operator to clone - ExternalItem& operator=(ExternalItem const& other) { - item_name = other.item_name; - visibility = other.visibility; - outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - ExternalItem(ExternalItem&& other) = default; - ExternalItem& operator=(ExternalItem&& other) = default; - - // Clone function implementation as pure virtual method - virtual ExternalItem* clone_external_item_impl() const = 0; - - // possibly make this public if required - ::std::string get_item_name() const { - return item_name; - } - }; - - // A static item used in an extern block - class ExternalStaticItem : public ExternalItem { - bool has_mut; - - // Type item_type; - ::std::unique_ptr item_type; - - public: - ExternalStaticItem(Identifier item_name, ::std::unique_ptr item_type, bool is_mut, - Visibility vis, ::std::vector outer_attrs, location_t locus) : - ExternalItem(::std::move(item_name), ::std::move(vis), ::std::move(outer_attrs), locus), - has_mut(is_mut), item_type(::std::move(item_type)) {} - - // Copy constructor - ExternalStaticItem(ExternalStaticItem const& other) : - ExternalItem(other), has_mut(other.has_mut), item_type(other.item_type->clone_type()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ExternalStaticItem& operator=(ExternalStaticItem const& other) { - ExternalItem::operator=(other); - item_type = other.item_type->clone_type(); - has_mut = other.has_mut; - - return *this; - } - - // move constructors - ExternalStaticItem(ExternalStaticItem&& other) = default; - ExternalStaticItem& operator=(ExternalStaticItem&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExternalStaticItem* clone_external_item_impl() const OVERRIDE { - return new ExternalStaticItem(*this); - } - }; - - // A named function parameter used in external functions - struct NamedFunctionParam { - private: - // bool has_name; // otherwise is _ - Identifier name; // TODO: handle wildcard in identifier? - - // Type param_type; - ::std::unique_ptr param_type; - - // TODO: should this store location data? - - public: - // Returns whether the named function parameter has a name (i.e. name is not '_'). - inline bool has_name() const { - return name != "_"; - } - - // Returns whether the named function parameter is in an error state. - inline bool is_error() const { - // also if identifier is "" but that is probably more costly to compute - return param_type == NULL; - } - - // Creates an error state named function parameter. - static NamedFunctionParam create_error() { - return NamedFunctionParam("", NULL); - } - - NamedFunctionParam(Identifier name, ::std::unique_ptr param_type) : - name(::std::move(name)), param_type(::std::move(param_type)) {} - - // Copy constructor - NamedFunctionParam(NamedFunctionParam const& other) : - name(other.name), param_type(other.param_type->clone_type()) {} - - ~NamedFunctionParam() = default; - - // Overloaded assignment operator to clone - NamedFunctionParam& operator=(NamedFunctionParam const& other) { - name = other.name; - param_type = other.param_type->clone_type(); - // has_name = other.has_name; - - return *this; - } - - // move constructors - NamedFunctionParam(NamedFunctionParam&& other) = default; - NamedFunctionParam& operator=(NamedFunctionParam&& other) = default; - - ::std::string as_string() const; - }; - - // A function item used in an extern block - class ExternalFunctionItem : public ExternalItem { - // bool has_generics; - // Generics generic_params; - ::std::vector< ::std::unique_ptr > generic_params; // inlined - - // bool has_return_type; - // FunctionReturnType return_type; - ::std::unique_ptr return_type; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - ::std::vector function_params; - - bool has_variadics; - - public: - // Returns whether item has generic parameters. - inline bool has_generics() const { - return !generic_params.empty(); - } - - // Returns whether item has a return type (otherwise void). - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether item has a where clause. - inline bool has_where_clause() const { - return !where_clause.is_empty(); - } - - ExternalFunctionItem(Identifier item_name, - ::std::vector< ::std::unique_ptr > generic_params, - ::std::unique_ptr return_type, WhereClause where_clause, - ::std::vector function_params, bool has_variadics, Visibility vis, - ::std::vector outer_attrs, location_t locus) : - ExternalItem(::std::move(item_name), ::std::move(vis), ::std::move(outer_attrs), locus), - generic_params(::std::move(generic_params)), return_type(::std::move(return_type)), - where_clause(::std::move(where_clause)), function_params(::std::move(function_params)), - has_variadics(has_variadics) {} - - // Copy constructor with clone - ExternalFunctionItem(ExternalFunctionItem const& other) : - ExternalItem(other), - /*generic_params(other.generic_params),*/ return_type(other.return_type->clone_type()), - where_clause(other.where_clause), function_params(other.function_params), - has_variadics(other.has_variadics) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator with clone - ExternalFunctionItem& operator=(ExternalFunctionItem const& other) { - ExternalItem::operator=(other); - // generic_params = other.generic_params; - return_type = other.return_type->clone_type(); - where_clause = other.where_clause; - function_params = other.function_params; - has_variadics = other.has_variadics; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - generic_params.reserve(other.generic_params.size()); - - for (const auto& e : other.generic_params) { - generic_params.push_back(e->clone_generic_param()); - } - - return *this; - } - - // move constructors - ExternalFunctionItem(ExternalFunctionItem&& other) = default; - ExternalFunctionItem& operator=(ExternalFunctionItem&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExternalFunctionItem* clone_external_item_impl() const OVERRIDE { - return new ExternalFunctionItem(*this); - } - }; - - // An extern block AST node - class ExternBlock : public VisItem { - // bool has_abi; - ::std::string abi; - - // bool has_inner_attrs; - ::std::vector inner_attrs; - - // bool has_extern_items; - ::std::vector< ::std::unique_ptr > extern_items; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns whether extern block has inner attributes. - inline bool has_inner_attrs() const { - return !inner_attrs.empty(); - } - - // Returns whether extern block has extern items. - inline bool has_extern_items() const { - return !extern_items.empty(); - } - - // Returns whether extern block has ABI name. - inline bool has_abi() const { - return !abi.empty(); - } - - ExternBlock(::std::string abi, - ::std::vector< ::std::unique_ptr > extern_items, Visibility vis, - ::std::vector inner_attrs, ::std::vector outer_attrs, - location_t locus) : - VisItem(::std::move(vis), ::std::move(outer_attrs)), - abi(::std::move(abi)), inner_attrs(::std::move(inner_attrs)), - extern_items(::std::move(extern_items)), locus(locus) {} - - // Copy constructor with vector clone - ExternBlock(ExternBlock const& other) : - VisItem(other), abi(other.abi), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - extern_items.reserve(other.extern_items.size()); - - for (const auto& e : other.extern_items) { - extern_items.push_back(e->clone_external_item()); - } - } - - // Overloaded assignment operator with vector clone - ExternBlock& operator=(ExternBlock const& other) { - VisItem::operator=(other); - abi = other.abi; - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - extern_items.reserve(other.extern_items.size()); - - for (const auto& e : other.extern_items) { - extern_items.push_back(e->clone_external_item()); - } - - return *this; - } - - // move constructors - ExternBlock(ExternBlock&& other) = default; - ExternBlock& operator=(ExternBlock&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExternBlock* clone_item_impl() const OVERRIDE { - return new ExternBlock(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - /*virtual ExternBlock* clone_statement_impl() const OVERRIDE { - return new ExternBlock(*this); - }*/ - }; - - // Replaced with forward decls - defined in "rust-macro.h" - class MacroItem; - class MacroInvocationSemi; - class MacroRulesDefinition; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-macro.h b/gcc/rust/test3/ast/rust-macro.h deleted file mode 100644 index 4c8237e..0000000 --- a/gcc/rust/test3/ast/rust-macro.h +++ /dev/null @@ -1,588 +0,0 @@ -#ifndef RUST_AST_MACRO_H -#define RUST_AST_MACRO_H - -#include "rust-ast.h" - -namespace Rust { - namespace AST { - // Decls as definitions moved to rust-ast.h - class MacroItem; - class MacroInvocationSemi; - - enum MacroFragSpec { - BLOCK, - EXPR, - IDENT, - ITEM, - LIFETIME, - LITERAL, - META, - PAT, - PATH, - STMT, - TT, - TY, - VIS, - INVALID // not really a specifier, but used to mark invalid one passed in - }; - - inline MacroFragSpec get_frag_spec_from_str(::std::string str) { - if (str == "block") - return BLOCK; - else if (str == "expr") - return EXPR; - else if (str == "ident") - return IDENT; - else if (str == "item") - return ITEM; - else if (str == "lifetime") - return LIFETIME; - else if (str == "literal") - return LITERAL; - else if (str == "meta") - return META; - else if (str == "pat") - return PAT; - else if (str == "path") - return PATH; - else if (str == "stmt") - return STMT; - else if (str == "tt") - return TT; - else if (str == "ty") - return TY; - else if (str == "vis") - return VIS; - else { - // error_at("invalid string '%s' used as fragment specifier", str->c_str()); - return INVALID; - } - } - - // A macro match that has an identifier and fragment spec - class MacroMatchFragment : public MacroMatch { - Identifier ident; - MacroFragSpec frag_spec; - - // TODO: should store location information? - - public: - MacroMatchFragment(Identifier ident, MacroFragSpec frag_spec) : - ident(::std::move(ident)), frag_spec(frag_spec) {} - - // Returns whether macro match fragment is in an error state. - inline bool is_error() const { - return frag_spec == INVALID; - } - - // Creates an error state macro match fragment. - static MacroMatchFragment create_error() { - return MacroMatchFragment(::std::string(""), INVALID); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatchFragment* clone_macro_match_impl() const OVERRIDE { - return new MacroMatchFragment(*this); - } - }; - - // A repetition macro match - class MacroMatchRepetition : public MacroMatch { - public: - enum MacroRepOp { NONE, ASTERISK, PLUS, QUESTION_MARK }; - - private: - //::std::vector matches; - ::std::vector< ::std::unique_ptr > matches; - MacroRepOp op; - - // bool has_sep; - typedef Token MacroRepSep; - // any token except delimiters and repetition operators - ::std::unique_ptr sep; - - // TODO: should store location information? - - public: - // Returns whether macro match repetition has separator token. - inline bool has_sep() const { - return sep != NULL; - } - - MacroMatchRepetition(::std::vector< ::std::unique_ptr > matches, - MacroRepOp op, ::std::unique_ptr sep) : - matches(::std::move(matches)), - op(op), sep(::std::move(sep)) {} - - // Copy constructor with clone - MacroMatchRepetition(MacroMatchRepetition const& other) : - /*matches(other.matches),*/ op(other.op), sep(other.sep->clone_token()) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - MacroMatchRepetition& operator=(MacroMatchRepetition const& other) { - // matches = other.matches; // TODO: this needs to clone somehow? - op = other.op; - sep = other.sep->clone_token(); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - - return *this; - } - - // move constructors - MacroMatchRepetition(MacroMatchRepetition&& other) = default; - MacroMatchRepetition& operator=(MacroMatchRepetition&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatchRepetition* clone_macro_match_impl() const OVERRIDE { - return new MacroMatchRepetition(*this); - } - }; - - // can't inline due to polymorphism - class MacroMatcher : public MacroMatch { - DelimType delim_type; - //::std::vector matches; - ::std::vector< ::std::unique_ptr > matches; - - // TODO: think of way to mark invalid that doesn't take up more space - bool is_invalid; - - // TODO: should store location information? - - public: - MacroMatcher( - DelimType delim_type, ::std::vector< ::std::unique_ptr > matches) : - delim_type(delim_type), - matches(::std::move(matches)), is_invalid(false) {} - - // copy constructor with vector clone - MacroMatcher(MacroMatcher const& other) : delim_type(other.delim_type) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - } - - // overloaded assignment operator with vector clone - MacroMatcher& operator=(MacroMatcher const& other) { - delim_type = other.delim_type; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - - return *this; - } - - // move constructors - MacroMatcher(MacroMatcher&& other) = default; - MacroMatcher& operator=(MacroMatcher&& other) = default; - - // Creates an error state macro matcher. - static MacroMatcher create_error() { - return MacroMatcher(true); - } - - // Returns whether MacroMatcher is in an error state. - inline bool is_error() const { - return is_invalid; - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatcher* clone_macro_match_impl() const OVERRIDE { - return new MacroMatcher(*this); - } - - // constructor only used to create error matcher - MacroMatcher(bool is_invalid) : delim_type(PARENS), is_invalid(is_invalid) {} - }; - - // TODO: inline? - struct MacroTranscriber { - private: - DelimTokenTree token_tree; - - // TODO: should store location information? - - public: - MacroTranscriber(DelimTokenTree token_tree) : token_tree(::std::move(token_tree)) {} - - ::std::string as_string() const { - return token_tree.as_string(); - } - }; - - // A macro rule? Matcher and transcriber pair? - struct MacroRule { - private: - MacroMatcher matcher; - MacroTranscriber transcriber; - - // TODO: should store location information? - - public: - MacroRule(MacroMatcher matcher, MacroTranscriber transcriber) : - matcher(::std::move(matcher)), transcriber(::std::move(transcriber)) {} - - // Returns whether macro rule is in error state. - inline bool is_error() const { - return matcher.is_error(); - } - - // Creates an error state macro rule. - static MacroRule create_error() { - return MacroRule( - MacroMatcher::create_error(), MacroTranscriber(DelimTokenTree::create_empty())); - } - - ::std::string as_string() const; - }; - - // A macro rules definition item AST node - class MacroRulesDefinition : public MacroItem { - Identifier rule_name; - // MacroRulesDef rules_def; // TODO: inline - // only curly without required semicolon at end - DelimType delim_type; - // MacroRules rules; - ::std::vector rules; // inlined form - - location_t locus; - - public: - ::std::string as_string() const; - - MacroRulesDefinition(Identifier rule_name, DelimType delim_type, - ::std::vector rules, ::std::vector outer_attrs, - location_t locus) : - MacroItem(::std::move(outer_attrs)), - rule_name(::std::move(rule_name)), delim_type(delim_type), rules(::std::move(rules)), - locus(locus) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroRulesDefinition* clone_item_impl() const OVERRIDE { - return new MacroRulesDefinition(*this); - } - }; - - // AST node of a macro invocation, which is replaced by the macro result at compile time - class MacroInvocation - : public TypeNoBounds - , public Pattern - , public ExprWithoutBlock { - SimplePath path; - DelimTokenTree token_tree; - - location_t locus; - - public: - ::std::string as_string() const; - - MacroInvocation(SimplePath path, DelimTokenTree token_tree, - ::std::vector outer_attrs, location_t locus) : - ExprWithoutBlock(::std::move(outer_attrs)), - path(::std::move(path)), token_tree(::std::move(token_tree)), locus(locus) {} - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_pattern_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_expr_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_expr_without_block_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_type_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_type_no_bounds_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - }; - - // more generic meta item path-only form - class MetaItemPath : public MetaItem { - SimplePath path; - - public: - MetaItemPath(SimplePath path) : path(::std::move(path)) {} - - ::std::string as_string() const OVERRIDE { - return path.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // HACK: used to simplify parsing - returns non-empty only in this case - virtual SimplePath to_path_item() const OVERRIDE { - // this should copy construct - TODO ensure it does - return path; - } - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemPath* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemPath(*this); - } - }; - - // more generic meta item sequence form - class MetaItemSeq : public MetaItem { - SimplePath path; - ::std::vector< ::std::unique_ptr > seq; - - public: - MetaItemSeq(SimplePath path, ::std::vector< ::std::unique_ptr > seq) : - path(::std::move(path)), seq(::std::move(seq)) {} - - // copy constructor with vector clone - MetaItemSeq(const MetaItemSeq& other) : path(other.path) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - seq.reserve(other.seq.size()); - - for (const auto& e : other.seq) { - seq.push_back(e->clone_meta_item_inner()); - } - } - - // destructor definition not required - - // overloaded assignment operator with vector clone - MetaItemSeq& operator=(const MetaItemSeq& other) { - MetaItem::operator=(other); - path = other.path; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - seq.reserve(other.seq.size()); - - for (const auto& e : other.seq) { - seq.push_back(e->clone_meta_item_inner()); - } - - return *this; - } - - // default move constructors - MetaItemSeq(MetaItemSeq&& other) = default; - MetaItemSeq& operator=(MetaItemSeq&& other) = default; - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemSeq* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemSeq(*this); - } - }; - - // Preferred specialisation for single-identifier meta items. - class MetaWord : public MetaItem { - Identifier ident; - - public: - MetaWord(Identifier ident) : ident(::std::move(ident)) {} - - ::std::string as_string() const OVERRIDE { - return ident; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaWord* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaWord(*this); - } - }; - - // Preferred specialisation for "identifier '=' string literal" meta items. - class MetaNameValueStr : public MetaItem { - Identifier ident; - ::std::string str; - - public: - MetaNameValueStr(Identifier ident, ::std::string str) : - ident(::std::move(ident)), str(::std::move(str)) {} - - ::std::string as_string() const OVERRIDE { - return ident + " = " + str; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // HACK: used to simplify parsing - creates a copy of this - virtual MetaNameValueStr* to_meta_name_value_str() const OVERRIDE { - return clone_meta_item_inner_impl(); - } - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaNameValueStr(*this); - } - }; - - // doubles up as MetaListIdents - determine via iterating through each path? - // Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'" - class MetaListPaths : public MetaItem { - Identifier ident; - ::std::vector paths; - - public: - MetaListPaths(Identifier ident, ::std::vector paths) : - ident(::std::move(ident)), paths(::std::move(paths)) {} - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - private: - bool check_path_exists_in_cfg(const Session& session, const SimplePath& path) const; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaListPaths* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaListPaths(*this); - } - }; - - // Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'" - class MetaListNameValueStr : public MetaItem { - Identifier ident; - ::std::vector strs; - - public: - MetaListNameValueStr(Identifier ident, ::std::vector strs) : - ident(::std::move(ident)), strs(::std::move(strs)) {} - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaListNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaListNameValueStr(*this); - } - }; - - // Object that parses macros from a token stream. - struct MacroParser { - private: - ::std::vector< ::std::unique_ptr > token_stream; - // probably have to make this mutable (mutable int stream_pos) otherwise const has to be - // removed up to DelimTokenTree or further ok since this changing would have an effect on - // the results of the methods run (i.e. not logically const), the parsing methods - // shouldn't be const - int stream_pos; - - public: - MacroParser( - ::std::vector< ::std::unique_ptr > token_stream, int stream_start_pos = 0) : - token_stream(::std::move(token_stream)), - stream_pos(stream_start_pos) {} - - ~MacroParser() = default; - - ::std::vector< ::std::unique_ptr > parse_meta_item_seq(); - - private: - // Parses a MetaItemInner. - ::std::unique_ptr parse_meta_item_inner(); - // Returns whether token can end a meta item. - bool is_end_meta_item_tok(TokenId id) const; - // Parses a simple path. - SimplePath parse_simple_path(); - // Parses a segment of a simple path (but not scope resolution operator). - SimplePathSegment parse_simple_path_segment(); - // Parses a MetaItemLitExpr. - ::std::unique_ptr parse_meta_item_lit(); - // Parses a literal. - Literal parse_literal(); - // Parses a meta item that begins with a simple path. - ::std::unique_ptr parse_path_meta_item(); - - // TODO: should this be const? - ::std::unique_ptr& peek_token(int i = 0) { - return token_stream[stream_pos + i]; - } - - void skip_token(int i = 0) { - stream_pos += 1 + i; - } - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-path.h b/gcc/rust/test3/ast/rust-path.h deleted file mode 100644 index cddd062..0000000 --- a/gcc/rust/test3/ast/rust-path.h +++ /dev/null @@ -1,803 +0,0 @@ -#ifndef RUST_AST_PATH_H -#define RUST_AST_PATH_H -/* "Path" (identifier within namespaces, essentially) handling. Required include for virtually all - * AST-related functionality. */ - -#include "rust-ast.h" - -#include -#include - -namespace Rust { - namespace AST { - // make intellisense calm - /*typedef ::std::string Symbol; - typedef int Lifetime; - typedef int Type; - typedef int Binding;*/ - - // The "identifier" (not generic args) aspect of each path expression segment - class PathIdentSegment { - ::std::string segment_name; - - // TODO: should this have location info stored? - - // only allow identifiers, "super", "self", "Self", "crate", or "$crate" - public: - PathIdentSegment(::std::string segment_name) : segment_name(::std::move(segment_name)) {} - - /* TODO: insert check in constructor for this? Or is this a semantic error best handled - * then? */ - - // TODO: does this require visitor. pretty sure this isn't polymorphic, but not entirely sure - - // Creates an error PathIdentSegment. - static PathIdentSegment create_error() { - return PathIdentSegment(""); - } - - // Returns whether PathIdentSegment is in an error state. - inline bool is_error() const { - return segment_name.empty(); - } - - ::std::string as_string() const { - return segment_name; - } - }; - - // A binding of an identifier to a type used in generic arguments in paths - struct GenericArgsBinding { - private: - Identifier identifier; - // Type type; - ::std::unique_ptr type; - - location_t locus; - - public: - // Returns whether binding is in an error state. - inline bool is_error() const { - return type == NULL; // and also identifier is empty, but cheaper computation - } - - // Creates an error state generic args binding. - static GenericArgsBinding create_error() { - return GenericArgsBinding("", NULL); - } - - // Pointer type for type in constructor to enable polymorphism - GenericArgsBinding(Identifier ident, ::std::unique_ptr type_ptr, - location_t locus = UNKNOWN_LOCATION) : - identifier(::std::move(ident)), - type(::std::move(type_ptr)), locus(locus) {} - - // Copy constructor has to deep copy the type as it is a unique pointer - GenericArgsBinding(GenericArgsBinding const& other) : - identifier(other.identifier), type(other.type->clone_type()), locus(other.locus) {} - - // default destructor - ~GenericArgsBinding() = default; - - // Overload assignment operator to deep copy the pointed-to type - GenericArgsBinding& operator=(GenericArgsBinding const& other) { - identifier = other.identifier; - type = other.type->clone_type(); - locus = other.locus; - return *this; - } - - // move constructors - GenericArgsBinding(GenericArgsBinding&& other) = default; - GenericArgsBinding& operator=(GenericArgsBinding&& other) = default; - - ::std::string as_string() const; - }; - - // Generic arguments allowed in each path expression segment - inline? - struct GenericArgs { - ::std::vector lifetime_args; - //::std::vector type_args; - ::std::vector< ::std::unique_ptr > type_args; - ::std::vector binding_args; - - location_t locus; - - public: - // Returns true if there are any generic arguments - inline bool has_generic_args() const { - return !(lifetime_args.empty() && type_args.empty() && binding_args.empty()); - } - - GenericArgs(::std::vector lifetime_args, - ::std::vector< ::std::unique_ptr > type_args, - ::std::vector binding_args, location_t locus = UNKNOWN_LOCATION) : - lifetime_args(::std::move(lifetime_args)), - type_args(::std::move(type_args)), binding_args(::std::move(binding_args)), - locus(locus) {} - - // copy constructor with vector clone - GenericArgs(GenericArgs const& other) : - lifetime_args(other.lifetime_args), binding_args(other.binding_args), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_args.reserve(other.type_args.size()); - - for (const auto& e : other.type_args) { - type_args.push_back(e->clone_type()); - } - } - - ~GenericArgs() = default; - - // overloaded assignment operator to vector clone - GenericArgs& operator=(GenericArgs const& other) { - lifetime_args = other.lifetime_args; - binding_args = other.binding_args; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_args.reserve(other.type_args.size()); - - for (const auto& e : other.type_args) { - type_args.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - GenericArgs(GenericArgs&& other) = default; - GenericArgs& operator=(GenericArgs&& other) = default; - - // Creates an empty GenericArgs (no arguments) - static GenericArgs create_empty() { - return GenericArgs(::std::vector(), - ::std::vector< ::std::unique_ptr >(), ::std::vector()); - } - - ::std::string as_string() const; - }; - - // A segment of a path in expression, including an identifier aspect and maybe generic args - class PathExprSegment { // or should this extend PathIdentSegment? - private: - PathIdentSegment segment_name; - - // bool has_generic_args; - GenericArgs generic_args; - - location_t locus; - - // TODO: does this require visitor? pretty sure not polymorphic - - public: - // Returns true if there are any generic arguments - inline bool has_generic_args() const { - return generic_args.has_generic_args(); - } - - // Constructor for segment (from IdentSegment and GenericArgs) - PathExprSegment(PathIdentSegment segment_name, location_t locus = UNKNOWN_LOCATION, - GenericArgs generic_args = GenericArgs::create_empty()) : - segment_name(::std::move(segment_name)), - generic_args(::std::move(generic_args)), locus(locus) {} - - // Constructor for segment with generic arguments (from segment name and all args) - PathExprSegment(::std::string segment_name, location_t locus, - ::std::vector lifetime_args = ::std::vector(), - ::std::vector< ::std::unique_ptr > type_args - = ::std::vector< ::std::unique_ptr >(), - ::std::vector binding_args = ::std::vector()) : - segment_name(PathIdentSegment(::std::move(segment_name))), - generic_args(GenericArgs( - ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))), - locus(locus) {} - - // Returns whether path expression segment is in an error state. - inline bool is_error() const { - return segment_name.is_error(); - } - - // Creates an error-state path expression segment. - static PathExprSegment create_error() { - return PathExprSegment(PathIdentSegment::create_error()); - } - - ::std::string as_string() const; - - inline location_t get_locus() const { - return locus; - } - }; - - // AST node representing a pattern that involves a "path" - abstract base class - class PathPattern : public Pattern { - ::std::vector segments; - - protected: - PathPattern(::std::vector segments) : segments(::std::move(segments)) {} - - // Returns whether path has segments. - inline bool has_segments() const { - return !segments.empty(); - } - - /* Converts path segments to their equivalent SimplePath segments if possible, and creates - * a SimplePath from them. */ - SimplePath convert_to_simple_path(bool with_opening_scope_resolution) const; - - public: - /* Returns whether the path is a single segment (excluding qualified path initial as - * segment). */ - inline bool is_single_segment() const { - return segments.size() == 1; - } - - virtual ::std::string as_string() const; - }; - - // AST node representing a path-in-expression pattern (path that allows generic arguments) - class PathInExpression - : public PathPattern - , public PathExpr { - bool has_opening_scope_resolution; - - location_t locus; - - public: - ::std::string as_string() const; - - // Constructor - PathInExpression(::std::vector path_segments, - location_t locus = UNKNOWN_LOCATION, bool has_opening_scope_resolution = false, - ::std::vector outer_attrs = ::std::vector()) : - PathPattern(::std::move(path_segments)), - PathExpr(::std::move(outer_attrs)), - has_opening_scope_resolution(has_opening_scope_resolution), locus(locus) {} - - // Creates an error state path in expression. - static PathInExpression create_error() { - return PathInExpression(::std::vector()); - } - - // Returns whether path in expression is in an error state. - inline bool is_error() const { - return !has_segments(); - } - - /* Converts PathInExpression to SimplePath if possible (i.e. no generic arguments). - * Otherwise returns an empty SimplePath. */ - inline SimplePath as_simple_path() const { - /* delegate to parent class as can't access segments. however, - * QualifiedPathInExpression conversion to simple path wouldn't make sense, so the - * method in the parent class should be protected, not public. - * Have to pass in opening scope resolution as parent class has no access to it. */ - return convert_to_simple_path(has_opening_scope_resolution); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathInExpression* clone_pattern_impl() const OVERRIDE { - return new PathInExpression(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathInExpression* clone_expr_without_block_impl() const OVERRIDE { - return new PathInExpression(*this); - } - }; - - // Base class for segments used in type paths - not abstract (represents an ident-only - // segment) - class TypePathSegment { - /* TODO: may have to unify TypePathSegment and PathExprSegment (which are mostly the - * same anyway) in order to resolve goddamn syntax ambiguities. - * One difference is that function on TypePathSegment is not allowed if GenericArgs are, - * so could disallow that in constructor, which won't give that much size overhead. */ - PathIdentSegment ident_segment; - - location_t locus; - - protected: - // This is protected because it is only really used by derived classes, not the base. - bool has_separating_scope_resolution; - - // Clone function implementation - not pure virtual as overrided by subclasses - virtual TypePathSegment* clone_type_path_segment_impl() const { - return new TypePathSegment(*this); - } - - public: - virtual ~TypePathSegment() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_type_path_segment() const { - return ::std::unique_ptr(clone_type_path_segment_impl()); - } - - TypePathSegment(PathIdentSegment ident_segment, bool has_separating_scope_resolution, - location_t locus) : - ident_segment(::std::move(ident_segment)), - locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} - - TypePathSegment( - ::std::string segment_name, bool has_separating_scope_resolution, location_t locus) : - ident_segment(PathIdentSegment(::std::move(segment_name))), - locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} - - virtual ::std::string as_string() const { - return ident_segment.as_string(); - } - - // Returns whether the type path segment is in an error state. May be virtual in future. - inline bool is_error() const { - return ident_segment.is_error(); - } - - /* Returns whether segment is identifier only (as opposed to generic args or function). - Overriden in derived classes with other segments. */ - virtual bool is_ident_only() const { - return true; - } - - inline bool get_locus() const { - return locus; - } - - // not pure virtual as class not abstract - virtual void accept_vis(ASTVisitor& vis); - }; - - // Segment used in type path with generic args - class TypePathSegmentGeneric : public TypePathSegment { - GenericArgs generic_args; - - public: - inline bool has_generic_args() const { - return generic_args.has_generic_args(); - } - - bool is_ident_only() const { - return false; - } - - // Constructor with PathIdentSegment and GenericArgs - TypePathSegmentGeneric(PathIdentSegment ident_segment, - bool has_separating_scope_resolution, GenericArgs generic_args, location_t locus) : - TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), - generic_args(::std::move(generic_args)) {} - - // Constructor from segment name and all args - TypePathSegmentGeneric(::std::string segment_name, bool has_separating_scope_resolution, - ::std::vector lifetime_args, - ::std::vector< ::std::unique_ptr > type_args, - ::std::vector binding_args, location_t locus) : - TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), - generic_args(GenericArgs( - ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to override base class method - virtual TypePathSegmentGeneric* clone_type_path_segment_impl() const OVERRIDE { - return new TypePathSegmentGeneric(*this); - } - }; - - // A function as represented in a type path - struct TypePathFunction { - private: - // TODO: remove - /*bool has_inputs; - TypePathFnInputs inputs;*/ - //::std::vector inputs; // inlined from TypePathFnInputs - ::std::vector< ::std::unique_ptr > inputs; - - // bool has_type; - // Type type; - ::std::unique_ptr return_type; - - // FIXME: think of better way to mark as invalid than taking up storage - bool is_invalid; - - // TODO: should this have location info? - - protected: - // Constructor only used to create invalid type path functions. - TypePathFunction(bool is_invalid) : is_invalid(is_invalid) {} - - public: - // Returns whether the return type of the function has been specified. - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether the function has inputs. - inline bool has_inputs() const { - return !inputs.empty(); - } - - // Returns whether function is in an error state. - inline bool is_error() const { - return is_invalid; - } - - // Creates an error state function. - static TypePathFunction create_error() { - return TypePathFunction(true); - } - - // Constructor - TypePathFunction(::std::vector< ::std::unique_ptr > inputs, Type* type = NULL) : - inputs(::std::move(inputs)), return_type(type), is_invalid(false) {} - // FIXME: deprecated - - // Constructor - TypePathFunction( - ::std::vector< ::std::unique_ptr > inputs, ::std::unique_ptr type = NULL) : - inputs(::std::move(inputs)), - return_type(::std::move(type)), is_invalid(false) {} - - // Copy constructor with clone - TypePathFunction(TypePathFunction const& other) : - /*inputs(other.inputs),*/ return_type(other.return_type->clone_type()), - is_invalid(other.is_invalid) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - inputs.reserve(other.inputs.size()); - - for (const auto& e : other.inputs) { - inputs.push_back(e->clone_type()); - } - } - - ~TypePathFunction() = default; - - // Overloaded assignment operator to clone type - TypePathFunction& operator=(TypePathFunction const& other) { - // inputs = other.inputs; - return_type = other.return_type->clone_type(); - is_invalid = other.is_invalid; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - inputs.reserve(other.inputs.size()); - - for (const auto& e : other.inputs) { - inputs.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - TypePathFunction(TypePathFunction&& other) = default; - TypePathFunction& operator=(TypePathFunction&& other) = default; - - ::std::string as_string() const; - }; - - // Segment used in type path with a function argument - class TypePathSegmentFunction : public TypePathSegment { - TypePathFunction function_path; - - public: - // Constructor with PathIdentSegment and TypePathFn - TypePathSegmentFunction(PathIdentSegment ident_segment, - bool has_separating_scope_resolution, TypePathFunction function_path, - location_t locus) : - TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), - function_path(::std::move(function_path)) {} - - // Constructor with segment name and TypePathFn - TypePathSegmentFunction(::std::string segment_name, bool has_separating_scope_resolution, - TypePathFunction function_path, location_t locus) : - TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), - function_path(::std::move(function_path)) {} - - ::std::string as_string() const; - - bool is_ident_only() const { - return false; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to override base class method - virtual TypePathSegmentFunction* clone_type_path_segment_impl() const OVERRIDE { - return new TypePathSegmentFunction(*this); - } - }; - - // Path used inside types - class TypePath : public TypeNoBounds { - bool has_opening_scope_resolution; - ::std::vector< ::std::unique_ptr > segments; - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TypePath* clone_type_impl() const OVERRIDE { - return new TypePath(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TypePath* clone_type_no_bounds_impl() const OVERRIDE { - return new TypePath(*this); - } - - public: - /* Returns whether the TypePath has an opening scope resolution operator (i.e. is global - * path or crate-relative path, not module-relative) */ - inline bool has_opening_scope_resolution_op() const { - return has_opening_scope_resolution; - } - - // Returns whether the TypePath is in an invalid state. - inline bool is_error() const { - return segments.empty(); - } - - // Creates an error state TypePath. - static TypePath create_error() { - return TypePath(::std::vector< ::std::unique_ptr >()); - } - - // Constructor - TypePath(::std::vector< ::std::unique_ptr > segments, - location_t locus = UNKNOWN_LOCATION, bool has_opening_scope_resolution = false) : - has_opening_scope_resolution(has_opening_scope_resolution), - segments(::std::move(segments)), locus(locus) {} - - // Copy constructor with vector clone - TypePath(TypePath const& other) : - has_opening_scope_resolution(other.has_opening_scope_resolution), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - } - - // Overloaded assignment operator with clone - TypePath& operator=(TypePath const& other) { - has_opening_scope_resolution = other.has_opening_scope_resolution; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - - return *this; - } - - // move constructors - TypePath(TypePath&& other) = default; - TypePath& operator=(TypePath&& other) = default; - - ::std::string as_string() const; - - /* Converts TypePath to SimplePath if possible (i.e. no generic or function arguments). - * Otherwise returns an empty SimplePath. */ - SimplePath as_simple_path() const; - - // Creates a trait bound with a clone of this type path as its only element. - virtual TraitBound* to_trait_bound(bool in_parens) const OVERRIDE; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - struct QualifiedPathType { - private: - // Type type_to_invoke_on; - ::std::unique_ptr type_to_invoke_on; - - // bool has_as_clause; - TypePath trait_path; - - location_t locus; - - public: - // Constructor - QualifiedPathType(::std::unique_ptr invoke_on_type, - location_t locus = UNKNOWN_LOCATION, TypePath trait_path = TypePath::create_error()) : - type_to_invoke_on(::std::move(invoke_on_type)), - trait_path(::std::move(trait_path)), locus(locus) {} - - // Copy constructor uses custom deep copy for Type to preserve polymorphism - QualifiedPathType(QualifiedPathType const& other) : - type_to_invoke_on(other.type_to_invoke_on->clone_type()), trait_path(other.trait_path), - locus(other.locus) {} - - // default destructor - ~QualifiedPathType() = default; - - // overload assignment operator to use custom clone method - QualifiedPathType& operator=(QualifiedPathType const& other) { - type_to_invoke_on = other.type_to_invoke_on->clone_type(); - trait_path = other.trait_path; - locus = other.locus; - return *this; - } - - // move constructor - QualifiedPathType(QualifiedPathType&& other) = default; - QualifiedPathType& operator=(QualifiedPathType&& other) = default; - - // Returns whether the qualified path type has a rebind as clause. - inline bool has_as_clause() const { - return !trait_path.is_error(); - } - - // Returns whether the qualified path type is in an error state. - inline bool is_error() const { - return type_to_invoke_on == NULL; - } - - // Creates an error state qualified path type. - static QualifiedPathType create_error() { - return QualifiedPathType(NULL); - } - - ::std::string as_string() const; - - inline location_t get_locus() const { - return locus; - } - }; - - /* AST node representing a qualified path-in-expression pattern (path that allows specifying - * trait functions) */ - class QualifiedPathInExpression - : public PathPattern - , public PathExpr { - QualifiedPathType path_type; - - location_t locus; - - public: - ::std::string as_string() const; - - QualifiedPathInExpression(QualifiedPathType qual_path_type, - ::std::vector path_segments, location_t locus = UNKNOWN_LOCATION, - ::std::vector outer_attrs = ::std::vector()) : - PathPattern(::std::move(path_segments)), - PathExpr(::std::move(outer_attrs)), path_type(::std::move(qual_path_type)), - locus(locus) {} - - // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params - - // Copy constructor, destructor, and assignment operator overload shouldn't be required - - // Returns whether qualified path in expression is in an error state. - inline bool is_error() const { - return path_type.is_error(); - } - - // Creates an error qualified path in expression. - static QualifiedPathInExpression create_error() { - return QualifiedPathInExpression( - QualifiedPathType::create_error(), ::std::vector()); - } - - location_t get_locus() const { - return locus; - } - - location_t get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInExpression* clone_pattern_impl() const OVERRIDE { - return new QualifiedPathInExpression(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInExpression* clone_expr_without_block_impl() const OVERRIDE { - return new QualifiedPathInExpression(*this); - } - }; - - // Represents a qualified path in a type; used for disambiguating trait function calls - class QualifiedPathInType : public TypeNoBounds { - QualifiedPathType path_type; - // ::std::vector segments; - ::std::vector< ::std::unique_ptr > segments; - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInType* clone_type_impl() const OVERRIDE { - return new QualifiedPathInType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInType* clone_type_no_bounds_impl() const OVERRIDE { - return new QualifiedPathInType(*this); - } - - public: - QualifiedPathInType(QualifiedPathType qual_path_type, - ::std::vector< ::std::unique_ptr > path_segments, - location_t locus = UNKNOWN_LOCATION) : - path_type(::std::move(qual_path_type)), - segments(::std::move(path_segments)), locus(locus) {} - - // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params - - // Copy constructor with vector clone - QualifiedPathInType(QualifiedPathInType const& other) : - path_type(other.path_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - } - - // Overloaded assignment operator with vector clone - QualifiedPathInType& operator=(QualifiedPathInType const& other) { - path_type = other.path_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - - return *this; - } - - // move constructors - QualifiedPathInType(QualifiedPathInType&& other) = default; - QualifiedPathInType& operator=(QualifiedPathInType&& other) = default; - - // Returns whether qualified path in type is in an error state. - inline bool is_error() const { - return path_type.is_error(); - } - - // Creates an error state qualified path in type. - static QualifiedPathInType create_error() { - return QualifiedPathInType(QualifiedPathType::create_error(), - ::std::vector< ::std::unique_ptr >()); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-pattern.h b/gcc/rust/test3/ast/rust-pattern.h deleted file mode 100644 index f0cabee..0000000 --- a/gcc/rust/test3/ast/rust-pattern.h +++ /dev/null @@ -1,1163 +0,0 @@ -#ifndef RUST_AST_PATTERN_H -#define RUST_AST_PATTERN_H - -#include "rust-ast.h" - -namespace Rust { - namespace AST { - // Literal pattern AST node (comparing to a literal) - class LiteralPattern : public Pattern { - Literal lit; // make literal have a type given by enum, etc. rustc uses an extended form - // of its literal token implementation - // FIXME: literal representation - use LiteralExpr? or another thing? - - // Minus prefixed to literal (if integer or floating-point) - bool has_minus; - // Actually, this might be a good place to use a template. - - location_t locus; - - public: - ::std::string as_string() const; - - // Constructor for a literal pattern - LiteralPattern(Literal lit, location_t locus, bool has_minus = false) : - lit(::std::move(lit)), has_minus(has_minus), locus(locus) {} - - LiteralPattern( - ::std::string val, Literal::LitType type, location_t locus, bool has_minus = false) : - lit(Literal(::std::move(val), type)), - has_minus(has_minus), locus(locus) {} - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralPattern* clone_pattern_impl() const OVERRIDE { - return new LiteralPattern(*this); - } - }; - - // Identifier pattern AST node (bind value matched to a variable) - class IdentifierPattern : public Pattern { - Identifier variable_ident; - bool is_ref; - bool is_mut; - - // bool has_pattern; - // Pattern* to_bind; - ::std::unique_ptr to_bind; - - location_t locus; - - public: - /*~IdentifierPattern() { - delete to_bind; - }*/ - - ::std::string as_string() const; - - // Returns whether the IdentifierPattern has a pattern to bind. - inline bool has_pattern_to_bind() const { - return to_bind != NULL; - } - - // Constructor - IdentifierPattern(Identifier ident, location_t locus, bool is_ref = false, - bool is_mut = false, ::std::unique_ptr to_bind = NULL) : - variable_ident(::std::move(ident)), - is_ref(is_ref), is_mut(is_mut), to_bind(::std::move(to_bind)), locus(locus) {} - - // Copy constructor with clone - IdentifierPattern(IdentifierPattern const& other) : - variable_ident(other.variable_ident), is_ref(other.is_ref), is_mut(other.is_mut), - locus(other.locus) { - // fix to get prevent null pointer dereference - if (other.to_bind != NULL) { - to_bind = other.to_bind->clone_pattern(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to use clone - IdentifierPattern& operator=(IdentifierPattern const& other) { - variable_ident = other.variable_ident; - is_ref = other.is_ref; - is_mut = other.is_mut; - locus = other.locus; - // fix to get prevent null pointer dereference - if (other.to_bind != NULL) { - to_bind = other.to_bind->clone_pattern(); - } - - return *this; - } - - // default move semantics - IdentifierPattern(IdentifierPattern&& other) = default; - IdentifierPattern& operator=(IdentifierPattern&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IdentifierPattern* clone_pattern_impl() const OVERRIDE { - return new IdentifierPattern(*this); - } - }; - - // AST node for using the '_' wildcard "match any value" pattern - class WildcardPattern : public Pattern { - location_t locus; - - public: - ::std::string as_string() const { - return ::std::string(1, '_'); - } - - WildcardPattern(location_t locus) : locus(locus) {} - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WildcardPattern* clone_pattern_impl() const OVERRIDE { - return new WildcardPattern(*this); - } - }; - - // Base range pattern bound (lower or upper limit) - abstract - class RangePatternBound { - /*union { - CharLiteral char_lit; - ByteLiteral byte_lit; - IntLiteral int_lit; - FloatLiteral float_lit; - PathInExpression path; - QualifiedPathInExpression qual_path; - } pattern;*/ - public: - virtual ~RangePatternBound() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_range_pattern_bound() const { - return ::std::unique_ptr(clone_range_pattern_bound_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual as RangePatternBound is abstract - virtual RangePatternBound* clone_range_pattern_bound_impl() const = 0; - }; - - // Literal-based pattern bound - class RangePatternBoundLiteral : public RangePatternBound { - Literal literal; - // Can only be a char, byte, int, or float literal - same impl here as previously - - // Minus prefixed to literal (if integer or floating-point) - bool has_minus; - - location_t locus; - - public: - // Constructor - RangePatternBoundLiteral(Literal literal, location_t locus, bool has_minus = false) : - literal(literal), has_minus(has_minus), locus(locus) {} - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundLiteral* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundLiteral(*this); - } - }; - - // Path-based pattern bound - class RangePatternBoundPath : public RangePatternBound { - PathInExpression path; - - // TODO: should this be refactored so that PathInExpression is a subclass of - // RangePatternBound? - - public: - RangePatternBoundPath(PathInExpression path) : path(::std::move(path)) {} - - ::std::string as_string() const { - return path.as_string(); - } - - location_t get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundPath* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundPath(*this); - } - }; - - // Qualified path-based pattern bound - class RangePatternBoundQualPath : public RangePatternBound { - QualifiedPathInExpression path; - - /* TODO: should this be refactored so that QualifiedPathInExpression is a subclass of - * RangePatternBound? */ - - public: - RangePatternBoundQualPath(QualifiedPathInExpression path) : path(::std::move(path)) {} - - ::std::string as_string() const { - return path.as_string(); - } - - location_t get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundQualPath* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundQualPath(*this); - } - }; - - // AST node for matching within a certain range (range pattern) - class RangePattern : public Pattern { - /*RangePatternBound lower; - RangePatternBound upper;*/ - ::std::unique_ptr lower; - ::std::unique_ptr upper; - - bool has_ellipsis_syntax; - - // location only stored to avoid a dereference - lower pattern should give correct - // location so maybe change in future - location_t locus; - - public: - ::std::string as_string() const; - - // Constructor - RangePattern(::std::unique_ptr lower, - ::std::unique_ptr upper, location_t locus, - bool has_ellipsis_syntax = false) : - lower(::std::move(lower)), - upper(::std::move(upper)), has_ellipsis_syntax(has_ellipsis_syntax), locus(locus) {} - - // Copy constructor with clone - RangePattern(RangePattern const& other) : - lower(other.lower->clone_range_pattern_bound()), - upper(other.upper->clone_range_pattern_bound()), - has_ellipsis_syntax(other.has_ellipsis_syntax), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - RangePattern& operator=(RangePattern const& other) { - lower = other.lower->clone_range_pattern_bound(); - upper = other.upper->clone_range_pattern_bound(); - has_ellipsis_syntax = other.has_ellipsis_syntax; - locus = other.locus; - - return *this; - } - - // default move semantics - RangePattern(RangePattern&& other) = default; - RangePattern& operator=(RangePattern&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePattern* clone_pattern_impl() const OVERRIDE { - return new RangePattern(*this); - } - }; - - // AST node for pattern based on dereferencing the pointers given - class ReferencePattern : public Pattern { - bool has_two_amps; - bool is_mut; - // Pattern* pattern; - ::std::unique_ptr pattern; - - location_t locus; - - public: - /*~ReferencePattern() { - delete pattern; - }*/ - - ::std::string as_string() const; - - ReferencePattern(::std::unique_ptr pattern, bool is_mut_reference, - bool ref_has_two_amps, location_t locus) : - has_two_amps(ref_has_two_amps), - is_mut(is_mut_reference), pattern(::std::move(pattern)), locus(locus) {} - - // Copy constructor requires clone - ReferencePattern(ReferencePattern const& other) : - has_two_amps(other.has_two_amps), is_mut(other.is_mut), - pattern(other.pattern->clone_pattern()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - ReferencePattern& operator=(ReferencePattern const& other) { - pattern = other.pattern->clone_pattern(); - is_mut = other.is_mut; - has_two_amps = other.has_two_amps; - locus = other.locus; - - return *this; - } - - // default move semantics - ReferencePattern(ReferencePattern&& other) = default; - ReferencePattern& operator=(ReferencePattern&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReferencePattern* clone_pattern_impl() const OVERRIDE { - return new ReferencePattern(*this); - } - }; - - // aka StructPatternEtCetera; potential element in struct pattern - struct StructPatternEtc { - private: - ::std::vector outer_attrs; - - // should this store location data? - - public: - StructPatternEtc(::std::vector outer_attribs) : - outer_attrs(::std::move(outer_attribs)) {} - - // Creates an empty StructPatternEtc - static StructPatternEtc create_empty() { - return StructPatternEtc(::std::vector()); - } - }; - - // Base class for a single field in a struct pattern - abstract - class StructPatternField { - ::std::vector outer_attrs; - /*union { - struct { - //TupleIndex index; - Pattern tuple_pattern; - } tuple_pattern; - struct { - //Identifier ident; - Pattern ident_pattern; - } ident_pattern; - struct { - bool has_ref; - bool has_mut; - //Identifier ident; - } ident; - } pattern;*/ - - location_t locus; - - public: - virtual ~StructPatternField() {} - - // Unique pointer custom clone function - ::std::unique_ptr clone_struct_pattern_field() const { - return ::std::unique_ptr(clone_struct_pattern_field_impl()); - } - - virtual ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - StructPatternField(::std::vector outer_attribs, location_t locus) : - outer_attrs(::std::move(outer_attribs)), locus(locus) {} - - // Clone function implementation as pure virtual method - virtual StructPatternField* clone_struct_pattern_field_impl() const = 0; - }; - - // Tuple pattern single field in a struct pattern - class StructPatternFieldTuplePat : public StructPatternField { - TupleIndex index; - // Pattern* tuple_pattern; - ::std::unique_ptr tuple_pattern; - - public: - /*~StructPatternFieldTuplePat() { - delete tuple_pattern; - }*/ - - StructPatternFieldTuplePat(TupleIndex index, ::std::unique_ptr tuple_pattern, - ::std::vector outer_attribs, location_t locus) : - StructPatternField(::std::move(outer_attribs), locus), - index(index), tuple_pattern(::std::move(tuple_pattern)) {} - - // Copy constructor requires clone - StructPatternFieldTuplePat(StructPatternFieldTuplePat const& other) : - StructPatternField(other), index(other.index), - tuple_pattern(other.tuple_pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to perform clone - StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat const& other) { - StructPatternField::operator=(other); - tuple_pattern = other.tuple_pattern->clone_pattern(); - index = other.index; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // default move semantics - StructPatternFieldTuplePat(StructPatternFieldTuplePat&& other) = default; - StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldTuplePat* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldTuplePat(*this); - } - }; - - // Identifier pattern single field in a struct pattern - class StructPatternFieldIdentPat : public StructPatternField { - Identifier ident; - // Pattern* ident_pattern; - ::std::unique_ptr ident_pattern; - - public: - /*~StructPatternFieldIdentPat() { - delete ident_pattern; - }*/ - - StructPatternFieldIdentPat(Identifier ident, ::std::unique_ptr ident_pattern, - ::std::vector outer_attrs, location_t locus) : - StructPatternField(::std::move(outer_attrs), locus), - ident(::std::move(ident)), ident_pattern(::std::move(ident_pattern)) {} - - // Copy constructor requires clone - StructPatternFieldIdentPat(StructPatternFieldIdentPat const& other) : - StructPatternField(other), ident(other.ident), - ident_pattern(other.ident_pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat const& other) { - StructPatternField::operator=(other); - ident = other.ident; - ident_pattern = other.ident_pattern->clone_pattern(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // default move semantics - StructPatternFieldIdentPat(StructPatternFieldIdentPat&& other) = default; - StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldIdentPat* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldIdentPat(*this); - } - }; - - // Identifier only (with no pattern) single field in a struct pattern - class StructPatternFieldIdent : public StructPatternField { - bool has_ref; - bool has_mut; - - Identifier ident; - - public: - StructPatternFieldIdent(Identifier ident, bool is_ref, bool is_mut, - ::std::vector outer_attrs, location_t locus) : - StructPatternField(::std::move(outer_attrs), locus), - has_ref(is_ref), has_mut(is_mut), ident(::std::move(ident)) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldIdent* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldIdent(*this); - } - }; - - // Elements of a struct pattern - struct StructPatternElements { - private: - // bool has_struct_pattern_fields; - //::std::vector fields; - ::std::vector< ::std::unique_ptr > fields; - - bool has_struct_pattern_etc; - StructPatternEtc etc; - - // must have at least one of the two and maybe both - - // should this store location data? - - public: - // Returns whether there are any struct pattern fields - inline bool has_struct_pattern_fields() const { - return !fields.empty(); - } - - // Returns whether the struct pattern elements is entirely empty (no fields, no etc). - inline bool is_empty() const { - return !has_struct_pattern_fields() && !has_struct_pattern_etc; - } - - // Constructor for StructPatternElements with both (potentially) - StructPatternElements( - ::std::vector< ::std::unique_ptr > fields, StructPatternEtc etc) : - fields(::std::move(fields)), - has_struct_pattern_etc(true), etc(::std::move(etc)) {} - - // Constructor for StructPatternElements with no StructPatternEtc - StructPatternElements(::std::vector< ::std::unique_ptr > fields) : - fields(::std::move(fields)), has_struct_pattern_etc(false), - etc(StructPatternEtc::create_empty()) {} - - // Copy constructor with vector clone - StructPatternElements(StructPatternElements const& other) : - has_struct_pattern_etc(other.has_struct_pattern_etc), etc(other.etc) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_pattern_field()); - } - } - - // Overloaded assignment operator with vector clone - StructPatternElements& operator=(StructPatternElements const& other) { - etc = other.etc; - has_struct_pattern_etc = other.has_struct_pattern_etc; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_pattern_field()); - } - - return *this; - } - - // move constructors - StructPatternElements(StructPatternElements&& other) = default; - StructPatternElements& operator=(StructPatternElements&& other) = default; - - // Creates an empty StructPatternElements - static StructPatternElements create_empty() { - return StructPatternElements( - ::std::vector< ::std::unique_ptr >()); - } - - ::std::string as_string() const; - }; - - // Struct pattern AST node representation - class StructPattern : public Pattern { - PathInExpression path; - - // bool has_struct_pattern_elements; - StructPatternElements elems; - - // TODO: should this store location data? Accessor uses path location data. - - public: - ::std::string as_string() const; - - // Constructs a struct pattern from specified StructPatternElements - StructPattern(PathInExpression struct_path, - StructPatternElements elems = StructPatternElements::create_empty()) : - path(::std::move(struct_path)), - elems(::std::move(elems)) {} - - // TODO: constructor to construct via elements included in StructPatternElements - - // Returns whether struct pattern has any struct pattern elements (if not, it is empty). - inline bool has_struct_pattern_elems() const { - return !elems.is_empty(); - } - - location_t get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPattern* clone_pattern_impl() const OVERRIDE { - return new StructPattern(*this); - } - }; - - // Base abstract class for patterns used in TupleStructPattern - class TupleStructItems { - public: - virtual ~TupleStructItems() {} - - // TODO: should this store location data? - - // Unique pointer custom clone function - ::std::unique_ptr clone_tuple_struct_items() const { - return ::std::unique_ptr(clone_tuple_struct_items_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual TupleStructItems* clone_tuple_struct_items_impl() const = 0; - }; - - // Class for non-ranged tuple struct pattern patterns - class TupleStructItemsNoRange : public TupleStructItems { - //::std::vector patterns; - ::std::vector< ::std::unique_ptr > patterns; - - public: - TupleStructItemsNoRange(::std::vector< ::std::unique_ptr > patterns) : - patterns(::std::move(patterns)) {} - - // Copy constructor with vector clone - TupleStructItemsNoRange(TupleStructItemsNoRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator with vector clone - TupleStructItemsNoRange& operator=(TupleStructItemsNoRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TupleStructItemsNoRange(TupleStructItemsNoRange&& other) = default; - TupleStructItemsNoRange& operator=(TupleStructItemsNoRange&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructItemsNoRange* clone_tuple_struct_items_impl() const OVERRIDE { - return new TupleStructItemsNoRange(*this); - } - }; - - // Class for ranged tuple struct pattern patterns - class TupleStructItemsRange : public TupleStructItems { - /*::std::vector lower_patterns; - ::std::vector upper_patterns;*/ - ::std::vector< ::std::unique_ptr > lower_patterns; - ::std::vector< ::std::unique_ptr > upper_patterns; - - public: - TupleStructItemsRange(::std::vector< ::std::unique_ptr > lower_patterns, - ::std::vector< ::std::unique_ptr > upper_patterns) : - lower_patterns(::std::move(lower_patterns)), - upper_patterns(::std::move(upper_patterns)) {} - - // Copy constructor with vector clone - TupleStructItemsRange(TupleStructItemsRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to clone - TupleStructItemsRange& operator=(TupleStructItemsRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TupleStructItemsRange(TupleStructItemsRange&& other) = default; - TupleStructItemsRange& operator=(TupleStructItemsRange&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructItemsRange* clone_tuple_struct_items_impl() const OVERRIDE { - return new TupleStructItemsRange(*this); - } - }; - - // AST node representing a tuple struct pattern - class TupleStructPattern : public Pattern { - PathInExpression path; - // TupleStructItems items; - ::std::unique_ptr items; - - // TOOD: should this store location data? current accessor uses path location data - - public: - ::std::string as_string() const; - - TupleStructPattern( - PathInExpression tuple_struct_path, ::std::unique_ptr items) : - path(::std::move(tuple_struct_path)), - items(::std::move(items)) {} - - // Copy constructor required to clone - TupleStructPattern(TupleStructPattern const& other) : - path(other.path), items(other.items->clone_tuple_struct_items()) {} - - // Destructor - define here if required - - // Operator overload assignment operator to clone - TupleStructPattern& operator=(TupleStructPattern const& other) { - path = other.path; - items = other.items->clone_tuple_struct_items(); - - return *this; - } - - // move constructors - TupleStructPattern(TupleStructPattern&& other) = default; - TupleStructPattern& operator=(TupleStructPattern&& other) = default; - - location_t get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructPattern* clone_pattern_impl() const OVERRIDE { - return new TupleStructPattern(*this); - } - }; - - // Base abstract class representing TuplePattern patterns - class TuplePatternItems { - public: - virtual ~TuplePatternItems() {} - - // TODO: should this store location data? - - // Unique pointer custom clone function - ::std::unique_ptr clone_tuple_pattern_items() const { - return ::std::unique_ptr(clone_tuple_pattern_items_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual TuplePatternItems* clone_tuple_pattern_items_impl() const = 0; - }; - - // Class representing TuplePattern patterns where there is only a single pattern - /*class TuplePatternItemsSingle : public TuplePatternItems { - // Pattern pattern; - ::std::unique_ptr pattern; - - public: - TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} - - // Copy constructor uses clone - TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : - pattern(other.pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { - pattern = other.pattern->clone_pattern(); - - return *this; - } - - // move constructors - TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; - TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = default; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsSingle* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsSingle(*this); - } - };*/ - // removed in favour of single-element TuplePatternItemsMultiple - - // Class representing TuplePattern patterns where there are multiple patterns - class TuplePatternItemsMultiple : public TuplePatternItems { - //::std::vector patterns; - ::std::vector< ::std::unique_ptr > patterns; - - public: - TuplePatternItemsMultiple(::std::vector< ::std::unique_ptr > patterns) : - patterns(::std::move(patterns)) {} - - // Copy constructor with vector clone - TuplePatternItemsMultiple(TuplePatternItemsMultiple const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TuplePatternItemsMultiple(TuplePatternItemsMultiple&& other) = default; - TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsMultiple* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsMultiple(*this); - } - }; - - // Class representing TuplePattern patterns where there are a range of patterns - class TuplePatternItemsRanged : public TuplePatternItems { - /*::std::vector lower_patterns; - ::std::vector upper_patterns;*/ - ::std::vector< ::std::unique_ptr > lower_patterns; - ::std::vector< ::std::unique_ptr > upper_patterns; - - public: - TuplePatternItemsRanged(::std::vector< ::std::unique_ptr > lower_patterns, - ::std::vector< ::std::unique_ptr > upper_patterns) : - lower_patterns(::std::move(lower_patterns)), - upper_patterns(::std::move(upper_patterns)) {} - - // Copy constructor with vector clone - TuplePatternItemsRanged(TuplePatternItemsRanged const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to clone - TuplePatternItemsRanged& operator=(TuplePatternItemsRanged const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TuplePatternItemsRanged(TuplePatternItemsRanged&& other) = default; - TuplePatternItemsRanged& operator=(TuplePatternItemsRanged&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsRanged* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsRanged(*this); - } - }; - - // AST node representing a tuple pattern - class TuplePattern : public Pattern { - // bool has_tuple_pattern_items; - // TuplePatternItems items; - ::std::unique_ptr items; - - location_t locus; - - public: - ::std::string as_string() const; - - // Returns true if the tuple pattern has items - inline bool has_tuple_pattern_items() const { - return items != NULL; - } - - TuplePattern(::std::unique_ptr items, location_t locus) : - items(::std::move(items)), locus(locus) {} - - // Copy constructor requires clone - TuplePattern(TuplePattern const& other) : - items(other.items->clone_tuple_pattern_items()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - TuplePattern& operator=(TuplePattern const& other) { - items = other.items->clone_tuple_pattern_items(); - locus = other.locus; - - return *this; - } - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePattern* clone_pattern_impl() const OVERRIDE { - return new TuplePattern(*this); - } - }; - - // AST node representing a pattern in parentheses, used to control precedence - class GroupedPattern : public Pattern { - // Pattern pattern_in_parens; - ::std::unique_ptr pattern_in_parens; - - location_t locus; - - public: - ::std::string as_string() const { - return "(" + pattern_in_parens->as_string() + ")"; - } - - GroupedPattern(::std::unique_ptr pattern_in_parens, location_t locus) : - pattern_in_parens(::std::move(pattern_in_parens)), locus(locus) {} - - // Copy constructor uses clone - GroupedPattern(GroupedPattern const& other) : - pattern_in_parens(other.pattern_in_parens->clone_pattern()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - GroupedPattern& operator=(GroupedPattern const& other) { - pattern_in_parens = other.pattern_in_parens->clone_pattern(); - locus = other.locus; - - return *this; - } - - // default move semantics - GroupedPattern(GroupedPattern&& other) = default; - GroupedPattern& operator=(GroupedPattern&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedPattern* clone_pattern_impl() const OVERRIDE { - return new GroupedPattern(*this); - } - }; - - // AST node representing patterns that can match slices and arrays - class SlicePattern : public Pattern { - //::std::vector items; - ::std::vector< ::std::unique_ptr > items; - - location_t locus; - - public: - ::std::string as_string() const; - - SlicePattern(::std::vector< ::std::unique_ptr > items, location_t locus) : - items(::std::move(items)), locus(locus) {} - - // Copy constructor with vector clone - SlicePattern(SlicePattern const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to vector clone - SlicePattern& operator=(SlicePattern const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - SlicePattern(SlicePattern&& other) = default; - SlicePattern& operator=(SlicePattern&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual SlicePattern* clone_pattern_impl() const OVERRIDE { - return new SlicePattern(*this); - } - }; - - // forward decl PathExprSegment - // class PathExprSegment; - - // Moved definition to rust-path.h - class PathPattern; - - // Forward decls for paths (defined in rust-path.h) - class PathInExpression; - class QualifiedPathInExpression; - - // Replaced with forward decl - defined in rust-macro.h - class MacroInvocation; - /*class MacroInvocation : public Pattern { - public: - ::std::string as_string() const; - };*/ - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-stmt.h b/gcc/rust/test3/ast/rust-stmt.h deleted file mode 100644 index ece0801..0000000 --- a/gcc/rust/test3/ast/rust-stmt.h +++ /dev/null @@ -1,245 +0,0 @@ -#ifndef RUST_AST_STATEMENT_H -#define RUST_AST_STATEMENT_H - -#include "rust-ast.h" -#include "rust-path.h" -#include "rust-expr.h" - -namespace Rust { - namespace AST { - // Just a semi-colon, which apparently is a statement. - class EmptyStmt : public Stmt { - location_t locus; - - public: - ::std::string as_string() const { - return ::std::string(1, ';'); - } - - EmptyStmt(location_t locus) : locus(locus) {} - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EmptyStmt* clone_stmt_impl() const OVERRIDE { - return new EmptyStmt(*this); - } - }; - - /* This is syntactically identical to declaring an item inside a module BUT it has block - * scope. Type of "declaration statement" as it introduces new name into scope */ - /*class ItemStatement : public Statement { - // TODO: put in same params as regular item - // maybe even merge data structure with module item? - - public: - ::std::string as_string() const; - };*/ - // removed - just made item inherit from statement - - /* Variable assignment let statement - type of "declaration statement" as it introduces new - * name into scope */ - class LetStmt : public Stmt { - // bool has_outer_attrs; - ::std::vector outer_attrs; - - // Pattern variables_pattern; - ::std::unique_ptr variables_pattern; - - // bool has_type; - // Type type; - ::std::unique_ptr type; - - // bool has_init_expr; - // Expr* init_expr; - ::std::unique_ptr init_expr; - - location_t locus; - - public: - // Returns whether let statement has outer attributes. - inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - } - - // Returns whether let statement has a given return type. - inline bool has_type() const { - return type != NULL; - } - - // Returns whether let statement has an initialisation expression. - inline bool has_init_expr() const { - return init_expr != NULL; - } - - /*~LetStatement() { - if (has_init_expr) { - delete init_expr; - } - }*/ - - ::std::string as_string() const; - - LetStmt(::std::unique_ptr variables_pattern, ::std::unique_ptr init_expr, - ::std::unique_ptr type, ::std::vector outer_attrs, location_t locus) : - outer_attrs(::std::move(outer_attrs)), - variables_pattern(::std::move(variables_pattern)), type(::std::move(type)), - init_expr(::std::move(init_expr)), locus(locus) {} - - // Copy constructor with clone - LetStmt(LetStmt const& other) : - outer_attrs(other.outer_attrs), - variables_pattern(other.variables_pattern->clone_pattern()), - type(other.type->clone_type()), init_expr(other.init_expr->clone_expr()), - locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - LetStmt& operator=(LetStmt const& other) { - variables_pattern = other.variables_pattern->clone_pattern(); - init_expr = other.init_expr->clone_expr(); - type = other.type->clone_type(); - outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - LetStmt(LetStmt&& other) = default; - LetStmt& operator=(LetStmt&& other) = default; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LetStmt* clone_stmt_impl() const OVERRIDE { - return new LetStmt(*this); - } - }; - - // Abstract base class for expression statements (statements containing an expression) - class ExprStmt : public Stmt { - // TODO: add any useful virtual functions - - location_t locus; - - public: - location_t get_locus() const { - return locus; - } - - protected: - ExprStmt(location_t locus) : locus(locus) {} - }; - - /* Statement containing an expression without a block (or, due to technical difficulties, can - * only be guaranteed to hold an expression). */ - class ExprStmtWithoutBlock : public ExprStmt { - // ExprWithoutBlock* expr; - /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, so have to - * store more general type of Expr. FIXME: fix this issue somehow or redesign AST. */ - //::std::unique_ptr expr; - ::std::unique_ptr expr; - - public: - /*~ExpressionStatementWithoutBlock() { - delete expr; - }*/ - - ::std::string as_string() const; - - // ExprStmtWithoutBlock(::std::unique_ptr expr) : - // expr(::std::move(expr)) {} - ExprStmtWithoutBlock(::std::unique_ptr expr, location_t locus) : - ExprStmt(locus), expr(::std::move(expr)) {} - - // Copy constructor with clone - ExprStmtWithoutBlock(ExprStmtWithoutBlock const& other) : - ExprStmt(other), expr(other.expr->clone_expr /*_without_block*/ ()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock const& other) { - ExprStmt::operator=(other); - expr = other.expr->clone_expr /*_without_block*/ (); - - return *this; - } - - // move constructors - ExprStmtWithoutBlock(ExprStmtWithoutBlock&& other) = default; - ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExprStmtWithoutBlock* clone_stmt_impl() const OVERRIDE { - return new ExprStmtWithoutBlock(*this); - } - }; - - // Statement containing an expression with a block - class ExprStmtWithBlock : public ExprStmt { - // ExprWithBlock* expr; - ::std::unique_ptr expr; - - public: - /*~ExpressionStatementWithBlock() { - delete expr; - }*/ - - ::std::string as_string() const; - - ExprStmtWithBlock(::std::unique_ptr expr, location_t locus) : - ExprStmt(locus), expr(::std::move(expr)) {} - - // Copy constructor with clone - ExprStmtWithBlock(ExprStmtWithBlock const& other) : - ExprStmt(other), expr(other.expr->clone_expr_with_block()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ExprStmtWithBlock& operator=(ExprStmtWithBlock const& other) { - ExprStmt::operator=(other); - expr = other.expr->clone_expr_with_block(); - - return *this; - } - - // move constructors - ExprStmtWithBlock(ExprStmtWithBlock&& other) = default; - ExprStmtWithBlock& operator=(ExprStmtWithBlock&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExprStmtWithBlock* clone_stmt_impl() const OVERRIDE { - return new ExprStmtWithBlock(*this); - } - }; - - // Replaced definition of MacroInvocationSemi with forward decl - defined in rust-macro.h - class MacroInvocationSemi; - /*class MacroInvocationSemi : public Statement { - public: - ::std::string as_string() const; - };*/ - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/ast/rust-type.h b/gcc/rust/test3/ast/rust-type.h deleted file mode 100644 index 4ca408d..0000000 --- a/gcc/rust/test3/ast/rust-type.h +++ /dev/null @@ -1,828 +0,0 @@ -#ifndef RUST_AST_TYPE_H -#define RUST_AST_TYPE_H - -#include "rust-ast.h" -#include "rust-path.h" - -namespace Rust { - namespace AST { - // definitions moved to rust-ast.h - class TypeParamBound; - class Lifetime; - - // A trait bound - class TraitBound : public TypeParamBound { - bool in_parens; - bool opening_question_mark; - - // bool has_for_lifetimes; - // LifetimeParams for_lifetimes; - ::std::vector for_lifetimes; // inlined LifetimeParams - - TypePath type_path; - - location_t locus; - - public: - // Returns whether trait bound has "for" lifetimes - inline bool has_for_lifetimes() const { - return !for_lifetimes.empty(); - } - - TraitBound(TypePath type_path, location_t locus, bool in_parens = false, - bool opening_question_mark = false, - ::std::vector for_lifetimes = ::std::vector()) : - in_parens(in_parens), - opening_question_mark(opening_question_mark), for_lifetimes(::std::move(for_lifetimes)), - type_path(::std::move(type_path)), locus(locus) {} - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitBound* clone_type_param_bound_impl() const { - return new TraitBound(*this); - } - }; - - // definition moved to rust-ast.h - class TypeNoBounds; - - // An impl trait? Poor reference material here. - class ImplTraitType : public Type { - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitType* clone_type_impl() const OVERRIDE { - return new ImplTraitType(*this); - } - - public: - ImplTraitType(::std::vector< ::std::unique_ptr > type_param_bounds, - location_t locus) : - type_param_bounds(::std::move(type_param_bounds)), - locus(locus) {} - - // copy constructor with vector clone - ImplTraitType(ImplTraitType const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // overloaded assignment operator to clone - ImplTraitType& operator=(ImplTraitType const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - ImplTraitType(ImplTraitType&& other) = default; - ImplTraitType& operator=(ImplTraitType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // An opaque value of another type that implements a set of traits - class TraitObjectType : public Type { - bool has_dyn; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr > type_param_bounds; // inlined form - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectType* clone_type_impl() const OVERRIDE { - return new TraitObjectType(*this); - } - - public: - TraitObjectType(::std::vector< ::std::unique_ptr > type_param_bounds, - location_t locus, bool is_dyn_dispatch = false) : - has_dyn(is_dyn_dispatch), - type_param_bounds(::std::move(type_param_bounds)), locus(locus) {} - - // copy constructor with vector clone - TraitObjectType(TraitObjectType const& other) : - has_dyn(other.has_dyn), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // overloaded assignment operator to clone - TraitObjectType& operator=(TraitObjectType const& other) { - has_dyn = other.has_dyn; - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - TraitObjectType(TraitObjectType&& other) = default; - TraitObjectType& operator=(TraitObjectType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // A type with parentheses around it, used to avoid ambiguity. - class ParenthesisedType : public TypeNoBounds { - // Type type_in_parens; - ::std::unique_ptr type_in_parens; - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ParenthesisedType* clone_type_impl() const OVERRIDE { - return new ParenthesisedType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ParenthesisedType* clone_type_no_bounds_impl() const OVERRIDE { - return new ParenthesisedType(*this); - } - - public: - // Constructor uses Type pointer for polymorphism - ParenthesisedType(::std::unique_ptr type_inside_parens, location_t locus) : - type_in_parens(::std::move(type_inside_parens)), locus(locus) {} - - // Copy constructor uses custom deep copy method for type to preserve polymorphism - ParenthesisedType(ParenthesisedType const& other) : - type_in_parens(other.type_in_parens->clone_type()), locus(other.locus) {} - - // define destructor here if required - - // overload assignment operator to use custom clone method - ParenthesisedType& operator=(ParenthesisedType const& other) { - type_in_parens = other.type_in_parens->clone_type(); - locus = other.locus; - return *this; - } - - // default move semantics - ParenthesisedType(ParenthesisedType&& other) = default; - ParenthesisedType& operator=(ParenthesisedType&& other) = default; - - ::std::string as_string() const { - return "(" + type_in_parens->as_string() + ")"; - } - - // Creates a trait bound (clone of this one's trait bound) - HACK - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { - /* NOTE: obviously it is unknown whether the internal type is a trait bound due to - * polymorphism, so just let the internal type handle it. As parenthesised type, it - * must be in parentheses. */ - return type_in_parens->to_trait_bound(true); - } - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // Impl trait with a single bound? Poor reference material here. - class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitTypeOneBound* clone_type_impl() const OVERRIDE { - return new ImplTraitTypeOneBound(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { - return new ImplTraitTypeOneBound(*this); - } - - public: - ImplTraitTypeOneBound(TraitBound trait_bound, location_t locus) : - trait_bound(::std::move(trait_bound)), locus(locus) {} - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - /* A trait object with a single trait bound. The "trait bound" is really just the trait. - * Basically like using an interface as a type in an OOP language. */ - class TraitObjectTypeOneBound : public TypeNoBounds { - bool has_dyn; - TraitBound trait_bound; - - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectTypeOneBound* clone_type_impl() const OVERRIDE { - return new TraitObjectTypeOneBound(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { - return new TraitObjectTypeOneBound(*this); - } - - public: - TraitObjectTypeOneBound( - TraitBound trait_bound, location_t locus, bool is_dyn_dispatch = false) : - has_dyn(is_dyn_dispatch), - trait_bound(::std::move(trait_bound)), locus(locus) {} - - ::std::string as_string() const; - - // Creates a trait bound (clone of this one's trait bound) - HACK - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { - /* NOTE: this assumes there is no dynamic dispatch specified- if there was, this - * cloning would not be required as parsing is unambiguous. */ - return new AST::TraitBound(trait_bound); - } - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - class TypePath; // definition moved to "rust-path.h" - - // A type consisting of the "product" of others (the tuple's elements) in a specific order - class TupleType : public TypeNoBounds { - //::std::vector elems; - ::std::vector< ::std::unique_ptr > elems; - - location_t locus; - - public: - // Returns whether the tuple type is the unit type, i.e. has no elements. - inline bool is_unit_type() const { - return elems.empty(); - } - - TupleType(::std::vector< ::std::unique_ptr > elems, location_t locus) : - elems(::std::move(elems)), locus(locus) {} - - // copy constructor with vector clone - TupleType(TupleType const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - elems.reserve(other.elems.size()); - - for (const auto& e : other.elems) { - elems.push_back(e->clone_type()); - } - } - - // overloaded assignment operator to clone - TupleType& operator=(TupleType const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - elems.reserve(other.elems.size()); - - for (const auto& e : other.elems) { - elems.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - TupleType(TupleType&& other) = default; - TupleType& operator=(TupleType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleType* clone_type_impl() const OVERRIDE { - return new TupleType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleType* clone_type_no_bounds_impl() const OVERRIDE { - return new TupleType(*this); - } - }; - - /* A type with no values, representing the result of computations that never complete. - * Expressions of NeverType can be coerced into any other types. Represented as "!". */ - class NeverType : public TypeNoBounds { - location_t locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual NeverType* clone_type_impl() const OVERRIDE { - return new NeverType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual NeverType* clone_type_no_bounds_impl() const OVERRIDE { - return new NeverType(*this); - } - - public: - NeverType(location_t locus) : locus(locus) {} - - ::std::string as_string() const { - return "! (never type)"; - } - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // A type consisting of a pointer without safety or liveness guarantees - class RawPointerType : public TypeNoBounds { - public: - enum PointerType { MUT, CONST }; - - private: - PointerType pointer_type; - - // TypeNoBounds type; - ::std::unique_ptr type; - - location_t locus; - - public: - // Returns whether the pointer is mutable or constant. - inline PointerType get_pointer_type() const { - return pointer_type; - } - - // Constructor requires pointer for polymorphism reasons - RawPointerType(PointerType pointer_type, ::std::unique_ptr type_no_bounds, - location_t locus) : - pointer_type(pointer_type), - type(::std::move(type_no_bounds)), locus(locus) {} - - // Copy constructor calls custom polymorphic clone function - RawPointerType(RawPointerType const& other) : - pointer_type(other.pointer_type), type(other.type->clone_type_no_bounds()), - locus(other.locus) {} - - // no destructor required? - - // overload assignment operator to use custom clone method - RawPointerType& operator=(RawPointerType const& other) { - pointer_type = other.pointer_type; - type = other.type->clone_type_no_bounds(); - locus = other.locus; - return *this; - } - - // default move semantics - RawPointerType(RawPointerType&& other) = default; - RawPointerType& operator=(RawPointerType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RawPointerType* clone_type_impl() const OVERRIDE { - return new RawPointerType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RawPointerType* clone_type_no_bounds_impl() const OVERRIDE { - return new RawPointerType(*this); - } - }; - - // A type pointing to memory owned by another value - class ReferenceType : public TypeNoBounds { - // bool has_lifetime; // TODO: handle in lifetime or something? - Lifetime lifetime; - - bool has_mut; - - // TypeNoBounds type; - ::std::unique_ptr type; - - location_t locus; - - public: - // Returns whether the reference is mutable or immutable. - inline bool is_mut() const { - return has_mut; - } - - // Returns whether the reference has a lifetime. - inline bool has_lifetime() const { - return !lifetime.is_error(); - } - - // Constructor - ReferenceType(bool is_mut, ::std::unique_ptr type_no_bounds, - location_t locus, Lifetime lifetime = Lifetime::error()) : - lifetime(::std::move(lifetime)), - has_mut(is_mut), type(::std::move(type_no_bounds)), locus(locus) {} - - // Copy constructor with custom clone method - ReferenceType(ReferenceType const& other) : - lifetime(other.lifetime), has_mut(other.has_mut), - type(other.type->clone_type_no_bounds()), locus(other.locus) {} - - // Destructor not required? - - // Operator overload assignment operator to custom clone the unique pointer - ReferenceType& operator=(ReferenceType const& other) { - lifetime = other.lifetime; - has_mut = other.has_mut; - type = other.type->clone_type_no_bounds(); - locus = other.locus; - - return *this; - } - - // move constructors - ReferenceType(ReferenceType&& other) = default; - ReferenceType& operator=(ReferenceType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReferenceType* clone_type_impl() const OVERRIDE { - return new ReferenceType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ReferenceType* clone_type_no_bounds_impl() const OVERRIDE { - return new ReferenceType(*this); - } - }; - - // A fixed-size sequence of elements of a specified type - class ArrayType : public TypeNoBounds { - // Type elem_type; - ::std::unique_ptr elem_type; - // Expr* size; - ::std::unique_ptr size; - - location_t locus; - - public: - // Constructor requires pointers for polymorphism - ArrayType( - ::std::unique_ptr type, ::std::unique_ptr array_size, location_t locus) : - elem_type(::std::move(type)), - size(::std::move(array_size)), locus(locus) {} - - // Copy constructor requires deep copies of both unique pointers - ArrayType(ArrayType const& other) : - elem_type(other.elem_type->clone_type()), size(other.size->clone_expr()), - locus(other.locus) {} - - // destructor not required? - - // Overload assignment operator to deep copy pointers - ArrayType& operator=(ArrayType const& other) { - elem_type = other.elem_type->clone_type(); - size = other.size->clone_expr(); - locus = other.locus; - return *this; - } - - // move constructors - ArrayType(ArrayType&& other) = default; - ArrayType& operator=(ArrayType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - /*~ArrayType() { - delete size; - }*/ - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayType* clone_type_impl() const OVERRIDE { - return new ArrayType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayType* clone_type_no_bounds_impl() const OVERRIDE { - return new ArrayType(*this); - } - }; - - // A dynamically-sized type representing a "view" into a sequence of elements of a type - class SliceType : public TypeNoBounds { - // Type elem_type; - ::std::unique_ptr elem_type; - - location_t locus; - - public: - // Constructor requires pointer for polymorphism - SliceType(::std::unique_ptr type, location_t locus) : - elem_type(::std::move(type)), locus(locus) {} - - // Copy constructor requires deep copy of Type smart pointer - SliceType(SliceType const& other) : - elem_type(other.elem_type->clone_type()), locus(other.locus) {} - - // destructor not required? - - // Overload assignment operator to deep copy - SliceType& operator=(SliceType const& other) { - elem_type = other.elem_type->clone_type(); - locus = other.locus; - - return *this; - } - - // move constructors - SliceType(SliceType&& other) = default; - SliceType& operator=(SliceType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual SliceType* clone_type_impl() const OVERRIDE { - return new SliceType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual SliceType* clone_type_no_bounds_impl() const OVERRIDE { - return new SliceType(*this); - } - }; - - // Type used in generic arguments to explicitly request type inference (wildcard pattern) - class InferredType : public TypeNoBounds { - location_t locus; - - // e.g. Vec<_> = whatever - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual InferredType* clone_type_impl() const OVERRIDE { - return new InferredType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual InferredType* clone_type_no_bounds_impl() const OVERRIDE { - return new InferredType(*this); - } - - public: - InferredType(location_t locus) : locus(locus) {} - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - class QualifiedPathInType; // definition moved to "rust-path.h" - - // A possibly named param used in a BaseFunctionType - struct MaybeNamedParam { - public: - enum ParamKind { UNNAMED, IDENTIFIER, WILDCARD }; - - private: - // Type param_type; - ::std::unique_ptr param_type; - - ParamKind param_kind; - Identifier name; // technically, can be an identifier or '_' - - location_t locus; - - public: - MaybeNamedParam(Identifier name, ParamKind param_kind, ::std::unique_ptr param_type, - location_t locus) : - param_type(::std::move(param_type)), - param_kind(param_kind), name(::std::move(name)), locus(locus) {} - - // Copy constructor with clone - MaybeNamedParam(MaybeNamedParam const& other) : - param_type(other.param_type->clone_type()), param_kind(other.param_kind), - name(other.name), locus(other.locus) {} - - ~MaybeNamedParam() = default; - - // Overloaded assignment operator with clone - MaybeNamedParam& operator=(MaybeNamedParam const& other) { - name = other.name; - param_kind = other.param_kind; - param_type = other.param_type->clone_type(); - locus = other.locus; - - return *this; - } - - // move constructors - MaybeNamedParam(MaybeNamedParam&& other) = default; - MaybeNamedParam& operator=(MaybeNamedParam&& other) = default; - - ::std::string as_string() const; - - // Returns whether the param is in an error state. - inline bool is_error() const { - return param_type == NULL; - } - - // Creates an error state param. - static MaybeNamedParam create_error() { - return MaybeNamedParam("", UNNAMED, NULL, UNKNOWN_LOCATION); - } - - location_t get_locus() const { - return locus; - } - }; - - /* A function pointer type - can be created via coercion from function items and non- - * capturing closures. */ - class BareFunctionType : public TypeNoBounds { - // bool has_for_lifetimes; - // ForLifetimes for_lifetimes; - ::std::vector for_lifetimes; // inlined version - - FunctionQualifiers function_qualifiers; - ::std::vector params; - bool is_variadic; - - // bool has_return_type; - // BareFunctionReturnType return_type; - ::std::unique_ptr return_type; // inlined version - - location_t locus; - - public: - // Whether a return type is defined with the function. - inline bool has_return_type() const { - return return_type != NULL; - } - - // Whether the function has ForLifetimes. - inline bool has_for_lifetimes() const { - return !for_lifetimes.empty(); - } - - BareFunctionType(::std::vector lifetime_params, - FunctionQualifiers qualifiers, ::std::vector named_params, - bool is_variadic, ::std::unique_ptr type, location_t locus) : - for_lifetimes(::std::move(lifetime_params)), - function_qualifiers(::std::move(qualifiers)), params(::std::move(named_params)), - is_variadic(is_variadic), return_type(::std::move(type)), locus(locus) {} - - // Copy constructor with clone - BareFunctionType(BareFunctionType const& other) : - for_lifetimes(other.for_lifetimes), function_qualifiers(other.function_qualifiers), - params(other.params), is_variadic(other.is_variadic), - return_type(other.return_type->clone_type_no_bounds()), locus(other.locus) {} - - // destructor - define here if required - - // Overload assignment operator to deep copy - BareFunctionType& operator=(BareFunctionType const& other) { - for_lifetimes = other.for_lifetimes; - function_qualifiers = other.function_qualifiers; - params = other.params; - is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds(); - locus = other.locus; - - return *this; - } - - // move constructors - BareFunctionType(BareFunctionType&& other) = default; - BareFunctionType& operator=(BareFunctionType&& other) = default; - - ::std::string as_string() const; - - location_t get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BareFunctionType* clone_type_impl() const OVERRIDE { - return new BareFunctionType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BareFunctionType* clone_type_no_bounds_impl() const OVERRIDE { - return new BareFunctionType(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MacroInvocation; - - /*// AST node of a macro invocation, which is replaced by the macro result at compile time - class MacroInvocation : public TypeNoBounds, public Pattern, public ExprWithoutBlock { - SimplePath path; - DelimTokenTree token_tree; - };*/ - - /* TODO: possible types - * struct type? - * "enum" (tagged union) type? - * C-like union type? - * function item type? - * closure expression types? - * primitive types (bool, int, float, char, str (the slice)) - * Although supposedly TypePaths are used to reference these types (including primitives) */ - - /* FIXME: Incomplete spec references: - * anonymous type parameters, aka "impl Trait in argument position" - impl then trait bounds - * abstract return types, aka "impl Trait in return position" - impl then trait bounds */ - } -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/config-lang.in b/gcc/rust/test3/config-lang.in deleted file mode 100644 index 5591340..0000000 --- a/gcc/rust/test3/config-lang.in +++ /dev/null @@ -1,49 +0,0 @@ -# config-lang.in -- Top level configure fragment for gcc Rust frontend. - -# Copyright (C) 2013 Free Software Foundation, Inc. - -# This file is part of GCC. - -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# Configure looks for the existence of this file to auto-config each language. -# We define several parameters used by configure: -# -# language - name of language as it would appear in $(LANGUAGES) -# compilers - value to add to $(COMPILERS) -# diff_excludes - files to ignore when building diffs between two versions. - -language="rust" - -# Space-separated list of compiler executables that will be run by the driver. The names here will -# each end with ‘\$(exeext)’. -compilers="grs1\$(exeext)" - -# Do not build by default. -build_by_default="no" - -# Lists (space-separated) language front ends other than C that this front end requires to be -# enabled (with the names given being their language settings). -lang_requires_boot_languages=c++ - -# Lists (space-separated) targets in the top level Makefile to build the runtime libraries -# for this language, such as target-libobjc. -target_libs="target-libbacktrace" - -# Space-separated list of files that should be scanned by gengtype.c to generate the garbage -# collection tables and routines for this language. This excludes the files that are common to all -# front ends. -# gtfiles="\$(srcdir)/rust/rs-lang.c \$(srcdir)/rust/rdot-impl.h" -gtfiles="\$(srcdir)/rust/rust-lang.cc" diff --git a/gcc/rust/test3/expand/rust-macro-expand.cc b/gcc/rust/test3/expand/rust-macro-expand.cc deleted file mode 100644 index 613d94f..0000000 --- a/gcc/rust/test3/expand/rust-macro-expand.cc +++ /dev/null @@ -1,69 +0,0 @@ -#include "rust-macro-expand.h" -#include "rust-ast-full.h" -// is full really required? - -namespace Rust { - void MacroExpander::expand_invoc(::std::unique_ptr& invoc) { - // if current expansion depth > recursion limit, create an error (maybe fatal error) and return - - /* switch on type of macro: - - '!' syntax macro (inner switch) - - procedural macro - "A token-based function-like macro" - - 'macro_rules' (by example/pattern-match) macro? or not? "an AST-based function-like macro" - - else is unreachable - - attribute syntax macro (inner switch) - - procedural macro attribute syntax - "A token-based attribute macro" - - legacy macro attribute syntax? - "an AST-based attribute macro" - - non-macro attribute: mark known - - else is unreachable - - derive macro (inner switch) - - derive or legacy derive - "token-based" vs "AST-based" - - else is unreachable - - derive container macro - unreachable*/ - - } - - // Determines whether cfg predicate is true and item with attribute should not be stripped. - bool check_cfg_predicate() {} - - // Determines whether cfg predicate is true and item with attribute should not be stripped. - bool check_cfg(AST::Attribute& attr) { - - } - - // Expands cfg_attr attributes. - void expand_attrs_cfgattr(::std::vector& attrs) { - for (auto it = attrs.begin(); it != attrs.end(); ) { - auto& attr = *it; - if (attr.get_path() == "cfg_attr") { - if (check_cfg(attr)) {} - - /* do something - if feature (first token in tree) is in fact enabled, make tokens listed - * afterwards into attributes. - * i.e.: for [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add attributes - * [wow1] and [wow2] to attribute list. - * This can also be recursive, so check for expanded attributes being recursive and - * possibly recursively call the expand_attrs? */ - } else { - ++it; - } - } - } - - void MacroExpander::expand_crate(AST::Crate& crate) { - // fill macro/decorator map from init list? not sure where init list comes from? - - // expand crate attributes - expand_attrs_cfgattr(crate.inner_attrs); - - // expand module attributes? - - // expand module tree recursively - - // post-process - - // extract exported macros? - - - } -} \ No newline at end of file diff --git a/gcc/rust/test3/expand/rust-macro-expand.h b/gcc/rust/test3/expand/rust-macro-expand.h deleted file mode 100644 index a252a41..0000000 --- a/gcc/rust/test3/expand/rust-macro-expand.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef RUST_MACRO_EXPAND_H -#define RUST_MACRO_EXPAND_H - -#include "rust-ast.h" - -// Provides objects and method prototypes for macro expansion - -namespace Rust { - // forward decls for AST - namespace AST { - class MacroInvocation; - } - - // Object used to store configuration data for macro expansion. - struct ExpansionCfg { - // features? - unsigned int recursion_limit; // TODO: determine default recursion limit - // trace macros? - // should test? - // more default stuff? - }; - - // Object used to store shared data (between functions) for macro expansion. - struct MacroExpander { - ExpansionCfg cfg; - unsigned int expansion_depth = 0; - - MacroExpander(AST::Crate& crate, ExpansionCfg cfg) : cfg(cfg), crate(crate) {} - - ~MacroExpander() = default; - - // Expands all macros in the crate passed in. - void expand_crate(AST::Crate& crate); - - /* Expands a macro invocation (not macro invocation semi) - possibly make both have similar - * duck-typed interface and use templates?*/ - // should this be public or private? - void expand_invoc(::std::unique_ptr& invoc); - - // TODO: make it extend ASTVisitor so that individual items can be accessed properly? - - private: - AST::Crate& crate; - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/lang-specs.h b/gcc/rust/test3/lang-specs.h deleted file mode 100644 index c36a9e7..0000000 --- a/gcc/rust/test3/lang-specs.h +++ /dev/null @@ -1,30 +0,0 @@ -/* This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -// describes Rust front-end to GCC driver - -/* tells GCC to invoke Rust frontend on .rs files, gives instructions on - other programs to be run, such as assembler, etc. - In this, it has grs1 as the actual compiler and whatever */ -/* This is the contribution to the `default_compilers' array in gcc.c - for the Rust language. */ -{".rs", "@rs", 0, 1, 0}, -/*{"@rs", "grs1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", - 0, 1, 0},*/ -{"@rs", "grs1 %i %{!Q:-quiet} %(cc1_options) %{!fsyntax-only:%(invoke_as)}", - 0, 1, 0}, - -// "May take a while" to write this file - refer to other language lang-specs.h \ No newline at end of file diff --git a/gcc/rust/test3/lang.opt b/gcc/rust/test3/lang.opt deleted file mode 100644 index 4757dfb..0000000 --- a/gcc/rust/test3/lang.opt +++ /dev/null @@ -1,46 +0,0 @@ -; Options for the Rust front end. -; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 -; Free Software Foundation, Inc. -; -; This file is part of GCC. -; -; GCC is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License as published by the Free -; Software Foundation; either version 3, or (at your option) any later -; version. -; -; GCC is distributed in the hope that it will be useful, but WITHOUT ANY -; WARRANTY; without even the implied warranty of MERCHANTABILITY or -; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -; for more details. -; -; You should have received a copy of the GNU General Public License -; along with GCC; see the file COPYING3. If not see -; . - -; See the GCC internals manual for a description of this file's format. - -; Please try to keep this file in ASCII collating order. - -; Describes command-line options used by this frontend - -Language -Rust - -I -Rust Joined Separate -; Documented in c.opt - -L -Rust Joined Separate -; Not documented - -frust-dump- -Rust Joined RejectNegative --frust-dump- Dump Rust frontend internal information. - -o -Rust Joined Separate -; Documented in common.opt - -; This comment is to ensure we retain the blank line above. diff --git a/gcc/rust/test3/lex/rust-codepoint.h b/gcc/rust/test3/lex/rust-codepoint.h deleted file mode 100644 index a00edb3..0000000 --- a/gcc/rust/test3/lex/rust-codepoint.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RUST_CODEPOINT_H -#define RUST_CODEPOINT_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -// config, system, coretypes - TODO: ensure all are needed - -#include - -namespace Rust { - struct Codepoint { - uint32_t value; - - // Creates a zero codepoint. - Codepoint() : value(0) {} - - // Creates a codepoint from UTF-8 value. - Codepoint(uint32_t value_) : value(value_) {} - - // Returns a C++ string containing value of codepoint. - ::std::string as_string(); - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/lex/rust-lex.cc b/gcc/rust/test3/lex/rust-lex.cc deleted file mode 100644 index 5a7b0cb..0000000 --- a/gcc/rust/test3/lex/rust-lex.cc +++ /dev/null @@ -1,2349 +0,0 @@ -#include "rust-lex.h" - -#include "diagnostic.h" // for error_at -#include "safe-ctype.h" - -#include // for ostringstream - -namespace Rust { - // TODO: move to separate compilation unit? - // overload += for uint32_t to allow 32-bit encoded utf-8 to be added - ::std::string& operator+=(::std::string& str, Codepoint char32) { - if (char32.value < 0x80) { - str += static_cast(char32.value); - } else if (char32.value < (0x1F + 1) << (1 * 6)) { - str += static_cast(0xC0 | ((char32.value >> 6) & 0x1F)); - str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); - } else if (char32.value < (0x0F + 1) << (2 * 6)) { - str += static_cast(0xE0 | ((char32.value >> 12) & 0x0F)); - str += static_cast(0x80 | ((char32.value >> 6) & 0x3F)); - str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); - } else if (char32.value < (0x07 + 1) << (3 * 6)) { - str += static_cast(0xF0 | ((char32.value >> 18) & 0x07)); - str += static_cast(0x80 | ((char32.value >> 12) & 0x3F)); - str += static_cast(0x80 | ((char32.value >> 6) & 0x3F)); - str += static_cast(0x80 | ((char32.value >> 0) & 0x3F)); - } else { - fprintf(stderr, "Invalid unicode codepoint found: '%u' \n", char32.value); - // error_at(get_current_location(), "Invalid unicode codepoint found: '%u'", - // char32.value); - } - return str; - } - - ::std::string Codepoint::as_string() { - std::string str; - - // do i need to do this? or can i just do str += value due to op overloading? - - // ok can't figure out how to just convert to codepoint or use "this" so create new one - str += Codepoint(value); - - /*if (value < 0x80) { - str += static_cast(value); - } else if (value < (0x1F + 1) << (1 * 6)) { - str += static_cast(0xC0 | ((value >> 6) & 0x1F)); - str += static_cast(0x80 | ((value >> 0) & 0x3F)); - } else if (value < (0x0F + 1) << (2 * 6)) { - str += static_cast(0xE0 | ((value >> 12) & 0x0F)); - str += static_cast(0x80 | ((value >> 6) & 0x3F)); - str += static_cast(0x80 | ((value >> 0) & 0x3F)); - } else if (value < (0x07 + 1) << (3 * 6)) { - str += static_cast(0xF0 | ((value >> 18) & 0x07)); - str += static_cast(0x80 | ((value >> 12) & 0x3F)); - str += static_cast(0x80 | ((value >> 6) & 0x3F)); - str += static_cast(0x80 | ((value >> 0) & 0x3F)); - } else { - error_at(get_current_location(), "Invalid unicode codepoint found: '%u'", value); - }*/ - return str; - } - - // Includes all allowable float digits EXCEPT _ and . as that needs lookahead for handling. - inline bool is_float_digit(char number) { - return ISDIGIT(number) || number == 'E' || number == 'e'; - } - - // Basically ISXDIGIT from safe-ctype but may change if Rust's encoding or whatever is different - inline bool is_x_digit(char number) { - return ISXDIGIT(number); - } - - inline bool is_octal_digit(char number) { - return number >= '0' && number <= '7'; - } - - inline bool is_bin_digit(char number) { - return number == '0' || number == '1'; - } - - inline bool check_valid_float_dot_end(char character) { - return character != '.' && character != '_' && !ISALPHA(character); - } - - // ISSPACE from safe-ctype but may change in future - inline bool is_whitespace(char character) { - return ISSPACE(character); - } - - Lexer::Lexer(const char* filename, FILE* input) : - input(input), current_line(1), current_column(1), line_map(0), input_source(input), - input_queue(input_source), token_source(this), token_queue(token_source) { - // inform line_table that file is being entered and is in line 1 - line_map - = ::linemap_add(::line_table, ::LC_ENTER, /* sysp */ 0, filename, /* current_line */ 1); - } - - Lexer::~Lexer() { - ::linemap_add(::line_table, ::LC_LEAVE, /* sysp */ 0, /* filename */ NULL, /* to_line */ 0); - } - - location_t Lexer::get_current_location() { - return ::linemap_position_for_column(::line_table, current_column); - } - - int Lexer::peek_input(int n) { - return input_queue.peek(n); - } - - int Lexer::peek_input() { - return peek_input(0); - } - - void Lexer::skip_input(int n) { - input_queue.skip(n); - } - - void Lexer::skip_input() { - skip_input(0); - } - - const_TokenPtr Lexer::peek_token(int n) { - return token_queue.peek(n); - } - - const_TokenPtr Lexer::peek_token() { - return peek_token(0); - } - - void Lexer::skip_token(int n) { - token_queue.skip(n); - } - - void Lexer::skip_token() { - skip_token(0); - } - - void Lexer::replace_current_token(TokenPtr replacement) { - token_queue.replace_current_value(replacement); - } - - /* shitty anonymous namespace that can only be accessed inside the compilation unit - used for - * classify_keyword - * Binary search in sorted array of keywords created with x-macros. */ - namespace { - const std::string keyword_index[] = { -#define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(name, keyword) keyword, - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - TokenId keyword_keys[] = { -#define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(name, keyword) name, - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - const int num_keywords = sizeof(keyword_index) / sizeof(*keyword_index); - } - - /* Determines whether the string passed in is a keyword or not. If it is, it returns the keyword - * name. */ - TokenId Lexer::classify_keyword(const std::string& str) { - const std::string* last = keyword_index + num_keywords; - const std::string* idx = std::lower_bound(keyword_index, last, str); - - if (idx == last || str != *idx) { - return IDENTIFIER; - } else { - return keyword_keys[idx - keyword_index]; - } - } - - TokenPtr Lexer::build_token() { - // loop to go through multiple characters to build a single token - while (true) { - location_t loc = get_current_location(); - /*int */ current_char = peek_input(); - skip_input(); - - // return end of file token if end of file - if (current_char == EOF) { - return Token::make(END_OF_FILE, loc); - } - - // detect shebang - if (loc == 1 && current_line == 1 && current_char == '#') { - current_char = peek_input(); - - if (current_char == '!') { - skip_input(); - current_char = peek_input(); - - switch (current_char) { - case '/': - // shebang - - skip_input(); - - // ignore rest of line - while (current_char != '\n') { - current_char = peek_input(); - skip_input(); - } - - // newline - current_line++; - current_column = 1; - // tell line_table that new line starts - linemap_line_start(::line_table, current_line, max_column_hint); - continue; - } - } - } - - // if not end of file, start tokenising - switch (current_char) { - // ignore whitespace characters for tokens but continue updating location - case '\n': // newline - current_line++; - current_column = 1; - // tell line_table that new line starts - linemap_line_start(::line_table, current_line, max_column_hint); - continue; - case ' ': // space - current_column++; - continue; - case '\t': // tab - // width of a tab is not well-defined, assume 8 spaces - current_column += 8; - continue; - - // punctuation - actual tokens - case '=': - if (peek_input() == '>') { - // match arm arrow - skip_input(); - current_column += 2; - - return Token::make(MATCH_ARROW, loc); - } else if (peek_input() == '=') { - // equality operator - skip_input(); - current_column += 2; - - return Token::make(EQUAL_EQUAL, loc); - } else { - // assignment operator - current_column++; - return Token::make(EQUAL, loc); - } - case '(': - current_column++; - return Token::make(LEFT_PAREN, loc); - case '-': - if (peek_input() == '>') { - // return type specifier - skip_input(); - current_column += 2; - - return Token::make(RETURN_TYPE, loc); - } else if (peek_input() == '=') { - // minus-assign - skip_input(); - current_column += 2; - - return Token::make(MINUS_EQ, loc); - } else { - // minus - current_column++; - return Token::make(MINUS, loc); - } - case '+': - if (peek_input() == '=') { - // add-assign - skip_input(); - current_column += 2; - - return Token::make(PLUS_EQ, loc); - } else { - // add - current_column++; - return Token::make(PLUS, loc); - } - case ')': - current_column++; - return Token::make(RIGHT_PAREN, loc); - case ';': - current_column++; - return Token::make(SEMICOLON, loc); - case '*': - if (peek_input() == '=') { - // multiplication-assign - skip_input(); - current_column += 2; - - return Token::make(ASTERISK_EQ, loc); - } else { - // multiplication - current_column++; - return Token::make(ASTERISK, loc); - } - case ',': - current_column++; - return Token::make(COMMA, loc); - case '/': - if (peek_input() == '=') { - // division-assign - skip_input(); - current_column += 2; - - return Token::make(DIV_EQ, loc); - } else if (peek_input() == '/') { - // TODO: single-line doc comments - - // single line comment - skip_input(); - current_column += 2; - - // basically ignore until line finishes - while (current_char != '\n' && current_char != EOF) { - skip_input(); - current_column++; // not used - current_char = peek_input(); - } - continue; - break; - } else if (peek_input() == '*') { - // block comment - skip_input(); - current_column += 2; - - // TODO: block doc comments - - current_char = peek_input(); - - int level = 1; - while (level > 0) { - skip_input(); - current_column++; // for error-handling - current_char = peek_input(); - - // if /* found - if (current_char == '/') { - if (peek_input(1) == '*') { - // skip /* characters - skip_input(1); - - current_column += 2; - - level += 1; - } - } - - // ignore until */ is found - if (current_char == '*') { - if (peek_input(1) == '/') { - // skip */ characters - skip_input(1); - - current_column += 2; - // should only break inner loop here - seems to do so - // break; - - level -= 1; - } - } - } - - // refresh new token - continue; - break; - } else { - // division - current_column++; - return Token::make(DIV, loc); - } - case '%': - if (peek_input() == '=') { - // modulo-assign - current_column += 2; - return Token::make(PERCENT_EQ, loc); - } else { - // modulo - current_column++; - return Token::make(PERCENT, loc); - } - case '^': - if (peek_input() == '=') { - // xor-assign? - current_column += 2; - return Token::make(CARET_EQ, loc); - } else { - // xor? - current_column++; - return Token::make(CARET, loc); - } - case '<': - if (peek_input() == '<') { - if (peek_input(1) == '=') { - // left-shift assign - skip_input(1); - current_column += 3; - - return Token::make(LEFT_SHIFT_EQ, loc); - } else { - // left-shift - skip_input(); - current_column += 2; - - return Token::make(LEFT_SHIFT, loc); - } - } else if (peek_input() == '=') { - // smaller than or equal to - skip_input(); - current_column += 2; - - return Token::make(LESS_OR_EQUAL, loc); - } else { - // smaller than - current_column++; - return Token::make(LEFT_ANGLE, loc); - } - break; - case '>': - if (peek_input() == '>') { - if (peek_input(1) == '=') { - // right-shift-assign - skip_input(1); - current_column += 3; - - return Token::make(RIGHT_SHIFT_EQ, loc); - } else { - // right-shift - skip_input(); - current_column += 2; - - return Token::make(RIGHT_SHIFT, loc); - } - } else if (peek_input() == '=') { - // larger than or equal to - skip_input(); - current_column += 2; - - return Token::make(GREATER_OR_EQUAL, loc); - } else { - // larger than - current_column++; - return Token::make(RIGHT_ANGLE, loc); - } - case ':': - if (peek_input() == ':') { - // scope resolution :: - skip_input(); - current_column += 2; - - return Token::make(SCOPE_RESOLUTION, loc); - } else { - // single colon : - current_column++; - return Token::make(COLON, loc); - } - case '!': - // no special handling for macros in lexer? - if (peek_input() == '=') { - // not equal boolean operator - skip_input(); - current_column += 2; - - return Token::make(NOT_EQUAL, loc); - } else { - // not equal unary operator - current_column++; - - return Token::make(EXCLAM, loc); - } - case '?': - current_column++; - return Token::make(QUESTION_MARK, loc); - case '#': - current_column++; - return Token::make(HASH, loc); - case '[': - current_column++; - return Token::make(LEFT_SQUARE, loc); - case ']': - current_column++; - return Token::make(RIGHT_SQUARE, loc); - case '{': - current_column++; - return Token::make(LEFT_CURLY, loc); - case '}': - current_column++; - return Token::make(RIGHT_CURLY, loc); - case '@': - // TODO: i don't know what this does, does it need special handling? - current_column++; - return Token::make(PATTERN_BIND, loc); - case '$': - // TODO: i don't know what this does, does it need special handling? - current_column++; - return Token::make(DOLLAR_SIGN, loc); - case '~': - // TODO: i don't know what this does, does it need special handling? - current_column++; - return Token::make(TILDE, loc); - case '\\': - // TODO: i don't know what this does, does it need special handling? - current_column++; - return Token::make(BACKSLASH, loc); - case '`': - // TODO: i don't know what this does, does it need special handling? - current_column++; - return Token::make(BACKTICK, loc); - case '|': - if (peek_input() == '=') { - // bitwise or-assign? - skip_input(); - current_column += 2; - - return Token::make(PIPE_EQ, loc); - } else if (peek_input() == '|') { - // logical or - skip_input(); - current_column += 2; - - return Token::make(OR, loc); - } else { - // bitwise or - current_column++; - - return Token::make(PIPE, loc); - } - case '&': - if (peek_input() == '=') { - // bitwise and-assign? - skip_input(); - current_column += 2; - - return Token::make(AMP_EQ, loc); - } else if (peek_input() == '&') { - // logical and - skip_input(); - current_column += 2; - - return Token::make(LOGICAL_AND, loc); - } else { - // bitwise and/reference - current_column++; - - return Token::make(AMP, loc); - } - case '.': - if (peek_input() == '.') { - if (peek_input(1) == '.') { - // ellipsis - skip_input(1); - current_column += 3; - - return Token::make(ELLIPSIS, loc); - } else if (peek_input(1) == '=') { - // ..= - skip_input(1); - current_column += 3; - - return Token::make(DOT_DOT_EQ, loc); - } else { - // .. - skip_input(); - current_column += 2; - - return Token::make(DOT_DOT, loc); - } - } else if (!ISDIGIT(peek_input())) { - // single dot . - // Only if followed by a non-number - current_column++; - return Token::make(DOT, loc); - } - } - // TODO: special handling of _ in the lexer? instead of being identifier - - // byte and byte string test - if (current_char == 'b') { - if (peek_input() == '\'') { - // byte - allows any ascii or escapes - // would also have to take into account escapes: \x hex_digit hex_digit, - // \n, \r, \t, \\, \0 - - int length = 1; - - // char to save - char byte_char; - - skip_input(); - // make current char the next character - current_char = peek_input(); - - // detect escapes - if (current_char == '\\') { - /*skip_input(); - - // make current_char next character (letter) - current_char = peek_input();*/ - - parse_escape(length, byte_char, '\''); - - if (byte_char > 127) { - error_at( - get_current_location(), "byte char '%c' out of range", byte_char); - byte_char = 0; - } - - // skip_input(); - current_char = peek_input(); - length++; - - if (current_char != '\'') { - error_at(get_current_location(), "unclosed byte char"); - } - - // TODO: ensure skipping is needed here - skip_input(); - current_char = peek_input(); - length++; // go to next char - } else if (current_char != '\'') { - // otherwise, get character from direct input character - byte_char = current_char; - - skip_input(); - current_char = peek_input(); - - if (current_char != '\'') { - error_at(get_current_location(), "unclosed byte char"); - } - - // TODO: ensure skipping is needed here - skip_input(); - current_char = peek_input(); - length++; // go to next char - } else { - error_at(get_current_location(), "no character inside '' for byte char"); - } - - current_column += length; - - return Token::make_byte_char(loc, byte_char); - } else if (peek_input() == '"') { - // byte string - - // skip quote character - skip_input(); - - std::string str; - str.reserve(16); // some sensible default - - int length = 1; - current_char = peek_input(); - // TODO: handle escapes properly - - while (current_char != '"' && current_char != '\n') { - if (current_char == '\\') { - char output_char = 0; - parse_escape(length, output_char, '"'); - - if (output_char > 127) { - error_at(get_current_location(), - "char '%c' in byte string out of range", output_char); - output_char = 0; - } - - str += output_char; - - continue; - } - - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - if (current_char == '\n') { - error_at(get_current_location(), "unended byte string literal"); - } else if (current_char == '"') { - skip_input(); - current_char = peek_input(); - } else { - gcc_unreachable(); - } - - return Token::make_byte_string(loc, str); - // TODO: ensure escapes and string continue work properly - } else if (peek_input() == 'r' && (peek_input(1) == '#' || peek_input(1) == '"')) { - // raw byte string literals - std::string str; - str.reserve(16); // some sensible default - - int length = 1; - int hash_count = 0; - - // get hash count at beginnning - skip_input(); - current_char = peek_input(); - while (current_char == '#') { - hash_count++; - length++; - - skip_input(); - current_char = peek_input(); - } - - if (current_char != '"') { - error_at(get_current_location(), "raw byte string has no opening '\"'"); - } - - skip_input(); - current_char = peek_input(); - - while (true) { - if (current_char == '"') { - bool enough_hashes = true; - - for (int i = 0; i < hash_count; i++) { - if (peek_input(i + 1) != '#') { - enough_hashes - = false; // could continue here - improve performance - } - } - - if (enough_hashes) { - // skip enough input and peek enough input - skip_input(hash_count); // is this enough? - current_char = peek_input(); - length += hash_count + 1; - break; - } - } - - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - return Token::make_byte_string(loc, str); // TODO: does this work properly - } - } - - // raw stuff - if (current_char == 'r') { - int peek = peek_input(); - int peek1 = peek_input(1); - - if (peek == '#' && (ISALPHA(peek1) || peek1 == '_')) { - // raw identifier - std::string str; - str.reserve(16); // default - - skip_input(); - current_char = peek_input(); - - current_column += 2; - - str += current_char; - - bool first_is_underscore = current_char == '_'; - - int length = 1; - current_char = peek_input(); - // loop through entire name - while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - // if just a single underscore, not an identifier - if (first_is_underscore && length == 1) { - error_at(get_current_location(), "'_' is not a valid raw identifier"); - } - - if (str == "crate" || str == "extern" || str == "self" || str == "super" - || str == "Self") { - error_at( - get_current_location(), "'%s' is a forbidden raw identifier", str.c_str()); - } else { - return Token::make_identifier(loc, str); - } - } else if (peek == '"' || (peek == '#' && (ISALPHA(peek1) || peek1 == '_'))) { - // raw string literals - std::string str; - str.reserve(16); // some sensible default - - int length = 1; - int hash_count = 0; - - // get hash count at beginnning - current_char = peek; - while (current_char == '#') { - hash_count++; - length++; - - skip_input(); - current_char = peek_input(); - } - - if (current_char != '"') { - error_at(get_current_location(), "raw string has no opening '\"'"); - } - - skip_input(); - Codepoint current_char32 = test_peek_codepoint_input(); - - while (true) { - if (current_char32.value == '"') { - bool enough_hashes = true; - - for (int i = 0; i < hash_count; i++) { - // if (test_peek_codepoint_input(i + 1) != '#') { - // TODO: ensure this is a good enough replacement - if (peek_input(i + 1) != '#') { - enough_hashes - = false; // could continue here - improve performance - } - } - - if (enough_hashes) { - // skip enough input and peek enough input - skip_input(hash_count); // is this enough? - current_char = peek_input(); - length += hash_count + 1; - break; - } - } - - length++; - - str += current_char32; - test_skip_codepoint_input(); - current_char32 = test_peek_codepoint_input(); - } - - current_column += length; - - return Token::make_string(loc, str); // TODO: does this work properly - } - } - - // find identifiers and keywords - if (ISALPHA(current_char) || current_char == '_') { - std::string str; - str.reserve(16); // default - str += current_char; - - bool first_is_underscore = current_char == '_'; - - int length = 1; - current_char = peek_input(); - // loop through entire name - while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - // if just a single underscore, not an identifier - if (first_is_underscore && length == 1) { - return Token::make(UNDERSCORE, loc); - } - - TokenId keyword = classify_keyword(str); - if (keyword == IDENTIFIER) { - return Token::make_identifier(loc, str); - } else { - return Token::make(keyword, loc); - } - } - - // identify literals - // int or float literals - not processed properly - if (ISDIGIT(current_char) || current_char == '.') { // _ not allowed as first char - std::string str; - str.reserve(16); // some sensible default - str += current_char; - - PrimitiveCoreType type_hint = CORETYPE_UNKNOWN; - - bool is_real = (current_char == '.'); - - int length = 1; - - // handle binary, octal, hex literals - if (current_char == '0' && !ISDIGIT(peek_input())) { - current_char = peek_input(); - - if (current_char == 'x') { - // hex (integer only) - - skip_input(); - current_char = peek_input(); - - length++; - - // add 'x' to string after 0 so it is 0xFFAA or whatever - str += 'x'; - - // loop through to add entire hex number to string - while (is_x_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw hex numbers - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - // convert hex value to decimal representation - long hex_num = ::std::strtol(str.c_str(), NULL, 16); - - // create output string stream for hex value to be converted to string - // again - // TODO: if too slow, use sprintf - ::std::ostringstream ostr; - ostr << hex_num; - - // reassign string representation to converted value - str = ostr.str(); - - // parse in type suffix if it exists - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { - error_at(get_current_location(), - "invalid type suffix '%s' for integer (hex) literal", - get_type_hint_string(type_hint)); - } - } else if (current_char == 'o') { - // octal (integer only) - - skip_input(); - current_char = peek_input(); - - length++; - - // don't add any characters as C octals are just 0124 or whatever - - // loop through to add entire octal number to string - while (is_octal_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw octal numbers - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - // convert octal value to decimal representation - long octal_num = ::std::strtol(str.c_str(), NULL, 8); - - // create output string stream for octal value to be converted to - // string again - // TODO: if too slow, use sprintf - ::std::ostringstream ostr; - ostr << octal_num; - - // reassign string representation to converted value - str = ostr.str(); - - // parse in type suffix if it exists - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { - error_at(get_current_location(), - "invalid type suffix '%s' for integer (octal) literal", - get_type_hint_string(type_hint)); - } - } else if (current_char == 'b') { - // binary (integer only) - - skip_input(); - current_char = peek_input(); - - length++; - - // don't add any characters as C binary numbers are not really - // supported - - // loop through to add entire binary number to string - while (is_bin_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw binary numbers - str += current_char; - skip_input(); - current_char = peek_input(); - } - - current_column += length; - - // convert binary value to decimal representation - long bin_num = ::std::strtol(str.c_str(), NULL, 2); - - // create output string stream for binary value to be converted to - // string again - // TODO: if too slow, use sprintf - ::std::ostringstream ostr; - ostr << bin_num; - - // reassign string representation to converted value - str = ostr.str(); - - // parse in type suffix if it exists - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { - error_at(get_current_location(), - "invalid type suffix '%s' for integer (binary) literal", - get_type_hint_string(type_hint)); - } - } - } else { - // handle decimals (integer or float) - - current_char = peek_input(); - - // parse initial decimal literal - assuming integer - // TODO: test if works - parse_in_decimal(/*current_char, */ str, length); - - // detect float literal - TODO: fix: "242." is not recognised as a float literal - if (current_char == '.' && is_float_digit(peek_input(1))) { - // float with a '.', parse another decimal into it - - is_real = true; - - // add . to str - str += current_char; - skip_input(); - current_char = peek_input(); - - length++; - - // parse another decimal number for float - // TODO: test if works - parse_in_decimal(/*current_char, */ str, length); - - // parse in exponent part if it exists - // test to see if this works: - parse_in_exponent_part(/*current_char, */ str, length); - - // parse in type suffix if it exists - // TODO: see if works: - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 - && type_hint != CORETYPE_UNKNOWN) { - error_at(get_current_location(), - "invalid type suffix '%s' for float literal", - get_type_hint_string(type_hint)); - } - - } else if (current_char == '.' && check_valid_float_dot_end(peek_input(1))) { - is_real = true; - - // add . to str - str += current_char; - skip_input(); - current_char = peek_input(); - length++; - - // add a '0' after the . to stop ambiguity - str += '0'; - - // don't parse another decimal number for float - - // parse in exponent part if it exists - shouldn't exist? - // parse_in_exponent_part(/*current_char, */ str, length); - - // parse in type suffix if it exists - shouldn't exist? - // TODO: see if works: - // parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 - && type_hint != CORETYPE_UNKNOWN) { - error_at(get_current_location(), - "invalid type suffix '%s' for float literal", - get_type_hint_string(type_hint)); - } - } else if (current_char == 'E' || current_char == 'e') { - is_real = true; - - // parse exponent part - parse_in_exponent_part(/*current_char, */ str, length); - - // parse in type suffix if it exists - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint != CORETYPE_F32 && type_hint != CORETYPE_F64 - && type_hint != CORETYPE_UNKNOWN) { - error_at(get_current_location(), - "invalid type suffix '%s' for float literal", - get_type_hint_string(type_hint)); - } - } else { - // is an integer - - // parse in type suffix if it exists - parse_in_type_suffix(/*current_char, */ type_hint, length); - - if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) { - error_at(get_current_location(), - "invalid type suffix '%s' for integer (decimal) literal", - get_type_hint_string(type_hint)); - } - } - - current_column += length; - } - - // actually make the tokens - if (is_real) { - return Token::make_float(loc, str, type_hint); - } else { - return Token::make_int(loc, str, type_hint); - } - } - - // string literals - not processed properly - if (current_char == '"') { - Codepoint current_char32; - - std::string str; - str.reserve(16); // some sensible default - - int length = 1; - current_char32 = test_peek_codepoint_input(); - - // ok initial peek_codepoint seems to work without "too long" - - while (current_char32.value != '\n' && current_char32.value != '"') { - // TODO: handle escapes and string continue - if (current_char32.value == '\\') { - // parse escape - parse_utf8_escape(length, current_char32, '\''); - - // TODO: find a way to parse additional characters after the escape? - // return after parsing escape? - - str += current_char32; - - // required as parsing utf8 escape only changes current_char or something - current_char32 = test_peek_codepoint_input(); - - continue; - } - - length += test_get_input_codepoint_length(); - - // does this work? not technically a char. maybe have to convert to char series - str += current_char32; - test_skip_codepoint_input(); - current_char32 = test_peek_codepoint_input(); - } - - current_column += length; - - if (current_char32.value == '\n') { - error_at(get_current_location(), "unended string literal"); - } else if (current_char32.value == '"') { - skip_input(); - - current_char = peek_input(); - } else { - gcc_unreachable(); - } - - return Token::make_string(loc, str); - // TODO: account for escapes and string continue - // also, in rust a string is a series of unicode characters (4 bytes) - } - - // char literal attempt - if (current_char == '\'') { - // rust chars are 4 bytes and have some weird unicode representation thing - Codepoint current_char32; - - int length = 1; - - current_char32 = test_peek_codepoint_input(); - - // parse escaped char literal - if (current_char32.value == '\\') { - // parse escape - parse_utf8_escape(length, current_char32, '\''); - - // TODO - this skip may not be needed? - // test_skip_codepoint_input(); - - if (test_peek_codepoint_input().value != '\'') { - error_at(get_current_location(), "unended char literal"); - } else { - test_skip_codepoint_input(); - current_char = peek_input(); - length++; - } - - current_column += length; - - // TODO: FIX - char is actually 4 bytes in Rust (uint32) due to unicode - return Token::make_char(loc, current_char32); - } else { - // current_char32 = test_peek_codepoint_input(); - test_skip_codepoint_input(); - - if (test_peek_codepoint_input().value == '\'') { - // parse normal char literal - // TODO: FIX - char is actually 4 bytes in Rust (uint32) due to unicode - - // skip the ' character - skip_input(); - current_char = peek_input(); - - // TODO fix due to different widths of utf-8 chars - current_column += 3; - - return Token::make_char(loc, current_char32); - } else if (ISDIGIT(current_char32.value) || ISALPHA(current_char32.value) - || current_char32.value == '_') { - // parse lifetime name - ::std::string str; - // TODO: does this work properly? - str += current_char32; - - // TODO: fix lifetime name thing - actually, why am I even using utf-8 here? - - int length = 1; - - current_char32 = test_peek_codepoint_input(); - - while (ISDIGIT(current_char32.value) || ISALPHA(current_char32.value) - || current_char32.value == '_') { - length += test_get_input_codepoint_length(); - - str += current_char32; - test_skip_codepoint_input(); - current_char32 = test_peek_codepoint_input(); - } - - current_column += length; - - return Token::make_lifetime(loc, str); - } else { - error_at(get_current_location(), "expected ' after character constant"); - } - } - } - - // didn't match anything so error - error_at(loc, "unexpected character '%x'", current_char); - current_column++; - } - } - - // Shitty pass-by-reference way of parsing in type suffix. - bool Lexer::parse_in_type_suffix( - /*char& current_char, */ PrimitiveCoreType& type_hint, int& length) { - ::std::string suffix; - suffix.reserve(5); - - // get suffix - while (ISALPHA(current_char) || ISDIGIT(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to suffix - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - suffix += current_char; - skip_input(); - current_char = peek_input(); - } - - if (suffix.empty()) { - // no type suffix: do nothing but also no error - return false; - } else if (suffix == "f32") { - type_hint = CORETYPE_F32; - } else if (suffix == "f64") { - type_hint = CORETYPE_F64; - } else if (suffix == "i8") { - type_hint = CORETYPE_I8; - } else if (suffix == "i16") { - type_hint = CORETYPE_I16; - } else if (suffix == "i32") { - type_hint = CORETYPE_I32; - } else if (suffix == "i64") { - type_hint = CORETYPE_I64; - } else if (suffix == "i128") { - type_hint = CORETYPE_I128; - } else if (suffix == "isize") { - type_hint = CORETYPE_ISIZE; - } else if (suffix == "u8") { - type_hint = CORETYPE_U8; - } else if (suffix == "u16") { - type_hint = CORETYPE_U16; - } else if (suffix == "u32") { - type_hint = CORETYPE_U32; - } else if (suffix == "u64") { - type_hint = CORETYPE_U64; - } else if (suffix == "u128") { - type_hint = CORETYPE_U128; - } else if (suffix == "usize") { - type_hint = CORETYPE_USIZE; - } else { - error_at(get_current_location(), "unknown number suffix '%s'", suffix.c_str()); - - return false; - } - - return true; - } - - void Lexer::parse_in_exponent_part(/*char& current_char, */ std::string& str, int& length) { - if (current_char == 'E' || current_char == 'e') { - // add exponent to string as strtod works with it - str += current_char; - skip_input(); - current_char = peek_input(); - - length++; - - // special - and + handling - if (current_char == '-') { - str += '-'; - - skip_input(); - current_char = peek_input(); - - length++; - } else if (current_char == '+') { - // don't add + but still skip input - skip_input(); - current_char = peek_input(); - - length++; - } - - // parse another decimal number for exponent - parse_in_decimal(/*current_char, */ str, length); - } - } - - void Lexer::parse_in_decimal(/*char& current_char, */ std::string& str, int& length) { - while (ISDIGIT(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - str += current_char; - skip_input(); - current_char = peek_input(); - } - } - - // Replace all assorted parse_x_escape with this? Avoids the backwards/peek issue. - bool Lexer::parse_escape(int& length, char& output_char, char opening_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - switch (current_char) { - case 'x': { - // hex char string (null-terminated) - char hexNum[3] = { 0, 0, 0 }; - - // first hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[0] = current_char; - - // second hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[1] = current_char; - - long hexLong = ::std::strtol(hexNum, NULL, 16); - - if (hexLong > 127) - error_at(get_current_location(), - "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); - // gcc_assert(hexLong < 128); // as ascii - char hexChar = static_cast(hexLong); - - // TODO: fix - does this actually give the right character? - output_char = hexChar; - } break; - case 'n': - output_char = '\n'; - break; - case 'r': - output_char = '\r'; - break; - case 't': - output_char = '\t'; - break; - case '\\': - output_char = '\\'; - break; - case '0': - output_char = '\0'; - break; - case '\'': - output_char = '\''; - break; - case '"': - output_char = '"'; - break; - case 'u': { - // TODO: shouldn't be used with this - use parse_utf8_escape - - skip_input(); - current_char = peek_input(); - length++; - - bool need_close_brace = false; - - // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at - // spec? - if (current_char == '{') { - need_close_brace = true; - - skip_input(); - current_char = peek_input(); - length++; - } - - // parse unicode escape - // 1-6 hex digits? - ::std::string num_str; - num_str.reserve(6); - - // test adding number directly - uint32_t test_val; - - // loop through to add entire hex number to string - while (is_x_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw hex numbers - num_str += current_char; - - // test adding number directly - char tmp[2] = { current_char, 0 }; - test_val *= 16; - test_val += ::std::strtol(tmp, NULL, 16); - - skip_input(); - current_char = peek_input(); - } - - // ensure closing brace - if (need_close_brace && current_char != '}') { - // actually an error - error_at(get_current_location(), "expected terminating '}' in unicode escape"); - return false; - } - - // ensure 1-6 hex characters - if (num_str.length() > 6 || num_str.length() < 1) { - error_at(get_current_location(), - "unicode escape should be between 1 and 6 hex characters; it is %lu", - num_str.length()); - return false; - } - - long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); - - // as debug, check hex_num = test_val - if (hex_num > 255) { - error_at( - get_current_location(), "non-ascii chars not implemented yet, defaulting to 0"); - hex_num = 0; - } - - // make output_char the value - UTF-8? - // TODO: actually make this work - output char must be 4 bytes, do I need a string for - // this? - output_char = static_cast(hex_num); - - return true; - } break; - case '\r': - case '\n': - // string continue - while (is_whitespace(current_char)) { - if (current_char == '\n') { - current_line++; - current_column = 1; - // tell line_table that new line starts - linemap_line_start(::line_table, current_line, max_column_hint); - - // reset "length" - length = 1; - - // get next char - skip_input(); - current_char = peek_input(); - - continue; - } - - skip_input(); - current_char = peek_input(); - length++; - } - - if (current_char == '\\') { - parse_escape(length, output_char, opening_char); - return true; - } else if (current_char == opening_char) { - // TODO: does this skip the ' or " character? It shouldn't. - output_char = 0; - return true; - } else { - output_char = current_char; - - // TODO: test has right result - /*skip_input(); - current_char = peek_input();*/ - - return true; - } - default: - error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); - // returns false if no parsing could be done - return false; - break; - } - // all non-special cases (unicode, string continue) should skip their used char - skip_input(); - current_char = peek_input(); - length++; - - // returns true if parsing was successful - return true; - } - - bool Lexer::parse_utf8_escape(int& length, Codepoint& output_char, char opening_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - switch (current_char) { - case 'x': { - // hex char string (null-terminated) - char hexNum[3] = { 0, 0, 0 }; - - // first hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[0] = current_char; - - // second hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[1] = current_char; - - long hexLong = ::std::strtol(hexNum, NULL, 16); - - if (hexLong > 127) - error_at(get_current_location(), - "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); - // gcc_assert(hexLong < 128); // as ascii - char hexChar = static_cast(hexLong); - - // TODO: fix - does this actually give the right character? - output_char = hexChar; - } break; - case 'n': - output_char = '\n'; - break; - case 'r': - output_char = '\r'; - break; - case 't': - output_char = '\t'; - break; - case '\\': - output_char = '\\'; - break; - case '0': - output_char = '\0'; - break; - case '\'': - output_char = '\''; - break; - case '"': - output_char = '"'; - break; - case 'u': { - skip_input(); - current_char = peek_input(); - length++; - - bool need_close_brace = false; - - // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at - // spec? - if (current_char == '{') { - need_close_brace = true; - - skip_input(); - current_char = peek_input(); - length++; - } - - // parse unicode escape - // 1-6 hex digits? - ::std::string num_str; - num_str.reserve(6); - - // test adding number directly - uint32_t test_val; - - // loop through to add entire hex number to string - while (is_x_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw hex numbers - num_str += current_char; - - // test adding number directly - char tmp[2] = { current_char, 0 }; - test_val *= 16; - test_val += ::std::strtol(tmp, NULL, 16); - - skip_input(); - current_char = peek_input(); - } - - // ensure closing brace if required - if (need_close_brace) { - if (current_char == '}') { - skip_input(); - current_char = peek_input(); - length++; - } else { - // actually an error - error_at( - get_current_location(), "expected terminating '}' in unicode escape"); - return false; - } - } - - // ensure 1-6 hex characters - if (num_str.length() > 6 || num_str.length() < 1) { - error_at(get_current_location(), - "unicode escape should be between 1 and 6 hex characters; it is %lu", - num_str.length()); - return false; - } - - long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); - - // assert fits a uint32_t - gcc_assert(hex_num < 4294967296); - - // ok can't figure out how to just convert to codepoint or use "this" so create new - // one - output_char = Codepoint(static_cast(hex_num)); - - // TODO: what is being outputted? the escape code for the unicode char (unicode - // number) or the character number? - - return true; - } break; - case '\r': - case '\n': - // string continue - while (is_whitespace(current_char)) { - if (current_char == '\n') { - current_line++; - current_column = 1; - // tell line_table that new line starts - linemap_line_start(::line_table, current_line, max_column_hint); - - // reset "length" - length = 1; - - // get next char - skip_input(); - current_char = peek_input(); - - continue; - } - - skip_input(); - current_char = peek_input(); - length++; - } - - if (current_char == '\\') { - parse_utf8_escape(length, output_char, opening_char); - return true; - } else if (current_char == opening_char) { - // TODO: does this skip the ' or " character? It shouldn't. - output_char = 0; - return true; - } else { - output_char = current_char; - - // TODO: test has right result - /*skip_input(); - current_char = peek_input();*/ - - return true; - } - default: - error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); - // returns false if no parsing could be done - return false; - break; - } - // all non-special cases (unicode, string continue) should skip their used char - skip_input(); - current_char = peek_input(); - length++; - - // returns true if parsing was successful - return true; - } - -#if 0 - bool Lexer::parse_ascii_escape(/*char& current_char, */ int& length, char& output_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - switch (current_char) { - case 'x': { - // hex char string (null-terminated) - char hexNum[3] = { 0, 0, 0 }; - - // first hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[0] = current_char; - - // second hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[1] = current_char; - - long hexLong = ::std::strtol(hexNum, NULL, 16); - - if (hexLong > 127) - error_at(get_current_location(), - "ascii \\x escape '\\x%s' out of range - allows up to '\\x7F'", hexNum); - // gcc_assert(hexLong < 128); // as ascii - char hexChar = static_cast(hexLong); - - // TODO: fix - does this actually give the right character? - output_char = hexChar; - } break; - case 'n': - output_char = '\n'; - break; - case 'r': - output_char = '\r'; - break; - case 't': - output_char = '\t'; - break; - case '\\': - output_char = '\\'; - break; - case '0': - output_char = '\0'; - break; - default: - // error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); - // returns false if no parsing could be done - return false; - break; - } - // returns true if parsing was successful - return true; - } - - bool Lexer::parse_quote_escape(/*char& current_char, */ int& length, char& output_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - switch (current_char) { - case '\'': - output_char = '\''; - break; - case '"': - output_char = '"'; - break; - default: - return false; - break; - } - return true; - } - - bool Lexer::parse_unicode_escape( - /*char& current_char, */ int& length, /*char*/ uint32_t& output_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - if (current_char != 'u') { - // not a unicode escape, but not necessarily an error - return false; - } - - skip_input(); - current_char = peek_input(); - length++; - - bool need_close_brace = false; - - // TODO: rustc lexer doesn't seem to allow not having { but mrustc lexer does? look at spec? - if (current_char == '{') { - need_close_brace = true; - - skip_input(); - current_char = peek_input(); - length++; - } - - // parse unicode escape - // 1-6 hex digits? - ::std::string num_str; - num_str.reserve(6); - - // test adding number directly - uint32_t test_val; - - // loop through to add entire hex number to string - while (is_x_digit(current_char) || current_char == '_') { - if (current_char == '_') { - // don't add _ to number - skip_input(); - current_char = peek_input(); - - length++; - - continue; - } - - length++; - - // add raw hex numbers - num_str += current_char; - - // test adding number directly - char tmp[2] = { current_char, 0 }; - test_val *= 16; - test_val += ::std::strtol(tmp, NULL, 16); - - skip_input(); - current_char = peek_input(); - } - - // ensure closing brace - if (need_close_brace && current_char != '}') { - // actually an error - error_at(get_current_location(), "expected terminating '}' in unicode escape"); - return false; - } - - // ensure 1-6 hex characters - if (num_str.length() > 6 || num_str.length() < 1) { - error_at(get_current_location(), - "unicode escape should be between 1 and 6 hex characters; it is %lu", num_str.length()); - return false; - } - - long hex_num = ::std::strtol(num_str.c_str(), NULL, 16); - - // as debug, check hex_num = test_val - - // make output_char the value - UTF-8? - // TODO: actually make this work - output char must be 4 bytes, do I need a string for this? - output_char = static_cast(hex_num); - - return true; - } - - bool Lexer::parse_byte_escape(/*char& current_char, */ int& length, char& output_char) { - // skip to actual letter - skip_input(); - current_char = peek_input(); - length++; - - switch (current_char) { - case 'x': { - // hex char string (null-terminated) - char hexNum[3] = { 0, 0, 0 }; - - // first hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[0] = current_char; - - // second hex char - skip_input(); - current_char = peek_input(); - length++; - - if (!ISXDIGIT(current_char)) { - error_at(get_current_location(), "invalid character '\\x%c' in \\x sequence", - current_char); - } - hexNum[1] = current_char; - - long hexLong = ::std::strtol(hexNum, NULL, 16); - - if (hexLong > 255) - error_at(get_current_location(), - "ascii \\x escape '\\x%s' out of range - allows up to '\\xFF'", hexNum); - // gcc_assert(hexLong < 128); // as ascii - char hexChar = static_cast(hexLong); - - // TODO: fix - does this actually give the right character? - output_char = hexChar; - } break; - case 'n': - output_char = '\n'; - break; - case 'r': - output_char = '\r'; - break; - case 't': - output_char = '\t'; - break; - case '\\': - output_char = '\\'; - break; - case '0': - output_char = '\0'; - break; - default: - // error_at(get_current_location(), "unknown escape sequence '\\%c'", current_char); - // returns false if no parsing could be done - return false; - break; - } - // returns true if parsing was successful - return true; - } -#endif - - int Lexer::test_get_input_codepoint_length() { - uint8_t input = peek_input(); - - if (input < 128) { - // ascii -- 1 byte - // return input; - - return 1; - } else if ((input & 0xC0) == 0x80) { - // invalid (continuation; can't be first char) - // return 0xFFFE; - - return 0; - } else if ((input & 0xE0) == 0xC0) { - // 2 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - // uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); - // return output; - return 2; - } else if ((input & 0xF0) == 0xE0) { - // 3 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - /*uint32_t output - = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); - return output;*/ - return 3; - } else if ((input & 0xF8) == 0xF0) { - // 4 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - uint8_t input4 = peek_input(3); - if ((input4 & 0xC0) != 0x80) - return 0; - // return 0xFFFE; - - /*uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) - | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); - return output;*/ - return 4; - } else { - error_at(get_current_location(), "invalid UTF-8 (too long)"); - return 0; - } - } - - // TODO: rewrite lexing system to use utf-8 "codepoints" rather than bytes? - Codepoint Lexer::test_peek_codepoint_input() { - uint8_t input = peek_input(); - - if (input < 128) { - // ascii -- 1 byte - return { input }; - } else if ((input & 0xC0) == 0x80) { - // invalid (continuation; can't be first char) - return { 0xFFFE }; - } else if ((input & 0xE0) == 0xC0) { - // 2 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); - return { output }; - } else if ((input & 0xF0) == 0xE0) { - // 3 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t output - = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); - return { output }; - } else if ((input & 0xF8) == 0xF0) { - // 4 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint8_t input4 = peek_input(3); - if ((input4 & 0xC0) != 0x80) - return { 0xFFFE }; - - uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) - | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); - return { output }; - } else { - error_at(get_current_location(), "invalid UTF-8 (too long)"); - return { 0xFFFE }; - } - } - - void Lexer::test_skip_codepoint_input() { - int toSkip = test_get_input_codepoint_length(); - gcc_assert(toSkip >= 1); - - skip_input(toSkip - 1); - } - - int Lexer::test_get_input_codepoint_n_length(int n_start_offset) { - uint8_t input = peek_input(n_start_offset); - - if (input < 128) { - // ascii -- 1 byte - // return input; - return 1; - } else if ((input & 0xC0) == 0x80) { - // invalid (continuation; can't be first char) - // return 0xFFFE; - return 0; - } else if ((input & 0xE0) == 0xC0) { - // 2 bytes - uint8_t input2 = peek_input(n_start_offset + 1); - if ((input2 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - // uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); - // return output; - return 2; - } else if ((input & 0xF0) == 0xE0) { - // 3 bytes - uint8_t input2 = peek_input(n_start_offset + 1); - if ((input2 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - uint8_t input3 = peek_input(n_start_offset + 2); - if ((input3 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - /*uint32_t output - = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); - return output;*/ - return 3; - } else if ((input & 0xF8) == 0xF0) { - // 4 bytes - uint8_t input2 = peek_input(n_start_offset + 1); - if ((input2 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - uint8_t input3 = peek_input(n_start_offset + 2); - if ((input3 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - uint8_t input4 = peek_input(n_start_offset + 3); - if ((input4 & 0xC0) != 0x80) - // return 0xFFFE; - return 0; - - /*uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) - | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); - return output;*/ - return 4; - } else { - error_at(get_current_location(), "invalid UTF-8 (too long)"); - return 0; - } - } - - // peeks the codepoint input at n codepoints ahead of current codepoint - try not to use - Codepoint Lexer::test_peek_codepoint_input(int n) { - int totalOffset = 0; - - // add up all offsets into total offset? does this do what I want? - for (int i = 0; i < n; i++) { - totalOffset += test_get_input_codepoint_n_length(totalOffset); - } - // issues: this would have (at least) O(n) lookup time, not O(1) like the rest? - - // TODO: implement if still needed - - // error out of function as it is not implemented - gcc_assert(1 == 0); - return { 0 }; - /* - uint8_t input = peek_input(); - - if (input < 128) { - // ascii -- 1 byte - return input; - } else if ((input & 0xC0) == 0x80) { - // invalid (continuation; can't be first char) - return 0xFFFE; - } else if ((input & 0xE0) == 0xC0) { - // 2 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0xFFFE; - - uint32_t output = ((input & 0x1F) << 6) | ((input2 & 0x3F) << 0); - return output; - } else if ((input & 0xF0) == 0xE0) { - // 3 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0xFFFE; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return 0xFFFE; - - uint32_t output - = ((input & 0x0F) << 12) | ((input2 & 0x3F) << 6) | ((input3 & 0x3F) << 0); - return output; - } else if ((input & 0xF8) == 0xF0) { - // 4 bytes - uint8_t input2 = peek_input(1); - if ((input2 & 0xC0) != 0x80) - return 0xFFFE; - - uint8_t input3 = peek_input(2); - if ((input3 & 0xC0) != 0x80) - return 0xFFFE; - - uint8_t input4 = peek_input(3); - if ((input4 & 0xC0) != 0x80) - return 0xFFFE; - - uint32_t output = ((input & 0x07) << 18) | ((input2 & 0x3F) << 12) - | ((input3 & 0x3F) << 6) | ((input4 & 0x3F) << 0); - return output; - } else { - error_at(get_current_location(), "invalid UTF-8 (too long)"); - return 0xFFFE; - }*/ - } -} \ No newline at end of file diff --git a/gcc/rust/test3/lex/rust-lex.h b/gcc/rust/test3/lex/rust-lex.h deleted file mode 100644 index b16cfeb..0000000 --- a/gcc/rust/test3/lex/rust-lex.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef RUST_LEX_H -#define RUST_LEX_H - -#include "rust-buffered-queue.h" -#include "rust-token.h" - -namespace Rust { - class Lexer { - private: - // Request new location_t for current column in line_table - location_t get_current_location(); - - // Skips the current input char. - void skip_input(); - // Advances current input char to n + 1 chars ahead of current position. - void skip_input(int n); - - // Returns char n chars ahead of current position. - int peek_input(); - // Peeks the current char. - int peek_input(int n); - - // Classifies keyword (i.e. gets id for keyword). - TokenId classify_keyword(const std::string& str); - - // Builds a token from the input queue. - TokenPtr build_token(); - - // ok maybe all these may mean the lexer structure needs to be rethought - /* separated into functions because main method was too long, but they rely on and change - * state in the lexer, so variables must be passed by reference. */ - inline void parse_in_decimal(/*char& current_char, */std::string& str, int& length); - inline void parse_in_exponent_part(/*char& current_char, */std::string& str, int& length); - inline bool parse_in_type_suffix( - /*char& current_char, */PrimitiveCoreType& type_hint, int& length); - inline bool parse_ascii_escape(/*char& current_char, */int& length, char& output_char); - inline bool parse_quote_escape(/*char& current_char, */int& length, char& output_char); - inline bool parse_unicode_escape(/*char& current_char, */int& length, Codepoint& output_char); - inline bool parse_byte_escape(/*char& current_char, */int& length, char& output_char); - inline bool parse_escape(int& length, char& output_char, char opening_char); - inline bool parse_utf8_escape(int& length, Codepoint& output_char, char opening_char); - inline int test_get_input_codepoint_length(); - inline int test_get_input_codepoint_n_length(int n_start_offset); - inline Codepoint test_peek_codepoint_input(); - inline Codepoint test_peek_codepoint_input(int n); // maybe can use get_input_codepoint_length to get starting index - inline void test_skip_codepoint_input(); - - public: - // Construct lexer with input file and filename provided - Lexer(const char* filename, FILE* input); - ~Lexer(); - - // Returns token n tokens ahead of current position. - const_TokenPtr peek_token(int n); - // Peeks the current token. - const_TokenPtr peek_token(); - - // Advances current token to n + 1 tokens ahead of current position. - void skip_token(int n); - // Skips the current token. - void skip_token(); - - // Replaces the current token with a specified token. - void replace_current_token(TokenPtr replacement); - - private: - // File for use as input. - FILE* input; - - // Current line number. - int current_line; - // Current column number. - int current_column; - // Line map. - const struct line_map* line_map; - - // Max column number that can be quickly allocated - higher may require allocating new linemap - static const int max_column_hint = 80; - - // Input source wrapper thing. - struct InputSource { - // Input source file. - FILE* input; - - // Create new input source from file. - InputSource(FILE* input) : input(input) {} - - // Overload operator () to return next char from input stream. - int operator()() { - return fgetc(input); - } - }; - - // The input source for the lexer. - InputSource input_source; - // Input file queue. - buffered_queue input_queue; - - // Token source wrapper thing. - struct TokenSource { - // The lexer object that will use this TokenSource. - Lexer* lexer; - - // Create a new TokenSource with given lexer. - TokenSource(Lexer* parLexer) : lexer(parLexer) {} - - // Overload operator () to build token in lexer. - TokenPtr operator()() { - return lexer->build_token(); - } - }; - - // The token source for the lexer. - TokenSource token_source; - // Token stream queue. - buffered_queue, TokenSource> token_queue; - - // START CRAPPY CHANGES - int current_char; - - // END CRAPPY CHANGES - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/lex/rust-token.cc b/gcc/rust/test3/lex/rust-token.cc deleted file mode 100644 index 47bf750..0000000 --- a/gcc/rust/test3/lex/rust-token.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include "rust-token.h" - -#include "diagnostic.h" // for error_at - -namespace Rust { - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id) { - switch (id) { -#define RS_TOKEN(name, descr) \ - case name: \ - return descr; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - default: - gcc_unreachable(); - } - } - - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id) { - switch (id) { -#define RS_TOKEN(name, _) \ - case name: \ - return #name; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - default: - gcc_unreachable(); - } - } - - const char* get_type_hint_string(PrimitiveCoreType type) { - switch (type) { - case CORETYPE_BOOL: - return "bool"; - case CORETYPE_CHAR: - return "char"; - case CORETYPE_STR: - return "str"; - // case CORETYPE_INT: - case CORETYPE_ISIZE: - return "isize"; - // case CORETYPE_UINT: - case CORETYPE_USIZE: - return "usize"; - case CORETYPE_F32: - return "f32"; - case CORETYPE_F64: - return "f64"; - case CORETYPE_I8: - return "i8"; - case CORETYPE_I16: - return "i16"; - case CORETYPE_I32: - return "i32"; - case CORETYPE_I64: - return "i64"; - case CORETYPE_I128: - return "i128"; - case CORETYPE_U8: - return "u8"; - case CORETYPE_U16: - return "u16"; - case CORETYPE_U32: - return "u32"; - case CORETYPE_U64: - return "u64"; - case CORETYPE_U128: - return "u128"; - case CORETYPE_UNKNOWN: - default: - return "unknown"; - } - } - - const char* Token::get_type_hint_str() const { - return get_type_hint_string(type_hint); - } - - const ::std::string& Token::get_str() const { - // FIXME: attempt to return null again - // gcc_assert(str != NULL); - - // HACK: allow referencing an empty string - static const ::std::string empty = ""; - - if (str == NULL) { - error_at(get_locus(), - "attempted to get string for '%s', which has no string. returning empty string " - "instead.", - get_token_description()); - return empty; - } - return *str; - } -} \ No newline at end of file diff --git a/gcc/rust/test3/lex/rust-token.h b/gcc/rust/test3/lex/rust-token.h deleted file mode 100644 index bf65ed3..0000000 --- a/gcc/rust/test3/lex/rust-token.h +++ /dev/null @@ -1,385 +0,0 @@ -#ifndef RUST_TOKEN_H -#define RUST_TOKEN_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "input.h" -// order: config, system, coretypes, input - -#include -//#include // as shared_ptr is not available in std memory in c++03 -// replace with proper std::memory in c++11 -#include - -#include "rust-codepoint.h" - -namespace Rust { - // "Primitive core types" in Rust - the different int and float types, as well as some others - enum PrimitiveCoreType { - CORETYPE_UNKNOWN, - // named primitives - CORETYPE_BOOL, - CORETYPE_CHAR, - CORETYPE_STR, - // okay technically int and uint are arch-dependent (pointer size) - CORETYPE_INT, - CORETYPE_UINT, - // numbered number primitives - CORETYPE_F32, - CORETYPE_F64, - CORETYPE_I8, - CORETYPE_I16, - CORETYPE_I32, - CORETYPE_I64, - CORETYPE_I128, - CORETYPE_U8, - CORETYPE_U16, - CORETYPE_U32, - CORETYPE_U64, - CORETYPE_U128, - // arch-dependent pointer sizes - CORETYPE_ISIZE = CORETYPE_INT, - CORETYPE_USIZE = CORETYPE_UINT - }; - -// RS_TOKEN(name, description) -// RS_TOKEN_KEYWORD(name, identifier) -// -// Keep RS_TOKEN_KEYWORD sorted - -// note that abstract, async, become, box, do, final, macro, override, priv, try, typeof, unsized, -// virtual, and yield are unused -// TODO finish converting to rust keywords -#define RS_TOKEN_LIST \ - RS_TOKEN(FIRST_TOKEN, "") \ - RS_TOKEN(END_OF_FILE, "end of file") \ - RS_TOKEN(EXCLAM, "!") \ - RS_TOKEN(NOT_EQUAL, "!=") \ - RS_TOKEN(PERCENT, "%") \ - RS_TOKEN(PERCENT_EQ, "%=") \ - RS_TOKEN(AMP, "&") \ - RS_TOKEN(AMP_EQ, "&=") \ - RS_TOKEN(LOGICAL_AND, "&&") \ - RS_TOKEN(ASTERISK, "*") \ - RS_TOKEN(ASTERISK_EQ, "*=") \ - RS_TOKEN(PLUS, "+") \ - RS_TOKEN(PLUS_EQ, "+=") \ - RS_TOKEN(COMMA, ",") \ - RS_TOKEN(MINUS, "-") \ - RS_TOKEN(MINUS_EQ, "-=") \ - RS_TOKEN(RETURN_TYPE, "->") \ - RS_TOKEN(DOT, ".") \ - RS_TOKEN(DOT_DOT, "..") \ - RS_TOKEN(DOT_DOT_EQ, "..=") \ - RS_TOKEN(ELLIPSIS, "...") \ - RS_TOKEN(DIV, "/") \ - RS_TOKEN(DIV_EQ, "/=") \ - RS_TOKEN(COLON, ":") \ - RS_TOKEN(SEMICOLON, ";") \ - RS_TOKEN(LEFT_SHIFT, "<<") \ - RS_TOKEN(LEFT_SHIFT_EQ, "<<=") \ - RS_TOKEN(LEFT_ANGLE, "<") \ - RS_TOKEN(LESS_OR_EQUAL, "<=") \ - RS_TOKEN(EQUAL, "=") \ - RS_TOKEN(EQUAL_EQUAL, "==") \ - RS_TOKEN(MATCH_ARROW, "=>") \ - RS_TOKEN(RIGHT_ANGLE, ">") \ - RS_TOKEN(GREATER_OR_EQUAL, ">=") \ - RS_TOKEN(RIGHT_SHIFT, ">>") \ - RS_TOKEN(RIGHT_SHIFT_EQ, ">>=") \ - RS_TOKEN(PATTERN_BIND, "@") \ - RS_TOKEN(TILDE, "~") \ - RS_TOKEN(BACKSLASH, "\\") \ - RS_TOKEN(BACKTICK, "`") \ - RS_TOKEN(CARET, "^") \ - RS_TOKEN(CARET_EQ, "^=") \ - RS_TOKEN(PIPE, "|") \ - RS_TOKEN(PIPE_EQ, "|=") \ - RS_TOKEN(OR, "||") \ - RS_TOKEN(QUESTION_MARK, "?") \ - RS_TOKEN(HASH, "#") \ - /* from here on, dodgy and may not be correct. not operators and may be symbols */ \ - /* RS_TOKEN(SPACE, " ") probably too dodgy */ \ - /* RS_TOKEN(NEWLINE, "\n")*/ \ - RS_TOKEN(SCOPE_RESOLUTION, "::") /* dodgy */ \ - RS_TOKEN(SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ \ - RS_TOKEN(DOUBLE_QUOTE, "\"") \ - RS_TOKEN(UNDERSCORE, "_") /* TODO: treat as reserved word like mrustc instead? */ \ - RS_TOKEN(IDENTIFIER, "identifier") \ - RS_TOKEN(INT_LITERAL, \ - "integer literal") /* do different int and float types need different literal types? */ \ - RS_TOKEN(FLOAT_LITERAL, "float literal") \ - RS_TOKEN(STRING_LITERAL, "string literal") \ - RS_TOKEN(CHAR_LITERAL, "character literal") \ - RS_TOKEN(BYTE_STRING_LITERAL, "byte string literal") \ - RS_TOKEN(BYTE_CHAR_LITERAL, "byte character literal") \ - RS_TOKEN(LIFETIME, "lifetime") /* TODO: improve token type */ \ - /* Have "interpolated" tokens (whatever that means)? identifer, path, type, pattern, */ \ - /* expression, statement, block, meta, item in mrustc (but not directly in lexer). */ \ - RS_TOKEN(LEFT_PAREN, "(") \ - RS_TOKEN(RIGHT_PAREN, ")") \ - RS_TOKEN(LEFT_CURLY, "{") \ - RS_TOKEN(RIGHT_CURLY, "}") \ - RS_TOKEN(LEFT_SQUARE, "[") \ - RS_TOKEN(RIGHT_SQUARE, "]") \ - /* Macros */ \ - RS_TOKEN(DOLLAR_SIGN, "$") \ - /* Comments */ \ - RS_TOKEN(LINE_COMMENT, "//") \ - RS_TOKEN(INNER_LINE_DOC, "//!") \ - RS_TOKEN(OUTER_LINE_DOC, "///") \ - RS_TOKEN(BLOCK_COMMENT_START, "/*") \ - RS_TOKEN(BLOCK_COMMENT_END, "*/") \ - RS_TOKEN(INNER_BLOCK_DOC_START, "/*!") \ - RS_TOKEN(OUTER_BLOCK_DOC_START, "/**") /* have "weak" union and 'static keywords? */ \ - \ - RS_TOKEN_KEYWORD(ABSTRACT, "abstract") /* unused */ \ - RS_TOKEN_KEYWORD(AS, "as") \ - RS_TOKEN_KEYWORD(ASYNC, "async") /* unused */ \ - RS_TOKEN_KEYWORD(BECOME, "become") /* unused */ \ - RS_TOKEN_KEYWORD(BOX, "box") /* unused */ \ - RS_TOKEN_KEYWORD(BREAK, "break") \ - RS_TOKEN_KEYWORD(CONST, "const") \ - RS_TOKEN_KEYWORD(CONTINUE, "continue") \ - RS_TOKEN_KEYWORD(CRATE, "crate") \ - RS_TOKEN_KEYWORD(DO, "do") /* unused */ \ - RS_TOKEN_KEYWORD(DYN, "dyn") \ - RS_TOKEN_KEYWORD(ELSE, "else") \ - RS_TOKEN_KEYWORD(ENUM_TOK, "enum") \ - RS_TOKEN_KEYWORD(EXTERN_TOK, "extern") \ - RS_TOKEN_KEYWORD(FALSE_LITERAL, "false") \ - RS_TOKEN_KEYWORD(FINAL_TOK, "final") /* unused */ \ - RS_TOKEN_KEYWORD(FN_TOK, "fn") \ - RS_TOKEN_KEYWORD(FOR, "for") \ - RS_TOKEN_KEYWORD(IF, "if") \ - RS_TOKEN_KEYWORD(IMPL, "impl") \ - RS_TOKEN_KEYWORD(IN, "in") \ - RS_TOKEN_KEYWORD(LET, "let") \ - RS_TOKEN_KEYWORD(LOOP, "loop") \ - RS_TOKEN_KEYWORD(MACRO, "macro") /* unused */ \ - RS_TOKEN_KEYWORD(MATCH_TOK, "match") \ - RS_TOKEN_KEYWORD(MOD, "mod") \ - RS_TOKEN_KEYWORD(MOVE, "move") \ - RS_TOKEN_KEYWORD(MUT, "mut") \ - RS_TOKEN_KEYWORD(OVERRIDE_TOK, "override") /* unused */ \ - RS_TOKEN_KEYWORD(PRIV, "priv") /* unused */ \ - RS_TOKEN_KEYWORD(PUB, "pub") \ - RS_TOKEN_KEYWORD(REF, "ref") \ - RS_TOKEN_KEYWORD(RETURN_TOK, "return") \ - RS_TOKEN_KEYWORD(SELF_ALIAS, "Self") /* mrustc does not treat this as a reserved word*/ \ - RS_TOKEN_KEYWORD(SELF, "self") \ - RS_TOKEN_KEYWORD(STATIC_TOK, "static") \ - RS_TOKEN_KEYWORD(STRUCT_TOK, "struct") \ - RS_TOKEN_KEYWORD(SUPER, "super") \ - RS_TOKEN_KEYWORD(TRAIT, "trait") \ - RS_TOKEN_KEYWORD(TRUE_LITERAL, "true") \ - RS_TOKEN_KEYWORD(TRY, "try") /* unused */ \ - RS_TOKEN_KEYWORD(TYPE, "type") \ - RS_TOKEN_KEYWORD(TYPEOF, "typeof") /* unused */ \ - RS_TOKEN_KEYWORD(UNSAFE, "unsafe") \ - RS_TOKEN_KEYWORD(UNSIZED, "unsized") /* unused */ \ - RS_TOKEN_KEYWORD(USE, "use") \ - RS_TOKEN_KEYWORD(VIRTUAL, "virtual") /* unused */ \ - RS_TOKEN_KEYWORD(WHERE, "where") \ - RS_TOKEN_KEYWORD(WHILE, "while") \ - RS_TOKEN_KEYWORD(YIELD, "yield") /* unused */ \ - \ - RS_TOKEN(LAST_TOKEN, "") - - // Contains all token types. Crappy implementation via x-macros. - enum TokenId { -#define RS_TOKEN(name, _) name, -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD -#undef RS_TOKEN - }; - - // dodgy "TokenPtr" declaration with Token forward declaration - class Token; - // A smart pointer (shared_ptr) to Token. - typedef ::std::shared_ptr TokenPtr; - // A smart pointer (shared_ptr) to a constant Token. - typedef ::std::shared_ptr const_TokenPtr; - - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id); - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id); - // Get type hint description as a string. - const char* get_type_hint_string(PrimitiveCoreType type); - - // Represents a single token. Create using factory static methods. - class Token { - private: - // Token kind. - TokenId token_id; - // Token location. - location_t locus; - // Associated text (if any) of token. - ::std::string* str; - // Type hint for token based on lexer data (e.g. type suffix). Does not exist for most tokens. - PrimitiveCoreType type_hint; - - // Token constructor from token id and location. Has a null string. - Token(TokenId token_id, location_t location) : - token_id(token_id), locus(location), str(NULL), type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a string. - Token(TokenId token_id, location_t location, const ::std::string& paramStr) : - token_id(token_id), locus(location), str(new ::std::string(paramStr)), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a char. - Token(TokenId token_id, location_t location, char paramChar) : - token_id(token_id), locus(location), str(new ::std::string(1, paramChar)), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a "codepoint". - Token(TokenId token_id, location_t location, Codepoint paramCodepoint) : - token_id(token_id), locus(location), str(new ::std::string(paramCodepoint.as_string())), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, a string, and type hint. - Token(TokenId token_id, location_t location, const ::std::string& paramStr, - PrimitiveCoreType parType) : - token_id(token_id), - locus(location), str(new ::std::string(paramStr)), type_hint(parType) {} - - // No default initialiser. - Token(); - // Do not copy/assign tokens. - Token(const Token&); - Token& operator=(const Token&); - - public: - ~Token() { - delete str; - } - - // Makes and returns a new TokenPtr (with null string). - static TokenPtr make(TokenId token_id, location_t locus) { - return TokenPtr(new Token(token_id, locus)); - } - - // Makes and returns a new TokenPtr of type IDENTIFIER. - static TokenPtr make_identifier(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(IDENTIFIER, locus, str)); - } - - // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(INT_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int( - location_t locus, const ::std::string& str, PrimitiveCoreType type_hint) { - return TokenPtr(new Token(INT_LITERAL, locus, str, type_hint)); - } - - // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(FLOAT_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float( - location_t locus, const ::std::string& str, PrimitiveCoreType type_hint) { - return TokenPtr(new Token(FLOAT_LITERAL, locus, str, type_hint)); - } - - // Makes and returns a new TokenPtr of type STRING_LITERAL. - static TokenPtr make_string(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(STRING_LITERAL, locus, str, CORETYPE_STR)); - } - - // Makes and returns a new TokenPtr of type CHAR_LITERAL (fix). - static TokenPtr make_char(location_t locus, Codepoint char_lit) { - return TokenPtr(new Token(CHAR_LITERAL, locus, char_lit)); - } - - // Makes and returns a new TokenPtr of type BYTE_CHAR_LITERAL (fix). - static TokenPtr make_byte_char(location_t locus, char byte_char) { - return TokenPtr(new Token(BYTE_CHAR_LITERAL, locus, byte_char)); - } - - // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). - static TokenPtr make_byte_string(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(BYTE_STRING_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type LIFETIME. - static TokenPtr make_lifetime(location_t locus, const ::std::string& str) { - return TokenPtr(new Token(LIFETIME, locus, str)); - } - - // Gets id of the token. - TokenId get_id() const { - return token_id; - } - - // Gets location of the token. - location_t get_locus() const { - return locus; - } - - // Gets string description of the token. - const ::std::string& get_str() const; /*{ - // FIXME: put in header again when fix null problem - //gcc_assert(str != NULL); - if (str == NULL) { - error_at(get_locus(), "attempted to get string for '%s', which has no string. returning empty string instead.", get_token_description()); - return ""; - } - return *str; - }*/ - - // Gets token's type hint info. - PrimitiveCoreType get_type_hint() const { - return type_hint; - } - - // diagnostics (error reporting) - const char* get_token_description() const { - return Rust::get_token_description(token_id); - } - - // debugging - const char* token_id_to_str() const { - return Rust::token_id_to_str(token_id); - } - - // debugging - const char* get_type_hint_str() const; - - /* Returns whether the token is a literal of any type (int, float, char, string, byte char, - * byte string). */ - inline bool is_literal() const { - switch (token_id) { - case INT_LITERAL: - case FLOAT_LITERAL: - case CHAR_LITERAL: - case STRING_LITERAL: - case BYTE_CHAR_LITERAL: - case BYTE_STRING_LITERAL: - return true; - default: - return false; - } - } - - // Returns whether the token actually has a string (regardless of whether it should or not). - inline bool has_str() const { - return str != NULL; - } - - // Returns whether the token should have a string. - inline bool should_have_str() const { - return is_literal() || token_id == IDENTIFIER || token_id == LIFETIME; - } - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-misc-convert.cc b/gcc/rust/test3/parse/rust-misc-convert.cc deleted file mode 100644 index 68dbc59..0000000 --- a/gcc/rust/test3/parse/rust-misc-convert.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -#include "fold-const.h" -#include "convert.h" -// order: config, system, coretypes, tree, fold-const, convert - -// Required by some GENERIC routines. Converts expression of value expr to type type. -tree convert(tree type, tree expr) { - if (type == error_mark_node || expr == error_mark_node || TREE_TYPE(expr) == error_mark_node) - return error_mark_node; - - if (type == TREE_TYPE(expr)) - return expr; - - if (TYPE_MAIN_VARIANT(type) == TYPE_MAIN_VARIANT(TREE_TYPE(expr))) - return fold_convert(type, expr); - - switch (TREE_CODE(type)) { - case VOID_TYPE: - case BOOLEAN_TYPE: - return fold_convert(type, expr); - case INTEGER_TYPE: - return fold(convert_to_integer(type, expr)); - case POINTER_TYPE: - return fold(convert_to_pointer(type, expr)); - case REAL_TYPE: - return fold(convert_to_real(type, expr)); - case COMPLEX_TYPE: - return fold(convert_to_complex(type, expr)); - default: - break; - } - - gcc_unreachable(); -} \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-parse-includes.h b/gcc/rust/test3/parse/rust-parse-includes.h deleted file mode 100644 index ad7b920..0000000 --- a/gcc/rust/test3/parse/rust-parse-includes.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RUST_PARSE_INCLUDES_H -#define RUST_PARSE_INCLUDES_H -/* basically, this is just to stop gcc includes in rust-parse.cc from getting out of order due to - * formatter, which I can not figure out how to modify to not do this. */ -// HACK: remove for final or near-final compiler where I don't have to use auto formatter anymore - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "tree-iterator.h" -#include "input.h" -#include "diagnostic.h" -#include "stringpool.h" -#include "cgraph.h" -#include "gimplify.h" -#include "gimple-expr.h" -#include "convert.h" -#include "print-tree.h" -#include "stor-layout.h" -#include "fold-const.h" -/* order: config, system, coretypes, target, tree, tree-iterator, input, diagnostic, stringpool, - * cgraph, gimplify, gimple-expr, convert, print-tree, stor-layout, fold-const */ -// probably don't need all these - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-parse.cc b/gcc/rust/test3/parse/rust-parse.cc deleted file mode 100644 index 1eac8a1..0000000 --- a/gcc/rust/test3/parse/rust-parse.cc +++ /dev/null @@ -1,13001 +0,0 @@ -#include "rust-parse.h" - -// instead of gcc includes specified here. Thanks clang-format. -#include "rust-parse-includes.h" - -#include // for std::find - -namespace Rust { - // Left binding powers of operations. - enum binding_powers { - // Highest priority - LBP_HIGHEST = 100, - - LBP_PATH = 95, - - LBP_METHOD_CALL = 90, - - LBP_FIELD_EXPR = 85, - - // LBP_DOT = 80, /* method call and field expr have different precedence now */ - - LBP_FUNCTION_CALL = 80, - LBP_ARRAY_REF = LBP_FUNCTION_CALL, - - LBP_QUESTION_MARK = 75, // unary postfix - counts as left - - LBP_UNARY_PLUS = 70, // Used only when the null denotation is + - LBP_UNARY_MINUS = LBP_UNARY_PLUS, // Used only when the null denotation is - - LBP_UNARY_ASTERISK = LBP_UNARY_PLUS, // deref operator - unary prefix - LBP_UNARY_EXCLAM = LBP_UNARY_PLUS, - LBP_UNARY_AMP = LBP_UNARY_PLUS, - LBP_UNARY_AMP_MUT = LBP_UNARY_PLUS, - - LBP_AS = 65, - - LBP_MUL = 60, - LBP_DIV = LBP_MUL, - LBP_MOD = LBP_MUL, - - LBP_PLUS = 55, - LBP_MINUS = LBP_PLUS, - - LBP_L_SHIFT = 50, - LBP_R_SHIFT = LBP_L_SHIFT, - - LBP_AMP = 45, - - LBP_CARET = 40, - - LBP_PIPE = 35, - - LBP_EQUAL = 30, - LBP_NOT_EQUAL = LBP_EQUAL, - LBP_SMALLER_THAN = LBP_EQUAL, - LBP_SMALLER_EQUAL = LBP_EQUAL, - LBP_GREATER_THAN = LBP_EQUAL, - LBP_GREATER_EQUAL = LBP_EQUAL, - - LBP_LOGICAL_AND = 25, - - LBP_LOGICAL_OR = 20, - - LBP_DOT_DOT = 15, - LBP_DOT_DOT_EQ = LBP_DOT_DOT, - - // TODO: note all these assig operators are RIGHT associative! - LBP_ASSIG = 10, - LBP_PLUS_ASSIG = LBP_ASSIG, - LBP_MINUS_ASSIG = LBP_ASSIG, - LBP_MULT_ASSIG = LBP_ASSIG, - LBP_DIV_ASSIG = LBP_ASSIG, - LBP_MOD_ASSIG = LBP_ASSIG, - LBP_AMP_ASSIG = LBP_ASSIG, - LBP_PIPE_ASSIG = LBP_ASSIG, - LBP_CARET_ASSIG = LBP_ASSIG, - LBP_L_SHIFT_ASSIG = LBP_ASSIG, - LBP_R_SHIFT_ASSIG = LBP_ASSIG, - - // return, break, and closures as lowest priority? - LBP_RETURN = 5, - LBP_BREAK = LBP_RETURN, - LBP_CLOSURE = LBP_RETURN, // unary prefix operators - -#if 0 - // rust precedences - PREC_CLOSURE = -40, // used for closures - PREC_JUMP = -30, // used for break, continue, return, and yield - PREC_RANGE = -10, // used for range (although weird comment in rustc about this) - PREC_BINOP = FROM_ASSOC_OP, - // used for binary operators mentioned below - also cast, colon (type), assign, assign_op - PREC_PREFIX = 50, // used for box, address_of, let, unary (again, weird comment on let) - PREC_POSTFIX = 60, // used for await, call, method call, field, index, try, inline asm, macro invocation - PREC_PAREN = 99, // used for array, repeat, tuple, literal, path, paren, if, while, for, 'loop', match, block, try block, async, struct - PREC_FORCE_PAREN = 100, -#endif - - // lowest priority - LBP_LOWEST = 0 - }; - - // Checks if Tree has a string type (tree code pointer_type and tree variant char node). - bool is_string_type(Tree type) { - // assert node represents a type - gcc_assert(TYPE_P(type.get_tree())); - - // ensure main variant of pointee is char_type_node (i.e. type is char*) - return type.get_tree_code() == POINTER_TYPE - && TYPE_MAIN_VARIANT(TREE_TYPE(type.get_tree())) == char_type_node; - } - - // Checks if Tree has array type. - bool is_array_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - return type.get_tree_code() == ARRAY_TYPE; - } - - // Checks if Tree has record type. - bool is_record_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - return type.get_tree_code() == RECORD_TYPE; - } - - // Returns whether the token can start a type (i.e. there is a valid type beginning with the - // token). - bool can_tok_start_type(TokenId id) { - switch (id) { - case EXCLAM: - case LEFT_SQUARE: - case LEFT_ANGLE: - case UNDERSCORE: - case ASTERISK: - case AMP: - case LIFETIME: - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case DOLLAR_SIGN: - case SCOPE_RESOLUTION: - case LEFT_PAREN: - case FOR: - case ASYNC: - case CONST: - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - case IMPL: - case DYN: - case QUESTION_MARK: - return true; - default: - return false; - } - } - - /* Returns whether the token id is (or is likely to be) a right angle bracket. i.e. '>', '>>', - * '>=' and '>>=' tokens. */ - bool is_right_angle_tok(TokenId id) { - switch (id) { - case RIGHT_ANGLE: - case RIGHT_SHIFT: - case GREATER_OR_EQUAL: - case RIGHT_SHIFT_EQ: - return true; - default: - return false; - } - } - - // HACK-y special handling for skipping a right angle token at the end of generic arguments. - bool Parser::skip_generics_right_angle() { - // HACK: special handling for right shift '>>', greater or equal '>=', and right shift assig - // '>>=' - const_TokenPtr tok = lexer.peek_token(); - switch (tok->get_id()) { - case RIGHT_ANGLE: - // this is good - skip token - lexer.skip_token(); - return true; - case RIGHT_SHIFT: { - /* shit. preferred HACK would be to replace this token in stream with '>', but may not - * be possible at this point. */ - // FIXME: ensure locations aren't messed up - TokenPtr right_angle = Token::make(RIGHT_ANGLE, tok->get_locus() + 1); - lexer.replace_current_token(right_angle); - return true; - } - case GREATER_OR_EQUAL: { - // another HACK - replace with equal (as assignment intended, probably) - /* FIXME: is this even required? how many people wouldn't leave a space? - apparently - * rustc has this feature */ - // FIXME: ensure locations aren't messed up - TokenPtr equal = Token::make(EQUAL, tok->get_locus() + 1); - lexer.replace_current_token(equal); - return true; - } - case RIGHT_SHIFT_EQ: { - // another HACK - replace with greater or equal - // FIXME: again, is this really required? rustc has the feature, though - // FIXME: ensure locations aren't messed up - TokenPtr greater_equal = Token::make(GREATER_OR_EQUAL, tok->get_locus() + 1); - lexer.replace_current_token(greater_equal); - return true; - } - default: - error_at(tok->get_locus(), "expected '>' at end of generic argument - found '%s'", - tok->get_token_description()); - return false; - } - } - - /* Gets left binding power for specified token. - * Not suitable for use at the moment or possibly ever because binding power cannot be purely - * determined from operator token with Rust grammar - e.g. method call and field access have - * different left binding powers but the same operator token. */ - int Parser::left_binding_power(const_TokenPtr token) { - // HACK: called with "peek_token()", so lookahead is "peek_token(1)" - switch (token->get_id()) { - /* TODO: issue here - distinguish between method calls and field access somehow? - Also would have to distinguish between paths and function calls (:: operator), - maybe more stuff. */ - /* Current plan for tackling LBP - don't do it based on token, use lookahead. - * Or alternatively, only use Pratt parsing for OperatorExpr and handle other - * expressions without it. rustc only considers arithmetic, logical/relational, 'as', - * '?=', ranges, colons, and assignment to have operator precedence and associativity - * rules applicable. It then has - * a separate "ExprPrecedence" that also includes binary operators. */ - - // TODO: handle operator overloading - have a function replace the operator? - - /*case DOT: - return LBP_DOT;*/ - - case SCOPE_RESOLUTION: - fprintf(stderr, "possible error - looked up LBP of scope resolution operator. should " - "be handled elsewhere. \n"); - return LBP_PATH; - - /* Resolved by lookahead HACK that should work with current code. If next token is - * identifier and token after that isn't parenthesised expression list, it is a field - * reference. */ - case DOT: - if (lexer.peek_token(1)->get_id() == IDENTIFIER - && lexer.peek_token(2)->get_id() != LEFT_PAREN) { - return LBP_FIELD_EXPR; - } - return LBP_METHOD_CALL; - - case LEFT_PAREN: - return LBP_FUNCTION_CALL; - - case LEFT_SQUARE: - return LBP_ARRAY_REF; - - // postfix question mark (i.e. error propagation expression) - case QUESTION_MARK: - return LBP_QUESTION_MARK; - - case AS: - return LBP_AS; - - case ASTERISK: - return LBP_MUL; - case DIV: - return LBP_DIV; - case PERCENT: - return LBP_MOD; - - case PLUS: - return LBP_PLUS; - case MINUS: - return LBP_MINUS; - - case LEFT_SHIFT: - return LBP_L_SHIFT; - case RIGHT_SHIFT: - return LBP_R_SHIFT; - - // binary & operator - case AMP: - return LBP_AMP; - - // binary ^ operator - case CARET: - return LBP_CARET; - - // binary | operator - case PIPE: - return LBP_PIPE; - - case EQUAL_EQUAL: - return LBP_EQUAL; - case NOT_EQUAL: - return LBP_NOT_EQUAL; - case RIGHT_ANGLE: - return LBP_GREATER_THAN; - case GREATER_OR_EQUAL: - return LBP_GREATER_EQUAL; - case LEFT_ANGLE: - return LBP_SMALLER_THAN; - case LESS_OR_EQUAL: - return LBP_SMALLER_EQUAL; - - case LOGICAL_AND: - return LBP_LOGICAL_AND; - - case OR: - return LBP_LOGICAL_OR; - - case DOT_DOT: - return LBP_DOT_DOT; - - case DOT_DOT_EQ: - return LBP_DOT_DOT_EQ; - - case EQUAL: - return LBP_ASSIG; - case PLUS_EQ: - return LBP_PLUS_ASSIG; - case MINUS_EQ: - return LBP_MINUS_ASSIG; - case ASTERISK_EQ: - return LBP_MULT_ASSIG; - case DIV_EQ: - return LBP_DIV_ASSIG; - case PERCENT_EQ: - return LBP_MOD_ASSIG; - case AMP_EQ: - return LBP_AMP_ASSIG; - case CARET_EQ: - return LBP_CARET_ASSIG; - case LEFT_SHIFT_EQ: - return LBP_L_SHIFT_ASSIG; - case RIGHT_SHIFT_EQ: - return LBP_R_SHIFT_ASSIG; - - // HACK: float literal due to lexer misidentifying a dot then an integer as a float - case FLOAT_LITERAL: - return LBP_FIELD_EXPR; - // field expr is same as tuple expr in precedence, i imagine - - // anything that can't appear in an infix position is given lowest priority - default: - return LBP_LOWEST; - } - } - - TreeStmtList& Parser::get_current_stmt_list() { - return stack_stmt_list.back(); - } - - // Parse statements until done (EOF) and append to current stmt list. - void Parser::parse_statement_seq(bool (Parser::*done)()) { - // Parse statements until done and append to the current stmt list - /*while (!(this->*done)()) { - // get stmt tree for parsed statement - Tree stmt = parse_statement(); - // append each stmt tree to current stmt list - get_current_stmt_list().append(stmt); - }*/ - } - - // Parse "items" until done (EOF) and append to current something list. Seems to be method taken - // rather than statements in rust. - /*void Parser::parse_item_seq(bool (Parser::*done)()) { - // Parse statements until done and append to the current stmt list - // TODO: fix - while (!(this->*done)()) { - // get stmt tree for parsed statement - Tree item = parse_item(); - // append each stmt tree to current stmt list - get_current_stmt_list().append(stmt); - } - }*/ - - // Returns true when current token is EOF. - bool Parser::done_end_of_file() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == END_OF_FILE); - } - - // Entry point - parse entire program (in file) from here. - void Parser::parse_program() { - // should be only able to parse decls at this point (scope)? - - // TODO: convert to a crate-based approach? parse_crate()? - parse_crate(); - - // TODO: structural changes - strongly-typed AST instead of Trees? - - // TODO: how much of this is fake main function vs actually required for any function? - // Built type of main "int (int, char**)" - tree main_fndecl_type_param[] - = { integer_type_node, build_pointer_type(build_pointer_type(char_type_node)) }; - tree main_fndecl_type - = build_function_type_array(integer_type_node, 2, main_fndecl_type_param); - // Create function declaration "int main(int, char**)" - main_fndecl = build_fn_decl("main", main_fndecl_type); - - // Enter top-level scope. - enter_scope(); - // program -> statement* - parse_statement_seq(&Parser::done_end_of_file); - // Append "return 0;" - tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); - // create decl_context of resdecl for main function (local variable of main function) - DECL_CONTEXT(resdecl) = main_fndecl; - DECL_RESULT(main_fndecl) = resdecl; - tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), - build_int_cst_type(integer_type_node, 0)); - tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); - - get_current_stmt_list().append(return_stmt); - - // Leave top-level scope, get its binding expression and its main block - TreeSymbolMapping main_tree_scope = leave_scope(); - Tree main_block = main_tree_scope.block; - - // Finish/finalise main function - BLOCK_SUPERCONTEXT(main_block.get_tree()) = main_fndecl; - DECL_INITIAL(main_fndecl) = main_block.get_tree(); - DECL_SAVED_TREE(main_fndecl) = main_tree_scope.bind_expr.get_tree(); - - // Main function is not external - DECL_EXTERNAL(main_fndecl) = 0; - // Preserve main function - DECL_PRESERVE_P(main_fndecl) = 1; - - // Convert from GENERIC to GIMPLE - gimplify_function_tree(main_fndecl); - - // Insert it into the graph (queue for compilation?) - cgraph_node::finalize_function(main_fndecl, true); - - main_fndecl = NULL_TREE; - } - - // Parses a crate (compilation unit) - entry point - AST::Crate Parser::parse_crate() { - /* TODO: determine if has utf8bom and shebang. Currently, they are eliminated by the lexing - * phase. - * Neither are useful for the compiler anyway, so maybe a better idea would be to eliminate - * the has_utf8bom and has_shebang variables from the crate data structure. */ - bool has_utf8bom = false; - bool has_shebang = false; - - // parse inner attributes - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse items - ::std::vector< ::std::unique_ptr > items; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != END_OF_FILE) { - ::std::unique_ptr item = parse_item(false); - if (item == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse item in crate"); - items = ::std::vector< ::std::unique_ptr >(); - break; - } - - items.push_back(::std::move(item)); - - t = lexer.peek_token(); - } - - return AST::Crate(::std::move(items), ::std::move(inner_attrs), has_utf8bom, has_shebang); - } - - // Parse a contiguous block of inner attributes. - ::std::vector Parser::parse_inner_attributes() { - ::std::vector inner_attributes; - - while (lexer.peek_token()->get_id() == HASH) { - AST::Attribute inner_attr = parse_inner_attribute(); - - // Ensure only valid inner attributes are added to the inner_attributes list - if (!inner_attr.is_empty()) { - inner_attributes.push_back(::std::move(inner_attr)); - } else { - /* If no more valid inner attributes, break out of loop (only contiguous inner - * attributes parsed). */ - break; - } - } - - return inner_attributes; - } - - // Parse a single inner attribute. - AST::Attribute Parser::parse_inner_attribute() { - if (lexer.peek_token()->get_id() != HASH) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - if (lexer.peek_token()->get_id() != EXCLAM) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - if (lexer.peek_token()->get_id() != LEFT_SQUARE) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - AST::Attribute actual_attribute = parse_attribute_body(); - - if (lexer.peek_token()->get_id() != RIGHT_SQUARE) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - return actual_attribute; - } - - // Parses the body of an attribute (inner or outer). - AST::Attribute Parser::parse_attribute_body() { - location_t locus = lexer.peek_token()->get_locus(); - - AST::SimplePath attr_path = parse_simple_path(); - // ensure path is valid to parse attribute input - if (attr_path.is_empty()) { - error_at(lexer.peek_token()->get_locus(), "empty simple path in attribute"); - - // Skip past potential further info in attribute (i.e. attr_input) - skip_after_end_attribute(); - return AST::Attribute::create_empty(); - } - - ::std::unique_ptr attr_input = parse_attr_input(); - // AttrInput is allowed to be null, so no checks here - - return AST::Attribute(::std::move(attr_path), ::std::move(attr_input), locus); - } - - // Parses a SimplePath AST node - AST::SimplePath Parser::parse_simple_path() { - bool has_opening_scope_resolution = false; - location_t locus = UNKNOWN_LOCATION; - - // Checks for opening scope resolution (i.e. global scope fully-qualified path) - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { - has_opening_scope_resolution = true; - - locus = lexer.peek_token()->get_locus(); - - lexer.skip_token(); - } - - // Parse single required simple path segment - AST::SimplePathSegment segment = parse_simple_path_segment(); - - // get location if not gotten already - if (locus == UNKNOWN_LOCATION) { - locus = segment.get_locus(); - } - - ::std::vector segments; - - // Return empty vector if first, actually required segment is an error - if (segment.is_error()) { - return AST::SimplePath::create_empty(); - } - - segments.push_back(segment); - - // Parse all other simple path segments - while (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { - // Skip scope resolution operator - lexer.skip_token(); - - AST::SimplePathSegment new_segment = parse_simple_path_segment(); - - // Return path as currently constructed if segment in error state. - if (new_segment.is_error()) { - break; - } - segments.push_back(new_segment); - } - - // DEBUG: check for any empty segments - for (const auto& seg : segments) { - if (seg.is_error()) { - fprintf(stderr, - "when parsing simple path, somehow empty path segment was not filtered out. Path " - "begins with '%s' \n", - segments.at(0).as_string().c_str()); - } - } - - return AST::SimplePath(::std::move(segments), has_opening_scope_resolution, locus); - } - - // Parses a single SimplePathSegment (does not handle the scope resolution operators) - AST::SimplePathSegment Parser::parse_simple_path_segment() { - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - lexer.skip_token(); - - return AST::SimplePathSegment(t->get_str(), t->get_locus()); - case SUPER: - lexer.skip_token(); - - return AST::SimplePathSegment(::std::string("super"), t->get_locus()); - case SELF: - lexer.skip_token(); - - return AST::SimplePathSegment(::std::string("self"), t->get_locus()); - case CRATE: - lexer.skip_token(); - - return AST::SimplePathSegment(::std::string("crate"), t->get_locus()); - case DOLLAR_SIGN: - if (lexer.peek_token(1)->get_id() == CRATE) { - lexer.skip_token(1); - - return AST::SimplePathSegment(::std::string("$crate"), t->get_locus()); - } - gcc_fallthrough(); - default: - // do nothing but inactivates warning from gcc when compiling - // could put the error_at thing here but fallthrough (from failing $crate condition) - // isn't completely obvious if it is. - - // test prevent error - return AST::SimplePathSegment::create_error(); - } - gcc_unreachable(); - /*error_at( - t->get_locus(), "invalid token '%s' in simple path segment", t->get_token_description());*/ - // this is not necessarily an error, e.g. end of path - // return AST::SimplePathSegment::create_error(); - } - - // Parses a PathIdentSegment - an identifier segment of a non-SimplePath path. - AST::PathIdentSegment Parser::parse_path_ident_segment() { - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - lexer.skip_token(); - - return AST::PathIdentSegment(t->get_str()); - case SUPER: - lexer.skip_token(); - - return AST::PathIdentSegment(::std::string("super")); - case SELF: - lexer.skip_token(); - - return AST::PathIdentSegment(::std::string("self")); - case SELF_ALIAS: - lexer.skip_token(); - - return AST::PathIdentSegment(::std::string("Self")); - case CRATE: - lexer.skip_token(); - - return AST::PathIdentSegment(::std::string("crate")); - case DOLLAR_SIGN: - if (lexer.peek_token(1)->get_id() == CRATE) { - lexer.skip_token(1); - - return AST::PathIdentSegment(::std::string("$crate")); - } - gcc_fallthrough(); - default: - // do nothing but inactivates warning from gcc when compiling - // could put the error_at thing here but fallthrough (from failing $crate condition) - // isn't completely obvious if it is. - - // test prevent error - return AST::PathIdentSegment::create_error(); - } - gcc_unreachable(); - // not necessarily an error - } - - // Parses an AttrInput AST node (polymorphic, as AttrInput is abstract) - ::std::unique_ptr Parser::parse_attr_input() { - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: - case LEFT_SQUARE: - case LEFT_CURLY: { - // must be a delimited token tree, so parse that - ::std::unique_ptr input_tree( - new AST::DelimTokenTree(parse_delim_token_tree())); - - // TODO: potential checks on DelimTokenTree before returning - - return input_tree; - } - case EQUAL: { - // = LiteralExpr - lexer.skip_token(); - - t = lexer.peek_token(); - - // Ensure token is a "literal expression" (literally only a literal token of any type) - if (!t->is_literal()) { - error_at(t->get_locus(), - "unknown token '%s' in attribute body - literal expected", - t->get_token_description()); - skip_after_end_attribute(); - return NULL; - } - - AST::Literal::LitType lit_type = AST::Literal::STRING; - // Crappy mapping of token type to literal type - switch (t->get_id()) { - case INT_LITERAL: - lit_type = AST::Literal::INT; - break; - case FLOAT_LITERAL: - lit_type = AST::Literal::FLOAT; - break; - case CHAR_LITERAL: - lit_type = AST::Literal::CHAR; - break; - case BYTE_CHAR_LITERAL: - lit_type = AST::Literal::BYTE; - break; - case BYTE_STRING_LITERAL: - lit_type = AST::Literal::BYTE_STRING; - break; - case STRING_LITERAL: - default: - lit_type = AST::Literal::STRING; - break; // TODO: raw string? don't eliminate it from lexer? - } - - // create actual LiteralExpr - AST::LiteralExpr lit_expr(t->get_str(), lit_type, t->get_locus()); - - ::std::unique_ptr attr_input_lit( - new AST::AttrInputLiteral(::std::move(lit_expr))); - - // do checks or whatever? none required, really - - // FIXME: shouldn't a skip token be required here? - - return attr_input_lit; - } break; - case RIGHT_SQUARE: - // means AttrInput is missing, which is allowed - return NULL; - default: - error_at(t->get_locus(), - "unknown token '%s' in attribute body - attribute input or none expected", - t->get_token_description()); - skip_after_end_attribute(); - return NULL; - } - gcc_unreachable(); - // TODO: find out how to stop gcc error on "no return value" - } - - /* Returns true if the token id matches the delimiter type. Note that this only operates for - * END delimiter tokens. */ - inline bool token_id_matches_delims(TokenId token_id, AST::DelimType delim_type) { - return ((token_id == RIGHT_PAREN && delim_type == AST::PARENS) - || (token_id == RIGHT_SQUARE && delim_type == AST::SQUARE) - || (token_id == RIGHT_CURLY && delim_type == AST::CURLY)); - } - - /* Returns true if the likely result of parsing the next few tokens is a path. Not guaranteed, - * though, especially in the case of syntax errors. */ - inline bool is_likely_path_next(TokenId next_token_id) { - switch (next_token_id) { - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - // maybe - maybe do extra check. But then requires another TokenId. - case DOLLAR_SIGN: - case SCOPE_RESOLUTION: - return true; - default: - return false; - } - } - - // Parses a delimited token tree - AST::DelimTokenTree Parser::parse_delim_token_tree() { - // DEBUG - fprintf(stderr, "new delim token tree parsing begun\n"); - - const_TokenPtr t = lexer.peek_token(); - lexer.skip_token(); - location_t initial_loc = t->get_locus(); - - // save delim type to ensure it is reused later - AST::DelimType delim_type = AST::PARENS; - - // Map tokens to DelimType - switch (t->get_id()) { - case LEFT_PAREN: - delim_type = AST::PARENS; - break; - case LEFT_SQUARE: - delim_type = AST::SQUARE; - break; - case LEFT_CURLY: - delim_type = AST::CURLY; - break; - default: - error_at(t->get_locus(), - "unexpected token '%s' - expecting delimiters (for a delimited token tree)", - t->get_token_description()); - return AST::DelimTokenTree::create_empty(); - } - - // parse actual token tree vector - 0 or more - ::std::vector< ::std::unique_ptr > token_trees_in_tree; - - // repeat loop until finding the matching delimiter - t = lexer.peek_token(); - while (!token_id_matches_delims(t->get_id(), delim_type)) { - ::std::unique_ptr tok_tree = parse_token_tree(); - - if (tok_tree == NULL) { - // TODO: is this error handling appropriate? - error_at(t->get_locus(), - "failed to parse token tree in delimited token tree - found '%s'", - t->get_token_description()); - return AST::DelimTokenTree::create_empty(); - } - - token_trees_in_tree.push_back(::std::move(tok_tree)); - - // lexer.skip_token(); - t = lexer.peek_token(); - } - - AST::DelimTokenTree token_tree(delim_type, ::std::move(token_trees_in_tree), initial_loc); - - // parse end delimiters - t = lexer.peek_token(); - - if (token_id_matches_delims(t->get_id(), delim_type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - // DEBUG - fprintf(stderr, - "finished parsing new delim token tree - peeked token is now '%s' while t is '%s'\n", - lexer.peek_token()->get_token_description(), t->get_token_description()); - - return token_tree; - } else { - // tokens don't match opening delimiters, so produce error - error_at(t->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a delimited token tree)", - t->get_token_description(), - (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); - - /* return empty token tree despite possibly parsing valid token tree - TODO is this a - * good idea? */ - return AST::DelimTokenTree::create_empty(); - } - } - - /* Parses a TokenTree syntactical production. This is either a delimited token tree or a - * non-delimiter token. */ - ::std::unique_ptr Parser::parse_token_tree() { - const_TokenPtr t = lexer.peek_token(); - - switch (t->get_id()) { - case LEFT_PAREN: - case LEFT_SQUARE: - case LEFT_CURLY: - // Parse delimited token tree - // TODO: use move rather than copy constructor - return ::std::unique_ptr( - new AST::DelimTokenTree(parse_delim_token_tree())); - case RIGHT_PAREN: - case RIGHT_SQUARE: - case RIGHT_CURLY: - // error - should not be called when this a token - error_at(t->get_locus(), - "unexpected closing delimiter '%s' - token tree requires either paired delimiters " - "or non-delimiter tokens", - t->get_token_description()); - lexer.skip_token(); - return NULL; - default: - // parse token itself as TokenTree - lexer.skip_token(); - // TODO: fix that token constructor, possibly with c++11 features - return ::std::unique_ptr(new AST::Token(t)); - } - } - - /* Parses a sequence of items within a module or the implicit top-level module in a crate. Note: - * this is not currently used as parsing an item sequence individually is pretty simple and allows - * for better error diagnostics and detection. */ - ::std::vector< ::std::unique_ptr > Parser::parse_items() { - ::std::vector< ::std::unique_ptr > items; - - // TODO: replace with do-while loop? - // infinite loop to save on comparisons (may be a tight loop) - breaks when next item is null - while (true) { - ::std::unique_ptr item = parse_item(false); - - if (item != NULL) { - items.push_back(::std::move(item)); - } else { - break; - } - } - - return items; - } - - // Parses a single item - ::std::unique_ptr Parser::parse_item(bool called_from_statement) { - // has a "called_from_statement" parameter for better error message handling - - // parse outer attributes for item - ::std::vector outer_attrs = parse_outer_attributes(); - - // TODO: decide how to deal with VisItem vs MacroItem dichotomy - // best current solution: catch all keywords that would imply a VisItem in a switch and have - // MacroItem as a last resort - - const_TokenPtr t = lexer.peek_token(); - - switch (t->get_id()) { - case END_OF_FILE: - // not necessarily an error - return NULL; - case PUB: - case MOD: - case EXTERN_TOK: - case USE: - case FN_TOK: - case TYPE: - case STRUCT_TOK: - case ENUM_TOK: - case CONST: - case STATIC_TOK: - case TRAIT: - case IMPL: - /* TODO: implement union keyword but not really because of context-dependence - * crappy hack way to parse a union written below to separate it from the good code. */ - // case UNION: - case UNSAFE: // maybe - unsafe traits are a thing - // if any of these (should be all possible VisItem prefixes), parse a VisItem - return parse_vis_item(::std::move(outer_attrs)); - break; - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: - // almost certainly macro invocation semi - return parse_macro_item(::std::move(outer_attrs)); - break; - // crappy hack to do union "keyword" - case IDENTIFIER: - // TODO: ensure std::string and literal comparison works - if (t->get_str() == "union") { - return parse_vis_item(::std::move(outer_attrs)); - // or should this go straight to parsing union? - } else if (t->get_str() == "macro_rules") { - // macro_rules! macro item - return parse_macro_item(::std::move(outer_attrs)); - } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION - || lexer.peek_token(1)->get_id() == EXCLAM) { - // path (probably) or macro invocation, so probably a macro invocation semi - return parse_macro_item(::std::move(outer_attrs)); - } - gcc_fallthrough(); - // TODO: find out how to disable gcc "implicit fallthrough" warning - default: - // otherwise unrecognised - // return parse_macro_item(::std::move(outer_attrs)); - error_at(t->get_locus(), "unrecognised token '%s' for start of %s", - t->get_token_description(), called_from_statement ? "statement" : "item"); - // skip somewhere? - return NULL; - break; - } - } - - // Parses a contiguous block of outer attributes. - ::std::vector Parser::parse_outer_attributes() { - ::std::vector outer_attributes; - - while (lexer.peek_token()->get_id() == HASH) { - AST::Attribute outer_attr = parse_outer_attribute(); - - // Ensure only valid outer attributes are added to the outer_attributes list - if (!outer_attr.is_empty()) { - outer_attributes.push_back(::std::move(outer_attr)); - } else { - /* If no more valid outer attributes, break out of loop (only contiguous outer - * attributes parsed). */ - break; - } - } - - return outer_attributes; - - // TODO: this shares basically all code with parse_inner_attributes except function call - // find way of making it more modular? - } - - // Parse a single outer attribute. - AST::Attribute Parser::parse_outer_attribute() { - /* OuterAttribute -> '#' '[' Attr ']' */ - - if (lexer.peek_token()->get_id() != HASH) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - TokenId id = lexer.peek_token()->get_id(); - if (id != LEFT_SQUARE) { - if (id == EXCLAM) { - // this is inner attribute syntax, so throw error - error_at(lexer.peek_token()->get_locus(), - "token '!' found, indicating inner attribute definition. Inner attributes are not " - "possible at this location."); - } // TODO: are there any cases where this wouldn't be an error? - return AST::Attribute::create_empty(); - } - - lexer.skip_token(); - - AST::Attribute actual_attribute = parse_attribute_body(); - - if (lexer.peek_token()->get_id() != RIGHT_SQUARE) - return AST::Attribute::create_empty(); - - lexer.skip_token(); - - return actual_attribute; - } - - // Parses a VisItem (item that can have non-default visibility). - ::std::unique_ptr Parser::parse_vis_item( - ::std::vector outer_attrs) { - // parse visibility, which may or may not exist - AST::Visibility vis = parse_visibility(); - - // select VisItem to create depending on keyword - const_TokenPtr t = lexer.peek_token(); - - switch (t->get_id()) { - case MOD: - return parse_module(::std::move(vis), ::std::move(outer_attrs)); - case EXTERN_TOK: - // lookahead to resolve syntactical production - t = lexer.peek_token(1); - - switch (t->get_id()) { - case CRATE: - return parse_extern_crate(::std::move(vis), ::std::move(outer_attrs)); - case FN_TOK: // extern function - return parse_function(::std::move(vis), ::std::move(outer_attrs)); - case LEFT_CURLY: // extern block - return parse_extern_block(::std::move(vis), ::std::move(outer_attrs)); - case STRING_LITERAL: // for specifying extern ABI - // could be extern block or extern function, so more lookahead - t = lexer.peek_token(2); - - switch (t->get_id()) { - case FN_TOK: - return parse_function(::std::move(vis), ::std::move(outer_attrs)); - case LEFT_CURLY: - return parse_extern_block(::std::move(vis), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of extern production", - t->get_token_description()); - lexer.skip_token(2); // TODO: is this right thing to do? - return NULL; - } - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of extern production", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - case USE: - return parse_use_decl(::std::move(vis), ::std::move(outer_attrs)); - case FN_TOK: - return parse_function(::std::move(vis), ::std::move(outer_attrs)); - case TYPE: - return parse_type_alias(::std::move(vis), ::std::move(outer_attrs)); - case STRUCT_TOK: - return parse_struct(::std::move(vis), ::std::move(outer_attrs)); - case ENUM_TOK: - return parse_enum(::std::move(vis), ::std::move(outer_attrs)); - // TODO: implement union keyword but not really because of context-dependence - // case UNION: - // crappy hack to do union "keyword" - case IDENTIFIER: - // TODO: ensure std::string and literal comparison works - if (t->get_str() == "union") { - return parse_union(::std::move(vis), ::std::move(outer_attrs)); - // or should item switch go straight to parsing union? - } else { - break; - } - case CONST: - // lookahead to resolve syntactical production - t = lexer.peek_token(1); - - switch (t->get_id()) { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_function(::std::move(vis), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of const production", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - case STATIC_TOK: - return parse_static_item(::std::move(vis), ::std::move(outer_attrs)); - case TRAIT: - return parse_trait(::std::move(vis), ::std::move(outer_attrs)); - case IMPL: - return parse_impl(::std::move(vis), ::std::move(outer_attrs)); - case UNSAFE: // unsafe traits, unsafe functions, unsafe impls (trait impls), - // lookahead to resolve syntactical production - t = lexer.peek_token(1); - - switch (t->get_id()) { - case TRAIT: - return parse_trait(::std::move(vis), ::std::move(outer_attrs)); - case EXTERN_TOK: - case FN_TOK: - return parse_function(::std::move(vis), ::std::move(outer_attrs)); - case IMPL: - return parse_impl(::std::move(vis), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of unsafe production", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - default: - // otherwise vis item clearly doesn't exist, which is not an error - // has a catch-all post-switch return to allow other breaks to occur - break; - } - return NULL; - } - - // Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition). - ::std::unique_ptr Parser::parse_macro_item( - ::std::vector outer_attrs) { - const_TokenPtr t = lexer.peek_token(); - - /* dodgy way of detecting macro due to weird context-dependence thing. probably can be - * improved */ - // TODO: ensure that string compare works properly - if (t->get_id() == IDENTIFIER && t->get_str() == ::std::string("macro_rules")) { - return parse_macro_rules_def(::std::move(outer_attrs)); - } else { - // DEBUG: TODO: remove - fprintf(stderr, "DEBUG - parse_macro_item called and token is not macro_rules"); - if (t->get_id() == IDENTIFIER) { - fprintf(stderr, - "just add to last error: token is not macro_rules and is instead '%s'", - t->get_str().c_str()); - } else { - fprintf(stderr, - "just add to last error: token is not macro_rules and is not an identifier either " - "- it is '%s'", - t->get_token_description()); - } - - return parse_macro_invocation_semi(::std::move(outer_attrs)); - } - } - - // Parses a macro rules definition syntax extension whatever thing. - ::std::unique_ptr Parser::parse_macro_rules_def( - ::std::vector outer_attrs) { - // ensure that first token is identifier saying "macro_rules" - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() != IDENTIFIER || t->get_str() != "macro_rules") { - error_at(t->get_locus(), "macro rules definition does not start with 'macro_rules'"); - // skip after somewhere? - return NULL; - } - lexer.skip_token(); - location_t macro_locus = t->get_locus(); - - if (!skip_token(EXCLAM)) { - // skip after somewhere? - return NULL; - } - - // parse macro name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - return NULL; - } - Identifier rule_name = ident_tok->get_str(); - - // DEBUG - fprintf(stderr, "in macro rules def, about to parse parens.\n"); - - // save delim type to ensure it is reused later - AST::DelimType delim_type = AST::PARENS; - - // Map tokens to DelimType - t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: - delim_type = AST::PARENS; - break; - case LEFT_SQUARE: - delim_type = AST::SQUARE; - break; - case LEFT_CURLY: - delim_type = AST::CURLY; - break; - default: - error_at(t->get_locus(), - "unexpected token '%s' - expecting delimiters (for a macro rules definition)", - t->get_token_description()); - return NULL; - } - lexer.skip_token(); - - // parse actual macro rules - ::std::vector macro_rules; - - // must be at least one macro rule, so parse it - AST::MacroRule initial_rule = parse_macro_rule(); - if (initial_rule.is_error()) { - error_at(lexer.peek_token()->get_locus(), - "required first macro rule in macro rules definition could not be parsed"); - // skip after somewhere? - return NULL; - } - macro_rules.push_back(::std::move(initial_rule)); - - // DEBUG - fprintf(stderr, "successfully pushed back initial macro rule\n"); - - t = lexer.peek_token(); - // parse macro rules - while (t->get_id() == SEMICOLON) { - // skip semicolon - lexer.skip_token(); - - // don't parse if end of macro rules - if (token_id_matches_delims(lexer.peek_token()->get_id(), delim_type)) { - // DEBUG - fprintf(stderr, "broke out of parsing macro rules loop due to finding delim\n"); - - break; - } - - // try to parse next rule - AST::MacroRule rule = parse_macro_rule(); - if (rule.is_error()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse macro rule in macro rules definition"); - return NULL; - } - - macro_rules.push_back(::std::move(rule)); - - // DEBUG - fprintf(stderr, "successfully pushed back another macro rule\n"); - - t = lexer.peek_token(); - } - - // parse end delimiters - t = lexer.peek_token(); - if (token_id_matches_delims(t->get_id(), delim_type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - if (delim_type != AST::CURLY) { - // skip semicolon at end of non-curly macro definitions - if (!skip_token(SEMICOLON)) { - // as this is the end, allow recovery (probably) - may change - return ::std::unique_ptr( - new AST::MacroRulesDefinition(::std::move(rule_name), delim_type, - ::std::move(macro_rules), ::std::move(outer_attrs), macro_locus)); - } - } - - return ::std::unique_ptr( - new AST::MacroRulesDefinition(::std::move(rule_name), delim_type, - ::std::move(macro_rules), ::std::move(outer_attrs), macro_locus)); - } else { - // tokens don't match opening delimiters, so produce error - error_at(t->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a macro rules " - "definition)", - t->get_token_description(), - (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); - - /* return empty macro definiton despite possibly parsing mostly valid one - TODO is this - * a good idea? */ - return NULL; - } - } - - // Parses a semi-coloned (except for full block) macro invocation item. - ::std::unique_ptr Parser::parse_macro_invocation_semi( - ::std::vector outer_attrs) { - location_t macro_locus = lexer.peek_token()->get_locus(); - AST::SimplePath path = parse_simple_path(); - - if (!skip_token(EXCLAM)) { - // skip after somewhere? - return NULL; - } - - // save delim type to ensure it is reused later - AST::DelimType delim_type = AST::PARENS; - - // Map tokens to DelimType - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: - delim_type = AST::PARENS; - break; - case LEFT_SQUARE: - delim_type = AST::SQUARE; - break; - case LEFT_CURLY: - delim_type = AST::CURLY; - break; - default: - error_at(t->get_locus(), - "unexpected token '%s' - expecting delimiters (for a macro invocation semi body)", - t->get_token_description()); - return NULL; - } - lexer.skip_token(); - - // parse actual token trees - ::std::vector< ::std::unique_ptr > token_trees; - - t = lexer.peek_token(); - // parse token trees until the initial delimiter token is found again - while (!token_id_matches_delims(t->get_id(), delim_type)) { - ::std::unique_ptr tree = parse_token_tree(); - - if (tree == NULL) { - error_at(t->get_locus(), - "failed to parse token tree for macro invocation semi - found '%s'", - t->get_token_description()); - return NULL; - } - - token_trees.push_back(::std::move(tree)); - - t = lexer.peek_token(); - } - - // parse end delimiters - t = lexer.peek_token(); - if (token_id_matches_delims(t->get_id(), delim_type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - if (delim_type != AST::CURLY) { - // skip semicolon at end of non-curly macro invocation semis - if (!skip_token(SEMICOLON)) { - // as this is the end, allow recovery (probably) - may change - return ::std::unique_ptr( - new AST::MacroInvocationSemi(::std::move(path), delim_type, - ::std::move(token_trees), ::std::move(outer_attrs), macro_locus)); - } - } - - // DEBUG: - fprintf(stderr, "skipped token is '%s', next token (current peek) is '%s'\n", - t->get_token_description(), lexer.peek_token()->get_token_description()); - - return ::std::unique_ptr( - new AST::MacroInvocationSemi(::std::move(path), delim_type, ::std::move(token_trees), - ::std::move(outer_attrs), macro_locus)); - } else { - // tokens don't match opening delimiters, so produce error - error_at(t->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a macro invocation " - "semi)", - t->get_token_description(), - (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); - - /* return empty macro invocation despite possibly parsing mostly valid one - TODO is this - * a good idea? */ - return NULL; - } - } - - // Parses a non-semicoloned macro invocation (i.e. as pattern or expression). - ::std::unique_ptr Parser::parse_macro_invocation( - ::std::vector outer_attrs) { - // parse macro path - AST::SimplePath macro_path = parse_simple_path(); - if (macro_path.is_empty()) { - error_at(lexer.peek_token()->get_locus(), "failed to parse macro invocation path"); - // skip? - return NULL; - } - - if (!skip_token(EXCLAM)) { - // skip after somewhere? - return NULL; - } - - // parse internal delim token tree - AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree(); - - location_t macro_locus = macro_path.get_locus(); - - return ::std::unique_ptr( - new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), - ::std::move(outer_attrs), macro_locus)); - } - - // Parses a macro rule definition - does not parse semicolons. - AST::MacroRule Parser::parse_macro_rule() { - // DEBUG - fprintf(stderr, "begun parsing macro rule\n"); - - // parse macro matcher - AST::MacroMatcher matcher = parse_macro_matcher(); - - // DEBUG - fprintf(stderr, "managed to get past parsing macro matcher\n"); - - if (matcher.is_error()) { - return AST::MacroRule::create_error(); - } - - // DEBUG - fprintf(stderr, "successfully parsed macro matcher\n"); - - if (!skip_token(MATCH_ARROW)) { - // skip after somewhere? - return AST::MacroRule::create_error(); - } - - // DEBUG - fprintf(stderr, "successfully skipped match arrow\n"); - - // parse transcriber (this is just a delim token tree) - AST::DelimTokenTree transcribe_tree = parse_delim_token_tree(); - - // DEBUG - fprintf(stderr, "successfully parsed transcribe tree\n"); - - AST::MacroTranscriber transcriber(::std::move(transcribe_tree)); - - // DEBUG - fprintf(stderr, "successfully parsed macro transcriber - returning macro rule\n"); - - return AST::MacroRule(::std::move(matcher), ::std::move(transcriber)); - } - - // Parses a macro matcher (part of a macro rule definition). - AST::MacroMatcher Parser::parse_macro_matcher() { - // save delim type to ensure it is reused later - AST::DelimType delim_type = AST::PARENS; - - // DEBUG - fprintf(stderr, "begun parsing macro matcher\n"); - - // Map tokens to DelimType - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: - delim_type = AST::PARENS; - break; - case LEFT_SQUARE: - delim_type = AST::SQUARE; - break; - case LEFT_CURLY: - delim_type = AST::CURLY; - break; - default: - error_at(t->get_locus(), - "unexpected token '%s' - expecting delimiters (for a macro matcher)", - t->get_token_description()); - return AST::MacroMatcher::create_error(); - } - lexer.skip_token(); - - // parse actual macro matches - ::std::vector< ::std::unique_ptr > matches; - - t = lexer.peek_token(); - // parse token trees until the initial delimiter token is found again - while (!token_id_matches_delims(t->get_id(), delim_type)) { - ::std::unique_ptr match = parse_macro_match(); - - if (match == NULL) { - error_at(t->get_locus(), "failed to parse macro match for macro matcher - found '%s'", - t->get_token_description()); - return AST::MacroMatcher::create_error(); - } - - matches.push_back(::std::move(match)); - - // DEBUG - fprintf(stderr, "pushed back a match in macro matcher\n"); - - t = lexer.peek_token(); - } - - // parse end delimiters - t = lexer.peek_token(); - if (token_id_matches_delims(t->get_id(), delim_type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - return AST::MacroMatcher(delim_type, ::std::move(matches)); - } else { - // tokens don't match opening delimiters, so produce error - error_at(t->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a macro matcher)", - t->get_token_description(), - (delim_type == AST::PARENS ? ")" : (delim_type == AST::SQUARE ? "]" : "}"))); - - /* return error macro matcher despite possibly parsing mostly correct one? TODO is this - * the best idea? */ - return AST::MacroMatcher::create_error(); - } - } - - // Parses a macro match (syntax match inside a matcher in a macro rule). - ::std::unique_ptr Parser::parse_macro_match() { - // branch based on token available - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: - case LEFT_SQUARE: - case LEFT_CURLY: { - // must be macro matcher as delimited - AST::MacroMatcher matcher = parse_macro_matcher(); - if (matcher.is_error()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse macro matcher in macro match"); - return NULL; - } - return ::std::unique_ptr( - new AST::MacroMatcher(::std::move(matcher))); - } - case DOLLAR_SIGN: { - // have to do more lookahead to determine if fragment or repetition - const_TokenPtr t2 = lexer.peek_token(1); - switch (t2->get_id()) { - case IDENTIFIER: - // macro fragment - return parse_macro_match_fragment(); - case LEFT_PAREN: - // macro repetition - return parse_macro_match_repetition(); - default: - // error: unrecognised - error_at(t2->get_locus(), - "unrecognised token combination '$%s' at start of macro match - did you " - "mean '$identifier' or '$('?", - t2->get_token_description()); - // skip somewhere? - return NULL; - } - } - case RIGHT_PAREN: - case RIGHT_SQUARE: - case RIGHT_CURLY: - // not allowed - error_at(t->get_locus(), - "closing delimiters like '%s' are not allowed at the start of a macro match", - t->get_token_description()); - // skip somewhere? - return NULL; - default: - // just the token - lexer.skip_token(); - return ::std::unique_ptr(new AST::Token(t)); - } - } - - // Parses a fragment macro match. - ::std::unique_ptr Parser::parse_macro_match_fragment() { - skip_token(DOLLAR_SIGN); - - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - error_at(lexer.peek_token()->get_locus(), "missing identifier in macro match fragment"); - return NULL; - } - Identifier ident = ident_tok->get_str(); - - if (!skip_token(COLON)) { - // skip after somewhere? - return NULL; - } - - // get MacroFragSpec for macro - const_TokenPtr t = expect_token(IDENTIFIER); - AST::MacroFragSpec frag = AST::get_frag_spec_from_str(t->get_str()); - if (frag == AST::INVALID) { - error_at(t->get_locus(), "invalid fragment specifier '%s' in fragment macro match", - t->get_str().c_str()); - return NULL; - } - - return ::std::unique_ptr( - new AST::MacroMatchFragment(::std::move(ident), frag)); - } - - // Parses a repetition macro match. - ::std::unique_ptr Parser::parse_macro_match_repetition() { - skip_token(DOLLAR_SIGN); - skip_token(LEFT_PAREN); - - ::std::vector< ::std::unique_ptr > matches; - - // parse required first macro match - ::std::unique_ptr initial_match = parse_macro_match(); - if (initial_match == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse required first macro match in macro match repetition"); - // skip after somewhere? - return NULL; - } - matches.push_back(::std::move(initial_match)); - - // parse optional later macro matches - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - ::std::unique_ptr match = parse_macro_match(); - - if (match == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse macro match in macro match repetition"); - return NULL; - } - - matches.push_back(::std::move(match)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - // skip after somewhere? - return NULL; - } - - t = lexer.peek_token(); - // see if separator token exists - ::std::unique_ptr separator = NULL; - switch (t->get_id()) { - // repetition operators - case ASTERISK: - case PLUS: - case QUESTION_MARK: - // delimiters - case LEFT_PAREN: - case LEFT_CURLY: - case LEFT_SQUARE: - case RIGHT_PAREN: - case RIGHT_CURLY: - case RIGHT_SQUARE: - // separator does not exist, so still null and don't skip token - break; - default: - // separator does exist - separator = ::std::unique_ptr(new AST::Token(t)); - lexer.skip_token(); - break; - } - - // parse repetition operator - t = lexer.peek_token(); - AST::MacroMatchRepetition::MacroRepOp op = AST::MacroMatchRepetition::ASTERISK; - switch (t->get_id()) { - case ASTERISK: - op = AST::MacroMatchRepetition::ASTERISK; - lexer.skip_token(); - break; - case PLUS: - op = AST::MacroMatchRepetition::PLUS; - lexer.skip_token(); - break; - case QUESTION_MARK: - op = AST::MacroMatchRepetition::QUESTION_MARK; - lexer.skip_token(); - break; - default: - error_at(t->get_locus(), - "expected macro repetition operator ('*', '+', or '?') in macro match - found '%s'", - t->get_token_description()); - // skip after somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::MacroMatchRepetition(::std::move(matches), op, ::std::move(separator))); - } - - // Parses a visibility syntactical production (i.e. creating a non-default visibility) - AST::Visibility Parser::parse_visibility() { - // check for no visibility - if (lexer.peek_token()->get_id() != PUB) { - return AST::Visibility::create_error(); - } - - lexer.skip_token(); - - // create simple pub visibility if no parentheses - if (lexer.peek_token()->get_id() != LEFT_PAREN) { - return AST::Visibility::create_public(); - // or whatever - } - - lexer.skip_token(); - - const_TokenPtr t = lexer.peek_token(); - - switch (t->get_id()) { - case CRATE: - lexer.skip_token(); - - skip_token(RIGHT_PAREN); - - return AST::Visibility::create_crate(); - case SELF: - lexer.skip_token(); - - skip_token(RIGHT_PAREN); - - return AST::Visibility::create_self(); - case SUPER: - lexer.skip_token(); - - skip_token(RIGHT_PAREN); - - return AST::Visibility::create_super(); - case IN: { - lexer.skip_token(); - - // parse the "in" path as well - AST::SimplePath path = parse_simple_path(); - if (path.is_empty()) { - error_at( - lexer.peek_token()->get_locus(), "missing path in pub(in path) visibility"); - // skip after somewhere? - return AST::Visibility::create_error(); - } - - skip_token(RIGHT_PAREN); - - return AST::Visibility::create_in_path(::std::move(path)); - } - default: - error_at( - t->get_locus(), "unexpected token '%s' in visibility", t->get_token_description()); - lexer.skip_token(); - return AST::Visibility::create_error(); - } - } - - // Parses a module - either a bodied module or a module defined in another file. - ::std::unique_ptr Parser::parse_module( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(MOD); - - const_TokenPtr module_name = expect_token(IDENTIFIER); - if (module_name == NULL) { - return NULL; - } - Identifier name = module_name->get_str(); - - const_TokenPtr t = lexer.peek_token(); - - switch (t->get_id()) { - case SEMICOLON: - lexer.skip_token(); - - return ::std::unique_ptr(new AST::ModuleNoBody(::std::move(name), - ::std::move(vis), ::std::move(outer_attrs), locus)); // module name? - case LEFT_CURLY: { - lexer.skip_token(); - - // parse inner attributes - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse items - ::std::vector< ::std::unique_ptr > items; - const_TokenPtr tok = lexer.peek_token(); - while (tok->get_id() != RIGHT_CURLY) { - ::std::unique_ptr item = parse_item(false); - if (item == NULL) { - error_at(tok->get_locus(), "failed to parse item in module"); - return NULL; - } - - items.push_back(::std::move(item)); - - tok = lexer.peek_token(); - } - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::ModuleBodied(::std::move(name), - locus, ::std::move(items), ::std::move(vis), ::std::move(inner_attrs), - ::std::move(outer_attrs))); // module name? - } - default: - error_at(t->get_locus(), - "unexpected token '%s' in module declaration/definition item", - t->get_token_description()); - lexer.skip_token(); - return NULL; - } - } - - // Parses an extern crate declaration (dependency on external crate) - ::std::unique_ptr Parser::parse_extern_crate( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - if (!skip_token(EXTERN_TOK)) { - skip_after_semicolon(); - return NULL; - } - - if (!skip_token(CRATE)) { - skip_after_semicolon(); - return NULL; - } - - /* parse crate reference name - this has its own syntactical rule in reference but seems - * to not be used elsewhere, so i'm putting it here */ - const_TokenPtr crate_name_tok = lexer.peek_token(); - ::std::string crate_name; - - switch (crate_name_tok->get_id()) { - case IDENTIFIER: - crate_name = crate_name_tok->get_str(); - lexer.skip_token(); - break; - case SELF: - crate_name = ::std::string("self"); - lexer.skip_token(); - break; - default: - error_at(crate_name_tok->get_locus(), - "expecting crate name (identifier or 'self'), found '%s'", - crate_name_tok->get_token_description()); - skip_after_semicolon(); - return NULL; - } - - // don't parse as clause if it doesn't exist - if (lexer.peek_token()->get_id() == SEMICOLON) { - lexer.skip_token(); - - return ::std::unique_ptr(new AST::ExternCrate( - ::std::move(crate_name), ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - /* parse as clause - this also has its own syntactical rule in reference and also seems to - * not be used elsewhere, so including here again. */ - if (!skip_token(AS)) { - skip_after_semicolon(); - return NULL; - } - - const_TokenPtr as_name_tok = lexer.peek_token(); - ::std::string as_name; - - switch (as_name_tok->get_id()) { - case IDENTIFIER: - as_name = as_name_tok->get_str(); - lexer.skip_token(); - break; - case UNDERSCORE: - as_name = ::std::string("_"); - lexer.skip_token(); - break; - default: - error_at(as_name_tok->get_locus(), - "expecting as clause name (identifier or '_'), found '%s'", - as_name_tok->get_token_description()); - skip_after_semicolon(); - return NULL; - } - - if (!skip_token(SEMICOLON)) { - skip_after_semicolon(); - return NULL; - } - - return ::std::unique_ptr(new AST::ExternCrate(::std::move(crate_name), - ::std::move(vis), ::std::move(outer_attrs), locus, ::std::move(as_name))); - } - - // Parses a use declaration. - ::std::unique_ptr Parser::parse_use_decl( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - if (!skip_token(USE)) { - skip_after_semicolon(); - return NULL; - } - - // parse use tree, which is required - ::std::unique_ptr use_tree = parse_use_tree(); - if (use_tree == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse use tree in use declaration"); - skip_after_semicolon(); - return NULL; - } - - if (!skip_token(SEMICOLON)) { - skip_after_semicolon(); - return NULL; - } - - return ::std::unique_ptr(new AST::UseDeclaration( - ::std::move(use_tree), ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // Parses a use tree (which can be recursive and is actually a base class). - ::std::unique_ptr Parser::parse_use_tree() { - /* potential syntax definitions in attempt to get algorithm: - * Glob: - * <- SimplePath :: * - * <- :: * - * <- * - * Nested tree thing: - * <- SimplePath :: { COMPLICATED_INNER_TREE_THING } - * <- :: COMPLICATED_INNER_TREE_THING } - * <- { COMPLICATED_INNER_TREE_THING } - * Rebind thing: - * <- SimplePath as IDENTIFIER - * <- SimplePath as _ - * <- SimplePath - */ - - /* current plan of attack: try to parse SimplePath first - if fails, one of top two - * then try parse :: - if fails, one of top two. Next is deciding character for top two. */ - - // Thus, parsing smaller parts of use tree may require feeding into function via parameters - // (or could handle all in this single function because other use tree types aren't - // recognised) as separate in the spec - - // TODO: I think this function is too complex, probably should split it - - location_t locus = lexer.peek_token()->get_locus(); - - // bool has_path = false; - AST::SimplePath path = parse_simple_path(); - - if (path.is_empty()) { - // has no path, so must be glob or nested tree UseTree type - - /* due to implementation issues, parsing simple path removes any trailing scope - * resolutions (or any, actually, if the use tree has no path given), so we'll just - * assume that there's one there. */ - // Check anyway, but optional. - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { - lexer.skip_token(); - } - /* Note that this implementation issue also makes it impossible to determine at the - * moment whether the tree has GLOBAL or NO_PATH path type. */ - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case ASTERISK: - // glob UseTree type - lexer.skip_token(); - - // TODO: find way to determine whether GLOBAL or NO_PATH path type - placeholder - return ::std::unique_ptr(new AST::UseTreeGlob( - AST::UseTreeGlob::NO_PATH, AST::SimplePath::create_empty(), locus)); - case LEFT_CURLY: { - // nested tree UseTree type - lexer.skip_token(); - - ::std::vector< ::std::unique_ptr > use_trees; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr use_tree = parse_use_tree(); - if (use_tree == NULL) { - break; - } - - use_trees.push_back(::std::move(use_tree)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // skip end curly delimiter - if (!skip_token(RIGHT_CURLY)) { - // skip after somewhere? - return NULL; - } - - // TODO: find way to determine whether GLOBAL or NO_PATH path type - placeholder - return ::std::unique_ptr( - new AST::UseTreeList(AST::UseTreeList::NO_PATH, AST::SimplePath::create_empty(), - ::std::move(use_trees), locus)); - } - case AS: - // this is not allowed - error_at(t->get_locus(), - "use declaration with rebind 'as' requires a valid simple path - none found."); - skip_after_semicolon(); - return NULL; - default: - error_at(t->get_locus(), - "unexpected token '%s' in use tree with no valid simple path (i.e. list or " - "glob use tree)", - t->get_token_description()); - skip_after_semicolon(); - return NULL; - } - } else { - /* Due to aforementioned implementation issues, the trailing :: token is consumed by the - * path, so it can not be used as a disambiguator. */ - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case ASTERISK: - // glob UseTree type - lexer.skip_token(); - - return ::std::unique_ptr(new AST::UseTreeGlob( - AST::UseTreeGlob::PATH_PREFIXED, ::std::move(path), locus)); - case LEFT_CURLY: { - // nested tree UseTree type - lexer.skip_token(); - - ::std::vector< ::std::unique_ptr > use_trees; - - // TODO: think of better control structure - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr use_tree = parse_use_tree(); - if (use_tree == NULL) { - break; - } - - use_trees.push_back(::std::move(use_tree)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // skip end curly delimiter - if (!skip_token(RIGHT_CURLY)) { - // skip after somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::UseTreeList(AST::UseTreeList::PATH_PREFIXED, ::std::move(path), - std::move(use_trees), locus)); - } - case AS: { - // rebind UseTree type - lexer.skip_token(); - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - // skip lexer token - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::UseTreeRebind(AST::UseTreeRebind::IDENTIFIER, - ::std::move(path), locus, t->get_str())); - case UNDERSCORE: - // skip lexer token - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::UseTreeRebind(AST::UseTreeRebind::WILDCARD, ::std::move(path), - locus, ::std::string("_"))); - default: - error_at(t->get_locus(), - "unexpected token '%s' in use tree with as clause - expected " - "identifier or '_'", - t->get_token_description()); - skip_after_semicolon(); - return NULL; - } - } - case SEMICOLON: - // rebind UseTree type without rebinding - path only - - // don't skip semicolon - handled in parse_use_tree - // lexer.skip_token(); - - return ::std::unique_ptr( - new AST::UseTreeRebind(AST::UseTreeRebind::NONE, ::std::move(path), locus)); - case COMMA: - case RIGHT_CURLY: - // this may occur in recursive calls - assume it is ok and ignore it - return ::std::unique_ptr( - new AST::UseTreeRebind(AST::UseTreeRebind::NONE, ::std::move(path), locus)); - default: - error_at(t->get_locus(), "unexpected token '%s' in use tree with valid path", - t->get_token_description()); - // skip_after_semicolon(); - return NULL; - } - } - } - - // Parses a function (not a method). - ::std::unique_ptr Parser::parse_function( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - // Get qualifiers for function if they exist - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - skip_token(FN_TOK); - - // Save function name token - const_TokenPtr function_name_tok = expect_token(IDENTIFIER); - if (function_name_tok == NULL) { - skip_after_next_block(); - return NULL; - } - Identifier function_name = function_name_tok->get_str(); - - // parse generic params - if exist - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - if (!skip_token(LEFT_PAREN)) { - error_at(lexer.peek_token()->get_locus(), - "function declaration missing opening parentheses before parameter list"); - skip_after_next_block(); - return NULL; - } - - // parse function parameters (only if next token isn't right paren) - ::std::vector function_params; - if (lexer.peek_token()->get_id() != RIGHT_PAREN) { - function_params = parse_function_params(); - } - - if (!skip_token(RIGHT_PAREN)) { - error_at(lexer.peek_token()->get_locus(), - "function declaration missing closing parentheses after parameter list"); - skip_after_next_block(); - return NULL; - } - - // parse function return type - if exists - ::std::unique_ptr return_type = parse_function_return_type(); - - // parse where clause - if exists - AST::WhereClause where_clause = parse_where_clause(); - - // parse block expression - ::std::unique_ptr block_expr = parse_block_expr(); - - return ::std::unique_ptr(new AST::Function(::std::move(function_name), - ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), - ::std::move(return_type), ::std::move(where_clause), ::std::move(block_expr), - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // Parses function or method qualifiers (i.e. const, unsafe, and extern). - AST::FunctionQualifiers Parser::parse_function_qualifiers() { - AST::FunctionQualifiers::AsyncConstStatus const_status = AST::FunctionQualifiers::NONE; - // bool has_const = false; - bool has_unsafe = false; - bool has_extern = false; - ::std::string abi; - - // Check in order of const, unsafe, then extern - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case CONST: - lexer.skip_token(); - const_status = AST::FunctionQualifiers::CONST; - break; - case ASYNC: - lexer.skip_token(); - const_status = AST::FunctionQualifiers::ASYNC; - break; - default: - // const status is still none - break; - } - - if (lexer.peek_token()->get_id() == UNSAFE) { - lexer.skip_token(); - has_unsafe = true; - } - - if (lexer.peek_token()->get_id() == EXTERN_TOK) { - lexer.skip_token(); - has_extern = true; - - // detect optional abi name - const_TokenPtr next_tok = lexer.peek_token(); - if (next_tok->get_id() == STRING_LITERAL) { - lexer.skip_token(); - abi = next_tok->get_str(); - } - } - - return AST::FunctionQualifiers(const_status, has_unsafe, has_extern, ::std::move(abi)); - } - - // Parses generic (lifetime or type) params inside angle brackets (optional). - ::std::vector< ::std::unique_ptr > Parser::parse_generic_params_in_angles() { - if (lexer.peek_token()->get_id() != LEFT_ANGLE) { - // seems to be no generic params, so exit with empty vector - return ::std::vector< ::std::unique_ptr >(); - } - lexer.skip_token(); - - // DEBUG: - fprintf(stderr, "skipped left angle in generic param\n"); - - ::std::vector< ::std::unique_ptr > generic_params = parse_generic_params(); - - // DEBUG: - fprintf(stderr, "finished parsing actual generic params (i.e. inside angles)\n"); - - if (!skip_generics_right_angle()) { - // DEBUG - fprintf(stderr, "failed to skip generics right angle - returning empty generic params\n"); - - return ::std::vector< ::std::unique_ptr >(); - } - - return generic_params; - } - - /* Parse generic (lifetime or type) params NOT INSIDE ANGLE BRACKETS!!! Almost always - * parse_generic_params_in_angles is what is wanted. */ - ::std::vector< ::std::unique_ptr > Parser::parse_generic_params() { - ::std::vector< ::std::unique_ptr > generic_params; - - // can't parse lifetime and type params separately due to lookahead issues - // thus, parse them all here - - // DEBUG - fprintf(stderr, "starting to parse generic params (inside angle brackets)\n"); - - // HACK: used to retain attribute data if a lifetime param is tentatively parsed but it turns - // out to be type param - AST::Attribute parsed_outer_attr = AST::Attribute::create_empty(); - - // HACK: generic params always in angle brackets with current syntax, so have that as end char - const_TokenPtr t = lexer.peek_token(); - // parse lifetime params - while (!is_right_angle_tok(t->get_id())) { - // HACK: reimpl of lifetime param parsing - AST::Attribute outer_attr = parse_outer_attribute(); - - // move attribute outward if type param - if (lexer.peek_token()->get_id() != LIFETIME) { - parsed_outer_attr = ::std::move(outer_attr); - - // DEBUG - fprintf(stderr, "broke from parsing lifetime params as next token isn't lifetime - " - "saved attribute\n"); - - break; - } - - location_t locus = lexer.peek_token()->get_locus(); - AST::Lifetime lifetime = parse_lifetime(); - - // DEBUG - fprintf(stderr, "parsed lifetime in lifetime params\n"); - - // parse optional bounds - ::std::vector lifetime_bounds; - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - // parse required bounds - lifetime_bounds = parse_lifetime_bounds(); - } - - ::std::unique_ptr param(new AST::LifetimeParam( - ::std::move(lifetime), locus, ::std::move(lifetime_bounds), ::std::move(outer_attr))); - generic_params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // parse type params (reimpl required for first one but not others) - if (!is_right_angle_tok(lexer.peek_token()->get_id()) && !parsed_outer_attr.is_empty()) { - // DEBUG - fprintf(stderr, "as parsed outer attr isn't empty, started parsing type param reimpl\n"); - - // reimpl as type param definitely exists - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse identifier in type param in generic params"); - return ::std::vector< ::std::unique_ptr >(); - } - Identifier ident = ident_tok->get_str(); - - // parse optional bounds - ::std::vector< ::std::unique_ptr > type_param_bounds; - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - - // parse optional type param bounds - type_param_bounds = parse_type_param_bounds(); - } - - // parse optional type - ::std::unique_ptr type = NULL; - if (lexer.peek_token()->get_id() == EQUAL) { - lexer.skip_token(); - - // parse required type - type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_id(), - "failed to parse type in type param in generic params"); - return ::std::vector< ::std::unique_ptr >(); - } - } - - ::std::unique_ptr param( - new AST::TypeParam(::std::move(ident), ident_tok->get_locus(), - ::std::move(type_param_bounds), ::std::move(type), ::std::move(parsed_outer_attr))); - generic_params.push_back(::std::move(param)); - - // handle comma - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - } - - // DEBUG - fprintf(stderr, "about to start parsing normally-parsed type params in generic params\n"); - - // parse rest of type params - reimpl due to right angle tokens - t = lexer.peek_token(); - while (!is_right_angle_tok(t->get_id())) { - ::std::unique_ptr type_param = parse_type_param(); - - if (type_param == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse type param in generic params"); - return ::std::vector< ::std::unique_ptr >(); - } - - // DEBUG - fprintf(stderr, "successfully parsed type param\n"); - - generic_params.push_back(::std::move(type_param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip commas, including trailing commas - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // old code - /* - // parse lifetime params (optional), allowed to end with a trailing comma - ::std::vector< ::std::unique_ptr > lifetime_params - = parse_lifetime_params(); - if (!lifetime_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - ::std::make_move_iterator(lifetime_params.begin()), - ::std::make_move_iterator(lifetime_params.end())); - } - - // parse type params (optional) - ::std::vector< ::std::unique_ptr > type_params = parse_type_params(); - if (!type_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - ::std::make_move_iterator(type_params.begin()), - ::std::make_move_iterator(type_params.end())); - }*/ - - return generic_params; - } - - // Parses lifetime generic parameters (pointers). Will also consume any trailing comma. - ::std::vector< ::std::unique_ptr > Parser::parse_lifetime_params() { - ::std::vector< ::std::unique_ptr > lifetime_params; - - // TODO: think of better control structure than infinite loop with break on failure? - while (true) { - AST::LifetimeParam lifetime_param = parse_lifetime_param(); - - if (lifetime_param.is_error()) { - // break if fails to parse - break; - } - - lifetime_params.push_back( - ::std::unique_ptr(new AST::LifetimeParam(lifetime_param))); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip commas, including trailing commas - lexer.skip_token(); - } - - return lifetime_params; - } - - /* Parses lifetime generic parameters (objects). Will also consume any trailing comma. - * TODO: is this best solution? implements most of the same algorithm. */ - ::std::vector Parser::parse_lifetime_params_objs() { - ::std::vector lifetime_params; - - // TODO: think of better control structure than infinite loop with break on failure? - while (true) { - AST::LifetimeParam lifetime_param = parse_lifetime_param(); - - if (lifetime_param.is_error()) { - // break if fails to parse - break; - } - - lifetime_params.push_back(lifetime_param); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip commas, including trailing commas - lexer.skip_token(); - } - - return lifetime_params; - } - - /* Parses a single lifetime generic parameter (not including comma). */ - AST::LifetimeParam Parser::parse_lifetime_param() { - // parse outer attribute, which is optional and may not exist - AST::Attribute outer_attr = parse_outer_attribute(); - - // save lifetime token - required - const_TokenPtr lifetime_tok = lexer.peek_token(); - if (lifetime_tok->get_id() != LIFETIME) { - // if lifetime is missing, must not be a lifetime param, so return null - return AST::LifetimeParam::create_error(); - } - // TODO: does this always create a named lifetime? or can a different type be made? - AST::Lifetime lifetime( - AST::Lifetime::NAMED, lifetime_tok->get_str(), lifetime_tok->get_locus()); - - // parse lifetime bounds, if it exists - ::std::vector lifetime_bounds; - if (lexer.peek_token()->get_id() == COLON) { - // parse lifetime bounds - lifetime_bounds = parse_lifetime_bounds(); - } - - return AST::LifetimeParam(::std::move(lifetime), lifetime_tok->get_locus(), - ::std::move(lifetime_bounds), ::std::move(outer_attr)); - } - - // Parses type generic parameters. Will also consume any trailing comma. - ::std::vector< ::std::unique_ptr > Parser::parse_type_params() { - ::std::vector< ::std::unique_ptr > type_params; - - // TODO: think of better control structure than infinite loop with break on failure? - while (true) { - ::std::unique_ptr type_param = parse_type_param(); - - if (type_param == NULL) { - // break if fails to parse - break; - } - - type_params.push_back(::std::move(type_param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip commas, including trailing commas - lexer.skip_token(); - } - - return type_params; - // TODO: this shares most code with parse_lifetime_params - good place to use template? - } - - // Parses a single type (generic) parameter, not including commas. May change to return value. - ::std::unique_ptr Parser::parse_type_param() { - // parse outer attribute, which is optional and may not exist - AST::Attribute outer_attr = parse_outer_attribute(); - - const_TokenPtr identifier_tok = lexer.peek_token(); - if (identifier_tok->get_id() != IDENTIFIER) { - // return null as type param can't exist without this required identifier - return NULL; - } - // TODO: create identifier from identifier token - Identifier ident = identifier_tok->get_str(); - lexer.skip_token(); - - // parse type param bounds (if they exist) - ::std::vector< ::std::unique_ptr > type_param_bounds; - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - - // parse type param bounds, which may or may not exist - type_param_bounds = parse_type_param_bounds(); - } - - // parse type (if it exists) - ::std::unique_ptr type = NULL; - if (lexer.peek_token()->get_id() == EQUAL) { - lexer.skip_token(); - - // parse type (now required) - type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse type in type param"); - return NULL; - } - } - - return ::std::unique_ptr( - new AST::TypeParam(::std::move(ident), identifier_tok->get_locus(), - ::std::move(type_param_bounds), ::std::move(type), ::std::move(outer_attr))); - } - - // Parses regular (i.e. non-generic) parameters in functions or methods. - ::std::vector Parser::parse_function_params() { - ::std::vector params; - - // HACK: return early if RIGHT_PAREN is found - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - return params; - } - - AST::FunctionParam initial_param = parse_function_param(); - - // Return empty parameter list if no parameter there - if (initial_param.is_error()) { - return params; - } - - params.push_back(::std::move(initial_param)); - - // maybe think of a better control structure here - do-while with an initial error state? - // basically, loop through parameter list until can't find any more params - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - // skip comma if applies - lexer.skip_token(); - - /* HACK: break if next token is a right (closing) paren - this is not strictly true via - * grammar rule but seems to be true in practice (i.e. with trailing comma). */ - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // now, as right paren would break, function param is required - AST::FunctionParam param = parse_function_param(); - if (param.is_error()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse function param (in function params)"); - // skip somewhere? - return ::std::vector(); - } - - params.push_back(::std::move(param)); - - t = lexer.peek_token(); - } - - return params; - } - - /* Parses a single regular (i.e. non-generic) parameter in a function or method, i.e. the - * "name: type" bit. Also handles it not existing. */ - AST::FunctionParam Parser::parse_function_param() { - location_t locus = lexer.peek_token()->get_locus(); - ::std::unique_ptr param_pattern = parse_pattern(); - - // create error function param if it doesn't exist - if (param_pattern == NULL) { - // skip after something - return AST::FunctionParam::create_error(); - } - - if (!skip_token(COLON)) { - // skip after something - return AST::FunctionParam::create_error(); - } - - ::std::unique_ptr param_type = parse_type(); - if (param_type == NULL) { - // skip? - return AST::FunctionParam::create_error(); - } - - return AST::FunctionParam(::std::move(param_pattern), ::std::move(param_type), locus); - } - - /* Parses a function or method return type syntactical construction. Also handles a function - * return type not existing. */ - ::std::unique_ptr Parser::parse_function_return_type() { - if (lexer.peek_token()->get_id() != RETURN_TYPE) { - return NULL; - } - // skip return type, as it now obviously exists - lexer.skip_token(); - - ::std::unique_ptr type = parse_type(); - - return type; - } - - /* Parses a "where clause" (in a function, struct, method, etc.). Also handles a where clause - * not existing, in which it will return WhereClause::create_empty(), which can be checked via - * WhereClause::is_empty(). */ - AST::WhereClause Parser::parse_where_clause() { - const_TokenPtr where_tok = lexer.peek_token(); - if (where_tok->get_id() != WHERE) { - // where clause doesn't exist, so create empty one - return AST::WhereClause::create_empty(); - } - - lexer.skip_token(); - - // parse where clause items - this is not a separate rule in the reference so won't be here - ::std::vector< ::std::unique_ptr > where_clause_items; - - // HACK: where clauses end with a right curly or semicolon or equals in all uses currently - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != LEFT_CURLY && t->get_id() != SEMICOLON && t->get_id() != EQUAL) { - ::std::unique_ptr where_clause_item = parse_where_clause_item(); - - if (where_clause_item == NULL) { - error_at(t->get_locus(), "failed to parse where clause item"); - return AST::WhereClause::create_empty(); - } - - where_clause_items.push_back(::std::move(where_clause_item)); - - // also skip comma if it exists - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - return AST::WhereClause(::std::move(where_clause_items)); - } - - // Parses a where clause item (lifetime or type bound). Does not parse any commas. - ::std::unique_ptr Parser::parse_where_clause_item() { - // shitty cheat way of determining lifetime or type bound - test for lifetime - const_TokenPtr t = lexer.peek_token(); - - if (t->get_id() == LIFETIME) { - return parse_lifetime_where_clause_item(); - } else { - return parse_type_bound_where_clause_item(); - } - } - - // Parses a lifetime where clause item. - ::std::unique_ptr Parser::parse_lifetime_where_clause_item() { - AST::Lifetime lifetime = parse_lifetime(); - if (lifetime.is_error()) { - // TODO: error here? - return NULL; - } - - if (!skip_token(COLON)) { - // TODO: skip after somewhere - return NULL; - } - - ::std::vector lifetime_bounds = parse_lifetime_bounds(); - - return ::std::unique_ptr( - new AST::LifetimeWhereClauseItem(::std::move(lifetime), ::std::move(lifetime_bounds))); - } - - // Parses a type bound where clause item. - ::std::unique_ptr Parser::parse_type_bound_where_clause_item() { - // parse for lifetimes, if it exists - ::std::vector for_lifetimes; - if (lexer.peek_token()->get_id() == FOR) { - for_lifetimes = parse_for_lifetimes(); - } - - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - return NULL; - } - - if (!skip_token(COLON)) { - // TODO: skip after somewhere - return NULL; - } - - // parse type param bounds if they exist - ::std::vector< ::std::unique_ptr > type_param_bounds - = parse_type_param_bounds(); - - return ::std::unique_ptr(new AST::TypeBoundWhereClauseItem( - ::std::move(for_lifetimes), ::std::move(type), ::std::move(type_param_bounds))); - } - - // Parses a for lifetimes clause, including the for keyword and angle brackets. - ::std::vector Parser::parse_for_lifetimes() { - ::std::vector params; - - if (!skip_token(FOR)) { - // skip after somewhere? - return params; - } - - if (!skip_token(LEFT_ANGLE)) { - // skip after somewhere? - return params; - } - - params = parse_lifetime_params_objs(); - - if (!skip_generics_right_angle()) { - // skip after somewhere? - return params; - } - - return params; - } - - // Parses type parameter bounds in where clause or generic arguments. - ::std::vector< ::std::unique_ptr > Parser::parse_type_param_bounds() { - ::std::vector< ::std::unique_ptr > type_param_bounds; - - ::std::unique_ptr initial_bound = parse_type_param_bound(); - - // quick exit if null - if (initial_bound == NULL) { - // error? type param bounds must have at least one term, but are bounds optional? - return type_param_bounds; - } - - type_param_bounds.push_back(::std::move(initial_bound)); - - // TODO think of better control structure than infinite loop - while (true) { - // Quick exit for no more bounds - if (lexer.peek_token()->get_id() != PLUS) { - return type_param_bounds; - } - lexer.skip_token(); - - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - // not an error: bound is allowed to be null as trailing plus is allowed - return type_param_bounds; - } - - type_param_bounds.push_back(::std::move(bound)); - } - - return type_param_bounds; - } - - /* Parses a single type parameter bound in a where clause or generic argument. Does not parse - * the '+' between arguments. */ - ::std::unique_ptr Parser::parse_type_param_bound() { - // shitty cheat way of determining lifetime or trait bound - test for lifetime - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LIFETIME: - return ::std::unique_ptr(new AST::Lifetime(parse_lifetime())); - case LEFT_PAREN: - case QUESTION_MARK: - case FOR: - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case DOLLAR_SIGN: - return parse_trait_bound(); - default: - // don't error - assume this is fine TODO - return NULL; - } - } - - // Parses a trait bound type param bound. - ::std::unique_ptr Parser::parse_trait_bound() { - bool has_parens = false; - bool has_question_mark = false; - - location_t locus = lexer.peek_token()->get_locus(); - - // handle trait bound being in parentheses - if (lexer.peek_token()->get_id() == LEFT_PAREN) { - has_parens = true; - lexer.skip_token(); - } - - // handle having question mark (optional) - if (lexer.peek_token()->get_id() == QUESTION_MARK) { - has_question_mark = true; - lexer.skip_token(); - } - - // parse for lifetimes, if it exists (although empty for lifetimes is ok to handle this) - ::std::vector for_lifetimes; - if (lexer.peek_token()->get_id() == FOR) { - for_lifetimes = parse_for_lifetimes(); - } - - // handle TypePath - AST::TypePath type_path = parse_type_path(); - - // handle closing parentheses - if (has_parens) { - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - } - - return ::std::unique_ptr(new AST::TraitBound( - ::std::move(type_path), locus, has_parens, has_question_mark, ::std::move(for_lifetimes))); - } - - // Parses lifetime bounds. - ::std::vector Parser::parse_lifetime_bounds() { - ::std::vector lifetime_bounds; - - // TODO: think of better control structure - while (true) { - AST::Lifetime lifetime = parse_lifetime(); - - // quick exit for parsing failure - if (lifetime.is_error()) { - return lifetime_bounds; - } - - lifetime_bounds.push_back(::std::move(lifetime)); - - // plus is maybe required - spec defines it poorly, so assuming not required - if (lexer.peek_token()->get_id() != PLUS) { - return lifetime_bounds; - } - - lexer.skip_token(); - } - - return lifetime_bounds; - } - - // Parses a lifetime token (named, 'static, or '_). Also handles lifetime not existing. - AST::Lifetime Parser::parse_lifetime() { - const_TokenPtr lifetime_tok = lexer.peek_token(); - location_t locus = lifetime_tok->get_locus(); - // create error lifetime if doesn't exist - if (lifetime_tok->get_id() != LIFETIME) { - return AST::Lifetime::error(); - } - lexer.skip_token(); - - ::std::string lifetime_ident = lifetime_tok->get_str(); - - if (lifetime_ident == "'static") { - return AST::Lifetime(AST::Lifetime::STATIC, "", locus); - } else if (lifetime_ident == "'_") { - return AST::Lifetime(AST::Lifetime::WILDCARD, "", locus); - } else { - return AST::Lifetime(AST::Lifetime::NAMED, ::std::move(lifetime_ident), locus); - } - } - - // Parses a "type alias" (typedef) item. - ::std::unique_ptr Parser::parse_type_alias( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(TYPE); - - // TODO: use this token for identifier when finished that - const_TokenPtr alias_name_tok = expect_token(IDENTIFIER); - if (alias_name_tok == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse identifier in type alias"); - skip_after_semicolon(); - return NULL; - } - Identifier alias_name = alias_name_tok->get_str(); - - // parse generic params, which may not exist - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // parse where clause, which may not exist - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(EQUAL)) { - skip_after_semicolon(); - return NULL; - } - - ::std::unique_ptr type_to_alias = parse_type(); - - if (!skip_token(SEMICOLON)) { - // should be skipping past this, not the next line - return NULL; - } - - return ::std::unique_ptr(new AST::TypeAlias(::std::move(alias_name), - ::std::move(generic_params), ::std::move(where_clause), ::std::move(type_to_alias), - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // Parse a struct item AST node. - ::std::unique_ptr Parser::parse_struct( - AST::Visibility vis, ::std::vector outer_attrs) { - /* TODO: determine best way to parse the proper struct vs tuple struct - share most of - * initial constructs so lookahead might be impossible, and if not probably too expensive. - * Best way is probably unified parsing for the initial parts and then pass them in as params - * to more derived functions. Alternatively, just parse everything in this one function - - * do this if function not too long. */ - - /* Proper struct <- 'struct' IDENTIFIER generic_params? where_clause? ( '{' struct_fields? '}' - * | ';' ) */ - /* Tuple struct <- 'struct' IDENTIFIER generic_params? '(' tuple_fields? ')' - * where_clause? ';' */ - location_t locus = lexer.peek_token()->get_locus(); - skip_token(STRUCT_TOK); - - // parse struct name - const_TokenPtr name_tok = expect_token(IDENTIFIER); - if (name_tok == NULL) { - error_at( - lexer.peek_token()->get_locus(), "could not parse struct or tuple struct identifier"); - // skip after somewhere? - return NULL; - } - Identifier struct_name = name_tok->get_str(); - - // parse generic params, which may or may not exist - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // branch on next token - determines whether proper struct or tuple struct - if (lexer.peek_token()->get_id() == LEFT_PAREN) { - // tuple struct - - // skip left parenthesis - lexer.skip_token(); - - // parse tuple fields - ::std::vector tuple_fields = parse_tuple_fields(); - - // tuple parameters must have closing parenthesis - if (!skip_token(RIGHT_PAREN)) { - skip_after_semicolon(); - return NULL; - } - - // parse where clause, which is optional - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(SEMICOLON)) { - // can't skip after semicolon because it's meant to be here - return NULL; - } - - return ::std::unique_ptr(new AST::TupleStruct(::std::move(tuple_fields), - ::std::move(struct_name), ::std::move(generic_params), ::std::move(where_clause), - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // assume it is a proper struct being parsed and continue outside of switch - label only here - // to suppress warning - - // parse where clause, which is optional - AST::WhereClause where_clause = parse_where_clause(); - - // branch on next token - determines whether struct is a unit struct - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_CURLY: { - // struct with body - - // skip curly bracket - lexer.skip_token(); - - // parse struct fields, if any - ::std::vector struct_fields = parse_struct_fields(); - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::StructStruct(::std::move(struct_fields), ::std::move(struct_name), - ::std::move(generic_params), ::std::move(where_clause), false, ::std::move(vis), - ::std::move(outer_attrs), locus)); - } - case SEMICOLON: - // unit struct declaration - - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::StructStruct(::std::move(struct_name), ::std::move(generic_params), - ::std::move(where_clause), ::std::move(vis), ::std::move(outer_attrs), locus)); - default: - error_at(t->get_locus(), "unexpected token '%s' in struct declaration", - t->get_token_description()); - // skip somewhere? - return NULL; - } - } - - // Parses struct fields in struct declarations. - ::std::vector Parser::parse_struct_fields() { - ::std::vector fields; - - AST::StructField initial_field = parse_struct_field(); - - // Return empty field list if no field there - if (initial_field.is_error()) { - return fields; - } - - fields.push_back(::std::move(initial_field)); - - // maybe think of a better control structure here - do-while with an initial error state? - // basically, loop through field list until can't find any more params - while (true) { - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - - // skip comma if applies - lexer.skip_token(); - - AST::StructField field = parse_struct_field(); - - if (!field.is_error()) { - fields.push_back(::std::move(field)); - } else { - // this would occur with a trailing comma, which is allowed - break; - } - } - - return fields; - - // TODO: this shares basically all code with function params and tuple fields - templates? - } - - // Parses a single struct field (in a struct definition). Does not parse commas. - AST::StructField Parser::parse_struct_field() { - // parse outer attributes, if they exist - ::std::vector outer_attrs = parse_outer_attributes(); - - // parse visibility, if it exists - AST::Visibility vis = parse_visibility(); - - // parse field name - const_TokenPtr field_name_tok = lexer.peek_token(); - if (field_name_tok->get_id() != IDENTIFIER) { - // if not identifier, assumes there is no struct field and exits - not necessarily error - return AST::StructField::create_error(); - } - Identifier field_name = field_name_tok->get_str(); - lexer.skip_token(); - - if (!skip_token(COLON)) { - // skip after somewhere? - return AST::StructField::create_error(); - } - - // parse field type - this is required - ::std::unique_ptr field_type = parse_type(); - if (field_type == NULL) { - error_at( - lexer.peek_token()->get_locus(), "could not parse type in struct field definition"); - // skip after somewhere - return AST::StructField::create_error(); - } - - return AST::StructField(::std::move(field_name), ::std::move(field_type), ::std::move(vis), - ::std::move(outer_attrs)); - } - - // Parses tuple fields in tuple/tuple struct declarations. - ::std::vector Parser::parse_tuple_fields() { - ::std::vector fields; - - AST::TupleField initial_field = parse_tuple_field(); - - // Return empty field list if no field there - if (initial_field.is_error()) { - return fields; - } - - fields.push_back(::std::move(initial_field)); - - // maybe think of a better control structure here - do-while with an initial error state? - // basically, loop through field list until can't find any more params - // HACK: all current syntax uses of tuple fields have them ending with a right paren token - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - // skip comma if applies - e.g. trailing comma - lexer.skip_token(); - - // break out due to right paren if it exists - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - AST::TupleField field = parse_tuple_field(); - if (field.is_error()) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse tuple field in tuple fields"); - return ::std::vector(); - } - - fields.push_back(::std::move(field)); - - t = lexer.peek_token(); - } - - return fields; - - // TODO: this shares basically all code with function params and struct fields - templates? - } - - // Parses a single tuple struct field in a tuple struct definition. Does not parse commas. - AST::TupleField Parser::parse_tuple_field() { - // parse outer attributes if they exist - ::std::vector outer_attrs = parse_outer_attributes(); - - // parse visibility if it exists - AST::Visibility vis = parse_visibility(); - - // parse type, which is required - ::std::unique_ptr field_type = parse_type(); - if (field_type == NULL) { - // error if null - error_at(lexer.peek_token()->get_locus(), "could not parse type in tuple struct field"); - // skip after something - return AST::TupleField::create_error(); - } - - return AST::TupleField(::std::move(field_type), ::std::move(vis), ::std::move(outer_attrs)); - } - - // Parses a Rust "enum" tagged union item definition. - ::std::unique_ptr Parser::parse_enum( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(ENUM_TOK); - - // parse enum name - const_TokenPtr enum_name_tok = expect_token(IDENTIFIER); - Identifier enum_name = enum_name_tok->get_str(); - - // parse generic params (of enum container, not enum variants) if they exist - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // parse where clause if it exists - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(LEFT_CURLY)) { - skip_after_end_block(); - return NULL; - } - - // parse actual enum variant definitions - ::std::vector< ::std::unique_ptr > enum_items = parse_enum_items(); - - if (!skip_token(RIGHT_CURLY)) { - skip_after_end_block(); - return NULL; - } - - return ::std::unique_ptr( - new AST::Enum(::std::move(enum_name), ::std::move(vis), ::std::move(generic_params), - ::std::move(where_clause), ::std::move(enum_items), ::std::move(outer_attrs), locus)); - } - - // Parses the enum variants inside an enum definiton. - ::std::vector< ::std::unique_ptr > Parser::parse_enum_items() { - ::std::vector< ::std::unique_ptr > items; - - ::std::unique_ptr initial_item = parse_enum_item(); - - // Return empty item list if no field there - if (initial_item == NULL) { - return items; - } - - items.push_back(::std::move(initial_item)); - - // maybe think of a better control structure here - do-while with an initial error state? - // basically, loop through item list until can't find any more params - while (true) { - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - - // skip comma if applies - lexer.skip_token(); - - ::std::unique_ptr item = parse_enum_item(); - - if (item != NULL) { - items.push_back(::std::move(item)); - } else { - // this would occur with a trailing comma, which is allowed - break; - } - } - - // TODO: does this need move? - return items; - - // TODO: shares virtually all code with function params, tuple and struct fields - templates? - } - - // Parses a single enum variant item in an enum definition. Does not parse commas. - ::std::unique_ptr Parser::parse_enum_item() { - // parse outer attributes if they exist - ::std::vector outer_attrs = parse_outer_attributes(); - - // parse name for enum item, which is required - const_TokenPtr item_name_tok = lexer.peek_token(); - if (item_name_tok->get_id() != IDENTIFIER) { - // this may not be an error but it means there is no enum item here - return NULL; - } - lexer.skip_token(); - Identifier item_name = item_name_tok->get_str(); - - // branch based on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_PAREN: { - // tuple enum item - lexer.skip_token(); - - ::std::vector tuple_fields = parse_tuple_fields(); - - if (!skip_token(RIGHT_PAREN)) { - // skip after somewhere - return NULL; - } - - return ::std::unique_ptr( - new AST::EnumItemTuple(::std::move(item_name), ::std::move(tuple_fields), - ::std::move(outer_attrs), item_name_tok->get_locus())); - } - case LEFT_CURLY: { - // struct enum item - lexer.skip_token(); - - ::std::vector struct_fields = parse_struct_fields(); - - if (!skip_token(RIGHT_CURLY)) { - // skip after somewhere - return NULL; - } - - return ::std::unique_ptr( - new AST::EnumItemStruct(::std::move(item_name), ::std::move(struct_fields), - ::std::move(outer_attrs), item_name_tok->get_locus())); - } - case EQUAL: { - // discriminant enum item - lexer.skip_token(); - - ::std::unique_ptr discriminant_expr = parse_expr(); - - return ::std::unique_ptr(new AST::EnumItemDiscriminant( - ::std::move(item_name), ::std::move(discriminant_expr), ::std::move(outer_attrs), - item_name_tok->get_locus())); - } - default: - // regular enum with just an identifier - return ::std::unique_ptr(new AST::EnumItem( - ::std::move(item_name), ::std::move(outer_attrs), item_name_tok->get_locus())); - } - } - - // Parses a C-style (and C-compat) untagged union declaration. - ::std::unique_ptr Parser::parse_union( - AST::Visibility vis, ::std::vector outer_attrs) { - // hack - "weak keyword" by finding identifier called "union" (lookahead in item switch) - location_t locus = lexer.peek_token()->get_locus(); - // skip union "identifier" - skip_token(IDENTIFIER); - - // parse actual union name - const_TokenPtr union_name_tok = expect_token(IDENTIFIER); - if (union_name_tok == NULL) { - skip_after_next_block(); - return NULL; - } - Identifier union_name = union_name_tok->get_str(); - - // parse optional generic parameters - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // parse optional where clause - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(LEFT_CURLY)) { - skip_after_end_block(); - return NULL; - } - - // parse union inner items as "struct fields" because hey, syntax reuse. Spec said so. - ::std::vector union_fields = parse_struct_fields(); - - if (!skip_token(RIGHT_CURLY)) { - // skip after somewhere - return NULL; - } - - return ::std::unique_ptr( - new AST::Union(::std::move(union_name), ::std::move(vis), ::std::move(generic_params), - ::std::move(where_clause), ::std::move(union_fields), ::std::move(outer_attrs), locus)); - } - - // Parses a "constant item" (compile-time constant to maybe "inline" throughout the program). - ::std::unique_ptr Parser::parse_const_item( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(CONST); - - // get constant identifier - this is either a proper identifier or the _ wildcard - const_TokenPtr ident_tok = lexer.peek_token(); - // make default identifier the underscore wildcard one - ::std::string ident("_"); - switch (ident_tok->get_id()) { - case IDENTIFIER: - ident = ident_tok->get_str(); - lexer.skip_token(); - break; - case UNDERSCORE: - // do nothing - identifier is already "_" - lexer.skip_token(); - break; - default: - error_at(ident_tok->get_locus(), - "expected item name (identifier or '_') in constant item declaration - found '%s'", - ident_tok->get_token_description()); - skip_after_semicolon(); - return NULL; - } - - if (!skip_token(COLON)) { - skip_after_semicolon(); - return NULL; - } - - // parse constant type (required) - ::std::unique_ptr type = parse_type(); - - if (!skip_token(EQUAL)) { - skip_after_semicolon(); - return NULL; - } - - // parse constant expression (required) - ::std::unique_ptr expr = parse_expr(); - - if (!skip_token(SEMICOLON)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::ConstantItem(::std::move(ident), - ::std::move(vis), ::std::move(type), ::std::move(expr), ::std::move(outer_attrs), locus)); - } - - // Parses a "static item" (static storage item, with 'static lifetime). - ::std::unique_ptr Parser::parse_static_item( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(STATIC_TOK); - - // determine whether static item is mutable - bool is_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - is_mut = true; - lexer.skip_token(); - } - - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - if (!skip_token(COLON)) { - skip_after_semicolon(); - return NULL; - } - - // parse static item type (required) - ::std::unique_ptr type = parse_type(); - - if (!skip_token(EQUAL)) { - skip_after_semicolon(); - return NULL; - } - - // parse static item expression (required) - ::std::unique_ptr expr = parse_expr(); - - if (!skip_token(SEMICOLON)) { - // skip after somewhere - return NULL; - } - - return ::std::unique_ptr(new AST::StaticItem(::std::move(ident), is_mut, - ::std::move(type), ::std::move(expr), ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // Parses a trait definition item, including unsafe ones. - ::std::unique_ptr Parser::parse_trait( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - bool is_unsafe = false; - if (lexer.peek_token()->get_id() == UNSAFE) { - is_unsafe = true; - lexer.skip_token(); - } - - skip_token(TRAIT); - - // parse trait name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - // parse generic parameters (if they exist) - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // create placeholder type param bounds in case they don't exist - ::std::vector< ::std::unique_ptr > type_param_bounds; - - // parse type param bounds (if they exist) - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - - // TODO: does this need move? - type_param_bounds = parse_type_param_bounds(); - } - - // parse where clause (if it exists) - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(LEFT_CURLY)) { - skip_after_end_block(); - return NULL; - } - - // parse trait items - ::std::vector< ::std::unique_ptr > trait_items; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr trait_item = parse_trait_item(); - - if (trait_item == NULL) { - // TODO: this is probably an error as next character should equal RIGHT_CURLY - break; - } - - trait_items.push_back(::std::move(trait_item)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_CURLY)) { - // skip after something - return NULL; - } - - return ::std::unique_ptr(new AST::Trait(::std::move(ident), is_unsafe, - ::std::move(generic_params), ::std::move(type_param_bounds), ::std::move(where_clause), - ::std::move(trait_items), ::std::move(vis), ::std::move(outer_attrs), locus)); - } - - // Parses a trait item used inside traits (not trait, the Item). - ::std::unique_ptr Parser::parse_trait_item() { - // parse outer attributes (if they exist) - ::std::vector outer_attrs = parse_outer_attributes(); - - // lookahead to determine what type of trait item to parse - const_TokenPtr tok = lexer.peek_token(); - switch (tok->get_id()) { - case TYPE: - return parse_trait_type(::std::move(outer_attrs)); - case CONST: - // disambiguate with function qualifier - if (lexer.peek_token(1)->get_id() == IDENTIFIER) { - return parse_trait_const(::std::move(outer_attrs)); - } - // else, fallthrough to function - // TODO: find out how to disable gcc "implicit fallthrough" error - gcc_fallthrough(); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: { - /* function and method can't be disambiguated by lookahead alone (without a lot of - * work and waste), so either make a "parse_trait_function_or_method" or parse here - * mostly and pass in most parameters (or if short enough, parse whole thing here). */ - // parse function and method here - - // parse function or method qualifiers - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - skip_token(FN_TOK); - - // parse function or method name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - // parse generic params - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - if (!skip_token(LEFT_PAREN)) { - // skip after somewhere? - return NULL; - } - - // now for function vs method disambiguation - method has opening "self" param - AST::SelfParam self_param = parse_self_param(); - // FIXME: ensure that self param doesn't accidently consume tokens for a function - bool is_method = false; - if (!self_param.is_error()) { - is_method = true; - - // skip comma so function and method regular params can be parsed in same way - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - } - - // parse trait function params - ::std::vector function_params = parse_function_params(); - - if (!skip_token(RIGHT_PAREN)) { - // skip after somewhere? - return NULL; - } - - // parse return type (optional) - ::std::unique_ptr return_type = parse_function_return_type(); - - // parse where clause (optional) - AST::WhereClause where_clause = parse_where_clause(); - - // parse semicolon or function definition (in block) - const_TokenPtr t = lexer.peek_token(); - ::std::unique_ptr definition = NULL; - switch (t->get_id()) { - case SEMICOLON: - lexer.skip_token(); - // definition is already NULL, so don't need to change it - break; - case LEFT_CURLY: - definition = parse_block_expr(); - // FIXME: are these outer attributes meant to be passed into the block? - break; - default: - error_at(t->get_locus(), - "expected ';' or definiton at the end of trait %s definition - found '%s' " - "instead", - is_method ? "method" : "function", t->get_token_description()); - // skip? - return NULL; - } - - // do actual if instead of ternary for return value optimisation - if (is_method) { - AST::TraitMethodDecl method_decl(::std::move(ident), ::std::move(qualifiers), - ::std::move(generic_params), ::std::move(self_param), - ::std::move(function_params), ::std::move(return_type), - ::std::move(where_clause)); - - // TODO: does this (method_decl) need move? - return ::std::unique_ptr( - new AST::TraitItemMethod(::std::move(method_decl), ::std::move(definition), - ::std::move(outer_attrs), tok->get_locus())); - } else { - AST::TraitFunctionDecl function_decl(::std::move(ident), ::std::move(qualifiers), - ::std::move(generic_params), ::std::move(function_params), - ::std::move(return_type), ::std::move(where_clause)); - - return ::std::unique_ptr( - new AST::TraitItemFunc(::std::move(function_decl), ::std::move(definition), - ::std::move(outer_attrs), tok->get_locus())); - } - } - default: { - // TODO: try and parse macro invocation semi - if fails, maybe error. - ::std::unique_ptr macro_invoc - = parse_macro_invocation_semi(outer_attrs); - - if (macro_invoc == NULL) { - // TODO: error? - return NULL; - } else { - return macro_invoc; - } - // FIXME: macro invocations can only start with certain tokens. be more picky with - // these? - } - } - } - - // Parse a typedef trait item. - ::std::unique_ptr Parser::parse_trait_type( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(TYPE); - - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - bool has_colon = false; - ::std::vector< ::std::unique_ptr > bounds; - - // parse optional colon - if (lexer.peek_token()->get_id() == COLON) { - has_colon = true; - lexer.skip_token(); - - // parse optional type param bounds - bounds = parse_type_param_bounds(); - } - - if (!skip_token(SEMICOLON)) { - // skip? - return NULL; - } - - return ::std::unique_ptr(new AST::TraitItemType( - ::std::move(ident), ::std::move(bounds), ::std::move(outer_attrs), locus)); - } - - // Parses a constant trait item. - ::std::unique_ptr Parser::parse_trait_const( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(CONST); - - // parse constant item name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - if (!skip_token(COLON)) { - skip_after_semicolon(); - return NULL; - } - - // parse constant trait item type - ::std::unique_ptr type = parse_type(); - - // parse constant trait body expression, if it exists - ::std::unique_ptr const_body = NULL; - if (lexer.peek_token()->get_id() == EQUAL) { - lexer.skip_token(); - - // expression must exist, so parse it - const_body = parse_expr(); - } - - if (!skip_token(SEMICOLON)) { - // skip after something? - return NULL; - } - - return ::std::unique_ptr(new AST::TraitItemConst(::std::move(ident), - ::std::move(type), ::std::move(const_body), ::std::move(outer_attrs), locus)); - } - - // Parses a struct "impl" item (both inherent impl and trait impl can be parsed here), - ::std::unique_ptr Parser::parse_impl( - AST::Visibility vis, ::std::vector outer_attrs) { - /* Note that only trait impls are allowed to be unsafe. So if unsafe, it must be a trait - * impl. However, this isn't enough for full disambiguation, so don't branch here. */ - location_t locus = lexer.peek_token()->get_locus(); - bool is_unsafe = false; - if (lexer.peek_token()->get_id() == UNSAFE) { - lexer.skip_token(); - is_unsafe = true; - } - - if (!skip_token(IMPL)) { - skip_after_next_block(); - return NULL; - } - - // parse generic params (shared by trait and inherent impls) - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // Again, trait impl-only feature, but optional one, so can be used for branching yet. - bool has_exclam = false; - if (lexer.peek_token()->get_id() == EXCLAM) { - lexer.skip_token(); - has_exclam = true; - } - - /* FIXME: code that doesn't look shit for TypePath. Also, make sure this doesn't parse too - * much and not work. */ - AST::TypePath type_path = parse_type_path(); - if (type_path.is_error() || lexer.peek_token()->get_id() != FOR) { - // cannot parse type path (or not for token next, at least), so must be inherent impl - - // hacky conversion of TypePath stack object to Type pointer - ::std::unique_ptr type = NULL; - if (!type_path.is_error()) { - // TODO: would move work here? - type = ::std::unique_ptr(new AST::TypePath(type_path)); - } else { - type = parse_type(); - } - // Type is required, so error if null - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse type in inherent impl"); - skip_after_next_block(); - return NULL; - } - - // parse optional where clause - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(LEFT_CURLY)) { - // TODO: does this still skip properly? - skip_after_end_block(); - return NULL; - } - - // parse inner attributes (optional) - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse inherent impl items - ::std::vector< ::std::unique_ptr > impl_items; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr impl_item = parse_inherent_impl_item(); - - if (impl_item == NULL) { - // TODO: this is probably an error as next character should equal RIGHT_CURLY - fprintf(stderr, - "impl item is null and next char wasn't RIGHT_CURLY - probably an error"); - break; - } - - impl_items.push_back(::std::move(impl_item)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere - return NULL; - } - - // DEBUG - fprintf(stderr, "successfully parsed inherent impl\n"); - - return ::std::unique_ptr(new AST::InherentImpl(::std::move(impl_items), - ::std::move(generic_params), ::std::move(type), ::std::move(where_clause), - ::std::move(vis), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else { - // type path must both be valid and next token is for, so trait impl - if (!skip_token(FOR)) { - skip_after_next_block(); - return NULL; - } - - // parse type - ::std::unique_ptr type = parse_type(); - // ensure type is included as it is required - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse type in trait impl"); - skip_after_next_block(); - return NULL; - } - - // parse optional where clause - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(LEFT_CURLY)) { - // TODO: does this still skip properly? - skip_after_end_block(); - return NULL; - } - - // parse inner attributes (optional) - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse trait impl items - ::std::vector< ::std::unique_ptr > impl_items; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr impl_item = parse_trait_impl_item(); - - if (impl_item == NULL) { - // DEBUG - fprintf( - stderr, "break out of parsing trait impl items (due to parse giving null)\n"); - - // TODO: this is probably an error as next character should equal RIGHT_CURLY - break; - } - - impl_items.push_back(::std::move(impl_item)); - - t = lexer.peek_token(); - - // DEBUG - fprintf(stderr, "successfully parsed a trait impl item\n"); - } - // DEBUG - fprintf(stderr, "successfully finished trait impl items\n"); - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere - return NULL; - } - - // DEBUG - fprintf(stderr, "successfully parsed trait impl\n"); - - return ::std::unique_ptr(new AST::TraitImpl(::std::move(type_path), - is_unsafe, has_exclam, ::std::move(impl_items), ::std::move(generic_params), - ::std::move(type), ::std::move(where_clause), ::std::move(vis), - ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - } - - // Parses a single inherent impl item (item inside an inherent impl block). - ::std::unique_ptr Parser::parse_inherent_impl_item() { - // parse outer attributes (if they exist) - ::std::vector outer_attrs = parse_outer_attributes(); - - // TODO: cleanup - currently an unreadable mess - - // branch on next token: - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: - // these seem to be SimplePath tokens, so this is a macro invocation semi - return parse_macro_invocation_semi(::std::move(outer_attrs)); - case PUB: { - // visibility, so not a macro invocation semi - must be constant, function, or method - AST::Visibility vis = parse_visibility(); - - // TODO: is a recursive call to parse_inherent_impl_item better? - switch (lexer.peek_token()->get_id()) { - case EXTERN_TOK: - case UNSAFE: - case FN_TOK: - // function or method - return parse_inherent_impl_function_or_method( - ::std::move(vis), ::std::move(outer_attrs)); - case CONST: - // lookahead to resolve production - could be function/method or const item - t = lexer.peek_token(1); - - switch (t->get_id()) { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_inherent_impl_function_or_method( - ::std::move(vis), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of const item in inherent impl", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - default: - error_at(t->get_locus(), "unrecognised token '%s' for item in inherent impl", - t->get_token_description()); - // skip? - return NULL; - } - } - case EXTERN_TOK: - case UNSAFE: - case FN_TOK: - // function or method - return parse_inherent_impl_function_or_method( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - case CONST: - // lookahead to resolve production - could be function/method or const item - t = lexer.peek_token(1); - - switch (t->get_id()) { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_inherent_impl_function_or_method( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of const item in inherent impl", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - gcc_unreachable(); - default: - error_at(t->get_locus(), "unrecognised token '%s' for item in inherent impl", - t->get_token_description()); - // skip? - return NULL; - } - } - - /* For internal use only by parse_inherent_impl_item() - splits giant method into smaller ones - * and prevents duplication of logic. Strictly, this parses a function or method item inside an - * inherent impl item block. */ - // TODO: make this a templated function with "return type" as type param - InherentImplItem is this - // specialisation of the template while TraitImplItem will be the other. - ::std::unique_ptr Parser::parse_inherent_impl_function_or_method( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - // parse function or method qualifiers - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - skip_token(FN_TOK); - - // parse function or method name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - // parse generic params - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - if (!skip_token(LEFT_PAREN)) { - // skip after somewhere? - return NULL; - } - - // now for function vs method disambiguation - method has opening "self" param - AST::SelfParam self_param = parse_self_param(); - // FIXME: ensure that self param doesn't accidently consume tokens for a function - // one idea is to lookahead up to 4 tokens to see whether self is one of them - bool is_method = false; - if (!self_param.is_error()) { - is_method = true; - - // skip comma so function and method regular params can be parsed in same way - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - } - - // parse trait function params - ::std::vector function_params = parse_function_params(); - - if (!skip_token(RIGHT_PAREN)) { - skip_after_end_block(); - return NULL; - } - - // parse return type (optional) - ::std::unique_ptr return_type = parse_function_return_type(); - - // parse where clause (optional) - AST::WhereClause where_clause = parse_where_clause(); - - // parse function definition (in block) - semicolon not allowed - if (lexer.peek_token()->get_id() == SEMICOLON) { - error_at(lexer.peek_token()->get_locus(), - "%s declaration in inherent impl not allowed - must have a definition", - is_method ? "method" : "function"); - lexer.skip_token(); - return NULL; - } - ::std::unique_ptr body = parse_block_expr(); - if (body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse definition in inherent impl %s definition", - is_method ? "method" : "function"); - skip_after_end_block(); - return NULL; - } - - // do actual if instead of ternary for return value optimisation - if (is_method) { - return ::std::unique_ptr(new AST::Method(::std::move(ident), - ::std::move(qualifiers), ::std::move(generic_params), ::std::move(self_param), - ::std::move(function_params), ::std::move(return_type), ::std::move(where_clause), - ::std::move(body), ::std::move(vis), ::std::move(outer_attrs), locus)); - } else { - return ::std::unique_ptr(new AST::Function(::std::move(ident), - ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), - ::std::move(return_type), ::std::move(where_clause), ::std::move(body), - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - } - - // Parses a single trait impl item (item inside a trait impl block). - ::std::unique_ptr Parser::parse_trait_impl_item() { - // parse outer attributes (if they exist) - ::std::vector outer_attrs = parse_outer_attributes(); - - // TODO: clean this function up, it is basically unreadable hacks - - // branch on next token: - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: - // these seem to be SimplePath tokens, so this is a macro invocation semi - return parse_macro_invocation_semi(::std::move(outer_attrs)); - case TYPE: - return parse_type_alias(AST::Visibility::create_error(), ::std::move(outer_attrs)); - case PUB: { - // visibility, so not a macro invocation semi - must be constant, function, or method - AST::Visibility vis = parse_visibility(); - - // TODO: is a recursive call to parse_trait_impl_item better? - switch (lexer.peek_token()->get_id()) { - case TYPE: - return parse_type_alias(::std::move(vis), ::std::move(outer_attrs)); - case EXTERN_TOK: - case UNSAFE: - case FN_TOK: - // function or method - return parse_trait_impl_function_or_method( - ::std::move(vis), ::std::move(outer_attrs)); - case CONST: - // lookahead to resolve production - could be function/method or const item - t = lexer.peek_token(1); - - switch (t->get_id()) { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item(::std::move(vis), ::std::move(outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_trait_impl_function_or_method( - ::std::move(vis), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of const item in trait impl", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - default: - error_at(t->get_locus(), "unrecognised token '%s' for item in trait impl", - t->get_token_description()); - // skip? - return NULL; - } - } - case EXTERN_TOK: - case UNSAFE: - case FN_TOK: - // function or method - return parse_trait_impl_function_or_method( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - case CONST: - // lookahead to resolve production - could be function/method or const item - t = lexer.peek_token(1); - - switch (t->get_id()) { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_trait_impl_function_or_method( - AST::Visibility::create_error(), ::std::move(outer_attrs)); - default: - error_at(t->get_locus(), - "unexpected token '%s' in some sort of const item in trait impl", - t->get_token_description()); - lexer.skip_token(1); // TODO: is this right thing to do? - return NULL; - } - gcc_unreachable(); - default: - error_at(t->get_locus(), "unrecognised token '%s' for item in trait impl", - t->get_token_description()); - // skip? - return NULL; - } - } - - /* For internal use only by parse_trait_impl_item() - splits giant method into smaller ones - * and prevents duplication of logic. Strictly, this parses a function or method item inside a - * trait impl item block. */ - ::std::unique_ptr Parser::parse_trait_impl_function_or_method( - AST::Visibility vis, ::std::vector outer_attrs) { - // this shares virtually all logic with parse_inherent_impl_function_or_method - template? - location_t locus = lexer.peek_token()->get_locus(); - - // parse function or method qualifiers - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - skip_token(FN_TOK); - - // parse function or method name - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - return NULL; - } - Identifier ident = ident_tok->get_str(); - - // DEBUG: - fprintf(stderr, "about to start parsing generic params in trait impl function or method\n"); - - // parse generic params - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - // DEBUG: - fprintf(stderr, "finished parsing generic params in trait impl function or method\n"); - - if (!skip_token(LEFT_PAREN)) { - // skip after somewhere? - return NULL; - } - - // now for function vs method disambiguation - method has opening "self" param - AST::SelfParam self_param = parse_self_param(); - // FIXME: ensure that self param doesn't accidently consume tokens for a function - bool is_method = false; - if (!self_param.is_error()) { - is_method = true; - - // skip comma so function and method regular params can be parsed in same way - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - - // DEBUG - fprintf(stderr, "successfully parsed self param in method trait impl item\n"); - } - - // DEBUG - fprintf(stderr, "started to parse function params in function or method trait impl item\n"); - - // parse trait function params (only if next token isn't right paren) - ::std::vector function_params; - if (lexer.peek_token()->get_id() != RIGHT_PAREN) { - function_params = parse_function_params(); - - if (function_params.empty()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse function params in trait impl %s definition", - is_method ? "method" : "function"); - skip_after_next_block(); - return NULL; - } - } - - // FIXME: segfault occurs during parsing of function params - - // DEBUG - fprintf( - stderr, "successfully parsed function params in function or method trait impl item\n"); - - if (!skip_token(RIGHT_PAREN)) { - skip_after_next_block(); - return NULL; - } - - // parse return type (optional) - ::std::unique_ptr return_type = parse_function_return_type(); - - // DEBUG - fprintf(stderr, "successfully parsed return type in function or method trait impl item\n"); - - // parse where clause (optional) - AST::WhereClause where_clause = parse_where_clause(); - - // DEBUG - fprintf(stderr, "successfully parsed where clause in function or method trait impl item\n"); - - // parse function definition (in block) - semicolon not allowed - if (lexer.peek_token()->get_id() == SEMICOLON) { - error_at(lexer.peek_token()->get_locus(), - "%s declaration in trait impl not allowed - must have a definition", - is_method ? "method" : "function"); - lexer.skip_token(); - return NULL; - } - ::std::unique_ptr body = parse_block_expr(); - if (body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse definition in trait impl %s definition", - is_method ? "method" : "function"); - skip_after_end_block(); - return NULL; - } - - // do actual if instead of ternary for return value optimisation - if (is_method) { - return ::std::unique_ptr(new AST::Method(::std::move(ident), - ::std::move(qualifiers), ::std::move(generic_params), ::std::move(self_param), - ::std::move(function_params), ::std::move(return_type), ::std::move(where_clause), - ::std::move(body), ::std::move(vis), ::std::move(outer_attrs), locus)); - } else { - return ::std::unique_ptr(new AST::Function(::std::move(ident), - ::std::move(qualifiers), ::std::move(generic_params), ::std::move(function_params), - ::std::move(return_type), ::std::move(where_clause), ::std::move(body), - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - } - - // Parses an extern block of declarations. - ::std::unique_ptr Parser::parse_extern_block( - AST::Visibility vis, ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(EXTERN_TOK); - - // detect optional abi name - ::std::string abi; - const_TokenPtr next_tok = lexer.peek_token(); - if (next_tok->get_id() == STRING_LITERAL) { - lexer.skip_token(); - abi = next_tok->get_str(); - } - - if (!skip_token(LEFT_CURLY)) { - skip_after_end_block(); - return NULL; - } - - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse declarations inside extern block - ::std::vector< ::std::unique_ptr > extern_items; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ::std::unique_ptr extern_item = parse_external_item(); - - if (extern_item == NULL) { - error_at(t->get_locus(), - "failed to parse external item despite not reaching end of extern block"); - return NULL; - } - - extern_items.push_back(::std::move(extern_item)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere - return NULL; - } - - return ::std::unique_ptr( - new AST::ExternBlock(::std::move(abi), ::std::move(extern_items), ::std::move(vis), - ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - - // Parses a single extern block item (static or function declaration). - ::std::unique_ptr Parser::parse_external_item() { - // parse optional outer attributes - ::std::vector outer_attrs = parse_outer_attributes(); - - location_t locus = lexer.peek_token()->get_locus(); - - // parse optional visibility - AST::Visibility vis = parse_visibility(); - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case STATIC_TOK: { - // parse extern static item - lexer.skip_token(); - - // parse mut (optional) - bool has_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - lexer.skip_token(); - has_mut = true; - } - - // parse identifier - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - skip_after_semicolon(); - return NULL; - } - Identifier ident = ident_tok->get_str(); - - if (!skip_token(COLON)) { - skip_after_semicolon(); - return NULL; - } - - // parse type (required) - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse type in external static item"); - skip_after_semicolon(); - return NULL; - } - - if (!skip_token(SEMICOLON)) { - // skip after somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ExternalStaticItem(::std::move(ident), ::std::move(type), has_mut, - ::std::move(vis), ::std::move(outer_attrs), locus)); - } - case FN_TOK: { - // parse extern function declaration item - // skip function token - lexer.skip_token(); - - // parse identifier - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - skip_after_semicolon(); - return NULL; - } - Identifier ident = ident_tok->get_str(); - - // parse (optional) generic params - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - if (!skip_token(LEFT_PAREN)) { - skip_after_semicolon(); - return NULL; - } - - // parse parameters - ::std::vector function_params; - bool is_variadic = false; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - AST::NamedFunctionParam param = parse_named_function_param(); - - if (param.is_error()) { - // is this an error? probably - error_at(t->get_locus(), - "could not parse named function parameter in external function"); - skip_after_semicolon(); - return NULL; - } - - function_params.push_back(::std::move(param)); - - t = lexer.peek_token(); - if (t->get_id() != COMMA) { - if (t->get_id() != RIGHT_PAREN) { - error_at(t->get_locus(), - "expected comma or right parentheses in named function parameters, " - "found '%s'", - t->get_token_description()); - } else { - // end of loop - break; - } - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - - // parse variadic ... if it exists - if (t->get_id() == ELLIPSIS && lexer.peek_token(1)->get_id() == RIGHT_PAREN) { - lexer.skip_token(); - - is_variadic = true; - - t = lexer.peek_token(); - } - } - - if (!skip_token(RIGHT_PAREN)) { - skip_after_semicolon(); - return NULL; - } - - // parse (optional) return type - ::std::unique_ptr return_type = parse_function_return_type(); - - // parse (optional) where clause - AST::WhereClause where_clause = parse_where_clause(); - - if (!skip_token(SEMICOLON)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ExternalFunctionItem(::std::move(ident), ::std::move(generic_params), - ::std::move(return_type), ::std::move(where_clause), ::std::move(function_params), - is_variadic, ::std::move(vis), ::std::move(outer_attrs), locus)); - } - default: - // error - error_at(t->get_locus(), "unrecognised token '%s' in extern block item declaration", - t->get_token_description()); - skip_after_semicolon(); - return NULL; - } - } - - // Parses an extern block function param (with "pattern" being _ or an identifier). - AST::NamedFunctionParam Parser::parse_named_function_param() { - // parse identifier/_ - Identifier name; - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - name = t->get_str(); - lexer.skip_token(); - break; - case UNDERSCORE: - name = "_"; - lexer.skip_token(); - break; - default: - // this is not a function param, but not necessarily an error - return AST::NamedFunctionParam::create_error(); - } - - if (!skip_token(COLON)) { - // skip after somewhere? - return AST::NamedFunctionParam::create_error(); - } - - // parse (required) type - ::std::unique_ptr param_type = parse_type(); - if (param_type == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse param type in extern block function declaration"); - skip_after_semicolon(); - return AST::NamedFunctionParam::create_error(); - } - - return AST::NamedFunctionParam(::std::move(name), ::std::move(param_type)); - } - - // Parses a statement (will further disambiguate any statement). - ::std::unique_ptr Parser::parse_stmt() { - // quick exit for empty statement - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() == SEMICOLON) { - lexer.skip_token(); - return ::std::unique_ptr(new AST::EmptyStmt(t->get_locus())); - } - - // parse outer attributes - ::std::vector outer_attrs = parse_outer_attributes(); - - // parsing this will be annoying because of the many different possibilities - /* best may be just to copy paste in parse_item switch, and failing that try to parse outer - * attributes, and then pass them in to either a let statement or (fallback) expression - * statement. */ - // FIXME: think of a way to do this without such a large switch? - t = lexer.peek_token(); - switch (t->get_id()) { - case LET: - // let statement - return parse_let_stmt(::std::move(outer_attrs)); - case PUB: - case MOD: - case EXTERN_TOK: - case USE: - case FN_TOK: - case TYPE: - case STRUCT_TOK: - case ENUM_TOK: - case CONST: - case STATIC_TOK: - case TRAIT: - case IMPL: - /* TODO: implement union keyword but not really because of context-dependence - * crappy hack way to parse a union written below to separate it from the good code. */ - // case UNION: - case UNSAFE: // maybe - unsafe traits are a thing - // if any of these (should be all possible VisItem prefixes), parse a VisItem - // can't parse item because would require reparsing outer attributes - return parse_vis_item(::std::move(outer_attrs)); - break; - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: - // almost certainly macro invocation semi - return parse_macro_item(::std::move(outer_attrs)); - break; - // crappy hack to do union "keyword" - case IDENTIFIER: - // TODO: ensure std::string and literal comparison works - if (t->get_str() == "union") { - return parse_vis_item(::std::move(outer_attrs)); - // or should this go straight to parsing union? - } else if (t->get_str() == "macro_rules") { - // macro_rules! macro item - return parse_macro_item(::std::move(outer_attrs)); - } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION - || lexer.peek_token(1)->get_id() == EXCLAM) { - // FIXME: ensure doesn't take any expressions by mistake - // path (probably) or macro invocation, so probably a macro invocation semi - return parse_macro_item(::std::move(outer_attrs)); - } - gcc_fallthrough(); - // TODO: find out how to disable gcc "implicit fallthrough" warning - default: - // fallback: expression statement - return parse_expr_stmt(::std::move(outer_attrs)); - break; - } - } - - // Parses a let statement. - ::std::unique_ptr Parser::parse_let_stmt( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(LET); - - // parse pattern (required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in let statement"); - skip_after_semicolon(); - return NULL; - } - - // parse type declaration (optional) - ::std::unique_ptr type = NULL; - if (lexer.peek_token()->get_id() == COLON) { - // must have a type declaration - lexer.skip_token(); - - type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse type in let statement"); - skip_after_semicolon(); - return NULL; - } - } - - // parse expression to set variable to (optional) - ::std::unique_ptr expr = NULL; - if (lexer.peek_token()->get_id() == EQUAL) { - // must have an expression - lexer.skip_token(); - - expr = parse_expr(); - if (expr == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse expression in let statement"); - skip_after_semicolon(); - return NULL; - } - } - - if (!skip_token(SEMICOLON)) { - // skip after somewhere - return NULL; - // TODO: how wise is it to ditch a mostly-valid let statement just because a semicolon is - // missing? - } - - return ::std::unique_ptr(new AST::LetStmt(::std::move(pattern), - ::std::move(expr), ::std::move(type), ::std::move(outer_attrs), locus)); - } - - // Parses a type path. - AST::TypePath Parser::parse_type_path() { - bool has_opening_scope_resolution = false; - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { - has_opening_scope_resolution = true; - lexer.skip_token(); - } - - // create segment vector - ::std::vector< ::std::unique_ptr > segments; - - // parse required initial segment - ::std::unique_ptr initial_segment = parse_type_path_segment(); - if (initial_segment == NULL) { - // skip after somewhere? - // don't necessarily throw error but yeah - return AST::TypePath::create_error(); - } - segments.push_back(::std::move(initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == SCOPE_RESOLUTION) { - // skip scope resolution operator - lexer.skip_token(); - - // parse the actual segment - it is an error if it doesn't exist now - ::std::unique_ptr segment = parse_type_path_segment(); - if (segment == NULL) { - // skip after somewhere? - error_at(t->get_locus(), "could not parse type path segment"); - return AST::TypePath::create_error(); - } - - segments.push_back(::std::move(segment)); - - t = lexer.peek_token(); - } - - return AST::TypePath(::std::move(segments), has_opening_scope_resolution); - } - - // Parses the generic arguments in each path segment. - AST::GenericArgs Parser::parse_path_generic_args() { - if (!skip_token(LEFT_ANGLE)) { - // skip after somewhere? - return AST::GenericArgs::create_empty(); - } - - // try to parse lifetimes first - ::std::vector lifetime_args; - - const_TokenPtr t = lexer.peek_token(); - location_t locus = t->get_locus(); - const_TokenPtr t2 = lexer.peek_token(1); - while ( - t->get_id() == LIFETIME && (t2->get_id() == COMMA || !is_right_angle_tok(t2->get_id()))) { - AST::Lifetime lifetime = parse_lifetime(); - if (lifetime.is_error()) { - // not necessarily an error - break; - } - - lifetime_args.push_back(::std::move(lifetime)); - - // if next token isn't comma, then it must be end of list - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - t2 = lexer.peek_token(1); - } - - // try to parse types second - ::std::vector< ::std::unique_ptr > type_args; - - // TODO: think of better control structure - t = lexer.peek_token(); - while (!is_right_angle_tok(t->get_id())) { - // ensure not binding being parsed as type accidently - if (t->get_id() == IDENTIFIER && lexer.peek_token(1)->get_id() == EQUAL) { - break; - } - - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - // not necessarily an error - break; - } - - type_args.push_back(::std::move(type)); - - // if next token isn't comma, then it must be end of list - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // try to parse bindings third - ::std::vector binding_args; - - // TODO: think of better control structure - t = lexer.peek_token(); - while (!is_right_angle_tok(t->get_id())) { - AST::GenericArgsBinding binding = parse_generic_args_binding(); - if (binding.is_error()) { - // not necessarily an error - break; - } - - binding_args.push_back(::std::move(binding)); - - // if next token isn't comma, then it must be end of list - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // skip any trailing commas - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - - if (!skip_generics_right_angle()) { - return AST::GenericArgs::create_empty(); - } - - return AST::GenericArgs( - ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args), locus); - } - - // Parses a binding in a generic args path segment. - AST::GenericArgsBinding Parser::parse_generic_args_binding() { - const_TokenPtr ident_tok = lexer.peek_token(); - if (ident_tok->get_id() != IDENTIFIER) { - // allow non error-inducing use - // skip somewhere? - return AST::GenericArgsBinding::create_error(); - } - lexer.skip_token(); - Identifier ident = ident_tok->get_str(); - - if (!skip_token(EQUAL)) { - // skip after somewhere? - return AST::GenericArgsBinding::create_error(); - } - - // parse type (required) - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - // skip somewhere? - return AST::GenericArgsBinding::create_error(); - } - - return AST::GenericArgsBinding(::std::move(ident), ::std::move(type), ident_tok->get_locus()); - } - - /* Parses a single type path segment (not including opening scope resolution, but includes any - * internal ones). Includes generic args or type path functions too. */ - ::std::unique_ptr Parser::parse_type_path_segment() { - location_t locus = lexer.peek_token()->get_locus(); - // parse ident segment part - AST::PathIdentSegment ident_segment = parse_path_ident_segment(); - if (ident_segment.is_error()) { - // not necessarily an error - return NULL; - } - - // lookahead to determine if variants exist - only consume scope resolution then - bool has_separating_scope_resolution = false; - const_TokenPtr next = lexer.peek_token(1); - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION - && (next->get_id() == LEFT_ANGLE || next->get_id() == LEFT_PAREN)) { - has_separating_scope_resolution = true; - lexer.skip_token(); - } - - // branch into variants on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_ANGLE: { - // parse generic args - AST::GenericArgs generic_args = parse_path_generic_args(); - - return ::std::unique_ptr( - new AST::TypePathSegmentGeneric(::std::move(ident_segment), - has_separating_scope_resolution, ::std::move(generic_args), locus)); - } - case LEFT_PAREN: { - // parse type path function - AST::TypePathFunction type_path_function = parse_type_path_function(); - - if (type_path_function.is_error()) { - // skip after somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::TypePathSegmentFunction(::std::move(ident_segment), - has_separating_scope_resolution, ::std::move(type_path_function), locus)); - } - default: - // neither of them - return ::std::unique_ptr(new AST::TypePathSegment( - ::std::move(ident_segment), has_separating_scope_resolution, locus)); - } - gcc_unreachable(); - } - - // Parses a function call representation inside a type path. - AST::TypePathFunction Parser::parse_type_path_function() { - if (!skip_token(LEFT_PAREN)) { - // skip somewhere? - return AST::TypePathFunction::create_error(); - } - - // parse function inputs - ::std::vector< ::std::unique_ptr > inputs; - - // TODO: think of better control structure - while (true) { - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - // not necessarily an error - break; - } - - inputs.push_back(::std::move(type)); - - // skip commas, including trailing commas - if (lexer.peek_token()->get_id() != COMMA) { - break; - } else { - lexer.skip_token(); - } - } - - if (!skip_token(RIGHT_PAREN)) { - // skip somewhere? - return AST::TypePathFunction::create_error(); - } - - // parse optional return type - ::std::unique_ptr return_type = parse_function_return_type(); - - return AST::TypePathFunction(::std::move(inputs), ::std::move(return_type)); - } - - // Parses a path inside an expression that allows generic arguments. - AST::PathInExpression Parser::parse_path_in_expression() { - location_t locus = UNKNOWN_LOCATION; - bool has_opening_scope_resolution = false; - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION) { - has_opening_scope_resolution = true; - - locus = lexer.peek_token()->get_locus(); - - lexer.skip_token(); - } - - // create segment vector - ::std::vector segments; - - if (locus == UNKNOWN_LOCATION) { - locus = lexer.peek_token()->get_locus(); - } - - // parse required initial segment - AST::PathExprSegment initial_segment = parse_path_expr_segment(); - if (initial_segment.is_error()) { - // skip after somewhere? - // don't necessarily throw error but yeah - return AST::PathInExpression::create_error(); - } - segments.push_back(::std::move(initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == SCOPE_RESOLUTION) { - // skip scope resolution operator - lexer.skip_token(); - - // parse the actual segment - it is an error if it doesn't exist now - AST::PathExprSegment segment = parse_path_expr_segment(); - if (segment.is_error()) { - // skip after somewhere? - error_at(t->get_locus(), "could not parse path expression segment"); - return AST::PathInExpression::create_error(); - } - - segments.push_back(::std::move(segment)); - - t = lexer.peek_token(); - } - - return AST::PathInExpression(::std::move(segments), locus, has_opening_scope_resolution, - ::std::vector()); - } - - // Parses a single path in expression path segment (including generic arguments). - AST::PathExprSegment Parser::parse_path_expr_segment() { - location_t locus = lexer.peek_token()->get_locus(); - // parse ident segment - AST::PathIdentSegment ident = parse_path_ident_segment(); - if (ident.is_error()) { - // not necessarily an error? - return AST::PathExprSegment::create_error(); - } - - // parse generic args (and turbofish), if they exist - /* use lookahead to determine if they actually exist (don't want to accidently parse over - * next ident segment) */ - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION - && lexer.peek_token(1)->get_id() == LEFT_ANGLE) { - // skip scope resolution - lexer.skip_token(); - - AST::GenericArgs generic_args = parse_path_generic_args(); - - return AST::PathExprSegment(::std::move(ident), locus, ::std::move(generic_args)); - } - - // return a generic parameter-less expr segment if not found - return AST::PathExprSegment(::std::move(ident), locus); - } - - // Parses a fully qualified path in expression (i.e. a pattern). FIXME does not parse outer attrs. - AST::QualifiedPathInExpression Parser::parse_qualified_path_in_expression(bool pratt_parse) { - /* Note: the Rust grammar is defined in such a way that it is impossible to determine whether - * a prospective qualified path is a QualifiedPathInExpression or QualifiedPathInType in all - * cases by the rules themselves (the only possible difference is a TypePathSegment with - * function, and lookahead to find this is too difficult). However, as this is a pattern and - * QualifiedPathInType is a type, I believe it that their construction will not be confused - * (due to rules regarding patterns vs types). - * As such, this function will not attempt to minimise errors created by their confusion. */ - - // parse the qualified path type (required) - AST::QualifiedPathType qual_path_type = parse_qualified_path_type(pratt_parse); - if (qual_path_type.is_error()) { - // TODO: should this create a parse error? - return AST::QualifiedPathInExpression::create_error(); - } - location_t locus = qual_path_type.get_locus(); - - // parse path segments - ::std::vector segments; - - // parse initial required segment - if (!expect_token(SCOPE_RESOLUTION)) { - // skip after somewhere? - - return AST::QualifiedPathInExpression::create_error(); - } - AST::PathExprSegment initial_segment = parse_path_expr_segment(); - if (initial_segment.is_error()) { - // skip after somewhere? - error_at(lexer.peek_token()->get_locus(), - "required initial path expression segment in " - "qualified path in expression could not be parsed"); - return AST::QualifiedPathInExpression::create_error(); - } - segments.push_back(::std::move(initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == SCOPE_RESOLUTION) { - // skip scope resolution operator - lexer.skip_token(); - - // parse the actual segment - it is an error if it doesn't exist now - AST::PathExprSegment segment = parse_path_expr_segment(); - if (segment.is_error()) { - // skip after somewhere? - error_at(t->get_locus(), - "could not parse path expression segment in qualified path in expression"); - return AST::QualifiedPathInExpression::create_error(); - } - - segments.push_back(::std::move(segment)); - - t = lexer.peek_token(); - } - - // FIXME: outer attr parsing - return AST::QualifiedPathInExpression( - ::std::move(qual_path_type), ::std::move(segments), locus, ::std::vector()); - } - - // Parses the type syntactical construction at the start of a qualified path. - AST::QualifiedPathType Parser::parse_qualified_path_type(bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - // TODO: should this actually be error? is there anywhere where this could be valid? - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - if (!skip_token(LEFT_ANGLE)) { - // skip after somewhere? - return AST::QualifiedPathType::create_error(); - } - } else { - // move back by 1 if pratt parsing due to skipping '<' - locus = lexer.peek_token()->get_locus() - 1; - } - - // parse type (required) - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse type in qualified path type"); - // skip somewhere? - return AST::QualifiedPathType::create_error(); - } - - // parse optional as clause - AST::TypePath as_type_path = AST::TypePath::create_error(); - if (lexer.peek_token()->get_id() == AS) { - lexer.skip_token(); - - // parse type path, which is required now - as_type_path = parse_type_path(); - if (as_type_path.is_error()) { - error_at(lexer.peek_token()->get_locus(), - "could not parse type path in as clause in qualified path type"); - // skip somewhere? - return AST::QualifiedPathType::create_error(); - } - } - - // NOTE: should actually be a right-angle token, so skip_generics_right_angle shouldn't be - // required - if (!skip_token(RIGHT_ANGLE)) { - // skip after somewhere? - return AST::QualifiedPathType::create_error(); - } - - return AST::QualifiedPathType(::std::move(type), locus, ::std::move(as_type_path)); - } - - // Parses a fully qualified path in type (i.e. a type). - AST::QualifiedPathInType Parser::parse_qualified_path_in_type() { - location_t locus = lexer.peek_token()->get_locus(); - // parse the qualified path type (required) - AST::QualifiedPathType qual_path_type = parse_qualified_path_type(); - if (qual_path_type.is_error()) { - // TODO: should this create a parse error? - return AST::QualifiedPathInType::create_error(); - } - - // parse path segments - ::std::vector< ::std::unique_ptr > segments; - - // parse initial required segment - if (!expect_token(SCOPE_RESOLUTION)) { - // skip after somewhere? - - return AST::QualifiedPathInType::create_error(); - } - ::std::unique_ptr initial_segment = parse_type_path_segment(); - if (initial_segment == NULL) { - // skip after somewhere? - error_at(lexer.peek_token()->get_locus(), - "required initial type path segment in qualified path in type could not be parsed"); - return AST::QualifiedPathInType::create_error(); - } - segments.push_back(::std::move(initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == SCOPE_RESOLUTION) { - // skip scope resolution operator - lexer.skip_token(); - - // parse the actual segment - it is an error if it doesn't exist now - ::std::unique_ptr segment = parse_type_path_segment(); - if (segment == NULL) { - // skip after somewhere? - error_at( - t->get_locus(), "could not parse type path segment in qualified path in type"); - return AST::QualifiedPathInType::create_error(); - } - - segments.push_back(::std::move(segment)); - - t = lexer.peek_token(); - } - - return AST::QualifiedPathInType(::std::move(qual_path_type), ::std::move(segments), locus); - } - - // Parses a self param. Also handles self param not existing. - AST::SelfParam Parser::parse_self_param() { - bool has_reference = false; - AST::Lifetime lifetime = AST::Lifetime::error(); - - location_t locus = lexer.peek_token()->get_locus(); - - // test if self is a reference parameter - if (lexer.peek_token()->get_id() == AMP) { - has_reference = true; - lexer.skip_token(); - - // now test whether it has a lifetime - if (lexer.peek_token()->get_id() == LIFETIME) { - lifetime = parse_lifetime(); - - // something went wrong somehow - if (lifetime.is_error()) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse lifetime in self param"); - // skip after somewhere? - return AST::SelfParam::create_error(); - } - } - } - - // test for mut - bool has_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - has_mut = true; - lexer.skip_token(); - } - - // skip self token - const_TokenPtr self_tok = lexer.peek_token(); - if (self_tok->get_id() != SELF) { - // skip after somewhere? - return AST::SelfParam::create_error(); - } - lexer.skip_token(); - - // parse optional type - ::std::unique_ptr type = NULL; - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - - // type is now required - type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "could not parse type in self param"); - // skip after somewhere? - return AST::SelfParam::create_error(); - } - } - - // ensure that cannot have both type and reference - if (type != NULL && has_reference) { - error_at(lexer.peek_token()->get_locus(), - "cannot have both a reference and a type specified in a self param"); - // skip after somewhere? - return AST::SelfParam::create_error(); - } - - if (has_reference) { - return AST::SelfParam(::std::move(lifetime), has_mut, locus); - } else { - // note that type may be NULL here and that's fine - return AST::SelfParam(::std::move(type), has_mut, locus); - } - } - - /* Parses a method. Note that this function is probably useless because using lookahead to - * determine whether a function is a method is a PITA (maybe not even doable), so most places - * probably parse a "function or method" and then resolve it into whatever it is afterward. As - * such, this is only here for algorithmically defining the grammar rule. */ - AST::Method Parser::parse_method() { - location_t locus = lexer.peek_token()->get_locus(); - // Note: as a result of the above, this will not attempt to disambiguate a function - // parse qualifiers - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - skip_token(FN_TOK); - - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - skip_after_next_block(); - return AST::Method::create_error(); - } - Identifier method_name = ident_tok->get_str(); - - // parse generic params - if exist - ::std::vector< ::std::unique_ptr > generic_params - = parse_generic_params_in_angles(); - - if (!skip_token(LEFT_PAREN)) { - error_at(lexer.peek_token()->get_locus(), - "method missing opening parentheses before parameter list"); - skip_after_next_block(); - return AST::Method::create_error(); - } - - // parse self param - AST::SelfParam self_param = parse_self_param(); - if (self_param.is_error()) { - error_at(lexer.peek_token()->get_locus(), "could not parse self param in method"); - skip_after_next_block(); - return AST::Method::create_error(); - } - - // skip comma if it exists - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - - // parse function parameters - ::std::vector function_params = parse_function_params(); - - if (!skip_token(RIGHT_PAREN)) { - error_at(lexer.peek_token()->get_locus(), - "method declaration missing closing parentheses after parameter list"); - skip_after_next_block(); - return AST::Method::create_error(); - } - - // parse function return type - if exists - ::std::unique_ptr return_type = parse_function_return_type(); - - // parse where clause - if exists - AST::WhereClause where_clause = parse_where_clause(); - - // parse block expression - ::std::unique_ptr block_expr = parse_block_expr(); - if (block_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), "method declaration missing block expression"); - skip_after_end_block(); - return AST::Method::create_error(); - } - - // does not parse visibility, but this method isn't used, so doesn't matter - return AST::Method(::std::move(method_name), ::std::move(qualifiers), - ::std::move(generic_params), ::std::move(self_param), ::std::move(function_params), - ::std::move(return_type), ::std::move(where_clause), ::std::move(block_expr), - AST::Visibility::create_error(), ::std::vector(), locus); - } - - // Parses an expression statement (disambiguates to expression with or without block statement). - ::std::unique_ptr Parser::parse_expr_stmt( - ::std::vector outer_attrs) { - /* potential thoughts - define new virtual method "has_block()" on expr. parse expr and then - * determine whether semicolon is needed as a result of this method. - * but then this would require dynamic_cast, which is not allowed. */ - - /* okay new thought - big switch to disambiguate exprs with blocks - either block expr, - * async block expr, unsafe block expr, loop expr, if expr, if let expr, or match expr. So - * all others are exprs without block. */ - /* new thought: possible initial tokens: 'loop', 'while', 'for', lifetime (and then ':' and - * then loop), 'if', 'match', '{', 'async', 'unsafe' (and then '{')). This seems to have no - * ambiguity. */ - - const_TokenPtr t = lexer.peek_token(); - /* TODO: should the switch just directly call the individual parse methods rather than adding - * another layer of indirection with parse_expr_stmt_with_block()? */ - switch (t->get_id()) { - case LOOP: - case WHILE: - case FOR: - case IF: - case MATCH_TOK: - case LEFT_CURLY: - case ASYNC: - // expression with block - return parse_expr_stmt_with_block(::std::move(outer_attrs)); - case LIFETIME: { - /* FIXME: are there any expressions without blocks that can have lifetime as their - * first token? Or is loop expr the only one? */ - // safe side for now: - if (lexer.peek_token(1)->get_id() == COLON && lexer.peek_token(2)->get_id() == LOOP) { - return parse_expr_stmt_with_block(::std::move(outer_attrs)); - } else { - return parse_expr_stmt_without_block(::std::move(outer_attrs)); - } - } - case UNSAFE: { - /* FIXME: are there any expressions without blocks that can have unsafe as their - * first token? Or is unsafe the only one? */ - // safe side for now - if (lexer.peek_token(1)->get_id() == LEFT_CURLY) { - return parse_expr_stmt_with_block(::std::move(outer_attrs)); - } else { - return parse_expr_stmt_without_block(::std::move(outer_attrs)); - } - } - default: - // not a parse expr with block, so must be expr without block - /* TODO: if possible, be more selective about possible expr without block initial - * tokens in order to prevent more syntactical errors at parse time. */ - return parse_expr_stmt_without_block(::std::move(outer_attrs)); - } - } - - // Parses a expression statement containing an expression with block. Disambiguates internally. - ::std::unique_ptr Parser::parse_expr_stmt_with_block( - ::std::vector outer_attrs) { - ::std::unique_ptr expr_parsed = NULL; - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IF: - // if or if let, so more lookahead to find out - if (lexer.peek_token(1)->get_id() == LET) { - // if let expr - expr_parsed = parse_if_let_expr(::std::move(outer_attrs)); - break; - } else { - // if expr - expr_parsed = parse_if_expr(::std::move(outer_attrs)); - break; - } - case LOOP: - // infinite loop - expr_parsed = parse_loop_expr(::std::move(outer_attrs)); - break; - case FOR: - // "for" iterator loop - expr_parsed = parse_for_loop_expr(::std::move(outer_attrs)); - break; - case WHILE: { - // while or while let, so more lookahead to find out - if (lexer.peek_token()->get_id() == LET) { - // while let loop expr - expr_parsed = parse_while_let_loop_expr(::std::move(outer_attrs)); - break; - } else { - // while loop expr - expr_parsed = parse_while_loop_expr(::std::move(outer_attrs)); - break; - } - } - case MATCH_TOK: - // match expression - expr_parsed = parse_match_expr(::std::move(outer_attrs)); - break; - case LEFT_CURLY: - // block expression - expr_parsed = parse_block_expr(::std::move(outer_attrs)); - break; - case ASYNC: - // async block expression - expr_parsed = parse_async_block_expr(::std::move(outer_attrs)); - break; - case UNSAFE: - // unsafe block expression - expr_parsed = parse_unsafe_block_expr(::std::move(outer_attrs)); - break; - case LIFETIME: - // some kind of loop expr (with loop label) - expr_parsed = parse_labelled_loop_expr(::std::move(outer_attrs)); - break; - default: - error_at(t->get_locus(), - "could not recognise expr beginning with '%s' as an expr with block in parsing " - "expr statement.", - t->get_token_description()); - skip_after_next_block(); - return NULL; - } - - // ensure expr parsed exists - if (expr_parsed == NULL) { - error_at(t->get_locus(), "failed to parse expr with block in parsing expr statement"); - skip_after_end_block(); - return NULL; - } - - // return expr stmt created from expr - return ::std::unique_ptr( - new AST::ExprStmtWithBlock(::std::move(expr_parsed), t->get_locus())); - } - - // Parses an expression statement containing an expression without block. Disambiguates further. - ::std::unique_ptr Parser::parse_expr_stmt_without_block( - ::std::vector outer_attrs) { - // TODO: maybe move more logic for expr without block in here for better error handling - - // try to parse expr without block - /*AST::ExprWithoutBlock* expr = NULL; - expr = parse_expr_without_block(::std::move(outer_attrs));*/ - // HACK: parse expression instead of expression without block, due to Pratt parsing issues - ::std::unique_ptr expr = NULL; - location_t locus = lexer.peek_token()->get_locus(); - expr = parse_expr(::std::move(outer_attrs)); - if (expr == NULL) { - // expr is required, error - error_at(lexer.peek_token()->get_locus(), - "failed to parse expr without block in expr statement"); - skip_after_semicolon(); - return NULL; - } - - // skip semicolon at end that is required - if (!skip_token(SEMICOLON)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ExprStmtWithoutBlock(::std::move(expr), locus)); - } - - // Parses an expression without a block associated with it (further disambiguates). - ::std::unique_ptr Parser::parse_expr_without_block( - ::std::vector outer_attrs) { - /* Notes on types of expr without block: - * - literal expr tokens that are literals - * - path expr path_in_expr or qual_path_in_expr - * - operator expr many different types - * unary: - * borrow expr ( '&' | '&&' ) 'mut'? expr - * dereference expr '*' expr - * error propagation expr '?' - * negation '-' expr - * not '!' expr - * binary: all start with expr - * - grouped/paren expr '(' inner_attributes expr ')' - * - array expr '[' inner_attributes array_elems? ']' - * - await expr expr '.' 'await' - * - (array/slice) index expr expr '[' expr ']' - * - tuple expr '(' inner_attributes tuple_elems? ')' - * note that a single elem tuple is distinguished from a grouped expr by a trailing - * comma, i.e. a grouped expr is preferred over a tuple expr - * - tuple index expr expr '.' tuple_index - * - struct expr path_in_expr (and optional other stuff) - * - enum variant expr path_in_expr (and optional other stuff) - * this means that there is no syntactic difference between an enum variant and a struct - * - only name resolution can tell the difference. Thus, maybe rework AST to take this - * into account ("struct or enum" nodes?) - * - (function) call expr expr '(' call_params? ')' - * - method call expr expr '.' path_expr_segment '(' call_params? ')' - * - field expr expr '.' identifier - * note that method call expr is preferred, i.e. field expr must not be followed by - * parenthesised expression sequence. - * - closure expr 'move'? ( '||' | '|' closure_params? '|' ) ( expr | '->' - * type_no_bounds block_expr ) - * - continue expr 'continue' labelled_lifetime? - * - break expr 'break' labelled_lifetime? expr? - * - range expr many different types but all involve '..' or '..=' - * - return expr 'return' as 1st tok - * - macro invocation identifier then :: or identifier then ! (simple_path '!') - * - * any that have rules beginning with 'expr' should probably be pratt-parsed, with parsing - * type to use determined by token AND lookahead. */ - - // ok well at least can do easy ones - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case RETURN_TOK: - // return expr - return parse_return_expr(::std::move(outer_attrs)); - case BREAK: - // break expr - return parse_break_expr(::std::move(outer_attrs)); - case CONTINUE: - // continue expr - return parse_continue_expr(::std::move(outer_attrs)); - case MOVE: - // closure expr (though not all closure exprs require this) - return parse_closure_expr(::std::move(outer_attrs)); - case LEFT_SQUARE: - // array expr (creation, not index) - return parse_array_expr(::std::move(outer_attrs)); - case LEFT_PAREN: - /* either grouped expr or tuple expr - depends on whether there is a comma inside the - * parentheses - if so, tuple expr, otherwise, grouped expr. */ - return parse_grouped_or_tuple_expr(::std::move(outer_attrs)); - default: { - // HACK: piggyback on pratt parsed expr and abuse polymorphism to essentially downcast - - // DEBUG - fprintf(stderr, "about to parse expr (in expr without block method)\n"); - - ::std::unique_ptr expr = parse_expr(::std::move(outer_attrs)); - - // DEBUG - fprintf(stderr, "successfully parsed expr (in expr without block method)\n"); - - if (expr == NULL) { - error_at(t->get_locus(), "failed to parse expression for expression without " - "block (pratt-parsed expression is null)"); - return NULL; - } - - ::std::unique_ptr expr_without_block( - expr->as_expr_without_block()); - // THIS IS THE CAUSE OF THE SEGFAULT - - // DEBUG - fprintf(stderr, "expr to expr without block conversion didn't error\n"); - - if (expr_without_block != NULL) { - - // DEBUG - fprintf( - stderr, "expr to expr without block conversion was successful; returning\n"); - - return expr_without_block; - } else { - error_at(t->get_locus(), "converted expr without block is null"); - return NULL; - } - } - } - } - - // Parses a block expression, including the curly braces at start and end. - ::std::unique_ptr Parser::parse_block_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - if (!skip_token(LEFT_CURLY)) { - skip_after_end_block(); - return NULL; - } - } else { - locus = lexer.peek_token()->get_locus() - 1; - } - - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse statements and expression - ::std::vector< ::std::unique_ptr > stmts; - ::std::unique_ptr expr = NULL; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY) { - ExprOrStmt expr_or_stmt = parse_stmt_or_expr_without_block(); - if (expr_or_stmt.is_error()) { - error_at(t->get_locus(), - "failed to parse statement or expression without block in block expression"); - return NULL; - } - - if (expr_or_stmt.stmt != NULL) { - // FIXME: determine if this move works - stmts.push_back(::std::move(expr_or_stmt.stmt)); - } else { - // assign to expression and end parsing inside - expr = ::std::move(expr_or_stmt.expr); - break; - } - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_CURLY)) { - error_at(t->get_locus(), "error may be from having an expression (as opposed to " - "statement) in the body of the function but not last"); - skip_after_end_block(); - return NULL; - } - - // ensure that there is at least either a statement or an expr - /*if (stmts.empty() && expr == NULL) { - error_at(lexer.peek_token()->get_id(), - "block expression requires statements or an expression without block - found neither"); - skip_after_end_block(); - return NULL; - }*/ - // grammar allows for empty block expressions - - return ::std::unique_ptr(new AST::BlockExpr(::std::move(stmts), - ::std::move(expr), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - - // Parses a "grouped" expression (expression in parentheses), used to control precedence. - ::std::unique_ptr Parser::parse_grouped_expr( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(LEFT_PAREN); - - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse required expr inside parentheses - ::std::unique_ptr expr_in_parens = parse_expr(); - if (expr_in_parens == NULL) { - // skip after somewhere? - // error? - return NULL; - } - - if (!skip_token(RIGHT_PAREN)) { - // skip after somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::GroupedExpr( - ::std::move(expr_in_parens), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - - // Parses a closure expression (closure definition). - ::std::unique_ptr Parser::parse_closure_expr( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - // detect optional "move" - bool has_move = false; - if (lexer.peek_token()->get_id() == MOVE) { - lexer.skip_token(); - has_move = true; - } - - // handle parameter list - ::std::vector params; - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case OR: - // skip token, no parameters - lexer.skip_token(); - break; - case PIPE: - // actually may have parameters - lexer.skip_token(); - - while (t->get_id() != PIPE) { - AST::ClosureParam param = parse_closure_param(); - if (param.is_error()) { - // TODO is this really an error? - error_at(t->get_locus(), "could not parse closure param"); - break; - } - params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - // not an error but means param list is done - break; - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - } - break; - default: - error_at(t->get_locus(), - "unexpected token '%s' in closure expression - expected '|' or '||'", - t->get_token_description()); - // skip somewhere? - return NULL; - } - - // again branch based on next token - t = lexer.peek_token(); - if (t->get_id() == RETURN_TYPE) { - // must be return type closure with block expr - - // skip "return type" token - lexer.skip_token(); - - // parse actual type, which is required - ::std::unique_ptr type = parse_type_no_bounds(); - if (type == NULL) { - // error - error_at(t->get_locus(), "failed to parse type for closure"); - // skip somewhere? - return NULL; - } - - // parse block expr, which is required - ::std::unique_ptr block = parse_block_expr(); - if (block == NULL) { - // error - error_at(lexer.peek_token()->get_locus(), "failed to parse block expr in closure"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ClosureExprInnerTyped(::std::move(type), ::std::move(block), - ::std::move(params), locus, has_move, ::std::move(outer_attrs))); - } else { - // must be expr-only closure - - // parse expr, which is required - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(t->get_locus(), "failed to parse expression in closure"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::ClosureExprInner( - ::std::move(expr), ::std::move(params), locus, has_move, ::std::move(outer_attrs))); - } - } - - // Parses a literal token (to literal expression). - ::std::unique_ptr Parser::parse_literal_expr( - ::std::vector outer_attrs) { - // TODO: change if literal representation in lexer changes - - ::std::string literal_value; - AST::Literal::LitType type = AST::Literal::STRING; - - // branch based on token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case CHAR_LITERAL: - type = AST::Literal::CHAR; - literal_value = t->get_str(); - lexer.skip_token(); - break; - case STRING_LITERAL: - type = AST::Literal::STRING; - literal_value = t->get_str(); - lexer.skip_token(); - break; - // case RAW_STRING_LITERAL: - // put here if lexer changes to have these - case BYTE_CHAR_LITERAL: - type = AST::Literal::BYTE; - literal_value = t->get_str(); - lexer.skip_token(); - break; - case BYTE_STRING_LITERAL: - type = AST::Literal::BYTE_STRING; - literal_value = t->get_str(); - lexer.skip_token(); - break; - // case RAW_BYTE_STRING_LITERAL: - case INT_LITERAL: - type = AST::Literal::INT; - literal_value = t->get_str(); - lexer.skip_token(); - break; - case FLOAT_LITERAL: - type = AST::Literal::FLOAT; - literal_value = t->get_str(); - lexer.skip_token(); - break; - // case BOOL_LITERAL - // use true and false keywords rather than "bool literal" Rust terminology - case TRUE_LITERAL: - type = AST::Literal::BOOL; - literal_value = ::std::string("true"); - lexer.skip_token(); - break; - case FALSE_LITERAL: - type = AST::Literal::BOOL; - literal_value = ::std::string("false"); - lexer.skip_token(); - break; - default: - // error - cannot be a literal expr - error_at(t->get_locus(), "unexpected token '%s' when parsing literal expression", - t->get_token_description()); - // skip? - return NULL; - } - - // create literal based on stuff in switch - return ::std::unique_ptr(new AST::LiteralExpr( - ::std::move(literal_value), ::std::move(type), t->get_locus(), ::std::move(outer_attrs))); - } - - // Parses a return expression (including any expression to return). - ::std::unique_ptr Parser::parse_return_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(RETURN_TOK); - } else { - // minus 7 chars for 6 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token()->get_locus() - 7; - } - - // parse expression to return, if it exists - ::std::unique_ptr returned_expr = parse_expr(); - // FIXME: ensure this doesn't ruin the middle of any expressions or anything - - return ::std::unique_ptr( - new AST::ReturnExpr(locus, ::std::move(returned_expr), ::std::move(outer_attrs))); - } - - // Parses a break expression (including any label to break to AND any return expression). - ::std::unique_ptr Parser::parse_break_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(BREAK); - } else { - // minus 6 chars for 5 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token()->get_locus() - 6; - } - - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error(); - if (lexer.peek_token()->get_id() == LIFETIME) { - label = parse_lifetime(); - } - - // parse break return expression if it exists - ::std::unique_ptr return_expr = parse_expr(); - - return ::std::unique_ptr(new AST::BreakExpr( - locus, ::std::move(label), ::std::move(return_expr), ::std::move(outer_attrs))); - } - - // Parses a continue expression (including any label to continue from). - ::std::unique_ptr Parser::parse_continue_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(CONTINUE); - } else { - // minus 9 chars for 8 in return and a space - // or just TODO: pass in location data - locus = lexer.peek_token()->get_locus() - 9; - } - - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error(); - if (lexer.peek_token()->get_id() == LIFETIME) { - label = parse_lifetime(); - } - - return ::std::unique_ptr( - new AST::ContinueExpr(locus, ::std::move(label), ::std::move(outer_attrs))); - } - - // Parses a loop label used in loop expressions. - AST::LoopLabel Parser::parse_loop_label() { - // parse lifetime - if doesn't exist, assume no label - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() != LIFETIME) { - // not necessarily an error - return AST::LoopLabel::error(); - } - // FIXME: check for named lifetime requirement here? or check in semantic analysis phase? - AST::Lifetime label = parse_lifetime(); - - if (!skip_token(COLON)) { - // skip somewhere? - return AST::LoopLabel::error(); - } - - return AST::LoopLabel(::std::move(label), t->get_locus()); - } - - /* Parses an if expression of any kind, including with else, else if, else if let, and neither. - * Note that any outer attributes will be ignored because if expressions don't support them. */ - ::std::unique_ptr Parser::parse_if_expr( - ::std::vector outer_attrs ATTRIBUTE_UNUSED) { - // TODO: make having outer attributes an error? - - location_t locus = lexer.peek_token()->get_locus(); - skip_token(IF); - - // detect accidental if let - if (lexer.peek_token()->get_id() == LET) { - error_at(lexer.peek_token()->get_locus(), - "if let expression probably exists, but is being parsed as an if expression. This may " - "be a parser error."); - // skip somewhere? - return NULL; - } - - // parse required condition expr - HACK to prevent struct expr from being parsed - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr condition - = parse_expr(::std::vector(), no_struct_expr); - if (condition == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse condition expression in if expression"); - // skip somewhere? - return NULL; - } - - // parse required block expr - ::std::unique_ptr if_body = parse_block_expr(); - if (if_body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse if body block expression in if expression"); - // skip somewhere? - return NULL; - } - - // branch to parse end or else (and then else, else if, or else if let) - if (lexer.peek_token()->get_id() != ELSE) { - // single selection - end of if expression - return ::std::unique_ptr( - new AST::IfExpr(::std::move(condition), ::std::move(if_body), locus)); - } else { - // double or multiple selection - branch on end, else if, or else if let - - // skip "else" - lexer.skip_token(); - - // branch on whether next token is '{' or 'if' - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_CURLY: { - // double selection - else - // parse else block expr (required) - ::std::unique_ptr else_body = parse_block_expr(); - if (else_body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse else body block expression in if expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::IfExprConseqElse( - ::std::move(condition), ::std::move(if_body), ::std::move(else_body), locus)); - } - case IF: { - // multiple selection - else if or else if let - // branch on whether next token is 'let' or not - if (lexer.peek_token(1)->get_id() == LET) { - // parse if let expr (required) - ::std::unique_ptr if_let_expr = parse_if_let_expr(); - if (if_let_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse (else) if let expression after if expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::IfExprConseqIfLet(::std::move(condition), ::std::move(if_body), - ::std::move(if_let_expr), locus)); - } else { - // parse if expr (required) - ::std::unique_ptr if_expr = parse_if_expr(); - if (if_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse (else) if expression after if expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::IfExprConseqIf( - ::std::move(condition), ::std::move(if_body), ::std::move(if_expr), locus)); - } - } - default: - // error - invalid token - error_at(t->get_locus(), "unexpected token '%s' after else in if expression", - t->get_token_description()); - // skip somewhere? - return NULL; - } - } - } - - /* Parses an if let expression of any kind, including with else, else if, else if let, and none. - * Note that any outer attributes will be ignored as if let expressions don't support them. */ - ::std::unique_ptr Parser::parse_if_let_expr( - ::std::vector outer_attrs ATTRIBUTE_UNUSED) { - // TODO: make having outer attributes an error? - - location_t locus = lexer.peek_token()->get_locus(); - skip_token(IF); - - // detect accidental if expr parsed as if let expr - if (lexer.peek_token()->get_id() != LET) { - error_at(lexer.peek_token()->get_locus(), - "if expression probably exists, but is being parsed as an if let expression. This may " - "be a parser error."); - // skip somewhere? - return NULL; - } - lexer.skip_token(); - - // parse match arm patterns (which are required) - ::std::vector< ::std::unique_ptr > match_arm_patterns - = parse_match_arm_patterns(EQUAL); - if (match_arm_patterns.empty()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse any match arm patterns in if let expression"); - // skip somewhere? - return NULL; - } - - if (!skip_token(EQUAL)) { - // skip somewhere? - return NULL; - } - - // parse expression (required) - HACK to prevent struct expr being parsed - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr scrutinee_expr - = parse_expr(::std::vector(), no_struct_expr); - if (scrutinee_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse scrutinee expression in if let expression"); - // skip somewhere? - return NULL; - } - /* TODO: check for expression not being a struct expression or lazy boolean expression here? - * or actually probably in semantic analysis. */ - - // parse block expression (required) - ::std::unique_ptr if_let_body = parse_block_expr(); - if (if_let_body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse if let body block expression in if let expression"); - // skip somewhere? - return NULL; - } - - // branch to parse end or else (and then else, else if, or else if let) - if (lexer.peek_token()->get_id() != ELSE) { - // single selection - end of if let expression - return ::std::unique_ptr( - new AST::IfLetExpr(::std::move(match_arm_patterns), ::std::move(scrutinee_expr), - ::std::move(if_let_body), locus)); - } else { - // double or multiple selection - branch on end, else if, or else if let - - // skip "else" - lexer.skip_token(); - - // branch on whether next token is '{' or 'if' - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LEFT_CURLY: { - // double selection - else - // parse else block expr (required) - ::std::unique_ptr else_body = parse_block_expr(); - if (else_body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse else body block expression in if let expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::IfLetExprConseqElse( - ::std::move(match_arm_patterns), ::std::move(scrutinee_expr), - ::std::move(if_let_body), ::std::move(else_body), locus)); - } - case IF: { - // multiple selection - else if or else if let - // branch on whether next token is 'let' or not - if (lexer.peek_token(1)->get_id() == LET) { - // parse if let expr (required) - ::std::unique_ptr if_let_expr = parse_if_let_expr(); - if (if_let_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse (else) if let expression after if let expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::IfLetExprConseqIfLet(::std::move(match_arm_patterns), - ::std::move(scrutinee_expr), ::std::move(if_let_body), - ::std::move(if_let_expr), locus)); - } else { - // parse if expr (required) - ::std::unique_ptr if_expr = parse_if_expr(); - if (if_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse (else) if expression after if let expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::IfLetExprConseqIf( - ::std::move(match_arm_patterns), ::std::move(scrutinee_expr), - ::std::move(if_let_body), ::std::move(if_expr), locus)); - } - } - default: - // error - invalid token - error_at(t->get_locus(), "unexpected token '%s' after else in if let expression", - t->get_token_description()); - // skip somewhere? - return NULL; - } - } - } - - // TODO: possibly decide on different method of handling label (i.e. not parameter) - - /* Parses a "loop" infinite loop expression. Label is not parsed and should be parsed via - * parse_labelled_loop_expr, which would call this. */ - ::std::unique_ptr Parser::parse_loop_expr( - ::std::vector outer_attrs, AST::LoopLabel label) { - location_t locus = UNKNOWN_LOCATION; - if (label.is_error()) { - locus = lexer.peek_token()->get_locus(); - } else { - locus = label.get_locus(); - } - skip_token(LOOP); - - // parse loop body, which is required - ::std::unique_ptr loop_body = parse_block_expr(); - if (loop_body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse loop body in (infinite) loop expression"); - return NULL; - } - - return ::std::unique_ptr(new AST::LoopExpr( - ::std::move(loop_body), locus, ::std::move(label), ::std::move(outer_attrs))); - } - - /* Parses a "while" loop expression. Label is not parsed and should be parsed via - * parse_labelled_loop_expr, which would call this. */ - ::std::unique_ptr Parser::parse_while_loop_expr( - ::std::vector outer_attrs, AST::LoopLabel label) { - location_t locus = UNKNOWN_LOCATION; - if (label.is_error()) { - locus = lexer.peek_token()->get_locus(); - } else { - locus = label.get_locus(); - } - skip_token(WHILE); - - // ensure it isn't a while let loop - if (lexer.peek_token()->get_id() == LET) { - error_at(lexer.peek_token()->get_locus(), - "appears to be while let loop but is being parsed by " - "while loop - this may be a compiler issue"); - // skip somewhere? - return NULL; - } - - // parse loop predicate (required) with HACK to prevent struct expr parsing - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr predicate - = parse_expr(::std::vector(), no_struct_expr); - if (predicate == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse predicate expression in while loop"); - // skip somewhere? - return NULL; - } - // TODO: check that it isn't struct expression here? actually, probably in semantic analysis - - // parse loop body (required) - ::std::unique_ptr body = parse_block_expr(); - if (body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse loop body block expression in while loop"); - // skip somewhere - return NULL; - } - - return ::std::unique_ptr(new AST::WhileLoopExpr(::std::move(predicate), - ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); - } - - /* Parses a "while let" loop expression. Label is not parsed and should be parsed via - * parse_labelled_loop_expr, which would call this. */ - ::std::unique_ptr Parser::parse_while_let_loop_expr( - ::std::vector outer_attrs, AST::LoopLabel label) { - location_t locus = UNKNOWN_LOCATION; - if (label.is_error()) { - locus = lexer.peek_token()->get_locus(); - } else { - locus = label.get_locus(); - } - skip_token(WHILE); - - // check for possible accidental recognition of a while loop as a while let loop - if (lexer.peek_token()->get_id() != LET) { - error_at(lexer.peek_token()->get_locus(), - "appears to be a while loop but is being parsed by " - "while let loop - this may be a compiler issue"); - // skip somewhere - return NULL; - } - // as this token is definitely let now, save the computation of comparison - lexer.skip_token(); - - // parse predicate patterns - ::std::vector< ::std::unique_ptr > predicate_patterns - = parse_match_arm_patterns(EQUAL); - // TODO: have to ensure that there is at least 1 pattern? - - if (!skip_token(EQUAL)) { - // skip somewhere? - return NULL; - } - - // parse predicate expression, which is required (and HACK to prevent struct expr) - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr predicate_expr - = parse_expr(::std::vector(), no_struct_expr); - if (predicate_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse predicate expression in while let loop"); - // skip somewhere? - return NULL; - } - // TODO: ensure that struct expression is not parsed? Actually, probably in semantic analysis. - - // parse loop body, which is required - ::std::unique_ptr body = parse_block_expr(); - if (body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse block expr (loop body) of while let loop"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::WhileLetLoopExpr(::std::move(predicate_patterns), ::std::move(predicate_expr), - ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); - } - - /* Parses a "for" iterative loop. Label is not parsed and should be parsed via - * parse_labelled_loop_expr, which would call this. */ - ::std::unique_ptr Parser::parse_for_loop_expr( - ::std::vector outer_attrs, AST::LoopLabel label) { - location_t locus = UNKNOWN_LOCATION; - if (label.is_error()) { - locus = lexer.peek_token()->get_locus(); - } else { - locus = label.get_locus(); - } - skip_token(FOR); - - // parse pattern, which is required - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse iterator pattern in for loop"); - // skip somewhere? - return NULL; - } - - if (!skip_token(IN)) { - // skip somewhere? - return NULL; - } - - // parse iterator expression, which is required - also HACK to prevent struct expr - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr expr - = parse_expr(::std::vector(), no_struct_expr); - if (expr == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse iterator expression in for loop"); - // skip somewhere? - return NULL; - } - // TODO: check to ensure this isn't struct expr? Or in semantic analysis. - - // parse loop body, which is required - ::std::unique_ptr body = parse_block_expr(); - if (body == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse loop body block expression in for loop"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::ForLoopExpr(::std::move(pattern), - ::std::move(expr), ::std::move(body), locus, ::std::move(label), ::std::move(outer_attrs))); - } - - // Parses a loop expression with label (any kind of loop - disambiguates). - ::std::unique_ptr Parser::parse_labelled_loop_expr( - ::std::vector outer_attrs) { - // TODO: decide whether it should not work if there is no label, or parse it with no label - // at the moment, I will make it not work with no label because that's the implication. - - if (lexer.peek_token()->get_id() != LIFETIME) { - error_at(lexer.peek_token()->get_locus(), - "expected lifetime in labelled loop expr (to parse loop label) - found '%s'", - lexer.peek_token()->get_token_description()); - // skip? - return NULL; - } - - // parse loop label (required) - AST::LoopLabel label = parse_loop_label(); - if (label.is_error()) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse loop label in labelled loop expr"); - // skip? - return NULL; - } - - // branch on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case LOOP: - return parse_loop_expr(::std::move(outer_attrs), ::std::move(label)); - case FOR: - return parse_for_loop_expr(::std::move(outer_attrs), ::std::move(label)); - case WHILE: - // further disambiguate into while vs while let - if (lexer.peek_token(1)->get_id() == LET) { - return parse_while_let_loop_expr(::std::move(outer_attrs), ::std::move(label)); - } else { - return parse_while_loop_expr(::std::move(outer_attrs), ::std::move(label)); - } - default: - // error - error_at(t->get_locus(), "unexpected token '%s' when parsing labelled loop", - t->get_token_description()); - // skip? - return NULL; - } - } - - // Parses a match expression. - ::std::unique_ptr Parser::parse_match_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(MATCH_TOK); - } else { - // TODO: probably just pass in location data as param - // get current pos then move back 6 - 5 for match, 1 for space - locus = lexer.peek_token()->get_locus() - 6; - } - - // parse scrutinee expression, which is required (and HACK to prevent struct expr) - ParseRestrictions no_struct_expr; - no_struct_expr.can_be_struct_expr = false; - ::std::unique_ptr scrutinee - = parse_expr(::std::vector(), no_struct_expr); - if (scrutinee == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse scrutinee expression in match expression"); - // skip somewhere? - return NULL; - } - // TODO: check for scrutinee expr not being struct expr? or do so in semantic analysis - - if (!skip_token(LEFT_CURLY)) { - // skip somewhere? - return NULL; - } - - // parse inner attributes (if they exist) - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse match arms (if they exist) - ::std::vector< ::std::unique_ptr > match_arms; - - // DEBUG - fprintf(stderr, "about to start loop to start parsing match cases\n"); - - // FIXME: absolute worst control structure ever - // parse match cases - while (true) { - // parse match arm itself, which is required - AST::MatchArm arm = parse_match_arm(); - if (arm.is_error()) { - // DEBUG - fprintf(stderr, "broke loop on invalid match arm\n"); - - // not necessarily an error - break; - } - - // DEBUG - fprintf(stderr, "parsed valid match arm\n"); - - if (!skip_token(MATCH_ARROW)) { - // skip after somewhere? - // TODO is returning here a good idea? or is break better? - return NULL; - } - - // DEBUG - fprintf(stderr, "skipped match arrow\n"); - - // branch on next token - if '{', block expr, otherwise just expr - if (lexer.peek_token()->get_id() == LEFT_CURLY) { - // block expr - ::std::unique_ptr block_expr = parse_block_expr(); - if (block_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse block expr in match arm in match expr"); - // skip somewhere - return NULL; - } - - // create match case block expr and add to cases - ::std::unique_ptr match_case_block( - new AST::MatchCaseBlockExpr(::std::move(arm), ::std::move(block_expr))); - match_arms.push_back(::std::move(match_case_block)); - - // skip optional comma - if (lexer.peek_token()->get_id() == COMMA) { - lexer.skip_token(); - } - } else { - // regular expr - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse expr in match arm in match expr"); - // skip somewhere? - return NULL; - } - - // construct match case expr and add to cases - ::std::unique_ptr match_case_expr( - new AST::MatchCaseExpr(::std::move(arm), ::std::move(expr))); - match_arms.push_back(::std::move(match_case_expr)); - - // skip REQUIRED comma - if no comma, break - if (lexer.peek_token()->get_id() != COMMA) { - // if no comma, must be end of cases - break; - } - lexer.skip_token(); - } - } - - if (!skip_token(RIGHT_CURLY)) { - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::MatchExpr(::std::move(scrutinee), - ::std::move(match_arms), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - - // Parses the "pattern" part of the match arm (the 'case x:' equivalent). - AST::MatchArm Parser::parse_match_arm() { - // parse optional outer attributes - ::std::vector outer_attrs = parse_outer_attributes(); - - // DEBUG - fprintf(stderr, "about to start parsing match arm patterns\n"); - - // break early if find right curly - if (lexer.peek_token()->get_id() == RIGHT_CURLY) { - // not an error - return AST::MatchArm::create_error(); - } - - // parse match arm patterns - at least 1 is required - ::std::vector< ::std::unique_ptr > match_arm_patterns - = parse_match_arm_patterns(RIGHT_CURLY); - if (match_arm_patterns.empty()) { - error_at(lexer.peek_token()->get_locus(), "failed to parse any patterns in match arm"); - // skip somewhere? - return AST::MatchArm::create_error(); - } - - // DEBUG - fprintf(stderr, "successfully parsed match arm patterns\n"); - - // parse match arm guard expr if it exists - ::std::unique_ptr guard_expr = NULL; - if (lexer.peek_token()->get_id() == IF) { - lexer.skip_token(); - - guard_expr = parse_expr(); - if (guard_expr == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse guard expression in match arm"); - // skip somewhere? - return AST::MatchArm::create_error(); - } - } - - // DEBUG - fprintf(stderr, "successfully parsed match arm\n"); - - return AST::MatchArm( - ::std::move(match_arm_patterns), ::std::move(guard_expr), ::std::move(outer_attrs)); - } - - /* Parses the patterns used in a match arm. End token id is the id of the token that would exist - * after the patterns are done (e.g. '}' for match expr, '=' for if let and while let). */ - ::std::vector< ::std::unique_ptr > Parser::parse_match_arm_patterns( - TokenId end_token_id) { - // skip optional leading '|' - bool has_leading_pipe = false; - if (lexer.peek_token()->get_id() == PIPE) { - has_leading_pipe = true; - lexer.skip_token(); - } - // TODO: do I even need to store the result of this? can't be used. - // If semantically different, I need a wrapped "match arm patterns" object for this. - - ::std::vector< ::std::unique_ptr > patterns; - - // quick break out if end_token_id - if (lexer.peek_token()->get_id() == end_token_id) { - return patterns; - } - - // parse required pattern - if doesn't exist, return empty - ::std::unique_ptr initial_pattern = parse_pattern(); - if (initial_pattern == NULL) { - // FIXME: should this be an error? - return patterns; - } - patterns.push_back(::std::move(initial_pattern)); - - // DEBUG - fprintf(stderr, "successfully parsed initial match arm pattern\n"); - - // parse new patterns as long as next char is '|' - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == PIPE) { - // skip pipe token - lexer.skip_token(); - - // break if hit end token id - if (lexer.peek_token()->get_id() == end_token_id) { - break; - } - - // parse pattern - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - // this is an error - error_at( - lexer.peek_token()->get_locus(), "failed to parse pattern in match arm patterns"); - // skip somewhere? - return ::std::vector< ::std::unique_ptr >(); - } - - patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - return patterns; - } - - // Parses an async block expression. - ::std::unique_ptr Parser::parse_async_block_expr( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(ASYNC); - - // detect optional move token - bool has_move = false; - if (lexer.peek_token()->get_id() == MOVE) { - lexer.skip_token(); - has_move = true; - } - - // parse block expression (required) - ::std::unique_ptr block_expr = parse_block_expr(); - if (block_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse block expression of async block expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::AsyncBlockExpr( - ::std::move(block_expr), has_move, ::std::move(outer_attrs), locus)); - } - - // Parses an unsafe block expression. - ::std::unique_ptr Parser::parse_unsafe_block_expr( - ::std::vector outer_attrs) { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(UNSAFE); - - // parse block expression (required) - ::std::unique_ptr block_expr = parse_block_expr(); - if (block_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse block expression of unsafe block expression"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::UnsafeBlockExpr(::std::move(block_expr), ::std::move(outer_attrs), locus)); - } - - // Parses an array definition expression. - ::std::unique_ptr Parser::parse_array_expr( - ::std::vector outer_attrs, bool pratt_parse) { - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(LEFT_SQUARE); - } else { - locus = lexer.peek_token()->get_locus() - 1; - } - - // parse optional inner attributes - ::std::vector inner_attrs = parse_inner_attributes(); - - // parse the "array elements" section, which is optional - if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { - // no array elements - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::ArrayExpr(NULL, ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else { - // should have array elements - // parse initial expression, which is required for either - ::std::unique_ptr initial_expr = parse_expr(); - if (initial_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse expression in array expression " - "(even though arrayelems seems to be present)"); - // skip somewhere? - return NULL; - } - - if (lexer.peek_token()->get_id() == SEMICOLON) { - // copy array elems - lexer.skip_token(); - - // parse copy amount expression (required) - ::std::unique_ptr copy_amount = parse_expr(); - if (copy_amount == NULL) { - error_at(lexer.peek_token()->get_locus(), - "could not parse copy amount expression in array expression (arrayelems)"); - // skip somewhere? - return NULL; - } - - ::std::unique_ptr copied_array_elems( - new AST::ArrayElemsCopied(::std::move(initial_expr), ::std::move(copy_amount))); - return ::std::unique_ptr( - new AST::ArrayExpr(::std::move(copied_array_elems), ::std::move(inner_attrs), - ::std::move(outer_attrs), locus)); - } else if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { - // single-element array expression - ::std::vector< ::std::unique_ptr > exprs; - exprs.push_back(::std::move(initial_expr)); - - ::std::unique_ptr array_elems( - new AST::ArrayElemsValues(::std::move(exprs))); - return ::std::unique_ptr(new AST::ArrayExpr(::std::move(array_elems), - ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else if (lexer.peek_token()->get_id() == COMMA) { - // multi-element array expression (or trailing comma) - ::std::vector< ::std::unique_ptr > exprs; - exprs.push_back(::std::move(initial_expr)); - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // quick break if right square bracket - if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { - break; - } - - // parse expression (required) - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse element in array expression"); - // skip somewhere? - return NULL; - } - exprs.push_back(::std::move(expr)); - - t = lexer.peek_token(); - } - - skip_token(RIGHT_SQUARE); - - ::std::unique_ptr array_elems( - new AST::ArrayElemsValues(::std::move(exprs))); - return ::std::unique_ptr(new AST::ArrayExpr(::std::move(array_elems), - ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else { - // error - error_at(lexer.peek_token()->get_locus(), - "unexpected token '%s' in array expression (arrayelems)", - lexer.peek_token()->get_token_description()); - // skip somewhere? - return NULL; - } - } - } - - // Parses a single parameter used in a closure definition. - AST::ClosureParam Parser::parse_closure_param() { - // parse pattern (which is required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - // not necessarily an error - return AST::ClosureParam::create_error(); - } - - // parse optional type of param - ::std::unique_ptr type = NULL; - if (lexer.peek_token()->get_id() == COLON) { - lexer.skip_token(); - - // parse type, which is now required - type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_id(), "failed to parse type in closure parameter"); - // skip somewhere? - return AST::ClosureParam::create_error(); - } - } - - return AST::ClosureParam(::std::move(pattern), ::std::move(type)); - } - - // Parses a grouped or tuple expression (disambiguates). - ::std::unique_ptr Parser::parse_grouped_or_tuple_expr( - ::std::vector outer_attrs, bool pratt_parse) { - // adjustment to allow Pratt parsing to reuse function without copy-paste - location_t locus = UNKNOWN_LOCATION; - if (!pratt_parse) { - locus = lexer.peek_token()->get_locus(); - - skip_token(LEFT_PAREN); - } else { - locus = lexer.peek_token()->get_locus() - 1; - } - - // parse optional inner attributes - ::std::vector inner_attrs = parse_inner_attributes(); - - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - // must be empty tuple - lexer.skip_token(); - - // create tuple with empty tuple elems - return ::std::unique_ptr( - new AST::TupleExpr(::std::vector< ::std::unique_ptr >(), - ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } - - // parse first expression (required) - ::std::unique_ptr first_expr = parse_expr(); - if (first_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse expression in grouped or tuple expression"); - // skip after somewhere? - return NULL; - } - - // detect whether grouped expression with right parentheses as next token - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - // must be grouped expr - lexer.skip_token(); - - // create grouped expr - return ::std::unique_ptr(new AST::GroupedExpr( - ::std::move(first_expr), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else if (lexer.peek_token()->get_id() == COMMA) { - // tuple expr - ::std::vector< ::std::unique_ptr > exprs; - exprs.push_back(::std::move(first_expr)); - - // parse potential other tuple exprs - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break out if right paren - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // parse expr, which is now required - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse expr in tuple expr"); - // skip somewhere? - return NULL; - } - exprs.push_back(::std::move(expr)); - - t = lexer.peek_token(); - } - - // skip right paren - skip_token(RIGHT_PAREN); - - return ::std::unique_ptr(new AST::TupleExpr( - ::std::move(exprs), ::std::move(inner_attrs), ::std::move(outer_attrs), locus)); - } else { - // error - const_TokenPtr t = lexer.peek_token(); - error_at(t->get_locus(), - "unexpected token '%s' in grouped or tuple expression (parenthesised expression) - " - "expected ')' for grouped expr and ',' for tuple expr", - t->get_token_description()); - // skip somewhere? - return NULL; - } - } - - // Parses a type (will further disambiguate any type). - ::std::unique_ptr Parser::parse_type() { - /* rules for all types: - * NeverType: '!' - * SliceType: '[' Type ']' - * InferredType: '_' - * MacroInvocation: SimplePath '!' DelimTokenTree - * ParenthesisedType: '(' Type ')' - * ImplTraitType: 'impl' TypeParamBounds - * TypeParamBounds (not type) TypeParamBound ( '+' TypeParamBound )* '+'? - * TypeParamBound Lifetime | TraitBound - * ImplTraitTypeOneBound: 'impl' TraitBound - * TraitObjectType: 'dyn'? TypeParamBounds - * TraitObjectTypeOneBound: 'dyn'? TraitBound - * TraitBound '?'? ForLifetimes? TypePath | '(' '?'? ForLifetimes? TypePath ')' - * BareFunctionType: ForLifetimes? FunctionQualifiers 'fn' etc. - * ForLifetimes (not type) 'for' '<' LifetimeParams '>' - * FunctionQualifiers ( 'async' | 'const' )? 'unsafe'? ('extern' abi?)? - * QualifiedPathInType: '<' Type ( 'as' TypePath )? '>' ( '::' TypePathSegment )+ - * TypePath: '::'? TypePathSegment ( '::' TypePathSegment)* - * ArrayType: '[' Type ';' Expr ']' - * ReferenceType: '&' Lifetime? 'mut'? TypeNoBounds - * RawPointerType: '*' ( 'mut' | 'const' ) TypeNoBounds - * TupleType: '(' Type etc. - regular tuple stuff. Also regular tuple vs - * parenthesised precedence - * - * Disambiguate between macro and type path via type path being parsed, and then if '!' - * found, convert type path to simple path for macro. - * Usual disambiguation for tuple vs parenthesised. - * For ImplTraitType and TraitObjectType individual disambiguations, they seem more like - * "special cases", so probably just try to parse the more general ImplTraitType or - * TraitObjectType and return OneBound versions if they satisfy those criteria. */ - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: - // never type - can't be macro as no path beforehand - lexer.skip_token(); - return ::std::unique_ptr(new AST::NeverType(t->get_locus())); - case LEFT_SQUARE: - // slice type or array type - requires further disambiguation - return parse_slice_or_array_type(); - case LEFT_ANGLE: { - // qualified path in type - AST::QualifiedPathInType path = parse_qualified_path_in_type(); - if (path.is_error()) { - error_at(t->get_locus(), "failed to parse qualified path in type"); - return NULL; - } - return ::std::unique_ptr( - new AST::QualifiedPathInType(::std::move(path))); - } - case UNDERSCORE: - // inferred type - lexer.skip_token(); - return ::std::unique_ptr(new AST::InferredType(t->get_locus())); - case ASTERISK: - // raw pointer type - return parse_raw_pointer_type(); - case AMP: // does this also include AMP_AMP? - // reference type - return parse_reference_type(); - case LIFETIME: { - // probably a lifetime bound, so probably type param bounds in TraitObjectType - ::std::vector< ::std::unique_ptr > bounds - = parse_type_param_bounds(); - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), t->get_locus())); - } - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { - // macro invocation or type path - requires further disambiguation. - /* for parsing path component of each rule, perhaps parse it as a typepath and - * attempt conversion to simplepath if a trailing '!' is found */ - /* Type path also includes TraitObjectTypeOneBound BUT if it starts with it, it is - * exactly the same as a TypePath syntactically, so this is a syntactical ambiguity. - * As such, the parser will parse it as a TypePath. - * This, however, does not prevent TraitObjectType from starting with a typepath. */ - - // parse path as type path - AST::TypePath path = parse_type_path(); - if (path.is_error()) { - error_at(t->get_locus(), "failed to parse path as first component of type"); - return NULL; - } - location_t locus = path.get_locus(); - - // branch on next token - t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: { - // macro invocation - // convert to simple path - AST::SimplePath macro_path = path.as_simple_path(); - if (macro_path.is_empty()) { - error_at(t->get_locus(), - "failed to parse simple path in macro invocation (for type)"); - return NULL; - } - - lexer.skip_token(); - - AST::DelimTokenTree tok_tree = parse_delim_token_tree(); - - return ::std::unique_ptr( - new AST::MacroInvocation(::std::move(macro_path), ::std::move(tok_tree), - ::std::vector(), locus)); - } - case PLUS: { - // type param bounds - ::std::vector< ::std::unique_ptr > bounds; - - // convert type path to trait bound - ::std::unique_ptr path_bound( - new AST::TraitBound(::std::move(path), locus, false, false)); - bounds.push_back(::std::move(path_bound)); - - // parse rest of bounds - FIXME: better way to find when to stop parsing - while (t->get_id() == PLUS) { - lexer.skip_token(); - - // parse bound if it exists - if not, assume end of sequence - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - break; - } - bounds.push_back(::std::move(bound)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), locus)); - } - default: - // assume that this is a type path and not an error - return ::std::unique_ptr(new AST::TypePath(::std::move(path))); - } - } - case LEFT_PAREN: - // tuple type or parenthesised type - requires further disambiguation (the usual) - // ok apparently can be a parenthesised TraitBound too, so could be - // TraitObjectTypeOneBound or TraitObjectType - return parse_paren_prefixed_type(); - case FOR: - // TraitObjectTypeOneBound or BareFunctionType - return parse_for_prefixed_type(); - case ASYNC: - case CONST: - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - // bare function type (with no for lifetimes) - return parse_bare_function_type(::std::vector()); - case IMPL: - lexer.skip_token(); - if (lexer.peek_token()->get_id() == LIFETIME) { - // cannot be one bound because lifetime prevents it from being traitbound - ::std::vector< ::std::unique_ptr > bounds - = parse_type_param_bounds(); - - return ::std::unique_ptr( - new AST::ImplTraitType(::std::move(bounds), t->get_locus())); - } else { - // should be trait bound, so parse trait bound - ::std::unique_ptr initial_bound = parse_trait_bound(); - if (initial_bound == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse ImplTraitType initial bound"); - return NULL; - } - - location_t locus = t->get_locus(); - - // short cut if next token isn't '+' - t = lexer.peek_token(); - if (t->get_id() != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound(*initial_bound); - - // DEBUG: removed as unique ptr, so should auto-delete - // delete initial_bound; - - return ::std::unique_ptr( - new AST::ImplTraitTypeOneBound(::std::move(value_bound), locus)); - } - - // parse additional type param bounds - ::std::vector< ::std::unique_ptr > bounds; - bounds.push_back(::std::move(initial_bound)); - while (t->get_id() == PLUS) { - lexer.skip_token(); - - // parse bound if it exists - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - // not an error as trailing plus may exist - break; - } - bounds.push_back(::std::move(bound)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr( - new AST::ImplTraitType(::std::move(bounds), locus)); - } - case DYN: - case QUESTION_MARK: { - // either TraitObjectType or TraitObjectTypeOneBound - bool has_dyn = false; - if (t->get_id() == DYN) { - lexer.skip_token(); - has_dyn = true; - } - - if (lexer.peek_token()->get_id() == LIFETIME) { - // cannot be one bound because lifetime prevents it from being traitbound - ::std::vector< ::std::unique_ptr > bounds - = parse_type_param_bounds(); - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), t->get_locus(), has_dyn)); - } else { - // should be trait bound, so parse trait bound - ::std::unique_ptr initial_bound = parse_trait_bound(); - if (initial_bound == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse TraitObjectType initial bound"); - return NULL; - } - - // short cut if next token isn't '+' - t = lexer.peek_token(); - if (t->get_id() != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound(*initial_bound); - - // DEBUG: removed as unique ptr, so should auto delete - // delete initial_bound; - - return ::std::unique_ptr( - new AST::TraitObjectTypeOneBound( - ::std::move(value_bound), t->get_locus(), has_dyn)); - } - - // parse additional type param bounds - ::std::vector< ::std::unique_ptr > bounds; - bounds.push_back(::std::move(initial_bound)); - while (t->get_id() == PLUS) { - lexer.skip_token(); - - // parse bound if it exists - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - // not an error as trailing plus may exist - break; - } - bounds.push_back(::std::move(bound)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), t->get_locus(), has_dyn)); - } - } - default: - error_at( - t->get_locus(), "unrecognised token '%s' in type", t->get_token_description()); - return NULL; - } - } - - /* Parses a type that has '(' as its first character. Returns a tuple type, parenthesised type, - * TraitObjectTypeOneBound, or TraitObjectType depending on following characters. */ - ::std::unique_ptr Parser::parse_paren_prefixed_type() { - /* NOTE: Syntactical ambiguity of a parenthesised trait bound is considered a trait bound, - * not a parenthesised type, so that it can still be used in type param bounds. */ - - /* NOTE: this implementation is really shit but I couldn't think of a better one. It requires - * essentially breaking polymorphism and downcasting via virtual method abuse, as it was - * copied from the rustc implementation (in which types are reified due to tagged union), - * after a more OOP attempt by me failed. */ - location_t left_delim_locus = lexer.peek_token()->get_locus(); - - // skip left delim - lexer.skip_token(); - // while next token isn't close delim, parse comma-separated types, saving whether trailing - // comma happens - const_TokenPtr t = lexer.peek_token(); - bool trailing_comma = true; - ::std::vector< ::std::unique_ptr > types; - - while (t->get_id() != RIGHT_PAREN) { - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - error_at(t->get_locus(), - "failed to parse type inside parentheses (probably tuple or parenthesised)"); - return NULL; - } - types.push_back(::std::move(type)); - - t = lexer.peek_token(); - if (t->get_id() != COMMA) { - trailing_comma = false; - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - // if only one type and no trailing comma, then not a tuple type - if (types.size() == 1 && !trailing_comma) { - // must be a TraitObjectType (with more than one bound) - if (lexer.peek_token()->get_id() == PLUS) { - // create type param bounds vector - ::std::vector< ::std::unique_ptr > bounds; - - // HACK: convert type to traitbound and add to bounds - AST::Type* released_ptr = types[0].release(); - AST::TraitBound* converted_bound = released_ptr->to_trait_bound(true); - delete released_ptr; - if (converted_bound == NULL) { - error_at(lexer.peek_token()->get_id(), - "failed to hackily converted parsed type to trait bound"); - return NULL; - } - bounds.push_back(::std::unique_ptr(converted_bound)); - // FIXME: possibly issues wrt memory here - - t = lexer.peek_token(); - while (t->get_id() == PLUS) { - lexer.skip_token(); - - // attempt to parse typeparambound - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - // not an error if null - break; - } - bounds.push_back(::std::move(bound)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), left_delim_locus)); - } else { - // release vector pointer - ::std::unique_ptr released_ptr(types[0].release()); - // HACK: attempt to convert to trait bound. if fails, parenthesised type - ::std::unique_ptr converted_bound( - released_ptr->to_trait_bound(true)); - if (converted_bound == NULL) { - // parenthesised type - return ::std::unique_ptr( - new AST::ParenthesisedType(::std::move(released_ptr), left_delim_locus)); - } else { - // trait object type (one bound) - - // DEBUG: removed as unique_ptr should auto-delete - // delete released_ptr; - - // get value semantics trait bound - AST::TraitBound value_bound(*converted_bound); - - // DEBUG: removed as unique ptr should auto-delete - // delete converted_bound; - - return ::std::unique_ptr( - new AST::TraitObjectTypeOneBound(value_bound, left_delim_locus)); - } - // FIXME: may be issues wrt memory here - } - } else { - return ::std::unique_ptr( - new AST::TupleType(::std::move(types), left_delim_locus)); - } - // TODO: ensure that this ensures that dynamic dispatch for traits is not lost somehow - } - - /* Parses a type that has 'for' as its first character. This means it has a "for lifetimes", so - * returns either a BareFunctionType, TraitObjectType, or TraitObjectTypeOneBound depending on - * following characters. */ - ::std::unique_ptr Parser::parse_for_prefixed_type() { - location_t for_locus = lexer.peek_token()->get_locus(); - // parse for lifetimes in type - ::std::vector for_lifetimes = parse_for_lifetimes(); - - // branch on next token - either function or a trait type - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case ASYNC: - case CONST: - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_bare_function_type(::std::move(for_lifetimes)); - case SCOPE_RESOLUTION: - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case DOLLAR_SIGN: { - // path, so trait type - - // parse type path to finish parsing trait bound - AST::TypePath path = parse_type_path(); - - t = lexer.peek_token(); - if (t->get_id() != PLUS) { - // must be one-bound trait type - // create trait bound value object - AST::TraitBound bound( - ::std::move(path), for_locus, false, false, ::std::move(for_lifetimes)); - - return ::std::unique_ptr( - new AST::TraitObjectTypeOneBound(::std::move(bound), for_locus)); - } - - // more than one bound trait type (or at least parsed as it - could be trailing '+') - // create trait bound pointer and bounds - ::std::unique_ptr initial_bound(new AST::TraitBound( - ::std::move(path), for_locus, false, false, ::std::move(for_lifetimes))); - ::std::vector< ::std::unique_ptr > bounds; - bounds.push_back(::std::move(initial_bound)); - - while (t->get_id() == PLUS) { - lexer.skip_token(); - - // parse type param bound if it exists - ::std::unique_ptr bound = parse_type_param_bound(); - if (bound == NULL) { - // not an error - e.g. trailing plus - return NULL; - } - bounds.push_back(::std::move(bound)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr( - new AST::TraitObjectType(::std::move(bounds), for_locus)); - } - default: - // error - error_at(t->get_locus(), - "unrecognised token '%s' in bare function type or trait object type or trait " - "object type one bound", - t->get_token_description()); - return NULL; - } - } - - // Parses a maybe named param used in bare function types. - AST::MaybeNamedParam Parser::parse_maybe_named_param() { - /* Basically guess that param is named if first token is identifier or underscore and - * second token is semicolon. This should probably have no exceptions. rustc uses - * backtracking to parse these, but at the time of writing gccrs has no backtracking - * capabilities. */ - const_TokenPtr current = lexer.peek_token(); - const_TokenPtr next = lexer.peek_token(1); - - Identifier name; - AST::MaybeNamedParam::ParamKind kind = AST::MaybeNamedParam::UNNAMED; - - if (current->get_id() == IDENTIFIER && next->get_id() == COLON) { - // named param - name = current->get_str(); - kind = AST::MaybeNamedParam::IDENTIFIER; - lexer.skip_token(1); - } else if (current->get_id() == UNDERSCORE && next->get_id() == COLON) { - // wildcard param - name = "_"; - kind = AST::MaybeNamedParam::WILDCARD; - lexer.skip_token(1); - } - - // parse type (required) - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse type in maybe named param"); - return AST::MaybeNamedParam::create_error(); - } - - return AST::MaybeNamedParam(::std::move(name), kind, ::std::move(type), current->get_locus()); - } - - /* Parses a bare function type (with the given for lifetimes for convenience - does not parse them - * itself). */ - ::std::unique_ptr Parser::parse_bare_function_type( - ::std::vector for_lifetimes) { - // TODO: pass in for lifetime location as param - location_t best_try_locus = lexer.peek_token()->get_locus(); - - AST::FunctionQualifiers qualifiers = parse_function_qualifiers(); - - if (!skip_token(FN_TOK)) { - return NULL; - } - - if (!skip_token(LEFT_PAREN)) { - return NULL; - } - - // parse function params, if they exist - ::std::vector params; - bool is_variadic = false; - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - // handle ellipsis (only if next character is right paren) - if (t->get_id() == ELLIPSIS) { - if (lexer.peek_token(1)->get_id() == RIGHT_PAREN) { - lexer.skip_token(); - is_variadic = true; - break; - } else { - error_at(t->get_locus(), - "ellipsis (for variadic) can only go at end of bare function type"); - return NULL; - } - } - - // parse required param - AST::MaybeNamedParam param = parse_maybe_named_param(); - if (param.is_error()) { - error_at(t->get_locus(), "failed to parse maybe named param in bare function type"); - return NULL; - } - params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - // bare function return type, if exists - ::std::unique_ptr return_type = NULL; - if (lexer.peek_token()->get_id() == RETURN_TYPE) { - lexer.skip_token(); - - // parse required TypeNoBounds - return_type = parse_type_no_bounds(); - if (return_type == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse return type (type no bounds) in bare function type"); - return NULL; - } - } - - return ::std::unique_ptr( - new AST::BareFunctionType(::std::move(for_lifetimes), ::std::move(qualifiers), - ::std::move(params), is_variadic, ::std::move(return_type), best_try_locus)); - } - - // Parses a reference type (mutable or immutable, with given lifetime). - ::std::unique_ptr Parser::parse_reference_type() { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(AMP); - - // parse optional lifetime - AST::Lifetime lifetime = AST::Lifetime::error(); - if (lexer.peek_token()->get_id() == LIFETIME) { - lifetime = parse_lifetime(); - if (lifetime.is_error()) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse lifetime in reference type"); - return NULL; - } - } - - bool is_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - lexer.skip_token(); - is_mut = true; - } - - // parse type no bounds, which is required - ::std::unique_ptr type = parse_type_no_bounds(); - if (type == NULL) { - error_at( - lexer.peek_token()->get_id(), "failed to parse referenced type in reference type"); - return NULL; - } - - return ::std::unique_ptr( - new AST::ReferenceType(is_mut, ::std::move(type), locus, ::std::move(lifetime))); - } - - // Parses a raw (unsafe) pointer type. - ::std::unique_ptr Parser::parse_raw_pointer_type() { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(ASTERISK); - - AST::RawPointerType::PointerType kind = AST::RawPointerType::CONST; - - // branch on next token for pointer kind info - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case MUT: - kind = AST::RawPointerType::MUT; - lexer.skip_token(); - break; - case CONST: - kind = AST::RawPointerType::CONST; - lexer.skip_token(); - break; - default: - error_at(t->get_locus(), "unrecognised token '%s' in raw pointer type", - t->get_token_description()); - return NULL; - } - - // parse type no bounds (required) - ::std::unique_ptr type = parse_type_no_bounds(); - if (type == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse pointed type of raw pointer type"); - return NULL; - } - - return ::std::unique_ptr( - new AST::RawPointerType(kind, ::std::move(type), locus)); - } - - // Parses a slice or array type, depending on following arguments (as lookahead is not possible). - ::std::unique_ptr Parser::parse_slice_or_array_type() { - location_t locus = lexer.peek_token()->get_locus(); - skip_token(LEFT_SQUARE); - - // parse inner type (required) - ::std::unique_ptr inner_type = parse_type(); - if (inner_type == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse inner type in slice or array type"); - return NULL; - } - - // branch on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case RIGHT_SQUARE: - // slice type - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::SliceType(::std::move(inner_type), locus)); - case SEMICOLON: { - // array type - lexer.skip_token(); - - // parse required array size expression - ::std::unique_ptr size = parse_expr(); - if (size == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse size expression in array type"); - return NULL; - } - - if (!skip_token(RIGHT_SQUARE)) { - return NULL; - } - - return ::std::unique_ptr( - new AST::ArrayType(::std::move(inner_type), ::std::move(size), locus)); - } - default: - // error - error_at(t->get_locus(), - "unrecognised token '%s' in slice or array type after inner type", - t->get_token_description()); - return NULL; - } - } - - // Parses a type, taking into account type boundary disambiguation. - ::std::unique_ptr Parser::parse_type_no_bounds() { - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: - // never type - can't be macro as no path beforehand - lexer.skip_token(); - return ::std::unique_ptr(new AST::NeverType(t->get_locus())); - case LEFT_SQUARE: - // slice type or array type - requires further disambiguation - return parse_slice_or_array_type(); - case LEFT_ANGLE: { - // qualified path in type - AST::QualifiedPathInType path = parse_qualified_path_in_type(); - if (path.is_error()) { - error_at(t->get_locus(), "failed to parse qualified path in type"); - return NULL; - } - return ::std::unique_ptr( - new AST::QualifiedPathInType(::std::move(path))); - } - case UNDERSCORE: - // inferred type - lexer.skip_token(); - return ::std::unique_ptr(new AST::InferredType(t->get_locus())); - case ASTERISK: - // raw pointer type - return parse_raw_pointer_type(); - case AMP: // does this also include AMP_AMP? - // reference type - return parse_reference_type(); - case LIFETIME: { - // probably a lifetime bound, so probably type param bounds in TraitObjectType - // this is not allowed, but detection here for error message - error_at(t->get_locus(), "lifetime bounds (i.e. in type param bounds, in " - "TraitObjectType) are not allowed as TypeNoBounds"); - return NULL; - } - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { - // macro invocation or type path - requires further disambiguation. - /* for parsing path component of each rule, perhaps parse it as a typepath and - * attempt conversion to simplepath if a trailing '!' is found */ - /* Type path also includes TraitObjectTypeOneBound BUT if it starts with it, it is - * exactly the same as a TypePath syntactically, so this is a syntactical ambiguity. - * As such, the parser will parse it as a TypePath. - * This, however, does not prevent TraitObjectType from starting with a typepath. */ - - // parse path as type path - AST::TypePath path = parse_type_path(); - if (path.is_error()) { - error_at( - t->get_locus(), "failed to parse path as first component of type no bounds"); - return NULL; - } - location_t locus = path.get_locus(); - - // branch on next token - t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: { - // macro invocation - // convert to simple path - AST::SimplePath macro_path = path.as_simple_path(); - if (macro_path.is_empty()) { - error_at(t->get_locus(), - "failed to parse simple path in macro invocation (for type)"); - return NULL; - } - - lexer.skip_token(); - - AST::DelimTokenTree tok_tree = parse_delim_token_tree(); - - return ::std::unique_ptr( - new AST::MacroInvocation(::std::move(macro_path), ::std::move(tok_tree), - ::std::vector(), locus)); - } - case PLUS: { - // type param bounds - not allowed, here for error message - error_at(t->get_locus(), - "type param bounds (in TraitObjectType) are not allowed as TypeNoBounds"); - return NULL; - } - default: - // assume that this is a type path and not an error - return ::std::unique_ptr(new AST::TypePath(::std::move(path))); - } - } - case LEFT_PAREN: - // tuple type or parenthesised type - requires further disambiguation (the usual) - // ok apparently can be a parenthesised TraitBound too, so could be - // TraitObjectTypeOneBound - return parse_paren_prefixed_type_no_bounds(); - case FOR: - case ASYNC: - case CONST: - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - // bare function type (with no for lifetimes) - return parse_bare_function_type(::std::vector()); - case IMPL: - lexer.skip_token(); - if (lexer.peek_token()->get_id() == LIFETIME) { - // cannot be one bound because lifetime prevents it from being traitbound - // not allowed as type no bounds, only here for error message - error_at(lexer.peek_token()->get_locus(), - "lifetime (probably lifetime bound, in type param bounds, in ImplTraitType) is " - "not allowed in TypeNoBounds"); - return NULL; - } else { - // should be trait bound, so parse trait bound - ::std::unique_ptr initial_bound = parse_trait_bound(); - if (initial_bound == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse ImplTraitTypeOneBound bound"); - return NULL; - } - - location_t locus = t->get_locus(); - - // ensure not a trait with multiple bounds - t = lexer.peek_token(); - if (t->get_id() == PLUS) { - error_at(t->get_locus(), "plus after trait bound means an ImplTraitType, " - "which is not allowed as a TypeNoBounds"); - return NULL; - } - - // convert trait bound to value object - AST::TraitBound value_bound(*initial_bound); - - // DEBUG: removed as unique ptr so should auto-delete - // delete initial_bound; - - return ::std::unique_ptr( - new AST::ImplTraitTypeOneBound(::std::move(value_bound), locus)); - } - case DYN: - case QUESTION_MARK: { - // either TraitObjectTypeOneBound - bool has_dyn = false; - if (t->get_id() == DYN) { - lexer.skip_token(); - has_dyn = true; - } - - if (lexer.peek_token()->get_id() == LIFETIME) { - // means that cannot be TraitObjectTypeOneBound - so here for error message - error_at(lexer.peek_token()->get_locus(), - "lifetime as bound in TraitObjectTypeOneBound " - "is not allowed, so cannot be TypeNoBounds"); - return NULL; - } - - // should be trait bound, so parse trait bound - ::std::unique_ptr initial_bound = parse_trait_bound(); - if (initial_bound == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse TraitObjectTypeOneBound initial bound"); - return NULL; - } - - location_t locus = t->get_locus(); - - // detect error with plus as next token - t = lexer.peek_token(); - if (t->get_id() == PLUS) { - error_at(t->get_locus(), "plus after trait bound means a TraitObjectType, " - "which is not allowed as a TypeNoBounds"); - return NULL; - } - - // convert trait bound to value object - AST::TraitBound value_bound(*initial_bound); - - // DEBUG: removed as unique ptr so should auto delete - // delete initial_bound; - - return ::std::unique_ptr( - new AST::TraitObjectTypeOneBound(::std::move(value_bound), locus, has_dyn)); - } - default: - error_at(t->get_locus(), "unrecognised token '%s' in type no bounds", - t->get_token_description()); - return NULL; - } - } - - // Parses a type no bounds beginning with '('. - ::std::unique_ptr Parser::parse_paren_prefixed_type_no_bounds() { - /* NOTE: this could probably be parsed without the HACK solution of parse_paren_prefixed_type, - * but I was lazy. So FIXME for future.*/ - - /* NOTE: again, syntactical ambiguity of a parenthesised trait bound is considered a trait - * bound, not a parenthesised type, so that it can still be used in type param bounds. */ - - location_t left_paren_locus = lexer.peek_token()->get_locus(); - - // skip left delim - lexer.skip_token(); - // while next token isn't close delim, parse comma-separated types, saving whether trailing - // comma happens - const_TokenPtr t = lexer.peek_token(); - bool trailing_comma = true; - ::std::vector< ::std::unique_ptr > types; - - while (t->get_id() != RIGHT_PAREN) { - ::std::unique_ptr type = parse_type(); - if (type == NULL) { - error_at(t->get_locus(), - "failed to parse type inside parentheses (probably tuple or parenthesised)"); - return NULL; - } - types.push_back(::std::move(type)); - - t = lexer.peek_token(); - if (t->get_id() != COMMA) { - trailing_comma = false; - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - // if only one type and no trailing comma, then not a tuple type - if (types.size() == 1 && !trailing_comma) { - // must be a TraitObjectType (with more than one bound) - if (lexer.peek_token()->get_id() == PLUS) { - // error - this is not allowed for type no bounds - error_at(lexer.peek_token()->get_id(), "plus (implying TraitObjectType as type param " - "bounds) is not allowed in type no bounds"); - return NULL; - } else { - // release vector pointer - ::std::unique_ptr released_ptr(types[0].release()); - // HACK: attempt to convert to trait bound. if fails, parenthesised type - ::std::unique_ptr converted_bound( - released_ptr->to_trait_bound(true)); - if (converted_bound == NULL) { - // parenthesised type - return ::std::unique_ptr( - new AST::ParenthesisedType(::std::move(released_ptr), left_paren_locus)); - } else { - // trait object type (one bound) - - // DEBUG: removed as unique_ptr should auto-delete - // delete released_ptr; - - // get value semantics trait bound - AST::TraitBound value_bound(*converted_bound); - - // DEBUG: removed as unique_ptr should auto-delete - // delete converted_bound; - - return ::std::unique_ptr( - new AST::TraitObjectTypeOneBound(value_bound, left_paren_locus)); - } - // FIXME: memory safety issues here - } - } else { - return ::std::unique_ptr( - new AST::TupleType(::std::move(types), left_paren_locus)); - } - // TODO: ensure that this ensures that dynamic dispatch for traits is not lost somehow - } - - /* Parses a literal pattern or range pattern. Assumes that literals passed in are valid range - * pattern bounds. Do not pass in paths in expressions, for instance. */ - ::std::unique_ptr Parser::parse_literal_or_range_pattern() { - const_TokenPtr range_lower = lexer.peek_token(); - AST::Literal::LitType type = AST::Literal::STRING; - bool has_minus = false; - - // get lit type - switch (range_lower->get_id()) { - case CHAR_LITERAL: - type = AST::Literal::CHAR; - lexer.skip_token(); - break; - case BYTE_CHAR_LITERAL: - type = AST::Literal::BYTE; - lexer.skip_token(); - break; - case INT_LITERAL: - type = AST::Literal::INT; - lexer.skip_token(); - break; - case FLOAT_LITERAL: - type = AST::Literal::FLOAT; - lexer.skip_token(); - break; - case MINUS: - // branch on next token - range_lower = lexer.peek_token(1); - switch (range_lower->get_id()) { - case INT_LITERAL: - type = AST::Literal::INT; - has_minus = true; - lexer.skip_token(1); - break; - case FLOAT_LITERAL: - type = AST::Literal::FLOAT; - has_minus = true; - lexer.skip_token(1); - break; - default: - error_at(range_lower->get_locus(), - "token type '%s' cannot be parsed as range pattern bound or literal after " - "minus " - "symbol", - range_lower->get_token_description()); - return NULL; - } - break; - default: - error_at(range_lower->get_locus(), - "token type '%s' cannot be parsed as range pattern bound", - range_lower->get_token_description()); - return NULL; - } - - const_TokenPtr next = lexer.peek_token(); - if (next->get_id() == DOT_DOT_EQ || next->get_id() == ELLIPSIS) { - // range pattern - lexer.skip_token(); - ::std::unique_ptr lower(new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), type), range_lower->get_locus(), has_minus)); - - ::std::unique_ptr upper = parse_range_pattern_bound(); - if (upper == NULL) { - error_at(next->get_locus(), "failed to parse range pattern bound in range pattern"); - return NULL; - } - - return ::std::unique_ptr(new AST::RangePattern( - ::std::move(lower), ::std::move(upper), range_lower->get_locus())); - } else { - // literal pattern - return ::std::unique_ptr(new AST::LiteralPattern( - range_lower->get_str(), type, range_lower->get_locus(), has_minus)); - } - } - - // Parses a range pattern bound (value only). - ::std::unique_ptr Parser::parse_range_pattern_bound() { - const_TokenPtr range_lower = lexer.peek_token(); - location_t range_lower_locus = range_lower->get_locus(); - - // get lit type - switch (range_lower->get_id()) { - case CHAR_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::CHAR), range_lower_locus)); - case BYTE_CHAR_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::BYTE), range_lower_locus)); - case INT_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::INT), range_lower_locus)); - case FLOAT_LITERAL: - lexer.skip_token(); - fprintf(stderr, "warning: used deprecated float range pattern bound"); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::FLOAT), range_lower_locus)); - case MINUS: - // branch on next token - range_lower = lexer.peek_token(1); - switch (range_lower->get_id()) { - case INT_LITERAL: - lexer.skip_token(1); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::INT), - range_lower_locus, true)); - case FLOAT_LITERAL: - lexer.skip_token(1); - fprintf(stderr, "warning: used deprecated float range pattern bound"); - return ::std::unique_ptr( - new AST::RangePatternBoundLiteral( - AST::Literal(range_lower->get_str(), AST::Literal::FLOAT), - range_lower_locus, true)); - default: - error_at(range_lower->get_locus(), - "token type '%s' cannot be parsed as range pattern bound after minus " - "symbol", - range_lower->get_token_description()); - return NULL; - } - case IDENTIFIER: - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { - // path in expression - AST::PathInExpression path = parse_path_in_expression(); - if (path.is_error()) { - error_at(range_lower->get_locus(), - "failed to parse path in expression range pattern bound"); - return NULL; - } - return ::std::unique_ptr( - new AST::RangePatternBoundPath(::std::move(path))); - } - case LEFT_ANGLE: { - // qualified path in expression - AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(); - if (path.is_error()) { - error_at(range_lower->get_locus(), - "failed to parse qualified path in expression range pattern bound"); - return NULL; - } - return ::std::unique_ptr( - new AST::RangePatternBoundQualPath(::std::move(path))); - } - default: - error_at(range_lower->get_locus(), - "token type '%s' cannot be parsed as range pattern bound", - range_lower->get_token_description()); - return NULL; - } - } - - // Parses a pattern (will further disambiguate any pattern). - ::std::unique_ptr Parser::parse_pattern() { - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case TRUE_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::LiteralPattern("true", AST::Literal::BOOL, t->get_locus())); - case FALSE_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::LiteralPattern("false", AST::Literal::BOOL, t->get_locus())); - case CHAR_LITERAL: - case BYTE_CHAR_LITERAL: - case INT_LITERAL: - case FLOAT_LITERAL: - return parse_literal_or_range_pattern(); - case STRING_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::LiteralPattern(t->get_str(), AST::Literal::STRING, t->get_locus())); - case BYTE_STRING_LITERAL: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::LiteralPattern(t->get_str(), AST::Literal::BYTE_STRING, t->get_locus())); - // raw string and raw byte string literals too if they are readded to lexer - case MINUS: - if (lexer.peek_token(1)->get_id() == INT_LITERAL) { - return parse_literal_or_range_pattern(); - } else if (lexer.peek_token(1)->get_id() == FLOAT_LITERAL) { - return parse_literal_or_range_pattern(); - } else { - error_at(t->get_locus(), - "unexpected token '-' in pattern - did you forget an integer literal?"); - return NULL; - } - case UNDERSCORE: - lexer.skip_token(); - return ::std::unique_ptr( - new AST::WildcardPattern(t->get_locus())); - case REF: - case MUT: - return parse_identifier_pattern(); - case IDENTIFIER: - // if identifier with no scope resolution afterwards, identifier pattern. - // if scope resolution afterwards, path pattern (or range pattern or struct pattern or - // tuple struct pattern) or macro invocation - return parse_ident_leading_pattern(); - case AMP: - case LOGICAL_AND: - // reference pattern - return parse_reference_pattern(); - case LEFT_PAREN: - // tuple pattern or grouped pattern - return parse_grouped_or_tuple_pattern(); - case LEFT_SQUARE: - // slice pattern - return parse_slice_pattern(); - case LEFT_ANGLE: { - // qualified path in expression or qualified range pattern bound - AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(); - - if (lexer.peek_token()->get_id() == DOT_DOT_EQ - || lexer.peek_token()->get_id() == ELLIPSIS) { - // qualified range pattern bound, so parse rest of range pattern - bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; - lexer.skip_token(); - - ::std::unique_ptr lower_bound( - new AST::RangePatternBoundQualPath(::std::move(path))); - ::std::unique_ptr upper_bound - = parse_range_pattern_bound(); - - return ::std::unique_ptr( - new AST::RangePattern(::std::move(lower_bound), ::std::move(upper_bound), - t->get_locus(), has_ellipsis_syntax)); - } else { - // just qualified path in expression - return ::std::unique_ptr( - new AST::QualifiedPathInExpression(::std::move(path))); - } - } - case SUPER: - case SELF: - case SELF_ALIAS: - case CRATE: - case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { - // path in expression or range pattern bound - AST::PathInExpression path = parse_path_in_expression(); - - const_TokenPtr next = lexer.peek_token(); - switch (next->get_id()) { - case DOT_DOT_EQ: - case ELLIPSIS: { - // qualified range pattern bound, so parse rest of range pattern - bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; - lexer.skip_token(); - - ::std::unique_ptr lower_bound( - new AST::RangePatternBoundPath(::std::move(path))); - ::std::unique_ptr upper_bound - = parse_range_pattern_bound(); - - return ::std::unique_ptr(new AST::RangePattern( - ::std::move(lower_bound), ::std::move(upper_bound), has_ellipsis_syntax)); - } - case EXCLAM: - return parse_macro_invocation_partial( - ::std::move(path), ::std::vector()); - case LEFT_PAREN: { - // tuple struct - lexer.skip_token(); - - // parse items - ::std::unique_ptr items = parse_tuple_struct_items(); - if (items == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse tuple struct items"); - return NULL; - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - return ::std::unique_ptr( - new AST::TupleStructPattern(::std::move(path), ::std::move(items))); - } - case LEFT_CURLY: { - // struct - lexer.skip_token(); - - // parse elements (optional) - AST::StructPatternElements elems = parse_struct_pattern_elems(); - - if (!skip_token(RIGHT_CURLY)) { - return NULL; - } - - return ::std::unique_ptr( - new AST::StructPattern(::std::move(path), ::std::move(elems))); - } - default: - // assume path in expression - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - } - default: - error_at( - t->get_locus(), "unexpected token '%s' in pattern", t->get_token_description()); - return NULL; - } - } - - // Parses a single or double reference pattern. - ::std::unique_ptr Parser::parse_reference_pattern() { - // parse double or single ref - bool is_double_ref = false; - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case AMP: - // still false - lexer.skip_token(); - break; - case LOGICAL_AND: - is_double_ref = true; - lexer.skip_token(); - break; - default: - error_at(t->get_locus(), "unexpected token '%s' in reference pattern", - t->get_token_description()); - return NULL; - } - - // parse mut (if it exists) - bool is_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - is_mut = true; - lexer.skip_token(); - } - - // parse pattern to get reference of (required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in reference pattern"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ReferencePattern(::std::move(pattern), is_mut, is_double_ref, t->get_locus())); - } - - /* Parses a grouped pattern or tuple pattern. Prefers grouped over tuple if only a single element - * with no commas. */ - ::std::unique_ptr Parser::parse_grouped_or_tuple_pattern() { - location_t paren_locus = lexer.peek_token()->get_locus(); - skip_token(LEFT_PAREN); - - // detect '..' token (ranged with no lower range) - if (lexer.peek_token()->get_id() == DOT_DOT) { - lexer.skip_token(); - - // parse new patterns while next token is a comma - ::std::vector< ::std::unique_ptr > patterns; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break if next token is ')' - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // parse pattern, which is required - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse pattern inside ranged tuple pattern"); - // skip somewhere? - return NULL; - } - patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - // skip somewhere? - return NULL; - } - - // create ranged tuple pattern items with only upper items - ::std::unique_ptr items(new AST::TuplePatternItemsRanged( - ::std::vector< ::std::unique_ptr >(), ::std::move(patterns))); - return ::std::unique_ptr( - new AST::TuplePattern(::std::move(items), paren_locus)); - } - - // parse initial pattern (required) - ::std::unique_ptr initial_pattern = parse_pattern(); - if (initial_pattern == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse pattern in grouped or tuple pattern"); - return NULL; - } - - // branch on whether next token is a comma or not - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case RIGHT_PAREN: - // grouped pattern - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::GroupedPattern(::std::move(initial_pattern), paren_locus)); - case COMMA: { - // tuple pattern - lexer.skip_token(); - - // create vector of patterns - ::std::vector< ::std::unique_ptr > patterns; - patterns.push_back(::std::move(initial_pattern)); - - t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN && t->get_id() != DOT_DOT) { - // parse pattern (required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(t->get_locus(), "failed to parse pattern in tuple pattern"); - return NULL; - } - patterns.push_back(::std::move(pattern)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - t = lexer.peek_token(); - if (t->get_id() == RIGHT_PAREN) { - // non-ranged tuple pattern - lexer.skip_token(); - - ::std::unique_ptr items( - new AST::TuplePatternItemsMultiple(::std::move(patterns))); - return ::std::unique_ptr( - new AST::TuplePattern(::std::move(items), paren_locus)); - } else if (t->get_id() == DOT_DOT) { - // ranged tuple pattern - lexer.skip_token(); - - // parse upper patterns - ::std::vector< ::std::unique_ptr > upper_patterns; - t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break if end - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // parse pattern (required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse pattern in tuple pattern"); - return NULL; - } - upper_patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - ::std::unique_ptr items( - new AST::TuplePatternItemsRanged( - ::std::move(patterns), ::std::move(upper_patterns))); - return ::std::unique_ptr( - new AST::TuplePattern(::std::move(items), paren_locus)); - } else { - // some kind of error - error_at(t->get_locus(), - "failed to parse tuple pattern (probably) or maybe grouped pattern"); - return NULL; - } - } - default: - // error - error_at(t->get_locus(), - "unrecognised token '%s' in grouped or tuple pattern after first pattern", - t->get_token_description()); - return NULL; - } - } - - // Parses a slice pattern that can match arrays or slices. Parses the square brackets too. - ::std::unique_ptr Parser::parse_slice_pattern() { - location_t square_locus = lexer.peek_token()->get_locus(); - skip_token(LEFT_SQUARE); - - // parse initial pattern (required) - ::std::unique_ptr initial_pattern = parse_pattern(); - if (initial_pattern == NULL) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse initial pattern in slice pattern"); - return NULL; - } - - ::std::vector< ::std::unique_ptr > patterns; - patterns.push_back(::std::move(initial_pattern)); - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break if end bracket - if (lexer.peek_token()->get_id() == RIGHT_SQUARE) { - break; - } - - // parse pattern (required) - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse pattern in slice pattern"); - return NULL; - } - patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_SQUARE)) { - return NULL; - } - - return ::std::unique_ptr( - new AST::SlicePattern(::std::move(patterns), square_locus)); - } - - // Parses an identifier pattern (pattern that binds a value matched to a variable). - ::std::unique_ptr Parser::parse_identifier_pattern() { - location_t locus = lexer.peek_token()->get_locus(); - - bool has_ref = false; - if (lexer.peek_token()->get_id() == REF) { - has_ref = true; - lexer.skip_token(); - - // DEBUG - fprintf(stderr, "parsed ref in identifier pattern\n"); - } - - bool has_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - has_mut = true; - lexer.skip_token(); - } - - // parse identifier (required) - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - // skip somewhere? - return NULL; - } - Identifier ident = ident_tok->get_str(); - - // DEBUG - fprintf(stderr, "parsed identifier in identifier pattern\n"); - - // parse optional pattern binding thing - ::std::unique_ptr bind_pattern = NULL; - if (lexer.peek_token()->get_id() == PATTERN_BIND) { - lexer.skip_token(); - - // parse required pattern to bind - bind_pattern = parse_pattern(); - if (bind_pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse pattern to bind in identifier pattern\n"); - return NULL; - } - } - - // DEBUG - fprintf(stderr, "about to return identifier pattern\n"); - - return ::std::unique_ptr(new AST::IdentifierPattern( - ::std::move(ident), locus, has_ref, has_mut, ::std::move(bind_pattern))); - } - - /* Parses a pattern that opens with an identifier. This includes identifier patterns, path - * patterns (and derivatives such as struct patterns, tuple struct patterns, and macro - * invocations), and ranges. */ - ::std::unique_ptr Parser::parse_ident_leading_pattern() { - // ensure first token is actually identifier - const_TokenPtr initial_tok = lexer.peek_token(); - if (initial_tok->get_id() != IDENTIFIER) { - return NULL; - } - - // save initial identifier as it may be useful (but don't skip) - ::std::string initial_ident = initial_tok->get_str(); - - // parse next tokens as a PathInExpression - AST::PathInExpression path = parse_path_in_expression(); - - // branch on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: - return parse_macro_invocation_partial( - ::std::move(path), ::std::vector()); - case LEFT_PAREN: { - // tuple struct - lexer.skip_token(); - - // DEBUG - fprintf(stderr, "parsing tuple struct pattern\n"); - - // parse items - ::std::unique_ptr items = parse_tuple_struct_items(); - if (items == NULL) { - error_at(lexer.peek_token()->get_locus(), "failed to parse tuple struct items"); - return NULL; - } - - // DEBUG - fprintf(stderr, "successfully parsed tuple struct items\n"); - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - // DEBUG - fprintf(stderr, "successfully parsed tuple struct pattern\n"); - - return ::std::unique_ptr( - new AST::TupleStructPattern(::std::move(path), ::std::move(items))); - } - case LEFT_CURLY: { - // struct - lexer.skip_token(); - - // parse elements (optional) - AST::StructPatternElements elems = parse_struct_pattern_elems(); - - if (!skip_token(RIGHT_CURLY)) { - return NULL; - } - - // DEBUG - fprintf(stderr, "successfully parsed struct pattern\n"); - - return ::std::unique_ptr( - new AST::StructPattern(::std::move(path), ::std::move(elems))); - } - case DOT_DOT_EQ: - case ELLIPSIS: { - // range - bool has_ellipsis_syntax = lexer.peek_token()->get_id() == ELLIPSIS; - - lexer.skip_token(); - - ::std::unique_ptr lower_bound( - new AST::RangePatternBoundPath(::std::move(path))); - ::std::unique_ptr upper_bound = parse_range_pattern_bound(); - - return ::std::unique_ptr(new AST::RangePattern( - ::std::move(lower_bound), ::std::move(upper_bound), has_ellipsis_syntax)); - } - case PATTERN_BIND: { - // only allow on single-segment paths - if (path.is_single_segment()) { - // identifier with pattern bind - lexer.skip_token(); - - ::std::unique_ptr bind_pattern = parse_pattern(); - if (bind_pattern == NULL) { - error_at( - t->get_locus(), "failed to parse pattern to bind to identifier pattern"); - return NULL; - } - return ::std::unique_ptr( - new AST::IdentifierPattern(::std::move(initial_ident), initial_tok->get_locus(), - false, false, ::std::move(bind_pattern))); - } - error_at(t->get_locus(), "failed to parse pattern bind to a path, not an identifier"); - return NULL; - } - default: - // assume identifier if single segment - if (path.is_single_segment()) { - return ::std::unique_ptr(new AST::IdentifierPattern( - ::std::move(initial_ident), initial_tok->get_locus())); - } - // return path otherwise - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - } - - // Parses tuple struct items if they exist. Does not parse parentheses. - ::std::unique_ptr Parser::parse_tuple_struct_items() { - ::std::vector< ::std::unique_ptr > lower_patterns; - - // DEBUG - fprintf(stderr, "started parsing tuple struct items\n"); - - // check for '..' at front - if (lexer.peek_token()->get_id() == DOT_DOT) { - // only parse upper patterns - lexer.skip_token(); - - // DEBUG - fprintf(stderr, "'..' at front in tuple struct items detected\n"); - - ::std::vector< ::std::unique_ptr > upper_patterns; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break if right paren - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // parse pattern, which is now required - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse pattern in tuple struct items"); - return NULL; - } - upper_patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - // DEBUG - fprintf(stderr, "finished parsing tuple struct items ranged (upper/none only)\n"); - - return ::std::unique_ptr(new AST::TupleStructItemsRange( - ::std::move(lower_patterns), ::std::move(upper_patterns))); - } - - // has at least some lower patterns - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN && t->get_id() != DOT_DOT) { - - // DEBUG - fprintf(stderr, "about to parse pattern in tuple struct items\n"); - - // parse pattern, which is required - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(t->get_locus(), "failed to parse pattern in tuple struct items"); - return NULL; - } - lower_patterns.push_back(::std::move(pattern)); - - // DEBUG - fprintf(stderr, "successfully parsed pattern in tuple struct items\n"); - - if (lexer.peek_token()->get_id() != COMMA) { - // DEBUG - fprintf(stderr, "broke out of parsing patterns in tuple struct items as no comma \n"); - - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // branch on next token - t = lexer.peek_token(); - switch (t->get_id()) { - case RIGHT_PAREN: - return ::std::unique_ptr( - new AST::TupleStructItemsNoRange(::std::move(lower_patterns))); - case DOT_DOT: { - // has an upper range that must be parsed separately - lexer.skip_token(); - - ::std::vector< ::std::unique_ptr > upper_patterns; - - t = lexer.peek_token(); - while (t->get_id() == COMMA) { - lexer.skip_token(); - - // break if next token is right paren - if (lexer.peek_token()->get_id() == RIGHT_PAREN) { - break; - } - - // parse pattern, which is required - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse pattern in tuple struct items"); - return NULL; - } - upper_patterns.push_back(::std::move(pattern)); - - t = lexer.peek_token(); - } - - return ::std::unique_ptr(new AST::TupleStructItemsRange( - ::std::move(lower_patterns), ::std::move(upper_patterns))); - } - default: - // error - error_at(t->get_locus(), "unexpected token '%s' in tuple struct items", - t->get_token_description()); - return NULL; - } - } - - // Parses struct pattern elements if they exist. - AST::StructPatternElements Parser::parse_struct_pattern_elems() { - ::std::vector< ::std::unique_ptr > fields; - - // try parsing struct pattern fields - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_CURLY && t->get_id() != DOT_DOT) { - ::std::unique_ptr field = parse_struct_pattern_field(); - if (field == NULL) { - // TODO: should this be an error? - // assuming that this means that it is a struct pattern etc instead - - // DEBUG - fprintf(stderr, "failed to parse struct pattern field - breaking from loop\n"); - - break; - } - - fields.push_back(::std::move(field)); - - // DEBUG - fprintf(stderr, "successfully pushed back a struct pattern field\n"); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // FIXME: this method of parsing prevents parsing any outer attributes on the .. - // also there seems to be no distinction between having etc and not having etc. - if (lexer.peek_token()->get_id() == DOT_DOT) { - lexer.skip_token(); - - // as no outer attributes - AST::StructPatternEtc etc = AST::StructPatternEtc::create_empty(); - - return AST::StructPatternElements(::std::move(fields), ::std::move(etc)); - } - - return AST::StructPatternElements(::std::move(fields)); - } - - // Parses a struct pattern field (tuple index/pattern, identifier/pattern, or identifier). - ::std::unique_ptr Parser::parse_struct_pattern_field() { - // parse outer attributes (if they exist) - ::std::vector outer_attrs = parse_outer_attributes(); - - // branch based on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case INT_LITERAL: { - // tuple index - ::std::string index_str = t->get_str(); - int index = atoi(index_str.c_str()); - - if (!skip_token(COLON)) { - return NULL; - } - - // parse required pattern - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at( - t->get_locus(), "failed to parse pattern in tuple index struct pattern field"); - return NULL; - } - - return ::std::unique_ptr( - new AST::StructPatternFieldTuplePat( - index, ::std::move(pattern), ::std::move(outer_attrs), t->get_locus())); - } - case IDENTIFIER: - // identifier-pattern OR only identifier - // branch on next token - switch (lexer.peek_token(1)->get_id()) { - case COLON: { - // identifier-pattern - Identifier ident = t->get_str(); - lexer.skip_token(); - - skip_token(COLON); - - // parse required pattern - ::std::unique_ptr pattern = parse_pattern(); - if (pattern == NULL) { - error_at( - t->get_locus(), "failed to parse pattern in struct pattern field"); - return NULL; - } - - return ::std::unique_ptr( - new AST::StructPatternFieldIdentPat(::std::move(ident), - ::std::move(pattern), ::std::move(outer_attrs), t->get_locus())); - } - case COMMA: - case RIGHT_CURLY: { - // identifier only - Identifier ident = t->get_str(); - lexer.skip_token(); - - return ::std::unique_ptr( - new AST::StructPatternFieldIdent(::std::move(ident), false, false, - ::std::move(outer_attrs), t->get_locus())); - } - default: - // error - error_at(t->get_locus(), "unrecognised token '%s' in struct pattern field", - t->get_token_description()); - return NULL; - } - case REF: - case MUT: { - // only identifier - bool has_ref = false; - if (t->get_id() == REF) { - has_ref = true; - lexer.skip_token(); - } - - bool has_mut = false; - if (lexer.peek_token()->get_id() == MUT) { - has_mut = true; - lexer.skip_token(); - } - - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - if (ident_tok == NULL) { - return NULL; - } - Identifier ident = ident_tok->get_str(); - - return ::std::unique_ptr( - new AST::StructPatternFieldIdent( - ::std::move(ident), has_ref, has_mut, ::std::move(outer_attrs), t->get_locus())); - } - default: - // not necessarily an error - return NULL; - } - } - - /* Parses a statement or expression (depending on whether a trailing semicolon exists). Useful for - * block expressions where it cannot be determined through lookahead whether it is a statement or - * expression to be parsed. */ - ExprOrStmt Parser::parse_stmt_or_expr_without_block() { - // quick exit for empty statement - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() == SEMICOLON) { - lexer.skip_token(); - ::std::unique_ptr stmt(new AST::EmptyStmt(t->get_locus())); - return ExprOrStmt(::std::move(stmt)); - } - - // parse outer attributes - ::std::vector outer_attrs = parse_outer_attributes(); - - // parsing this will be annoying because of the many different possibilities - /* best may be just to copy paste in parse_item switch, and failing that try to parse outer - * attributes, and then pass them in to either a let statement or (fallback) expression - * statement. */ - // FIXME: think of a way to do this without such a large switch? - - /* FIXME: for expressions at least, the only way that they can really be parsed properly in - * this way is if they don't support operators on them. They must be pratt-parsed otherwise. - * As such due to composability, only explicit statements will have special cases here. This - * should roughly correspond to "expr-with-block", but this warning is here in case it isn't - * the case. */ - t = lexer.peek_token(); - switch (t->get_id()) { - case LET: { - // let statement - ::std::unique_ptr stmt(parse_let_stmt(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(stmt)); - } - case PUB: - case MOD: - case EXTERN_TOK: - case USE: - case FN_TOK: - case TYPE: - case STRUCT_TOK: - case ENUM_TOK: - case CONST: - case STATIC_TOK: - case TRAIT: - case IMPL: { - ::std::unique_ptr item(parse_vis_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - } - /* TODO: implement union keyword but not really because of context-dependence - * crappy hack way to parse a union written below to separate it from the good code. */ - // case UNION: - case UNSAFE: { // maybe - unsafe traits are a thing - // if any of these (should be all possible VisItem prefixes), parse a VisItem - // can't parse item because would require reparsing outer attributes - const_TokenPtr t2 = lexer.peek_token(1); - switch (t2->get_id()) { - case LEFT_CURLY: { - // unsafe block - ::std::unique_ptr stmt( - parse_expr_stmt_with_block(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(stmt)); - } - case TRAIT: { - // unsafe trait - ::std::unique_ptr item( - parse_vis_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - } - case EXTERN_TOK: - case FN_TOK: { - // unsafe function - ::std::unique_ptr item( - parse_vis_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - } - case IMPL: { - // unsafe trait impl - ::std::unique_ptr item( - parse_vis_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - } - default: - error_at(t2->get_locus(), - "unrecognised token '%s' after parsing unsafe - expected beginning of " - "expression or statement", - t->get_token_description()); - // skip somewhere? - return ExprOrStmt::create_error(); - } - } - case SUPER: - case SELF: - case CRATE: - case DOLLAR_SIGN: { - /* path-based thing so struct/enum or path or macro invocation of a kind. however, the - * expressions are composable (i think) */ - - ::std::unique_ptr expr = parse_expr_without_block(); - - if (lexer.peek_token()->get_id() == SEMICOLON) { - // must be expression statement - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); - return ExprOrStmt(::std::move(stmt)); - } - - // return expression - return ExprOrStmt(::std::move(expr)); - } - /* FIXME: this is either a macro invocation or macro invocation semi. start parsing to - * determine which one it is. */ - // FIXME: or this is another path-based thing - struct/enum or path itself - // return parse_path_based_stmt_or_expr(::std::move(outer_attrs)); - // FIXME: old code there - case LOOP: - case WHILE: - case FOR: - case IF: - case MATCH_TOK: - case LEFT_CURLY: - case ASYNC: { - // all expressions with block, so cannot be final expr without block in function - ::std::unique_ptr stmt( - parse_expr_stmt_with_block(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(stmt)); - } - case LIFETIME: { - /* FIXME: are there any expressions without blocks that can have lifetime as their - * first token? Or is loop expr the only one? */ - // safe side for now: - const_TokenPtr t2 = lexer.peek_token(2); - if (lexer.peek_token(1)->get_id() == COLON - && (t2->get_id() == LOOP || t2->get_id() == WHILE || t2->get_id() == FOR)) { - ::std::unique_ptr stmt( - parse_expr_stmt_with_block(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(stmt)); - } else { - // should be expr without block - ::std::unique_ptr expr = parse_expr_without_block(); - - if (lexer.peek_token()->get_id() == SEMICOLON) { - // must be expression statement - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); - return ExprOrStmt(::std::move(stmt)); - } - - // return expression - return ExprOrStmt(::std::move(expr)); - } - } - // crappy hack to do union "keyword" - case IDENTIFIER: - // TODO: ensure std::string and literal comparison works - if (t->get_str() == "union") { - ::std::unique_ptr item(parse_vis_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - // or should this go straight to parsing union? - } else if (t->get_str() == "macro_rules") { - // macro_rules! macro item - ::std::unique_ptr item( - parse_macro_item(::std::move(outer_attrs))); - return ExprOrStmt(::std::move(item)); - } else if (lexer.peek_token(1)->get_id() == SCOPE_RESOLUTION - || lexer.peek_token(1)->get_id() == EXCLAM - || lexer.peek_token(1)->get_id() == LEFT_CURLY) { - // path (probably) or macro invocation or struct or enum, so probably a macro - // invocation semi decide how to parse - probably parse path and then get macro - // from it - - // FIXME: old code was good until composability was required - // return parse_path_based_stmt_or_expr(::std::move(outer_attrs)); - ::std::unique_ptr expr = parse_expr_without_block(); - - if (lexer.peek_token()->get_id() == SEMICOLON) { - // must be expression statement - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); - return ExprOrStmt(::std::move(stmt)); - } - - // return expression - return ExprOrStmt(::std::move(expr)); - } - gcc_fallthrough(); - // TODO: find out how to disable gcc "implicit fallthrough" warning - default: { - // expression statement (without block) or expression itself - parse expression then - // make it statement if semi afterwards - - ::std::unique_ptr expr = parse_expr_without_block(); - - if (lexer.peek_token()->get_id() == SEMICOLON) { - // must be expression statement - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), t->get_locus())); - return ExprOrStmt(::std::move(stmt)); - } - - // return expression - return ExprOrStmt(::std::move(expr)); - } - } - } - - // Parses a statement or expression beginning with a path (i.e. macro, struct/enum, or path expr) - ExprOrStmt Parser::parse_path_based_stmt_or_expr(::std::vector outer_attrs) { - // attempt to parse path - location_t stmt_or_expr_loc = lexer.peek_token()->get_locus(); - AST::PathInExpression path = parse_path_in_expression(); - - // branch on next token - const_TokenPtr t2 = lexer.peek_token(); - switch (t2->get_id()) { - case EXCLAM: { - // macro invocation or macro invocation semi - depends on whether there is - // a final ';' convert path in expr to simple path (as that is used in - // macros) - AST::SimplePath macro_path = path.as_simple_path(); - if (macro_path.is_empty()) { - error_at(t2->get_locus(), "failed to convert parsed path to simple " - "path (for macro invocation or semi)"); - return ExprOrStmt::create_error(); - } - - // skip exclamation mark - lexer.skip_token(); - - const_TokenPtr t3 = lexer.peek_token(); - location_t tok_tree_loc = t3->get_locus(); - - AST::DelimType type = AST::PARENS; - switch (t3->get_id()) { - case LEFT_PAREN: - type = AST::PARENS; - break; - case LEFT_SQUARE: - type = AST::SQUARE; - break; - case LEFT_CURLY: - type = AST::CURLY; - break; - default: - error_at(t3->get_locus(), - "unrecognised token '%s' in macro invocation - (opening) " - "delimiter expected", - t3->get_token_description()); - return ExprOrStmt::create_error(); - } - lexer.skip_token(); - - // parse actual token trees - ::std::vector< ::std::unique_ptr > token_trees; - - t3 = lexer.peek_token(); - // parse token trees until the initial delimiter token is found again - while (!token_id_matches_delims(t3->get_id(), type)) { - ::std::unique_ptr tree = parse_token_tree(); - - if (tree == NULL) { - error_at(t3->get_locus(), - "failed to parse token tree for macro invocation (or semi) - " - "found " - "'%s'", - t3->get_token_description()); - return ExprOrStmt::create_error(); - } - - token_trees.push_back(::std::move(tree)); - - t3 = lexer.peek_token(); - } - - // parse end delimiters - t3 = lexer.peek_token(); - if (token_id_matches_delims(t3->get_id(), type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - /* with curly bracketed macros, assume it is a macro invocation unless - * a semicolon is explicitly put at the end. this is not necessarily - * true (i.e. context-dependence) and so may have to be fixed up via - * HACKs in semantic - * analysis (by checking whether it is the last elem in the vector). - */ - - if (lexer.peek_token()->get_id() == SEMICOLON) { - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::MacroInvocationSemi(::std::move(macro_path), type, - ::std::move(token_trees), ::std::move(outer_attrs), stmt_or_expr_loc)); - return ExprOrStmt(::std::move(stmt)); - } - - // otherwise, create macro invocation - AST::DelimTokenTree delim_tok_tree(type, ::std::move(token_trees), tok_tree_loc); - - ::std::unique_ptr expr( - new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), - ::std::move(outer_attrs), stmt_or_expr_loc)); - return ExprOrStmt(::std::move(expr)); - } else { - // tokens don't match opening delimiters, so produce error - error_at(t2->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a " - "macro invocation)", - t2->get_token_description(), - (type == AST::PARENS ? ")" : (type == AST::SQUARE ? "]" : "}"))); - return ExprOrStmt::create_error(); - } - } - case LEFT_CURLY: { - /* definitely not a block: - * path '{' ident ',' - * path '{' ident ':' [anything] ',' - * path '{' ident ':' [not a type] - * otherwise, assume block expr and thus path */ - bool not_a_block - = lexer.peek_token(1)->get_id() == IDENTIFIER - && (lexer.peek_token(2)->get_id() == COMMA - || (lexer.peek_token(2)->get_id() == COLON - && (lexer.peek_token(4)->get_id() == COMMA - || !can_tok_start_type(lexer.peek_token(3)->get_id())))); - ::std::unique_ptr expr = NULL; - - if (not_a_block) { - // assume struct expr struct (as struct-enum disambiguation requires name - // lookup) again, make statement if final ';' - expr - = parse_struct_expr_struct_partial(::std::move(path), ::std::move(outer_attrs)); - if (expr == NULL) { - error_at(t2->get_locus(), "failed to parse struct expr struct"); - return ExprOrStmt::create_error(); - } - } else { - // assume path - make statement if final ';' - // lexer.skip_token(); - - // HACK: add outer attrs to path - path.replace_outer_attrs(::std::move(outer_attrs)); - expr = ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - - // determine if statement if ends with semicolon - if (lexer.peek_token()->get_id() == SEMICOLON) { - // statement - lexer.skip_token(); - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), stmt_or_expr_loc)); - return ExprOrStmt(::std::move(stmt)); - } - - // otherwise, expression - return ExprOrStmt(::std::move(expr)); - } - case LEFT_PAREN: { - // assume struct expr tuple (as struct-enum disambiguation requires name - // lookup) again, make statement if final ';' - ::std::unique_ptr struct_expr - = parse_struct_expr_tuple_partial(::std::move(path), ::std::move(outer_attrs)); - if (struct_expr == NULL) { - error_at(t2->get_locus(), "failed to parse struct expr tuple"); - return ExprOrStmt::create_error(); - } - - // determine if statement if ends with semicolon - if (lexer.peek_token()->get_id() == SEMICOLON) { - // statement - lexer.skip_token(); - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(struct_expr), stmt_or_expr_loc)); - return ExprOrStmt(::std::move(stmt)); - } - - // otherwise, expression - return ExprOrStmt(::std::move(struct_expr)); - } - default: { - // assume path - make statement if final ';' - // lexer.skip_token(); - - // HACK: replace outer attributes in path - path.replace_outer_attrs(::std::move(outer_attrs)); - ::std::unique_ptr expr( - new AST::PathInExpression(::std::move(path))); - - if (lexer.peek_token()->get_id() == SEMICOLON) { - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::ExprStmtWithoutBlock(::std::move(expr), stmt_or_expr_loc)); - return ExprOrStmt(::std::move(stmt)); - } - - return ExprOrStmt(::std::move(expr)); - } - } - } - - // Parses a struct expression field. - ::std::unique_ptr Parser::parse_struct_expr_field() { - // DEBUG: - fprintf(stderr, "beginning struct/enum expr field parsing \n"); - - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case IDENTIFIER: - if (lexer.peek_token(1)->get_id() == COLON) { - // struct expr field with identifier and expr - Identifier ident = t->get_str(); - lexer.skip_token(1); - - // parse expression (required) - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(t->get_locus(), - "failed to parse struct expression field with identifier and expression"); - return NULL; - } - - // DEBUG: - fprintf(stderr, "struct/enum expr field parsing field identifier value done \n"); - - return ::std::unique_ptr( - new AST::StructExprFieldIdentifierValue(::std::move(ident), ::std::move(expr))); - } else { - // struct expr field with identifier only - Identifier ident = t->get_str(); - lexer.skip_token(); - - // DEBUG: - fprintf(stderr, "struct/enum expr field parsing field identifier done \n"); - - return ::std::unique_ptr( - new AST::StructExprFieldIdentifier(::std::move(ident))); - } - case INT_LITERAL: { - // parse tuple index field - int index = atoi(t->get_str().c_str()); - lexer.skip_token(); - - if (!skip_token(COLON)) { - // skip somewhere? - return NULL; - } - - // parse field expression (required) - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(t->get_locus(), - "failed to parse expr in struct (or enum) expr field with tuple index"); - return NULL; - } - - // DEBUG: - fprintf(stderr, "struct/enum expr field parsing field index value done \n"); - - return ::std::unique_ptr( - new AST::StructExprFieldIndexValue(index, ::std::move(expr))); - } - case DOT_DOT: - // this is a struct base and can't be parsed here, so just return nothing without - // erroring - - // DEBUG: - fprintf(stderr, "struct/enum expr field parsing failed - '..' \n"); - - return NULL; - default: - // DEBUG: - fprintf(stderr, "struct/enum expr field parsing failed - unrecognised char \n"); - - error_at(t->get_locus(), - "unrecognised token '%s' as first token of struct expr field - expected identifier " - "or int literal", - t->get_token_description()); - return NULL; - } - } - - // Parses a macro invocation or macro invocation semi. - ExprOrStmt Parser::parse_macro_invocation_maybe_semi(::std::vector outer_attrs) { - location_t macro_locus = lexer.peek_token()->get_locus(); - AST::SimplePath macro_path = parse_simple_path(); - if (macro_path.is_empty()) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse simple path in macro invocation or semi"); - return ExprOrStmt::create_error(); - } - - if (!skip_token(EXCLAM)) { - return ExprOrStmt::create_error(); - } - - const_TokenPtr t3 = lexer.peek_token(); - location_t tok_tree_loc = t3->get_locus(); - - AST::DelimType type = AST::PARENS; - switch (t3->get_id()) { - case LEFT_PAREN: - type = AST::PARENS; - break; - case LEFT_SQUARE: - type = AST::SQUARE; - break; - case LEFT_CURLY: - type = AST::CURLY; - break; - default: - error_at(t3->get_locus(), - "unrecognised token '%s' in macro invocation - (opening) " - "delimiter expected", - t3->get_token_description()); - return ExprOrStmt::create_error(); - } - lexer.skip_token(); - - // parse actual token trees - ::std::vector< ::std::unique_ptr > token_trees; - - t3 = lexer.peek_token(); - // parse token trees until the initial delimiter token is found again - while (!token_id_matches_delims(t3->get_id(), type)) { - ::std::unique_ptr tree = parse_token_tree(); - - if (tree == NULL) { - error_at(t3->get_locus(), - "failed to parse token tree for macro invocation (or semi) - found '%s'", - t3->get_token_description()); - return ExprOrStmt::create_error(); - } - - token_trees.push_back(::std::move(tree)); - - t3 = lexer.peek_token(); - } - - // parse end delimiters - t3 = lexer.peek_token(); - if (token_id_matches_delims(t3->get_id(), type)) { - // tokens match opening delimiter, so skip. - lexer.skip_token(); - - /* with curly bracketed macros, assume it is a macro invocation unless - * a semicolon is explicitly put at the end. this is not necessarily - * true (i.e. context-dependence) and so may have to be fixed up via - * HACKs in semantic - * analysis (by checking whether it is the last elem in the vector). - */ - - if (lexer.peek_token()->get_id() == SEMICOLON) { - lexer.skip_token(); - - ::std::unique_ptr stmt( - new AST::MacroInvocationSemi(::std::move(macro_path), type, - ::std::move(token_trees), ::std::move(outer_attrs), macro_locus)); - return ExprOrStmt(::std::move(stmt)); - } - - // otherwise, create macro invocation - AST::DelimTokenTree delim_tok_tree(type, ::std::move(token_trees), tok_tree_loc); - - ::std::unique_ptr expr( - new AST::MacroInvocation(::std::move(macro_path), ::std::move(delim_tok_tree), - ::std::move(outer_attrs), macro_locus)); - return ExprOrStmt(::std::move(expr)); - } else { - const_TokenPtr t = lexer.peek_token(); - // tokens don't match opening delimiters, so produce error - error_at(t->get_locus(), - "unexpected token '%s' - expecting closing delimiter '%s' (for a " - "macro invocation)", - t->get_token_description(), - (type == AST::PARENS ? ")" : (type == AST::SQUARE ? "]" : "}"))); - return ExprOrStmt::create_error(); - } - } - - // "Unexpected token" panic mode - flags gcc error at unexpected token - void Parser::unexpected_token(const_TokenPtr t) { - ::error_at(t->get_locus(), "unexpected %s\n", t->get_token_description()); - } - - // Crappy "error recovery" performed after error by skipping tokens until a semi-colon is found - void Parser::skip_after_semicolon() { - const_TokenPtr t = lexer.peek_token(); - - while (t->get_id() != END_OF_FILE && t->get_id() != SEMICOLON) { - lexer.skip_token(); - t = lexer.peek_token(); - } - - if (t->get_id() == SEMICOLON) - lexer.skip_token(); - } - -#if 0 - // Parses a variable declaration statement. - Tree Parser::parse_variable_declaration() { - // skip initial var keyword - TODO: fix - if (!skip_token(/*VAR*/ COLON)) { - skip_after_semicolon(); - return Tree::error(); - } - - // keep identifier token as used later - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip colon - if (!skip_token(COLON)) { - skip_after_semicolon(); - return Tree::error(); - } - - // parse the actual type of the variable - Tree type_tree = parse_type(); - - if (type_tree.is_error()) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip the semicolon - skip_token(SEMICOLON); - - // check if current mapping of the scope already contains a mapping for identifier - if (scope.get_current_mapping().get(identifier->get_str())) { - // create error if this is true - error_at(identifier->get_locus(), "name %s already declared in this scope", - identifier->get_str().c_str()); - return Tree::error(); - } - - // create a new symbol using the given identifier - SymbolPtr sym(new Symbol(VARIABLE, identifier->get_str())); - // put new symbol into scope mapping - scope.get_current_mapping().insert(sym); - - // create GENERIC tree for variable declaration - Tree decl = build_decl(identifier->get_locus(), VAR_DECL, - get_identifier(sym->get_name().c_str()), type_tree.get_tree()); - // set decl_context of decl to main function (make it local variable of main function) - DECL_CONTEXT(decl.get_tree()) = main_fndecl; - - // keep VAR_DECL tree in top list of stack_var_decl_chain stack for block purposes - gcc_assert(!stack_var_decl_chain.empty()); - stack_var_decl_chain.back().append(decl); - - // associate new symbol with VAR_DECL tree - sym->set_tree_decl(decl); - - Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); - - return stmt; - } -#endif - - /* Checks if current token has inputted id - skips it and returns true if so, diagnoses an error - * and returns false otherwise. */ - bool Parser::skip_token(TokenId token_id) { - return expect_token(token_id) != const_TokenPtr(); - } - - /* Checks the current token - if id is same as expected, skips and returns it, otherwise diagnoses - * error and returns null. */ - const_TokenPtr Parser::expect_token(TokenId token_id) { - const_TokenPtr t = lexer.peek_token(); - if (t->get_id() == token_id) { - lexer.skip_token(); - return t; - } else { - error_at(t->get_locus(), "expecting %s but %s found!\n", get_token_description(token_id), - t->get_token_description()); - - return const_TokenPtr(); - } - } - -#if 0 - // Parses type in variable declaration. - Tree Parser::parse_type() { - const_TokenPtr t = lexer.peek_token(); - - Tree type; - - switch (t->get_id()) { - // TODO: fix - case /*INT*/ COLON: - lexer.skip_token(); - type = integer_type_node; - break; - case /*FLOAT*/ ELLIPSIS: - lexer.skip_token(); - type = float_type_node; - break; - case /*BOOL*/ BREAK: - lexer.skip_token(); - type = boolean_type_node; - break; - case IDENTIFIER: { - SymbolPtr s = query_type(t->get_str(), t->get_locus()); - lexer.skip_token(); - - if (s == NULL) - type = Tree::error(); - else { - type = TREE_TYPE(s->get_tree_decl().get_tree()); - } - } break; - case /*RECORD*/ DOT: - type = parse_record(); - break; - default: - unexpected_token(t); - return Tree::error(); - break; - } - - // start parsing index ranges: list of expression pairs (lower and upper indexes of array) - typedef std::vector > Dimensions; - Dimensions dimensions; - - t = lexer.peek_token(); - while (t->get_id() == LEFT_PAREN || t->get_id() == LEFT_SQUARE) { - lexer.skip_token(); - - // array bounds - Tree lower_bound, upper_bound; - - if (t->get_id() == LEFT_SQUARE) { - // for array of form [e] - Tree size = parse_integer_expression(); - skip_token(RIGHT_SQUARE); - - lower_bound = Tree(build_int_cst_type(integer_type_node, 0), size.get_locus()); - - // set upper to e - 1 - upper_bound = build_tree(MINUS_EXPR, size.get_locus(), integer_type_node, size, - build_int_cst(integer_type_node, 1)); - } else if (t->get_id() == LEFT_PAREN) { - // for array of form [e0:e1] - // parse e0 - lower_bound = parse_integer_expression(); - skip_token(COLON); - - // parse e1 - upper_bound = parse_integer_expression(); - skip_token(RIGHT_PAREN); - } else { - gcc_unreachable(); - } - - dimensions.push_back(std::make_pair(lower_bound, upper_bound)); - t = lexer.peek_token(); - } - - // start building array type - // transverse list in reverse order - for (Dimensions::reverse_iterator it = dimensions.rbegin(); it != dimensions.rend(); it++) { - // fold lower and upper expressions (simplify expressions if possible) - it->first = Tree(fold(it->first.get_tree()), it->first.get_locus()); - it->second = Tree(fold(it->second.get_tree()), it->second.get_locus()); - - if (!type.is_error()) { - // build GCC range type using lower and upper - Tree range_type - = build_range_type(integer_type_node, it->first.get_tree(), it->second.get_tree()); - // build array type - type = build_array_type(type.get_tree(), range_type.get_tree()); - } - } - - return type; - } -#endif - - // Parses an if statement. Probably important to study as it seems complex. - Tree Parser::parse_if_statement() { - // skip if statement token - if (!skip_token(IF)) { - skip_after_end(); - return Tree::error(); - } - - // parse expression in statement body - Tree expr = parse_boolean_expression(); - - // skip the "THEN" after expression - skip_token(LEFT_CURLY); - - // enter new block scope - enter_scope(); - // parse statement sequence? inside if body. Finish at "end if" or "else" - parse_statement_seq(&Parser::done_end_or_else); - - TreeSymbolMapping then_tree_scope = leave_scope(); - Tree then_stmt = then_tree_scope.bind_expr; - - Tree else_stmt; - const_TokenPtr tok = lexer.peek_token(); - // if there is an else, parse statement seq inside its body too - if (tok->get_id() == ELSE) { - // Consume 'else' - skip_token(ELSE); - - // enter block scope - enter_scope(); - parse_statement_seq(&Parser::done_end); - TreeSymbolMapping else_tree_scope = leave_scope(); - else_stmt = else_tree_scope.bind_expr; - - // Consume 'end' - skip_token(RIGHT_CURLY); - } else if (tok->get_id() == RIGHT_CURLY) { - // Consume 'end' - skip_token(RIGHT_CURLY); - } else { - unexpected_token(tok); - return Tree::error(); - } - - // build GENERIC if statement node. - return build_if_statement(expr, then_stmt, else_stmt); - } - - // Builds an if statement tree. - Tree Parser::build_if_statement(Tree bool_expr, Tree then_part, Tree else_part) { - if (bool_expr.is_error()) - return bool_expr; - - // create then label declaration tree - Tree then_label_decl = build_label_decl("then", then_part.get_locus()); - - // create else label declaration if it exists - Tree else_label_decl; - if (!else_part.is_null()) - else_label_decl = build_label_decl("else", else_part.get_locus()); - - // create endif label declaration - Tree endif_label_decl = build_label_decl("end_if", then_part.get_locus()); - - // create goto expressions for entering "if" branch, "else" branch, and code after if block - Tree goto_then - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, then_label_decl); - Tree goto_endif - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, endif_label_decl); - - Tree goto_else_or_endif; - if (!else_part.is_null()) - goto_else_or_endif - = build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, else_label_decl); - else - goto_else_or_endif = goto_endif; - - // create statement list for if statement which will have required statements appended - TreeStmtList stmt_list; - - // create conditional branch expression and append to stmt_list - Tree cond_expr = build_tree( - COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, goto_then, goto_else_or_endif); - stmt_list.append(cond_expr); - - // define location related to "then" part and append to stmt_list - Tree then_label_expr - = build_tree(LABEL_EXPR, then_part.get_locus(), void_type_node, then_label_decl); - stmt_list.append(then_label_expr); - - // append parameter "then_part" to statement list - stmt_list.append(then_part); - - // if else part exists, append a goto endif - if (!else_part.is_null()) { - // Make sure after then part has been executed we go to the end if - stmt_list.append(goto_endif); - - // define location of else label, append it, and append else_part parameter tree - Tree else_label_expr - = build_tree(LABEL_EXPR, else_part.get_locus(), void_type_node, else_label_decl); - stmt_list.append(else_label_expr); - stmt_list.append(else_part); - // do not need to jump to endif as handled implicitly here - } - - // define label for endif, append to statement list - Tree endif_label_expr - = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, endif_label_decl); - stmt_list.append(endif_label_expr); - - // return the statement list in tree form - return stmt_list.get_tree(); - } - - // Builds a GENERIC tree LABEL_DECL (represents a label, as in a "goto" label). - Tree Parser::build_label_decl(const char* name, location_t loc) { - tree t = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node); - - gcc_assert(main_fndecl != NULL_TREE); - DECL_CONTEXT(t) = main_fndecl; - - return t; - } - - // Skips all tokens until EOF or }. Don't use. - void Parser::skip_after_end() { - const_TokenPtr t = lexer.peek_token(); - - while (t->get_id() != END_OF_FILE && t->get_id() != RIGHT_CURLY) { - lexer.skip_token(); - t = lexer.peek_token(); - } - - if (t->get_id() == RIGHT_CURLY) { - lexer.skip_token(); - } - } - - /* A slightly more aware error-handler that skips all tokens until it reaches the end of the - * block scope (i.e. when left curly brackets = right curly brackets). Note: assumes currently in - * the middle of a block. Use skip_after_next_block to skip based on the assumption that the block - * has not been entered yet. */ - void Parser::skip_after_end_block() { - const_TokenPtr t = lexer.peek_token(); - int curly_count = 1; - - while (curly_count > 0 && t->get_id() != END_OF_FILE) { - switch (t->get_id()) { - case LEFT_CURLY: - curly_count++; - break; - case RIGHT_CURLY: - curly_count--; - break; - default: - break; - } - lexer.skip_token(); - t = lexer.peek_token(); - } - } - - /* Skips tokens until the end of the next block. i.e. assumes that the block has not been entered - * yet. */ - void Parser::skip_after_next_block() { - const_TokenPtr t = lexer.peek_token(); - - // initial loop - skip until EOF if no left curlies encountered - while (t->get_id() != END_OF_FILE && t->get_id() != LEFT_CURLY) { - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // if next token is left, skip it and then skip after the block ends - if (t->get_id() == LEFT_CURLY) { - lexer.skip_token(); - - skip_after_end_block(); - } - // otherwise, do nothing as EOF - } - - // Skips all tokens until ] (the end of an attribute) - does not skip the ] (as designed for - // attribute body use) - void Parser::skip_after_end_attribute() { - const_TokenPtr t = lexer.peek_token(); - - while (t->get_id() != RIGHT_SQUARE) { - lexer.skip_token(); - t = lexer.peek_token(); - } - - // Don't skip the RIGHT_SQUARE token - /*if (t->get_id() == RIGHT_SQUARE) { - lexer.skip_token(); - }*/ - } - - /* Pratt parser impl of parse_expr. FIXME: this is only provisional and probably will be changed. - * FIXME: this may only parse expressions without blocks as they are the only expressions to have - * precedence? */ - ::std::unique_ptr Parser::parse_expr(int right_binding_power, - ::std::vector outer_attrs, ParseRestrictions restrictions) { - const_TokenPtr current_token = lexer.peek_token(); - lexer.skip_token(); - - // parse null denotation (unary part of expression) - ::std::unique_ptr expr - = null_denotation_NEW(current_token, ::std::move(outer_attrs), restrictions); - - // DEBUG - fprintf(stderr, "finished parsing null denotation\n"); - - if (expr == NULL) { - // DEBUG - fprintf(stderr, "null denotation is null; returning null for parse_expr\n"); - return NULL; - } - - // DEBUG - fprintf(stderr, "null denotation is not null - going on to left denotation\n"); - - // DEBUG - fprintf(stderr, "initial rbp: '%i', initial lbp: '%i' (for '%s')\n", right_binding_power, - left_binding_power(lexer.peek_token()), lexer.peek_token()->get_token_description()); - - // stop parsing if find lower priority token - parse higher priority first - while (right_binding_power < left_binding_power(lexer.peek_token())) { - current_token = lexer.peek_token(); - lexer.skip_token(); - - expr = left_denotation( - current_token, ::std::move(expr), ::std::vector(), restrictions); - - // DEBUG - fprintf(stderr, "successfully got left_denotation in parse_expr \n"); - - if (expr == NULL) { - - // DEBUG - fprintf(stderr, "left denotation is null; returning null for parse_expr\n"); - - return NULL; - } - - // DEBUG - fprintf(stderr, "left denotation is not null - going to next iteration \n"); - } - - // DEBUG - fprintf(stderr, "successfully parsed expr in parse_expr - returning \n"); - - return expr; - } - - /* Parse expression with lowest left binding power. FIXME: this may only apply to expressions - * without blocks as they are the only ones to have precedence? */ - ::std::unique_ptr Parser::parse_expr( - ::std::vector outer_attrs, ParseRestrictions restrictions) { - // HACK: only call parse_expr(LBP_LOWEST) after ensuring it is not an expression with block? - return parse_expr(LBP_LOWEST, ::std::move(outer_attrs), restrictions); - } - - // Pratt parser impl of parse_expression. - Tree Parser::parse_expression(int right_binding_power) { - const_TokenPtr current_token = lexer.peek_token(); - lexer.skip_token(); - - Tree expr = null_denotation(current_token); - - if (expr.is_error()) { - return Tree::error(); - } - - // stop parsing if find lower priority token - parse higher priority first - while (right_binding_power < left_binding_power(lexer.peek_token())) { - current_token = lexer.peek_token(); - lexer.skip_token(); - - expr = left_denotation(current_token, expr); - if (expr.is_error()) - return Tree::error(); - } - - return expr; - } - - // Parse an expression with lowest left binding power. - Tree Parser::parse_expression() { - return parse_expression(LBP_LOWEST); - } - - // Parses a boolean expression (basically parses expression and ensures boolean result). - Tree Parser::parse_boolean_expression() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_type() != boolean_type_node) { - error_at(expr.get_locus(), "expected expression of boolean type but its type is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return expr; - } - - // Parses an integer expression (basically parses expression and ensures integer result). - Tree Parser::parse_integer_expression() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_type() != integer_type_node) { - error_at(expr.get_locus(), "expected expression of integer type but its type is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return expr; - } - - /* Determines action to take when finding token at beginning of expression. - * FIXME: this may only apply to precedence-capable expressions (which are all expressions without - * blocks), so make return type ExprWithoutBlock? It would simplify stuff. */ - ::std::unique_ptr Parser::null_denotation_NEW( - const_TokenPtr tok, ::std::vector outer_attrs, ParseRestrictions restrictions) { - // note: tok is previous character in input stream, not current one, as parse_expr - // skips it before passing it in - - /* as a Pratt parser (which works by decomposing expressions into a null denotation and then a - * left denotation), null denotations handle primaries and unary operands (but only prefix - * unary operands) */ - - switch (tok->get_id()) { - /*case IDENTIFIER: { - // when encountering identifier, lookup in scope - SymbolPtr s = scope.lookup(tok->get_str()); - if (s == NULL) { - error_at(tok->get_locus(), "variable '%s' not declared in the current scope", - tok->get_str().c_str()); - - return Tree::error(); - } - // expression is just its VAR_DECL that was stored in the Symbol at declaration - return Tree(s->get_tree_decl(), tok->get_locus()); - }*/ - // symbol table must be created in semantic analysis pass, so can't use this - case IDENTIFIER: { - // DEBUG - fprintf(stderr, "beginning null denotation identifier handling\n"); - - // best option: parse as path, then extract identifier, macro, struct/enum, or just - // path info from it - AST::PathInExpression path = parse_path_in_expression_pratt(tok); - - // DEBUG: - fprintf( - stderr, "finished null denotation identifier path parsing - next is branching \n"); - - // branch on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: - // macro - return parse_macro_invocation_partial( - ::std::move(path), ::std::move(outer_attrs)); - case LEFT_CURLY: { - bool not_a_block - = lexer.peek_token(1)->get_id() == IDENTIFIER - && (lexer.peek_token(2)->get_id() == COMMA - || (lexer.peek_token(2)->get_id() == COLON - && (lexer.peek_token(4)->get_id() == COMMA - || !can_tok_start_type(lexer.peek_token(3)->get_id())))); - - /* definitely not a block: - * path '{' ident ',' - * path '{' ident ':' [anything] ',' - * path '{' ident ':' [not a type] - * otherwise, assume block expr and thus path */ - // DEBUG - fprintf(stderr, "values of lookahead: '%s' '%s' '%s' '%s' \n", - lexer.peek_token(1)->get_token_description(), - lexer.peek_token(2)->get_token_description(), - lexer.peek_token(3)->get_token_description(), - lexer.peek_token(4)->get_token_description()); - - fprintf(stderr, "can be struct expr: '%s', not a block: '%s'\n", - restrictions.can_be_struct_expr ? "true" : "false", - not_a_block ? "true" : "false"); - - // struct/enum expr struct - if (!restrictions.can_be_struct_expr && !not_a_block) { - // assume path is returned if not single segment - if (path.is_single_segment()) { - // have to return an identifier expression or something, idk - // HACK: may have to become permanent, but this is my current - // identifier expression - return ::std::unique_ptr( - new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); - } - // HACK: add outer attrs to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - return parse_struct_expr_struct_partial( - ::std::move(path), ::std::move(outer_attrs)); - } - case LEFT_PAREN: - // struct/enum expr tuple - if (!restrictions.can_be_struct_expr) { - // assume path is returned if not single segment - if (path.is_single_segment()) { - // have to return an identifier expression or something, idk - // HACK: may have to become permanent, but this is my current - // identifier expression - return ::std::unique_ptr( - new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); - } - // HACK: add outer attrs to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - return parse_struct_expr_tuple_partial( - ::std::move(path), ::std::move(outer_attrs)); - default: - // assume path is returned if not single segment - if (path.is_single_segment()) { - // have to return an identifier expression or something, idk - // HACK: may have to become permanent, but this is my current identifier - // expression - return ::std::unique_ptr( - new AST::IdentifierExpr(tok->get_str(), tok->get_locus())); - } - // HACK: add outer attrs to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - gcc_unreachable(); - } - // FIXME: delegate to parse_literal_expr instead? would have to rejig tokens and whatever. - // FIXME: could also be path expression (and hence macro expression, struct/enum expr) - case LEFT_ANGLE: { - // qualified path - // HACK: add outer attrs to path - AST::QualifiedPathInExpression path = parse_qualified_path_in_expression(true); - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::QualifiedPathInExpression(::std::move(path))); - } - case INT_LITERAL: - // we should check the range, but ignore for now - // encode as int? - return ::std::unique_ptr( - new AST::LiteralExpr(tok->get_str(), AST::Literal::INT, tok->get_locus())); - case FLOAT_LITERAL: - // encode as float? - return ::std::unique_ptr( - new AST::LiteralExpr(tok->get_str(), AST::Literal::FLOAT, tok->get_locus())); - case STRING_LITERAL: - return ::std::unique_ptr( - new AST::LiteralExpr(tok->get_str(), AST::Literal::STRING, tok->get_locus())); - case TRUE_LITERAL: - return ::std::unique_ptr( - new AST::LiteralExpr("true", AST::Literal::BOOL, tok->get_locus())); - case FALSE_LITERAL: - return ::std::unique_ptr( - new AST::LiteralExpr("false", AST::Literal::BOOL, tok->get_locus())); - case LEFT_PAREN: { // have to parse whole expression if inside brackets - /* recursively invoke parse_expression with lowest priority possible as it it were - * a top-level expression. */ - /*AST::Expr* expr = parse_expr(); - tok = lexer.peek_token(); - - // end of expression must be a close-bracket - if (tok->get_id() != RIGHT_PAREN) - error_at( - tok->get_locus(), "expecting ')' but %s found\n", tok->get_token_description()); - else - lexer.skip_token(); - - return expr; - // FIXME: this assumes grouped expression - could be tuple expression if commas - inside*/ - - return parse_grouped_or_tuple_expr(::std::move(outer_attrs), true); - } - /*case PLUS: { // unary plus operator - // invoke parse_expr recursively with appropriate priority, etc. for below - AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); - - if (expr == NULL) - return NULL; - // can only apply to integer and float expressions - if (expr->get_type() != integer_type_node || expr->get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary plus must be int or float but it is %s", - print_type(expr->get_type())); - return NULL; - } - - return Tree(expr, tok->get_locus()); - }*/ - // Rust has no unary plus operator - case MINUS: { // unary minus - ParseRestrictions entered_from_unary; - entered_from_unary.entered_from_unary = true; - ::std::unique_ptr expr - = parse_expr(LBP_UNARY_MINUS, ::std::vector(), entered_from_unary); - - if (expr == NULL) - return NULL; - // can only apply to integer and float expressions - /*if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary minus must be int or float but it is %s", - print_type(expr.get_type())); - return Tree::error(); - }*/ - /* FIXME: when implemented the "get type" method on expr, ensure it is int or float - * type (except unsigned int). Actually, this would probably have to be done in - * semantic analysis (as type checking). */ - - /* FIXME: allow outer attributes on these expressions by having an outer attrs - * parameter in function*/ - return ::std::unique_ptr(new AST::NegationExpr(::std::move(expr), - AST::NegationExpr::NEGATE, ::std::move(outer_attrs), tok->get_locus())); - } - case EXCLAM: { // logical or bitwise not - ParseRestrictions entered_from_unary; - entered_from_unary.entered_from_unary = true; - ::std::unique_ptr expr - = parse_expr(LBP_UNARY_EXCLAM, ::std::vector(), entered_from_unary); - - if (expr == NULL) - return NULL; - // can only apply to boolean expressions - /*if (expr.get_type() != boolean_type_node) { - error_at(tok->get_locus(), - "operand of logical not must be a boolean but it is %s", - print_type(expr.get_type())); - return Tree::error(); - }*/ - // FIXME: type checking for boolean or integer expressions in semantic analysis - - // FIXME: allow outer attributes on these expressions - return ::std::unique_ptr(new AST::NegationExpr(::std::move(expr), - AST::NegationExpr::NOT, ::std::move(outer_attrs), tok->get_locus())); - } - case ASTERISK: { - // pointer dereference only - HACK: as struct expressions should always be value - // expressions, cannot be dereferenced - ParseRestrictions entered_from_unary; - entered_from_unary.entered_from_unary = true; - entered_from_unary.can_be_struct_expr = false; - ::std::unique_ptr expr = parse_expr( - LBP_UNARY_ASTERISK, ::std::vector(), entered_from_unary); - // FIXME: allow outer attributes on expression - return ::std::unique_ptr(new AST::DereferenceExpr( - ::std::move(expr), ::std::move(outer_attrs), tok->get_locus())); - } - case AMP: { - // (single) "borrow" expression - shared (mutable) or immutable - ::std::unique_ptr expr = NULL; - bool is_mut_borrow = false; - - // HACK: as struct expressions should always be value expressions, cannot be - // referenced - ParseRestrictions entered_from_unary; - entered_from_unary.entered_from_unary = true; - entered_from_unary.can_be_struct_expr = false; - - if (lexer.peek_token()->get_id() == MUT) { - lexer.skip_token(); - expr = parse_expr( - LBP_UNARY_AMP_MUT, ::std::vector(), entered_from_unary); - is_mut_borrow = true; - } else { - expr = parse_expr( - LBP_UNARY_AMP, ::std::vector(), entered_from_unary); - } - - // FIXME: allow outer attributes on expression - return ::std::unique_ptr(new AST::BorrowExpr(::std::move(expr), - is_mut_borrow, false, ::std::move(outer_attrs), tok->get_locus())); - } - case LOGICAL_AND: { - // (double) "borrow" expression - shared (mutable) or immutable - ::std::unique_ptr expr = NULL; - bool is_mut_borrow = false; - - ParseRestrictions entered_from_unary; - entered_from_unary.entered_from_unary = true; - - if (lexer.peek_token()->get_id() == MUT) { - lexer.skip_token(); - expr = parse_expr( - LBP_UNARY_AMP_MUT, ::std::vector(), entered_from_unary); - is_mut_borrow = true; - } else { - expr = parse_expr( - LBP_UNARY_AMP, ::std::vector(), entered_from_unary); - } - - // FIXME: allow outer attributes on expression - return ::std::unique_ptr(new AST::BorrowExpr(::std::move(expr), - is_mut_borrow, true, ::std::move(outer_attrs), tok->get_locus())); - } - case SCOPE_RESOLUTION: { - // TODO: fix: this is for global paths, i.e. ::std::string::whatever - error_at(tok->get_locus(), "found null denotation scope resolution operator, and " - "haven't written handling for it."); - return NULL; - } - case SELF: - case SELF_ALIAS: - case DOLLAR_SIGN: - case CRATE: - case SUPER: { - // DEBUG - fprintf( - stderr, "beginning null denotation self/self-alias/dollar/crate/super handling\n"); - - // best option: parse as path, then extract identifier, macro, struct/enum, or just - // path info from it - AST::PathInExpression path = parse_path_in_expression_pratt(tok); - - // DEBUG - fprintf(stderr, - "just finished parsing path (going to disambiguate) - peeked token is '%s'\n", - lexer.peek_token()->get_token_description()); - - // HACK: always make "self" by itself a path (regardless of next tokens) - if (tok->get_id() == SELF && path.is_single_segment()) { - // HACK: add outer attrs to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - - // branch on next token - const_TokenPtr t = lexer.peek_token(); - switch (t->get_id()) { - case EXCLAM: - // macro - return parse_macro_invocation_partial( - ::std::move(path), ::std::move(outer_attrs)); - case LEFT_CURLY: { - // struct/enum expr struct - fprintf(stderr, "can_be_struct_expr: %s\n", - restrictions.can_be_struct_expr ? "true" : "false"); - - bool not_a_block - = lexer.peek_token(1)->get_id() == IDENTIFIER - && (lexer.peek_token(2)->get_id() == COMMA - || (lexer.peek_token(2)->get_id() == COLON - && (lexer.peek_token(4)->get_id() == COMMA - || !can_tok_start_type(lexer.peek_token(3)->get_id())))); - - if (!restrictions.can_be_struct_expr && !not_a_block) { - // assume path is returned - // HACK: add outer attributes to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - return parse_struct_expr_struct_partial( - ::std::move(path), ::std::move(outer_attrs)); - } - case LEFT_PAREN: - // struct/enum expr tuple - if (!restrictions.can_be_struct_expr) { - // assume path is returned - // HACK: add outer attributes to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - return parse_struct_expr_tuple_partial( - ::std::move(path), ::std::move(outer_attrs)); - default: - // assume path is returned - // HACK: add outer attributes to path - path.replace_outer_attrs(::std::move(outer_attrs)); - return ::std::unique_ptr( - new AST::PathInExpression(::std::move(path))); - } - gcc_unreachable(); - } - case OR: - case PIPE: - case MOVE: - // closure expression - return parse_closure_expr_pratt(tok, ::std::move(outer_attrs)); - case DOT_DOT: - // either "range to" or "range full" expressions - return parse_nud_range_exclusive_expr(tok, ::std::move(outer_attrs)); - case DOT_DOT_EQ: - // range to inclusive expr - return parse_range_to_inclusive_expr(tok, ::std::move(outer_attrs)); - case RETURN_TOK: - // FIXME: is this really a null denotation expression? - return parse_return_expr(::std::move(outer_attrs), true); - case BREAK: - // FIXME: is this really a null denotation expression? - return parse_break_expr(::std::move(outer_attrs), true); - case CONTINUE: - return parse_continue_expr(::std::move(outer_attrs), true); - case LEFT_CURLY: - // ok - this is an expression with block for once. - return parse_block_expr(::std::move(outer_attrs), true); - case MATCH_TOK: - // also an expression with block - return parse_match_expr(::std::move(outer_attrs), true); - case LEFT_SQUARE: - // array definition expr (not indexing) - return parse_array_expr(::std::move(outer_attrs), true); - default: - error_at(tok->get_locus(), "found unexpected token '%s' in null denotation", - tok->get_token_description()); - return NULL; - } - } - - /* Called for each token that can appear in infix (between) position. Can be operators or other - * punctuation. - * Returns a function pointer to member function that implements the left denotation for the token - * given. */ - ::std::unique_ptr Parser::left_denotation(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions) { - // Token passed in has already been skipped, so peek gives "next" token - /*BinaryHandler binary_handler = get_binary_handler(tok->get_id()); - if (binary_handler == NULL) { - unexpected_token(tok); - return NULL; - } - - return (this->*binary_handler)(tok, left);*/ - // can't do with binary handler because same token used for several operators - - switch (tok->get_id()) { - // FIXME: allow for outer attributes to be applied - case QUESTION_MARK: { - location_t left_locus = left->get_locus_slow(); - // error propagation expression - unary postfix - return ::std::unique_ptr(new AST::ErrorPropagationExpr( - ::std::move(left), ::std::move(outer_attrs), left_locus)); - } - case PLUS: - // sum expression - binary infix - return parse_binary_plus_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case MINUS: - // difference expression - binary infix - return parse_binary_minus_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case ASTERISK: - // product expression - binary infix - return parse_binary_mult_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case DIV: - // quotient expression - binary infix - return parse_binary_div_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case PERCENT: - // modulo expression - binary infix - return parse_binary_mod_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case AMP: - // logical or bitwise and expression - binary infix - return parse_bitwise_and_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case PIPE: - // logical or bitwise or expression - binary infix - return parse_bitwise_or_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case CARET: - // logical or bitwise xor expression - binary infix - return parse_bitwise_xor_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LEFT_SHIFT: - // left shift expression - binary infix - return parse_left_shift_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case RIGHT_SHIFT: - // right shift expression - binary infix - return parse_right_shift_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case EQUAL_EQUAL: - // equal to expression - binary infix (no associativity) - return parse_binary_equal_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case NOT_EQUAL: - // not equal to expression - binary infix (no associativity) - return parse_binary_not_equal_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case RIGHT_ANGLE: - // greater than expression - binary infix (no associativity) - return parse_binary_greater_than_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LEFT_ANGLE: - // less than expression - binary infix (no associativity) - return parse_binary_less_than_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case GREATER_OR_EQUAL: - // greater than or equal to expression - binary infix (no associativity) - return parse_binary_greater_equal_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LESS_OR_EQUAL: - // less than or equal to expression - binary infix (no associativity) - return parse_binary_less_equal_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case OR: - // lazy logical or expression - binary infix - return parse_lazy_or_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LOGICAL_AND: - // lazy logical and expression - binary infix - return parse_lazy_and_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case AS: - // type cast expression - kind of binary infix (RHS is actually a TypeNoBounds) - return parse_type_cast_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case EQUAL: - // assignment expression - binary infix (note right-to-left associativity) - return parse_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case PLUS_EQ: - // plus-assignment expression - binary infix (note right-to-left associativity) - return parse_plus_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case MINUS_EQ: - // minus-assignment expression - binary infix (note right-to-left associativity) - return parse_minus_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case ASTERISK_EQ: - // multiply-assignment expression - binary infix (note right-to-left associativity) - return parse_mult_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case DIV_EQ: - // division-assignment expression - binary infix (note right-to-left associativity) - return parse_div_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case PERCENT_EQ: - // modulo-assignment expression - binary infix (note right-to-left associativity) - return parse_mod_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case AMP_EQ: - // bitwise and-assignment expression - binary infix (note right-to-left associativity) - return parse_and_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case PIPE_EQ: - // bitwise or-assignment expression - binary infix (note right-to-left associativity) - return parse_or_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case CARET_EQ: - // bitwise xor-assignment expression - binary infix (note right-to-left associativity) - return parse_xor_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LEFT_SHIFT_EQ: - // left shift-assignment expression - binary infix (note right-to-left associativity) - return parse_left_shift_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case RIGHT_SHIFT_EQ: - // right shift-assignment expression - binary infix (note right-to-left associativity) - return parse_right_shift_assig_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case DOT_DOT: - // range exclusive expression - binary infix (no associativity) - // either "range" or "range from" - return parse_led_range_exclusive_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case DOT_DOT_EQ: - // range inclusive expression - binary infix (no associativity) - // unambiguously RangeInclusiveExpr - return parse_range_inclusive_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case SCOPE_RESOLUTION: - // path expression - binary infix? FIXME should this even be parsed here? - error_at(tok->get_locus(), "found scope resolution operator in left denotation " - "function - this should probably be handled elsewhere."); - return NULL; - case DOT: { - // field expression or method call - relies on parentheses after next identifier - // or await if token after is "await" (unary postfix) - // or tuple index if token after is a decimal int literal - - const_TokenPtr next_tok = lexer.peek_token(); - if (next_tok->get_id() == IDENTIFIER && next_tok->get_str() == "await") { - // await expression - return parse_await_expr(tok, ::std::move(left), ::std::move(outer_attrs)); - } else if (next_tok->get_id() == INT_LITERAL) { - // tuple index expression - TODO check for decimal int literal - return parse_tuple_index_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - } else if (next_tok->get_id() == IDENTIFIER - && lexer.peek_token(1)->get_id() != LEFT_PAREN - && lexer.peek_token(1)->get_id() != SCOPE_RESOLUTION) { - // field expression (or should be) - FIXME: scope resolution right after - // identifier should always be method, I'm pretty sure - return parse_field_access_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - } else { - // method call (probably) - return parse_method_call_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - } - } - case LEFT_PAREN: - // function call - method call is based on dot notation first - return parse_function_call_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case LEFT_SQUARE: - // array or slice index expression (pseudo binary infix) - return parse_index_expr( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - case FLOAT_LITERAL: - // HACK: get around lexer mis-identifying '.0' or '.1' or whatever as a float literal - return parse_tuple_index_expr_float( - tok, ::std::move(left), ::std::move(outer_attrs), restrictions); - default: - error_at(tok->get_locus(), "found unexpected token '%s' in left denotation", - tok->get_token_description()); - return NULL; - } - } - - // Parses a binary addition expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_plus_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_PLUS, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::ADD, locus)); - } - - // Parses a binary subtraction expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_minus_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MINUS, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::SUBTRACT, locus)); - } - - // Parses a binary multiplication expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_mult_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MUL, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::MULTIPLY, locus)); - } - - // Parses a binary division expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_div_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_DIV, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::DIVIDE, locus)); - } - - // Parses a binary modulo expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_mod_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MOD, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::MODULUS, locus)); - } - - // Parses a binary bitwise (or eager logical) and expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_bitwise_and_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_AMP, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_AND, locus)); - } - - // Parses a binary bitwise (or eager logical) or expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_bitwise_or_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_PIPE, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_OR, locus)); - } - - // Parses a binary bitwise (or eager logical) xor expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_bitwise_xor_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_CARET, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::BITWISE_XOR, locus)); - } - - // Parses a binary left shift expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_left_shift_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_L_SHIFT, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::LEFT_SHIFT, locus)); - } - - // Parses a binary right shift expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_right_shift_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_R_SHIFT, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArithmeticOrLogicalExpr( - ::std::move(left), ::std::move(right), AST::ArithmeticOrLogicalExpr::RIGHT_SHIFT, locus)); - } - - // Parses a binary equal to expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_equal_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_EQUAL, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::EQUAL, locus)); - } - - // Parses a binary not equal to expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_not_equal_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_NOT_EQUAL, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::NOT_EQUAL, locus)); - } - - // Parses a binary greater than expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_greater_than_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_GREATER_THAN, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::GREATER_THAN, locus)); - } - - // Parses a binary less than expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_less_than_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_SMALLER_THAN, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::LESS_THAN, locus)); - } - - // Parses a binary greater than or equal to expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_greater_equal_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_GREATER_EQUAL, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::GREATER_OR_EQUAL, locus)); - } - - // Parses a binary less than or equal to expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_binary_less_equal_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_SMALLER_EQUAL, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::ComparisonExpr( - ::std::move(left), ::std::move(right), AST::ComparisonExpr::LESS_OR_EQUAL, locus)); - } - - // Parses a binary lazy boolean or expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_lazy_or_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_LOGICAL_OR, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::LazyBooleanExpr( - ::std::move(left), ::std::move(right), AST::LazyBooleanExpr::LOGICAL_OR, locus)); - } - - // Parses a binary lazy boolean and expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_lazy_and_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_LOGICAL_AND, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::LazyBooleanExpr( - ::std::move(left), ::std::move(right), AST::LazyBooleanExpr::LOGICAL_AND, locus)); - } - - // Parses a pseudo-binary infix type cast expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_type_cast_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr expr_to_cast, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, - ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr type = parse_type_no_bounds(); - if (type == NULL) - return NULL; - // FIXME: how do I get precedence put in here? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = expr_to_cast->get_locus_slow(); - - return ::std::unique_ptr( - new AST::TypeCastExpr(::std::move(expr_to_cast), ::std::move(type), locus)); - } - - // Parses a binary assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr( - new AST::AssignmentExpr(::std::move(left), ::std::move(right), locus)); - } - - // Parses a binary add-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_plus_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_PLUS_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::ADD, locus)); - } - - // Parses a binary minus-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_minus_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MINUS_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::SUBTRACT, locus)); - } - - // Parses a binary multiplication-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_mult_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MULT_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::MULTIPLY, locus)); - } - - // Parses a binary division-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_div_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_DIV_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::DIVIDE, locus)); - } - - // Parses a binary modulo-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_mod_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_MOD_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::MODULUS, locus)); - } - - // Parses a binary and-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_and_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_AMP_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_AND, locus)); - } - - // Parses a binary or-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_or_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_PIPE_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_OR, locus)); - } - - // Parses a binary xor-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_xor_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_CARET_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::BITWISE_XOR, locus)); - } - - // Parses a binary left shift-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_left_shift_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_L_SHIFT_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::LEFT_SHIFT, locus)); - } - - // Parses a binary right shift-assignment expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_right_shift_assig_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_R_SHIFT_ASSIG - 1, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr(new AST::CompoundAssignmentExpr( - ::std::move(left), ::std::move(right), AST::CompoundAssignmentExpr::RIGHT_SHIFT, locus)); - } - - // Parses a postfix unary await expression (with Pratt parsing). - ::std::unique_ptr Parser::parse_await_expr(const_TokenPtr tok, - ::std::unique_ptr expr_to_await, ::std::vector outer_attrs) { - // skip "await" identifier (as "." has already been consumed in parse_expression) - // this assumes that the identifier was already identified as await - if (!skip_token(IDENTIFIER)) { - error_at(tok->get_locus(), - "failed to skip 'await' in await expr - this is probably a deep issue."); - // skip somewhere? - return NULL; - } - - // TODO: check inside async block in semantic analysis - location_t locus = expr_to_await->get_locus_slow(); - - return ::std::unique_ptr( - new AST::AwaitExpr(::std::move(expr_to_await), ::std::move(outer_attrs), locus)); - } - - /* Parses an exclusive range ('..') in left denotation position (i.e. RangeFromExpr or - * RangeFromToExpr). */ - ::std::unique_ptr Parser::parse_led_range_exclusive_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // FIXME: this probably parses expressions accidently or whatever - // try parsing RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_DOT_DOT, ::std::vector(), restrictions); - - location_t locus = left->get_locus_slow(); - - if (right == NULL) { - // range from expr - return ::std::unique_ptr( - new AST::RangeFromExpr(::std::move(left), locus)); - } else { - return ::std::unique_ptr( - new AST::RangeFromToExpr(::std::move(left), ::std::move(right), locus)); - } - // FIXME: make non-associative - } - - /* Parses an exclusive range ('..') in null denotation position (i.e. RangeToExpr or - * RangeFullExpr). */ - ::std::unique_ptr Parser::parse_nud_range_exclusive_expr( - const_TokenPtr tok, ::std::vector outer_attrs ATTRIBUTE_UNUSED) { - // FIXME: this probably parses expressions accidently or whatever - // try parsing RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right = parse_expr(LBP_DOT_DOT, ::std::vector()); - - location_t locus = tok->get_locus(); - - if (right == NULL) { - // range from expr - return ::std::unique_ptr(new AST::RangeFullExpr(locus)); - } else { - return ::std::unique_ptr( - new AST::RangeToExpr(::std::move(right), locus)); - } - // FIXME: make non-associative - } - - // Parses a full binary range inclusive expression. - ::std::unique_ptr Parser::parse_range_inclusive_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr left, - ::std::vector outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right - = parse_expr(LBP_DOT_DOT_EQ, ::std::vector(), restrictions); - if (right == NULL) - return NULL; - // FIXME: make non-associative - - // TODO: check types. actually, do so during semantic analysis - location_t locus = left->get_locus_slow(); - - return ::std::unique_ptr( - new AST::RangeFromToInclExpr(::std::move(left), ::std::move(right), locus)); - } - - // Parses an inclusive range-to prefix unary expression. - ::std::unique_ptr Parser::parse_range_to_inclusive_expr( - const_TokenPtr tok, ::std::vector outer_attrs ATTRIBUTE_UNUSED) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr right = parse_expr(LBP_DOT_DOT_EQ); - if (right == NULL) - return NULL; - // FIXME: make non-associative - - // TODO: check types. actually, do so during semantic analysis - - return ::std::unique_ptr( - new AST::RangeToInclExpr(::std::move(right), tok->get_locus())); - } - - // Parses a pseudo-binary infix tuple index expression. - ::std::unique_ptr Parser::parse_tuple_index_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr tuple_expr, - ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // parse int literal (as token already skipped) - const_TokenPtr index_tok = expect_token(INT_LITERAL); - if (index_tok == NULL) { - return NULL; - } - ::std::string index = index_tok->get_str(); - - // convert to integer - int index_int = atoi(index.c_str()); - - location_t locus = tuple_expr->get_locus_slow(); - - return ::std::unique_ptr(new AST::TupleIndexExpr( - ::std::move(tuple_expr), index_int, ::std::move(outer_attrs), locus)); - } - - // Parses a pseudo-binary infix array (or slice) index expression. - ::std::unique_ptr Parser::parse_index_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr array_expr, - ::std::vector outer_attrs, ParseRestrictions restrictions) { - // parse RHS (as tok has already been consumed in parse_expression) - ::std::unique_ptr index_expr - = parse_expr(LBP_ARRAY_REF, ::std::vector(), restrictions); - if (index_expr == NULL) - return NULL; - - // skip ']' at end of array - if (!skip_token(RIGHT_SQUARE)) { - // skip somewhere? - return NULL; - } - - // TODO: check types. actually, do so during semantic analysis - location_t locus = array_expr->get_locus_slow(); - - return ::std::unique_ptr(new AST::ArrayIndexExpr( - ::std::move(array_expr), ::std::move(index_expr), ::std::move(outer_attrs), locus)); - } - - // Parses a pseudo-binary infix struct field access expression. - ::std::unique_ptr Parser::parse_field_access_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr struct_expr, - ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // get field name identifier (assume that this is a field access expr and not say await) - const_TokenPtr ident_tok = expect_token(IDENTIFIER); - Identifier ident = ident_tok->get_str(); - - location_t locus = struct_expr->get_locus_slow(); - - // TODO: check types. actually, do so during semantic analysis - return ::std::unique_ptr(new AST::FieldAccessExpr( - ::std::move(struct_expr), ::std::move(ident), ::std::move(outer_attrs), locus)); - } - - // Parses a pseudo-binary infix method call expression. - ::std::unique_ptr Parser::parse_method_call_expr(const_TokenPtr tok, - ::std::unique_ptr receiver_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // parse path expr segment - AST::PathExprSegment segment = parse_path_expr_segment(); - if (segment.is_error()) { - error_at(tok->get_locus(), "failed to parse path expr segment of method call expr"); - return NULL; - } - - // skip left parentheses - if (!skip_token(LEFT_PAREN)) { - return NULL; - } - - // parse method params (if they exist) - ::std::vector< ::std::unique_ptr > params; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - ::std::unique_ptr param = parse_expr(); - if (param == NULL) { - error_at(t->get_locus(), "failed to parse method param in method call"); - return NULL; - } - params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // skip right paren - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - // TODO: check types. actually do so in semantic analysis pass. - location_t locus = receiver_expr->get_locus_slow(); - - return ::std::unique_ptr( - new AST::MethodCallExpr(::std::move(receiver_expr), ::std::move(segment), - ::std::move(params), ::std::move(outer_attrs), locus)); - } - - // Parses a pseudo-binary infix function call expression. - ::std::unique_ptr Parser::parse_function_call_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, ::std::unique_ptr function_expr, - ::std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // parse function params (if they exist) - ::std::vector< ::std::unique_ptr > params; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - ::std::unique_ptr param = parse_expr(); - if (param == NULL) { - error_at(t->get_locus(), "failed to parse function param in function call"); - return NULL; - } - params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - // skip ')' at end of param list - if (!skip_token(RIGHT_PAREN)) { - // skip somewhere? - return NULL; - } - - // TODO: check types. actually, do so during semantic analysis - location_t locus = function_expr->get_locus_slow(); - - return ::std::unique_ptr(new AST::CallExpr( - ::std::move(function_expr), ::std::move(params), ::std::move(outer_attrs), locus)); - } - - // Parses a macro invocation with a path in expression already parsed (but not '!' token). - ::std::unique_ptr Parser::parse_macro_invocation_partial( - AST::PathInExpression path, ::std::vector outer_attrs) { - // macro invocation - if (!skip_token(EXCLAM)) { - return NULL; - } - - // convert PathInExpression to SimplePath - if this isn't possible, error - AST::SimplePath converted_path = path.as_simple_path(); - if (converted_path.is_empty()) { - error_at( - lexer.peek_token()->get_locus(), "failed to parse simple path in macro invocation"); - return NULL; - } - - AST::DelimTokenTree tok_tree = parse_delim_token_tree(); - - fprintf(stderr, "successfully parsed macro invocation (via partial)\n"); - - location_t macro_locus = converted_path.get_locus(); - - return ::std::unique_ptr(new AST::MacroInvocation( - ::std::move(converted_path), ::std::move(tok_tree), ::std::move(outer_attrs), macro_locus)); - } - - // Parses a struct expr struct with a path in expression already parsed (but not '{' token). - ::std::unique_ptr Parser::parse_struct_expr_struct_partial( - AST::PathInExpression path, ::std::vector outer_attrs) { - // assume struct expr struct (as struct-enum disambiguation requires name - // lookup) again, make statement if final ';' - if (!skip_token(LEFT_CURLY)) { - return NULL; - } - - // parse inner attributes - ::std::vector inner_attrs = parse_inner_attributes(); - - // branch based on next token - const_TokenPtr t = lexer.peek_token(); - location_t path_locus = path.get_locus(); - switch (t->get_id()) { - case RIGHT_CURLY: - // struct with no body - lexer.skip_token(); - - return ::std::unique_ptr(new AST::StructExprStruct( - ::std::move(path), ::std::move(inner_attrs), ::std::move(outer_attrs), path_locus)); - case DOT_DOT: - /* technically this would give a struct base-only struct, but this - * algorithm should work too. As such, AST type not happening. */ - case IDENTIFIER: - case INT_LITERAL: { - // struct with struct expr fields - - // parse struct expr fields - ::std::vector< ::std::unique_ptr > fields; - - while (t->get_id() != RIGHT_CURLY && t->get_id() != DOT_DOT) { - ::std::unique_ptr field = parse_struct_expr_field(); - if (field == NULL) { - error_at(t->get_locus(), "failed to parse struct (or enum) expr field"); - return NULL; - } - - // DEBUG: - fprintf(stderr, "struct/enum expr field validated to not be null \n"); - - fields.push_back(::std::move(field)); - - // DEBUG: - fprintf(stderr, "struct/enum expr field pushed back \n"); - - if (lexer.peek_token()->get_id() != COMMA) { - // DEBUG: - fprintf( - stderr, "lack of comma detected in struct/enum expr fields - break \n"); - break; - } - lexer.skip_token(); - - // DEBUG: - fprintf(stderr, "struct/enum expr fields comma skipped \n"); - - t = lexer.peek_token(); - } - - // DEBUG: - fprintf(stderr, "struct/enum expr about to parse struct base \n"); - - // parse struct base if it exists - AST::StructBase struct_base = AST::StructBase::error(); - if (lexer.peek_token()->get_id() == DOT_DOT) { - lexer.skip_token(); - - // parse required struct base expr - ::std::unique_ptr base_expr = parse_expr(); - if (base_expr == NULL) { - error_at(lexer.peek_token()->get_locus(), - "failed to parse struct base expression in struct " - "expression"); - return NULL; - } - - // DEBUG: - fprintf(stderr, "struct/enum expr - parsed and validated base expr \n"); - - struct_base = AST::StructBase(::std::move(base_expr)); - - // DEBUG: - fprintf(stderr, "assigned struct base to new struct base \n"); - } - - if (!skip_token(RIGHT_CURLY)) { - return NULL; - } - - // DEBUG: - fprintf(stderr, "struct/enum expr skipped right curly - done and ready to return \n"); - - return ::std::unique_ptr( - new AST::StructExprStructFields(::std::move(path), ::std::move(fields), path_locus, - ::std::move(struct_base), ::std::move(inner_attrs), ::std::move(outer_attrs))); - } - default: - error_at(t->get_locus(), - "unrecognised token '%s' in struct (or enum) expression - " - "expected '}', identifier, int literal, or '..'", - t->get_token_description()); - return NULL; - } - } - - // Parses a struct expr tuple with a path in expression already parsed (but not '(' token). - ::std::unique_ptr Parser::parse_struct_expr_tuple_partial( - AST::PathInExpression path, ::std::vector outer_attrs) { - if (!skip_token(LEFT_PAREN)) { - return NULL; - } - - ::std::vector inner_attrs = parse_inner_attributes(); - - ::std::vector< ::std::unique_ptr > exprs; - - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != RIGHT_PAREN) { - // parse expression (required) - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(t->get_locus(), "failed to parse expression in struct " - "(or enum) expression tuple"); - return NULL; - } - exprs.push_back(::std::move(expr)); - - if (lexer.peek_token()->get_id() != COMMA) { - break; - } - lexer.skip_token(); - - t = lexer.peek_token(); - } - - if (!skip_token(RIGHT_PAREN)) { - return NULL; - } - - location_t path_locus = path.get_locus(); - - return ::std::unique_ptr(new AST::StructExprTuple(::std::move(path), - ::std::move(exprs), ::std::move(inner_attrs), ::std::move(outer_attrs), path_locus)); - } - - /* Parses a path in expression with the first token passed as a parameter (as it is skipped in - * token stream). Note that this only parses segment-first paths, not global ones. */ - AST::PathInExpression Parser::parse_path_in_expression_pratt(const_TokenPtr tok) { - // HACK-y way of making up for pratt-parsing consuming first token - - // DEBUG - fprintf(stderr, "current peek token when starting path pratt parse: '%s'\n", - lexer.peek_token()->get_token_description()); - - // create segment vector - ::std::vector segments; - - ::std::string initial_str; - - switch (tok->get_id()) { - case IDENTIFIER: - initial_str = tok->get_str(); - break; - case SUPER: - initial_str = "super"; - break; - case SELF: - initial_str = "self"; - break; - case SELF_ALIAS: - initial_str = "Self"; - break; - case CRATE: - initial_str = "crate"; - break; - case DOLLAR_SIGN: - if (lexer.peek_token()->get_id() == CRATE) { - initial_str = "$crate"; - break; - } - gcc_fallthrough(); - default: - error_at(tok->get_locus(), "unrecognised token '%s' in path in expression", - tok->get_token_description()); - return AST::PathInExpression::create_error(); - } - - // parse required initial segment - AST::PathExprSegment initial_segment(initial_str, tok->get_locus()); - // parse generic args (and turbofish), if they exist - /* use lookahead to determine if they actually exist (don't want to accidently parse - * over next ident segment) */ - if (lexer.peek_token()->get_id() == SCOPE_RESOLUTION - && lexer.peek_token(1)->get_id() == LEFT_ANGLE) { - // skip scope resolution - lexer.skip_token(); - - AST::GenericArgs generic_args = parse_path_generic_args(); - - initial_segment - = AST::PathExprSegment(initial_str, tok->get_locus(), ::std::move(generic_args)); - } - if (initial_segment.is_error()) { - // skip after somewhere? - // don't necessarily throw error but yeah - - // DEBUG - fprintf(stderr, "initial segment is error - returning null\n"); - - return AST::PathInExpression::create_error(); - } - segments.push_back(::std::move(initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() == SCOPE_RESOLUTION) { - // skip scope resolution operator - lexer.skip_token(); - - // parse the actual segment - it is an error if it doesn't exist now - AST::PathExprSegment segment = parse_path_expr_segment(); - if (segment.is_error()) { - // skip after somewhere? - error_at(t->get_locus(), "could not parse path expression segment"); - return AST::PathInExpression::create_error(); - } - - segments.push_back(::std::move(segment)); - - t = lexer.peek_token(); - } - - // DEBUG: - fprintf(stderr, "current token (just about to return path to null denotation): '%s'\n", - lexer.peek_token()->get_token_description()); - - return AST::PathInExpression(::std::move(segments), tok->get_locus(), false); - } - - // Parses a closure expression with pratt parsing (from null denotation). - ::std::unique_ptr Parser::parse_closure_expr_pratt( - const_TokenPtr tok, ::std::vector outer_attrs) { - // TODO: does this need pratt parsing (for precedence)? probably not, but idk - location_t locus = tok->get_locus(); - bool has_move = false; - if (tok->get_id() == MOVE) { - has_move = true; - tok = lexer.peek_token(); - lexer.skip_token(); - // skip token and reassign - } - - // handle parameter list - ::std::vector params; - - switch (tok->get_id()) { - case OR: - // no parameters, don't skip token - break; - case PIPE: { - // actually may have parameters - // don't skip token - const_TokenPtr t = lexer.peek_token(); - while (t->get_id() != PIPE) { - AST::ClosureParam param = parse_closure_param(); - if (param.is_error()) { - // TODO is this really an error? - error_at(t->get_locus(), "could not parse closure param"); - return NULL; - } - params.push_back(::std::move(param)); - - if (lexer.peek_token()->get_id() != COMMA) { - // not an error but means param list is done - break; - } - // skip comma - lexer.skip_token(); - - t = lexer.peek_token(); - } - - if (!skip_token(PIPE)) { - return NULL; - } - break; - } - default: - error_at(tok->get_locus(), - "unexpected token '%s' in closure expression - expected '|' or '||'", - tok->get_token_description()); - // skip somewhere? - return NULL; - } - - // again branch based on next token - tok = lexer.peek_token(); - if (tok->get_id() == RETURN_TYPE) { - // must be return type closure with block expr - - // skip "return type" token - lexer.skip_token(); - - // parse actual type, which is required - ::std::unique_ptr type = parse_type_no_bounds(); - if (type == NULL) { - // error - error_at(tok->get_locus(), "failed to parse type for closure"); - // skip somewhere? - return NULL; - } - - // parse block expr, which is required - ::std::unique_ptr block = parse_block_expr(); - if (block == NULL) { - // error - error_at(lexer.peek_token()->get_locus(), "failed to parse block expr in closure"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr( - new AST::ClosureExprInnerTyped(::std::move(type), ::std::move(block), - ::std::move(params), locus, has_move, ::std::move(outer_attrs))); - } else { - // must be expr-only closure - - // parse expr, which is required - ::std::unique_ptr expr = parse_expr(); - if (expr == NULL) { - error_at(tok->get_locus(), "failed to parse expression in closure"); - // skip somewhere? - return NULL; - } - - return ::std::unique_ptr(new AST::ClosureExprInner( - ::std::move(expr), ::std::move(params), locus, has_move, ::std::move(outer_attrs))); - } - } - - /* Parses a tuple index expression (pratt-parsed) from a 'float' token as a result of lexer - * misidentification. */ - ::std::unique_ptr Parser::parse_tuple_index_expr_float(const_TokenPtr tok, - ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // only works on float literals - if (tok->get_id() != FLOAT_LITERAL) { - return NULL; - } - - // DEBUG: - fprintf(stderr, "exact string form of float: '%s'\n", tok->get_str().c_str()); - - // get float string and remove dot and initial 0 - ::std::string index_str = tok->get_str(); - index_str.erase(index_str.begin()); - - // get int from string - int index = atoi(index_str.c_str()); - - location_t locus = tuple_expr->get_locus_slow(); - - return ::std::unique_ptr( - new AST::TupleIndexExpr(::std::move(tuple_expr), index, ::std::move(outer_attrs), locus)); - } - - // Determines action to take when finding token at beginning of expression. - Tree Parser::null_denotation(const_TokenPtr tok) { - // note: tok is previous character in input stream, not current one, as parse_expression - // skips it before passing it in - - /* as a Pratt parser (which works by decomposing expressions into a null denotation and then a - * left denotation), null denotations handle primaries and unary operands (but only prefix - * unary operands) */ - - switch (tok->get_id()) { - case IDENTIFIER: { - // when encountering identifier, lookup in scope - SymbolPtr s = scope.lookup(tok->get_str()); - if (s == NULL) { - error_at(tok->get_locus(), "variable '%s' not declared in the current scope", - tok->get_str().c_str()); - - return Tree::error(); - } - // expression is just its VAR_DECL that was stored in the Symbol at declaration - return Tree(s->get_tree_decl(), tok->get_locus()); - } - case INT_LITERAL: - // we should check the range, but ignore for now - // literal itself encodes value, so token's text has to be interpreted as int. use - // atoi for this - return Tree(build_int_cst_type(integer_type_node, atoi(tok->get_str().c_str())), - tok->get_locus()); - case FLOAT_LITERAL: { - REAL_VALUE_TYPE float_value; - // invoke real_from_string3 to get float value representation from string - real_from_string3(&float_value, tok->get_str().c_str(), TYPE_MODE(float_type_node)); - // this is because machine-dependent - - // create actual tree with that built constant value - return Tree(build_real(float_type_node, float_value), tok->get_locus()); - } - case STRING_LITERAL: { - // get c string from token - std::string str = tok->get_str(); - const char* c_str = str.c_str(); - - // use GCC's build_string_literal (with null terminator) to create tree - return Tree(build_string_literal(strlen(c_str) + 1, c_str), tok->get_locus()); - } - case TRUE_LITERAL: { - // construct tree with code INTEGER_CST and value 1 but with boolean_type_node - return Tree(build_int_cst_type(boolean_type_node, 1), tok->get_locus()); - break; - } - case FALSE_LITERAL: { - return Tree(build_int_cst_type(boolean_type_node, 0), tok->get_locus()); - break; - } - case LEFT_PAREN: { // have to parse whole expression if inside brackets - /* recursively invoke parse_expression with lowest priority possible as it it were - * a top-level expression. */ - Tree expr = parse_expression(); - tok = lexer.peek_token(); - - // end of expression must be a close-bracket - if (tok->get_id() != RIGHT_PAREN) - error_at( - tok->get_locus(), "expecting ')' but %s found\n", tok->get_token_description()); - else - lexer.skip_token(); - - return Tree(expr, tok->get_locus()); - } - case PLUS: { // unary plus operator - // invoke parse_expression recursively with appropriate priority, etc. for below - Tree expr = parse_expression(LBP_UNARY_PLUS); - - if (expr.is_error()) - return Tree::error(); - // can only apply to integer and float expressions - if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary plus must be int or float but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - return Tree(expr, tok->get_locus()); - } - case MINUS: { // unary minus - TODO: does not work on unsigned integers - Tree expr = parse_expression(LBP_UNARY_MINUS); - - if (expr.is_error()) - return Tree::error(); - // can only apply to integer and float expressions - if (expr.get_type() != integer_type_node || expr.get_type() != float_type_node) { - error_at(tok->get_locus(), - "operand of unary minus must be int or float but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - // create NEGATE_EXPR tree, which computes negation of operand - expr = build_tree(NEGATE_EXPR, tok->get_locus(), expr.get_type(), expr); - return expr; - } - case EXCLAM: { // logical not - TODO: this could also be bitwise not - Tree expr = parse_expression(LBP_UNARY_EXCLAM /*LOGICAL_NOT*/); - - if (expr.is_error()) - return Tree::error(); - // can only apply to boolean expressions - if (expr.get_type() != boolean_type_node) { - error_at(tok->get_locus(), - "operand of logical not must be a boolean but it is %s", - print_type(expr.get_type())); - return Tree::error(); - } - - // create TRUTH_NOT_EXPR tree, which computes logical negation of operand - expr = build_tree(TRUTH_NOT_EXPR, tok->get_locus(), boolean_type_node, expr); - return expr; - } - case ASTERISK: { - // TODO: fix: this is pointer dereference only, I think - Tree expr = parse_expression(LBP_UNARY_ASTERISK); - return expr; - } - case AMP: { - // TODO: fix: this is reference only, I think - Tree expr = NULL_TREE; - - if (lexer.peek_token()->get_id() == MUT) - expr = parse_expression(LBP_UNARY_AMP_MUT); - else - expr = parse_expression(LBP_UNARY_AMP); - - return expr; - } - case SCOPE_RESOLUTION: { - // TODO: fix: this is for global paths, i.e. ::std::string::whatever - } - default: - unexpected_token(tok); - return Tree::error(); - } - } - - /* Called for each token that can appear in infix (between) position. Can be operators or other - * punctuation. - * Returns a function pointer to member function that implements the left denotation for the token - * given. */ - Tree Parser::left_denotation(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - /*BinaryHandler binary_handler = get_binary_handler(tok->get_id()); - if (binary_handler == NULL) { - unexpected_token(tok); - return Tree::error(); - } - - return (this->*binary_handler)(tok, left);*/ - return Tree::error(); - } - - // Gets method for handling binary operation parsing for specific token type. - /*Parser::BinaryHandler Parser::get_binary_handler(TokenId id) { - switch (id) { -#define BINARY_HANDLER(name, token_id) \ - case token_id: \ - return &Parser::binary_##name; - BINARY_HANDLER_LIST -#undef BINARY_HANDLER - default: - return NULL; - } - }*/ - - /* Returns the type of the binary operation. May also modify input trees if types do not match, - * e.g. change a float and int to two floats in addition. */ - Tree Parser::coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right) { - Tree left_type = left->get_type(); - Tree right_type = right->get_type(); - - // return error if either types are invalid - if (left_type.is_error() || right_type.is_error()) - return Tree::error(); - - // good, easy, no type conversion required - if (left_type == right_type) { - if (left_type == integer_type_node || left_type == float_type_node) { - return left_type; - } - // dodgy type coercion happening if types don't match but are both numerical - } else if ((left_type == integer_type_node && right_type == float_type_node) - || (left_type == float_type_node && right_type == integer_type_node)) { - // rebuild one tree as float - if (left_type == integer_type_node) { - *left = build_tree(FLOAT_EXPR, left->get_locus(), float_type_node, left->get_tree()); - } else { - *right - = build_tree(FLOAT_EXPR, right->get_locus(), float_type_node, right->get_tree()); - } - - return float_type_node; - } - - // unhandled - e.g. int + boolean - error_at(tok->get_locus(), "invalid operands of type %s and %s for operator %s", - print_type(left_type), print_type(right_type), tok->get_token_description()); - return Tree::error(); - } - - // Verifies that both left and right trees are boolean-type nodes. - bool Parser::check_logical_operands(const_TokenPtr tok, Tree left, Tree right) { - // ensure both operands are boolean types - if (left.get_type() != boolean_type_node || right.get_type() != boolean_type_node) { - error_at(tok->get_locus(), - "operands of operator %s must be boolean but they are %s and %s\n", - tok->get_token_description(), print_type(left.get_type()), - print_type(right.get_type())); - - return false; - } - - return true; - } - - // Implementation of addition expression parsing. - Tree Parser::binary_plus(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code PLUS_EXPR to represent binary addition - return build_tree(PLUS_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of subtraction expression parsing. - Tree Parser::binary_minus(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code MINUS_EXPR to represent binary subtraction - return build_tree(MINUS_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of multiplication expression parsing. - Tree Parser::binary_mult(const_TokenPtr tok, Tree left) { - // parse RHS (as tok has already been consumed in parse_expression) - Tree right = parse_expression(LBP_PLUS); - if (right.is_error()) - return Tree::error(); - - /* compute resulting type of binary operator with coerce_binary_arithmetic method, which may - * also modify input trees. */ - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - // construct tree with code MULT_EXPR to represent binary multiplication - return build_tree(MULT_EXPR, tok->get_locus(), tree_type, left, right); - } - - // Implementation of divison expression parsing. - Tree Parser::binary_div(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_DIV); - if (right.is_error()) - return Tree::error(); - - // if integer division, create C-like truncated division expression tree - if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { - return build_tree(TRUNC_DIV_EXPR, tok->get_locus(), integer_type_node, left, right); - } else { - // floating-point division - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - gcc_assert(tree_type == float_type_node); - - return build_tree(RDIV_EXPR, tok->get_locus(), tree_type, left, right); - } - } - - // Implementation of modulo expression parsing. - Tree Parser::binary_mod(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_MOD); - if (right.is_error()) - return Tree::error(); - - // if integer modulo, create truncated modulo expression - if (left.get_type() == integer_type_node && right.get_type() == integer_type_node) { - return build_tree(TRUNC_MOD_EXPR, tok->get_locus(), integer_type_node, left, right); - } else { - // no floating-point modulo - return Tree::error(); - } - } - - // Implementation of binary equal comparison relational operator parsing. - Tree Parser::binary_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(EQ_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary different comparison relational operator parsing. - Tree Parser::binary_not_equal /*different*/ (const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_NOT_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(NE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary smaller than comparison relational operator parsing. - Tree Parser::binary_smaller_than(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_SMALLER_THAN); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(LT_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary greater than comparison relational operator parsing. - Tree Parser::binary_greater_than(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_GREATER_THAN); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(GT_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary smaller than or equal to comparison relational operator parsing. - Tree Parser::binary_smaller_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_SMALLER_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(LE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary greater than or equal to comparison relational operator parsing. - Tree Parser::binary_greater_equal(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_GREATER_EQUAL); - if (right.is_error()) - return Tree::error(); - - Tree tree_type = coerce_binary_arithmetic(tok, &left, &right); - if (tree_type.is_error()) - return Tree::error(); - - return build_tree(GE_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary "and" logical operator parsing. - Tree Parser::binary_logical_and(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_LOGICAL_AND); - if (right.is_error()) - return Tree::error(); - - if (!check_logical_operands(tok, left, right)) - return Tree::error(); - - return build_tree(TRUTH_ANDIF_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary "or" logical operator parsing. - Tree Parser::binary_logical_or(const_TokenPtr tok, Tree left) { - // parse RHS - Tree right = parse_expression(LBP_LOGICAL_OR); - if (right.is_error()) - return Tree::error(); - - if (!check_logical_operands(tok, left, right)) - return Tree::error(); - - return build_tree(TRUTH_ORIF_EXPR, tok->get_locus(), boolean_type_node, left, right); - } - - // Implementation of binary array reference ([) operator parsing; - Tree Parser::binary_array_index(const_TokenPtr tok, Tree left) { - // parse integer expression inside square brackets (array index) - Tree right = parse_integer_expression(); - if (right.is_error()) - return Tree::error(); - - // array close token - if (!skip_token(RIGHT_SQUARE)) - return Tree::error(); - - // verify left operand has array type - if (!is_array_type(left.get_type())) { - error_at(left.get_locus(), "does not have array type"); - return Tree::error(); - } - - // compute type of array element - Tree element_type = TREE_TYPE(left.get_type().get_tree()); - - // build GENERIC tree ARRAY_REF that represents array access - return build_tree(ARRAY_REF, tok->get_locus(), element_type, left, right, Tree(), Tree()); - } - - // Parses a binary field access on a record. - Tree Parser::binary_field_ref(const_TokenPtr tok, Tree left) { - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) - return Tree::error(); - - // ensure left expression has record type - if (!is_record_type(left.get_type())) { - error_at(left.get_locus(), "does not have record type"); - return Tree::error(); - } - - // traverse each FIELD_DECL chaining through TREE_CHAIN - // list of fields in record type is available through TYPE_FIELDS - Tree field_decl = TYPE_FIELDS(left.get_type().get_tree()); - while (!field_decl.is_null()) { - // FIELD_DECL has a DECL_NAME containing an IDENTIFIER_POINTER to get field name - Tree decl_name = DECL_NAME(field_decl.get_tree()); - const char* field_name = IDENTIFIER_POINTER(decl_name.get_tree()); - - if (field_name == identifier->get_str()) - break; - - field_decl = TREE_CHAIN(field_decl.get_tree()); - } - - // if can't find a field with given name, this is an error - if (field_decl.is_null()) { - error_at(left.get_locus(), "record type does not have a field named '%s'", - identifier->get_str().c_str()); - return Tree::error(); - } - - // build COMPONENT_REF tree using left tree (record type) and appropriate FIELD_DECL - return build_tree(COMPONENT_REF, tok->get_locus(), TREE_TYPE(field_decl.get_tree()), left, - field_decl, Tree()); - } - - // Method stub - Tree Parser::binary_bitwise_or(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_left_shift(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_bitwise_and(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_bitwise_xor(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_right_shift(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_as_cast(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_div_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_mod_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_mult_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_plus_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_minus_assig(const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_assignment_expr( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_bitwise_or_assig( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_bitwise_xor_assig( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_bitwise_and_assig( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_left_shift_assig( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Method stub - Tree Parser::binary_right_shift_assig( - const_TokenPtr tok ATTRIBUTE_UNUSED, Tree left ATTRIBUTE_UNUSED) { - return NULL_TREE; - } - - // Parse variable assignment statement. This is not the same as variable declaration. - Tree Parser::parse_assignment_statement() { - Tree variable = parse_lhs_assignment_expression(); - - if (variable.is_error()) - return Tree::error(); - - // TODO: fix - const_TokenPtr assig_tok = expect_token(/*ASSIG*/ COLON); - if (assig_tok == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip assignment token and parse expression - const_TokenPtr first_of_expr = lexer.peek_token(); - - Tree expr = parse_expression(); - if (expr.is_error()) - return Tree::error(); - - // skip semicolon token - skip_token(SEMICOLON); - - // enforce rule that rhs of assignment has to have same type as declared lhs type - if (variable.get_type() != expr.get_type()) { - // diagnostic - error_at(first_of_expr->get_locus(), - "cannot assign value of type %s to a variable of type %s", print_type(expr.get_type()), - print_type(variable.get_type())); - - return Tree::error(); - } - - Tree assig_expr - = build_tree(MODIFY_EXPR, assig_tok->get_locus(), void_type_node, variable, expr); - return assig_expr; - } - - // Print human-readable name for type. - const char* Parser::print_type(Tree type) { - gcc_assert(TYPE_P(type.get_tree())); - - if (type == void_type_node) - return "void"; - else if (type == integer_type_node) - return "int"; - else if (type == float_type_node) - return "float"; - else if (is_string_type(type)) - return "string"; - else if (type == boolean_type_node) - return "boolean"; - else - return "<>"; - } - - // Returns address to function declaration of printf. - Tree Parser::get_printf_addr() { - // only run if printf_fn is null to avoid making repeated function declarations - if (printf_fn.is_null()) { - // build const char* type (printf fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type as vararg function - tree fndecl_type - = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree printf_fn_decl = build_fn_decl("printf", fndecl_type); - // mark as external - DECL_EXTERNAL(printf_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), printf_fn_decl); - } - - return printf_fn; - } - - // Returns address to function declaration of puts. - Tree Parser::get_puts_addr() { - if (puts_fn.is_null()) { - // build const char* type (puts fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type - tree fndecl_type = build_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree puts_fn_decl = build_fn_decl("puts", fndecl_type); - // mark as external - DECL_EXTERNAL(puts_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - puts_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), puts_fn_decl); - } - - return puts_fn; - } - - // Returns address to function declaration of scanf. - Tree Parser::get_scanf_addr() { - // only run if scanf_fn is null to avoid making repeated function declarations - if (scanf_fn.is_null()) { - // build const char* type (scanf fixed parameter) - tree fndecl_type_param[] - = { build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) }; - - // build function type as vararg function - tree fndecl_type - = build_varargs_function_type_array(integer_type_node, 1, fndecl_type_param); - - // build declaration - tree scanf_fn_decl = build_fn_decl("scanf", fndecl_type); - // mark as external - DECL_EXTERNAL(scanf_fn_decl) = 1; - - // build an ADDR_EXPR, which returns a pointer to type of function type (function address) - scanf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), scanf_fn_decl); - } - - return scanf_fn; - } - - // Parses a "write statement". - /*Tree Parser::parse_write_statement() { - // write_statement -> "write" expression ";" - - if (!skip_token(WRITE)) { - skip_after_semicolon(); - return Tree::error(); - } - - const_TokenPtr first_of_expr = lexer.peek_token(); - Tree expr = parse_expression(); - - skip_token(SEMICOLON); - - if (expr.is_error()) - return Tree::error(); - - // enable printing of value of expression - if (expr.get_type() == integer_type_node) { - // printf("%d\n", expr) - // build format string for integer (also add null terminator) and integer expression - const char* format_integer = "%d\n"; - tree args[] - = { build_string_literal(strlen(format_integer) + 1, format_integer), expr.get_tree() }; - - // used as trees do not allow calling a FUNCTIONAL_DECL directly - Tree printf_fn = get_printf_addr(); - - // build call to print function (printf_fn), in which two arguments in args are passed - // first argument is format string - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); - - return stmt; - } else if (expr.get_type() == float_type_node) { - // printf("%f\n" (double)expr) - // have to convert float to double - const char* format_float = "%f\n"; - tree args[] = { build_string_literal(strlen(format_float) + 1, format_float), - convert(double_type_node, expr.get_tree()) }; - - Tree printf_fn = get_printf_addr(); - - // build call, etc. - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, printf_fn.get_tree(), 2, args); - - return stmt; - } else if (is_string_type(expr.get_type())) { - // Alternatively we could use printf('%s\n', expr) instead of puts(expr) - tree args[] = { expr.get_tree() }; - - Tree puts_fn = get_puts_addr(); - - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, puts_fn.get_tree(), 1, args); - - return stmt; - } else { - // no more valid types - error_at(first_of_expr->get_locus(), "value of type %s is not a valid write operand", - print_type(expr.get_type())); - return Tree::error(); - } - - gcc_unreachable(); - }*/ - - // Enters new scope (like block scope or whatever). - void Parser::enter_scope() { - // push new symbol mapping - scope.push_scope(); - - TreeStmtList stmt_list; - // Used as stack for statements. - stack_stmt_list.push_back(stmt_list); - - // Used as stack of var decls. - stack_var_decl_chain.push_back(TreeChain()); - // Used as stack for blocks. - stack_block_chain.push_back(BlockChain()); - } - - // Leaves current scope (as defined by blocks - like block scope). - Parser::TreeSymbolMapping Parser::leave_scope() { - // Get current list of statements and pop them from stack of statement lists - TreeStmtList current_stmt_list = get_current_stmt_list(); - stack_stmt_list.pop_back(); - - // Get current list of var decls and pop them from stack of var decl lists - TreeChain var_decl_chain = stack_var_decl_chain.back(); - stack_var_decl_chain.pop_back(); - - // Get current list of blocks and pop them from stack of block lists - BlockChain subblocks = stack_block_chain.back(); - stack_block_chain.pop_back(); - - // Create a new block from var decls and subblocks - tree new_block = build_block(var_decl_chain.first.get_tree(), subblocks.first.get_tree(), - /* supercontext */ NULL_TREE, /* chain */ NULL_TREE); - - // Add the new block to the current chain of blocks (if any) - if (!stack_block_chain.empty()) { - stack_block_chain.back().append(new_block); - } - - // Set the subblocks to have the new block as their parent - for (tree it = subblocks.first.get_tree(); it != NULL_TREE; it = BLOCK_CHAIN(it)) - BLOCK_SUPERCONTEXT(it) = new_block; - // Do it this way because of double-linkage - - // Create BIND_EXPR from decl chain, stmt list, and new block - tree bind_expr = build3(BIND_EXPR, void_type_node, var_decl_chain.first.get_tree(), - current_stmt_list.get_tree(), new_block); - - // create, basically, a tuple of bind_expr and new_block - TreeSymbolMapping tree_scope; - tree_scope.bind_expr = bind_expr; - tree_scope.block = new_block; - - // pop symbol mapping - scope.pop_scope(); - - return tree_scope; - } - -#if 0 - // Parses the "read" statement. - Tree Parser::parse_read_statement() { - if (!skip_token(READ)) { - skip_after_semicolon(); - return Tree::error(); - } - - const_TokenPtr first_of_expr = lexer.peek_token(); - Tree expr = parse_expression_naming_variable(); - - skip_token(SEMICOLON); - - if (expr.is_error()) - return Tree::error(); - - // force variable name instead of manually looking up identifier token - /* if (expr.get_tree_code() != VAR_DECL) { - error_at(first_of_expr->get_locus(), "invalid expression in read statement"); - return Tree::error(); - }*/ - // not used anymore due to parse_expression_naming_variable - - // Variable must be addressable (variable needs address computed) - TREE_ADDRESSABLE(expr.get_tree()) = 1; - - // determine appropriate format string - const char* format = NULL; - if (expr.get_type() == integer_type_node) { - format = "%d"; - } else if (expr.get_type() == float_type_node) { - format = "%f"; - } else { - error_at(first_of_expr->get_locus(), "variable of type %s is not a valid read operand", - print_type(expr.get_type())); - return Tree::error(); - } - - // build args for scanf - tree args[] = { build_string_literal(strlen(format) + 1, format), - build_tree(ADDR_EXPR, first_of_expr->get_locus(), - build_pointer_type(expr.get_type().get_tree()), expr) - .get_tree() }; - - // get scanf address - Tree scanf_fn = get_scanf_addr(); - - // create tree to call scanf - tree stmt = build_call_array_loc( - first_of_expr->get_locus(), integer_type_node, scanf_fn.get_tree(), 2, args); - - return stmt; - } -#endif - - // Parses a while statement. - Tree Parser::parse_while_statement() { - if (!skip_token(WHILE)) { - skip_after_end(); - return Tree::error(); - } - - // parse while's conditional expression - Tree expr = parse_boolean_expression(); - if (!skip_token(DO)) { - skip_after_end(); - return Tree::error(); - } - - // enter loop body scope - enter_scope(); - parse_statement_seq(&Parser::done_end); - TreeSymbolMapping while_body_tree_scope = leave_scope(); - - Tree while_body_stmt = while_body_tree_scope.bind_expr; - - skip_token(RIGHT_CURLY); - - // build while statement tree - return build_while_statement(expr, while_body_stmt); - } - - // Builds a while statement tree. - Tree Parser::build_while_statement(Tree bool_expr, Tree while_body) { - if (bool_expr.is_error()) - return Tree::error(); - - TreeStmtList stmt_list; - - // build label decl for while condition check - Tree while_check_label_decl = build_label_decl("while_check", bool_expr.get_locus()); - - // build label expr for while condition check and add to statement list - Tree while_check_label_expr - = build_tree(LABEL_EXPR, bool_expr.get_locus(), void_type_node, while_check_label_decl); - stmt_list.append(while_check_label_expr); - - // build label decl for loop body and end of loop - Tree while_body_label_decl = build_label_decl("while_body", while_body.get_locus()); - Tree end_of_while_label_decl = build_label_decl("end_of_while", UNKNOWN_LOCATION); - - // add cond_expr tree that evaluates condition expression and branches to correct label - Tree cond_expr = build_tree(COND_EXPR, bool_expr.get_locus(), void_type_node, bool_expr, - build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, while_body_label_decl), - build_tree(GOTO_EXPR, bool_expr.get_locus(), void_type_node, end_of_while_label_decl)); - stmt_list.append(cond_expr); - - // define location of label for body of loop and append to while body - Tree while_body_label_expr - = build_tree(LABEL_EXPR, while_body.get_locus(), void_type_node, while_body_label_decl); - stmt_list.append(while_body_label_expr); - - stmt_list.append(while_body); - - // branch back to condition check (as it is a loop) - Tree goto_check - = build_tree(GOTO_EXPR, UNKNOWN_LOCATION, void_type_node, while_check_label_decl); - stmt_list.append(goto_check); - - // define location of label for end of the while loop - Tree end_of_while_label_expr - = build_tree(LABEL_EXPR, UNKNOWN_LOCATION, void_type_node, end_of_while_label_decl); - stmt_list.append(end_of_while_label_expr); - - return stmt_list.get_tree(); - } - - // Parse a for statement. - Tree Parser::parse_for_statement() { - // for -> for := to do end - if (!skip_token(FOR)) { - skip_after_end(); - return Tree::error(); - } - - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_end(); - return Tree::error(); - } - - // TODO - if (!skip_token(/*ASSIG*/ COLON)) { - skip_after_end(); - return Tree::error(); - } - - // parse lower bound expression - Tree lower_bound = parse_integer_expression(); - - // TODO - if (!skip_token(/*TO*/ DOT)) { - skip_after_end(); - return Tree::error(); - } - - // parse upper bound expression - Tree upper_bound = parse_integer_expression(); - - if (!skip_token(DO)) { - skip_after_end(); - return Tree::error(); - } - - // enter loop body scope and parse internal statements - enter_scope(); - parse_statement_seq(&Parser::done_end); - - TreeSymbolMapping for_body_tree_scope = leave_scope(); - Tree for_body_stmt = for_body_tree_scope.bind_expr; - - skip_token(RIGHT_CURLY); - - // Induction variable ("loop counter" variable) handling - SymbolPtr ind_var = query_integer_variable(identifier->get_str(), identifier->get_locus()); - - // build for statement - return build_for_statement(ind_var, lower_bound, upper_bound, for_body_stmt); - } - - // Builds a for statement tree (piggybacks on while statement tree building). - Tree Parser::build_for_statement( - SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list) { - if (ind_var == NULL) - return Tree::error(); - Tree ind_var_decl = ind_var->get_tree_decl(); - - // lower - if (lower_bound.is_error()) - return Tree::error(); - - // upper - if (upper_bound.is_error()) - return Tree::error(); - - // ind_var = lower - TreeStmtList stmt_list; - - // initialise induction variable with value of lower bound and append to stmt_list - Tree init_ind_var - = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, lower_bound); - stmt_list.append(init_ind_var); - - // define condition ind_var <= upper for use in while loop - Tree while_condition = build_tree( - LE_EXPR, upper_bound.get_locus(), boolean_type_node, ind_var_decl, upper_bound); - - // simulate incrementing ind_var - Tree incr_ind_var = build_tree(MODIFY_EXPR, UNKNOWN_LOCATION, void_type_node, ind_var_decl, - build_tree(PLUS_EXPR, UNKNOWN_LOCATION, integer_type_node, ind_var_decl, - build_int_cst_type(integer_type_node, 1))); - - // Wrap as stmt list - TreeStmtList for_stmt_list = for_body_stmt_list; - for_stmt_list.append(incr_ind_var); - - // construct associated while statement and append to stmt_list - Tree while_stmt = build_while_statement(while_condition, for_stmt_list.get_tree()); - stmt_list.append(while_stmt); - - // return entire stmt_list - return stmt_list.get_tree(); - } - - // Gets type (as in typedef) of name in current scope. - SymbolPtr Parser::query_type(const std::string& name, location_t loc) { - SymbolPtr sym = scope.lookup(name); - if (sym == NULL) { - error_at(loc, "type '%s' not declared in the current scope", name.c_str()); - } else if (sym->get_kind() != TYPENAME) { - error_at(loc, "name '%s' is not a type", name.c_str()); - sym = SymbolPtr(); - } - - return sym; - } - - // Get variable of name in current scope. - SymbolPtr Parser::query_variable(const std::string& name, location_t loc) { - SymbolPtr sym = scope.lookup(name); - if (sym == NULL) { - error_at(loc, "variable '%s' not declared in the current scope", name.c_str()); - } else if (sym->get_kind() != VARIABLE) { - error_at(loc, "name '%s' is not a variable", name.c_str()); - sym = SymbolPtr(); - } - return sym; - } - - // Gets variable of name in current scope and ensures it has integer type. - SymbolPtr Parser::query_integer_variable(const std::string& name, location_t loc) { - SymbolPtr sym = query_variable(name, loc); - if (sym != NULL) { - Tree var_decl = sym->get_tree_decl(); - gcc_assert(!var_decl.is_null()); - - if (var_decl.get_type() != integer_type_node) { - error_at(loc, "variable '%s' does not have integer type", name.c_str()); - sym = SymbolPtr(); - } - } - - return sym; - } - - // Returns true if the next token is END, ELSE, or EOF; - bool Parser::done_end_or_else() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == RIGHT_CURLY || t->get_id() == ELSE || t->get_id() == END_OF_FILE); - } - - // Returns true if the next token is END or EOF. - bool Parser::done_end() { - const_TokenPtr t = lexer.peek_token(); - return (t->get_id() == RIGHT_CURLY || t->get_id() == END_OF_FILE); - } - - // Parses expression and ensures it is a variable declaration or array reference. - Tree Parser::parse_expression_naming_variable() { - Tree expr = parse_expression(); - if (expr.is_error()) - return expr; - - if (expr.get_tree_code() != VAR_DECL && expr.get_tree_code() != ARRAY_REF - && expr.get_tree_code() != COMPONENT_REF) { - error_at(expr.get_locus(), "does not designate a variable, array element or field"); - return Tree::error(); - } - - return expr; - } - - // Parses expression and ensures it is an assignment expression? - Tree Parser::parse_lhs_assignment_expression() { - return parse_expression_naming_variable(); - } - - // Parses type (as in typedef) declaration statement. - /*Tree Parser::parse_type_declaration() { - // type_declaration -> "type" identifier ":" type ";" - if (!skip_token(TYPE)) { - skip_after_semicolon(); - return Tree::error(); - } - - // get identifier - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // skip colon - if (!skip_token(COLON)) { - skip_after_semicolon(); - return Tree::error(); - } - - // get type of expression - Tree type_tree = parse_type(); - - if (type_tree.is_error()) { - skip_after_semicolon(); - return Tree::error(); - } - - skip_token(SEMICOLON); - - // ensure not already delcared in scope - if (scope.get_current_mapping().get(identifier->get_str())) { - error_at(identifier->get_locus(), "name '%s' already declared in this scope", - identifier->get_str().c_str()); - } - - // create new symbol for typedef and put in mapping for current scope - SymbolPtr sym(new Symbol(TYPENAME, identifier->get_str())); - scope.get_current_mapping().insert(sym); - - // build typedef tree - Tree decl = build_decl(identifier->get_locus(), TYPE_DECL, - get_identifier(sym->get_name().c_str()), type_tree.get_tree()); - DECL_CONTEXT(decl.get_tree()) = main_fndecl; - - // add type declaration to variable declaration stack - gcc_assert(!stack_var_decl_chain.empty()); - stack_var_decl_chain.back().append(decl); - - // set symbol's declaration tree to declaration tree - sym->set_tree_decl(decl); - - // build declaration statement for tree - Tree stmt = build_tree(DECL_EXPR, identifier->get_locus(), void_type_node, decl); - - return stmt; - }*/ - - // Parses a record type field declaration. - /*Tree Parser::parse_field_declaration(std::vector& field_names) { - // identifier ':' type ';' - const_TokenPtr identifier = expect_token(IDENTIFIER); - if (identifier == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - skip_token(COLON); - - Tree type = parse_type(); - - skip_token(SEMICOLON); - - if (type.is_error()) - return Tree::error(); - - // pass vector of fields to avoid repeated field names - error if they exist - if (std::find(field_names.begin(), field_names.end(), identifier->get_str()) - != field_names.end()) { - error_at(identifier->get_locus(), "repeated field name"); - return Tree::error(); - } - - field_names.push_back(identifier->get_str()); - - // create GENERIC FIELD_DECL tree with name of tree and type - Tree field_decl = build_decl(identifier->get_locus(), FIELD_DECL, - get_identifier(identifier->get_str().c_str()), type.get_tree()); - // required for read statement to work on fields - TREE_ADDRESSABLE(field_decl.get_tree()) = 1; - - return field_decl; - }*/ - - // TODO: remove: here to solve link errors - Tree Parser::parse_record() { - return Tree::error(); - } - // Parses a record. - /*Tree Parser::parse_record() { - // "record" field-decl* "end" - const_TokenPtr record_tok = expect_token(RECORD); - if (record_tok == NULL) { - skip_after_semicolon(); - return Tree::error(); - } - - // create empty record type tree - Tree record_type = make_node(RECORD_TYPE); - Tree field_list, field_last; - std::vector field_names; - - // parse field declarations inside record until the end token is found - const_TokenPtr next = lexer.peek_token(); - while (next->get_id() != END) { - Tree field_decl = parse_field_declaration(field_names); - - if (!field_decl.is_error()) { - // set field declaration's decl_context to this record type - DECL_CONTEXT(field_decl.get_tree()) = record_type.get_tree(); - if (field_list.is_null()) - field_list = field_decl; - if (!field_last.is_null()) - // chain fields in record type by using tree_chain - TREE_CHAIN(field_last.get_tree()) = field_decl.get_tree(); - field_last = field_decl; - } - - next = lexer.peek_token(); - } - - skip_token(END); - - // first field sets TYPE_FIELDS attribute of the RECORD_TYPE tree - TYPE_FIELDS(record_type.get_tree()) = field_list.get_tree(); - // request GCC to layout type in memory - layout_type(record_type.get_tree()); - - return record_type; - }*/ - - // Dumps lexer output to stderr. - void Parser::debug_dump_lex_output() { - Rust::const_TokenPtr tok = lexer.peek_token(); - - while (true) { - bool has_text - = tok->get_id() == Rust::IDENTIFIER || tok->get_id() == Rust::INT_LITERAL - || tok->get_id() == Rust::FLOAT_LITERAL || tok->get_id() == Rust::STRING_LITERAL - || tok->get_id() == Rust::CHAR_LITERAL || tok->get_id() == Rust::BYTE_STRING_LITERAL - || tok->get_id() == Rust::BYTE_CHAR_LITERAL; - - location_t loc = tok->get_locus(); - - fprintf(stderr, "\n", tok->token_id_to_str(), - has_text ? (std::string(", text=") + tok->get_str() + std::string(", typehint=") - + std::string(tok->get_type_hint_str())) - .c_str() - : "", - LOCATION_FILE(loc), LOCATION_LINE(loc), LOCATION_COLUMN(loc)); - - if (tok->get_id() == Rust::END_OF_FILE) - break; - - lexer.skip_token(); - tok = lexer.peek_token(); - } - } - - // Parses crate and dumps AST to stderr, recursively. - void Parser::debug_dump_ast_output() { - AST::Crate crate = parse_crate(); - - // print crate "as string", which then calls each item as string, etc. - fprintf(stderr, crate.as_string().c_str()); - } -} \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-parse.h b/gcc/rust/test3/parse/rust-parse.h deleted file mode 100644 index 94d1eab..0000000 --- a/gcc/rust/test3/parse/rust-parse.h +++ /dev/null @@ -1,613 +0,0 @@ -#ifndef RUST_PARSE_H -#define RUST_PARSE_H - -#include "rust-lex.h" -//#include "rust-tree.h" -#include "rust-scope.h" - -//#include "rust-ast-containers.h" -// TODO: change, maybe? -#include "rust-ast-full.h" - -namespace Rust { - /* HACK: used to resolve the expression-or-statement problem at the end of a block by allowing - * either to be returned (technically). Tagged union would probably take up the same amount of - * space. */ - struct ExprOrStmt { - ::std::unique_ptr expr; - ::std::unique_ptr stmt; - - /* I was going to resist the urge to make this a real class and make it POD, but construction - * in steps is too difficult. So it'll just also have a constructor. */ - - // expression constructor - ExprOrStmt(::std::unique_ptr expr) : expr(::std::move(expr)) {} - - // statement constructor - ExprOrStmt(::std::unique_ptr stmt) : stmt(::std::move(stmt)) {} - - // Returns whether this object is in an error state. - inline bool is_error() const { - return (expr == NULL && stmt == NULL) || (expr != NULL && stmt != NULL); - } - - // Returns an error state object. - static ExprOrStmt create_error() { - return ExprOrStmt(NULL, NULL); - } - - ~ExprOrStmt() = default; - - // no copy constructors/assignment copy as simple object like this shouldn't require it - - // move constructors - ExprOrStmt(ExprOrStmt&& other) = default; - ExprOrStmt& operator=(ExprOrStmt&& other) = default; - - private: - // private constructor only used for creating error state expr or stmt objects - ExprOrStmt(AST::ExprWithoutBlock* expr, AST::Stmt* stmt) : expr(expr), stmt(stmt) {} - - // make this work: have a disambiguation specifically for known statements (i.e. ';' and - // 'let'). then, have a special "parse expr or stmt" function that returns this type. inside - // it, it parses an expression, and then determines whether to return expr or stmt via whether - // the next token is a semicolon. should be able to disambiguate inside that function between - // stmts with blocks and without blocks. - }; - - /* Restrictions on parsing used to signal that certain ambiguous grammar features should be parsed - * in a certain way.*/ - struct ParseRestrictions { - bool can_be_struct_expr = true; - /* Whether the expression was entered from a unary expression - prevents stuff like struct - * exprs being parsed from a dereference. */ - bool entered_from_unary = false; - }; - - // Parser implementation for gccrs. - class Parser { - private: - void skip_after_semicolon(); - void skip_after_end(); - void skip_after_end_block(); - void skip_after_next_block(); - void skip_after_end_attribute(); - - bool skip_token(TokenId t); - const_TokenPtr expect_token(TokenId t); - void unexpected_token(const_TokenPtr t); - bool skip_generics_right_angle(); - - // expression parsing - int left_binding_power(const_TokenPtr tok); - Tree null_denotation(const_TokenPtr tok); - Tree left_denotation(const_TokenPtr tok, Tree left); - - Tree parse_expression(int right_binding_power); - - Tree coerce_binary_arithmetic(const_TokenPtr tok, Tree* left, Tree* right); - bool check_logical_operands(const_TokenPtr tok, Tree left, Tree right); - - Tree get_printf_addr(); - Tree get_puts_addr(); - - Tree get_scanf_addr(); - - Tree build_label_decl(const char* name, location_t loc); - Tree build_if_statement(Tree bool_expr, Tree then_part, Tree else_part); - Tree build_while_statement(Tree bool_expr, Tree while_body); - Tree build_for_statement( - SymbolPtr ind_var, Tree lower_bound, Tree upper_bound, Tree for_body_stmt_list); - - const char* print_type(Tree type); - - TreeStmtList& get_current_stmt_list(); - - void enter_scope(); - - struct TreeSymbolMapping { - Tree bind_expr; - Tree block; - }; - - TreeSymbolMapping leave_scope(); - - SymbolPtr query_type(const std::string& name, location_t loc); - SymbolPtr query_variable(const std::string& name, location_t loc); - SymbolPtr query_integer_variable(const std::string& name, location_t loc); - - void parse_statement_seq(bool (Parser::*done)()); - - // AST-related stuff - maybe move or something? - ::std::vector parse_inner_attributes(); - AST::Attribute parse_inner_attribute(); - ::std::vector parse_outer_attributes(); - AST::Attribute parse_outer_attribute(); - AST::Attribute parse_attribute_body(); - ::std::unique_ptr parse_attr_input(); - - // Path-related - AST::SimplePath parse_simple_path(); - AST::SimplePathSegment parse_simple_path_segment(); - AST::TypePath parse_type_path(); - ::std::unique_ptr parse_type_path_segment(); - AST::PathIdentSegment parse_path_ident_segment(); - AST::GenericArgs parse_path_generic_args(); - AST::GenericArgsBinding parse_generic_args_binding(); - AST::TypePathFunction parse_type_path_function(); - AST::PathInExpression parse_path_in_expression(); - AST::PathExprSegment parse_path_expr_segment(); - AST::QualifiedPathInExpression parse_qualified_path_in_expression(bool pratt_parse = false); - AST::QualifiedPathType parse_qualified_path_type(bool pratt_parse = false); - AST::QualifiedPathInType parse_qualified_path_in_type(); - - // Token tree or macro related - AST::DelimTokenTree parse_delim_token_tree(); - ::std::unique_ptr parse_token_tree(); - ::std::unique_ptr parse_macro_rules_def( - ::std::vector outer_attrs); - ::std::unique_ptr parse_macro_invocation_semi( - ::std::vector outer_attrs); - ::std::unique_ptr parse_macro_invocation( - ::std::vector outer_attrs); - AST::MacroRule parse_macro_rule(); - AST::MacroMatcher parse_macro_matcher(); - ::std::unique_ptr parse_macro_match(); - ::std::unique_ptr parse_macro_match_fragment(); - ::std::unique_ptr parse_macro_match_repetition(); - - // Top-level item-related - ::std::vector< ::std::unique_ptr > parse_items(); - ::std::unique_ptr parse_item(bool called_from_statement); - ::std::unique_ptr parse_vis_item(::std::vector outer_attrs); - ::std::unique_ptr parse_macro_item(::std::vector outer_attrs); - AST::Visibility parse_visibility(); - - // VisItem subclass-related - ::std::unique_ptr parse_module( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_extern_crate( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_use_decl( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_use_tree(); - ::std::unique_ptr parse_function( - AST::Visibility vis, ::std::vector outer_attrs); - AST::FunctionQualifiers parse_function_qualifiers(); - ::std::vector< ::std::unique_ptr > parse_generic_params_in_angles(); - ::std::vector< ::std::unique_ptr > parse_generic_params(); - ::std::vector< ::std::unique_ptr > parse_lifetime_params(); - ::std::vector parse_lifetime_params_objs(); - AST::LifetimeParam parse_lifetime_param(); - ::std::vector< ::std::unique_ptr > parse_type_params(); - ::std::unique_ptr parse_type_param(); - ::std::vector parse_function_params(); - AST::FunctionParam parse_function_param(); - ::std::unique_ptr parse_function_return_type(); - AST::WhereClause parse_where_clause(); - ::std::unique_ptr parse_where_clause_item(); - ::std::unique_ptr parse_lifetime_where_clause_item(); - ::std::unique_ptr parse_type_bound_where_clause_item(); - ::std::vector parse_for_lifetimes(); - ::std::vector< ::std::unique_ptr > parse_type_param_bounds(); - ::std::unique_ptr parse_type_param_bound(); - ::std::unique_ptr parse_trait_bound(); - ::std::vector parse_lifetime_bounds(); - AST::Lifetime parse_lifetime(); - ::std::unique_ptr parse_type_alias( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_struct( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::vector parse_struct_fields(); - AST::StructField parse_struct_field(); - ::std::vector parse_tuple_fields(); - AST::TupleField parse_tuple_field(); - ::std::unique_ptr parse_enum( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::vector< ::std::unique_ptr > parse_enum_items(); - ::std::unique_ptr parse_enum_item(); - ::std::unique_ptr parse_union( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_const_item( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_static_item( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_trait( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_trait_item(); - ::std::unique_ptr parse_trait_type( - ::std::vector outer_attrs); - ::std::unique_ptr parse_trait_const( - ::std::vector outer_attrs); - AST::SelfParam parse_self_param(); - ::std::unique_ptr parse_impl( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_inherent_impl_item(); - ::std::unique_ptr parse_inherent_impl_function_or_method( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_trait_impl_item(); - ::std::unique_ptr parse_trait_impl_function_or_method( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_extern_block( - AST::Visibility vis, ::std::vector outer_attrs); - ::std::unique_ptr parse_external_item(); - AST::NamedFunctionParam parse_named_function_param(); - AST::Method parse_method(); - - // Expression-related (Pratt parsed) - ::std::unique_ptr parse_expr( - ::std::vector outer_attrs = ::std::vector(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_expr(int right_binding_power, - ::std::vector outer_attrs = ::std::vector(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr null_denotation_NEW(const_TokenPtr t, - ::std::vector outer_attrs = ::std::vector(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr left_denotation(const_TokenPtr t, - ::std::unique_ptr left, - ::std::vector outer_attrs = ::std::vector(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_plus_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_minus_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_mult_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_div_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_mod_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_bitwise_and_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_bitwise_or_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_bitwise_xor_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_left_shift_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_right_shift_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_equal_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_not_equal_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_greater_than_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_less_than_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_greater_equal_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_binary_less_equal_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_lazy_or_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_lazy_and_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_type_cast_expr(const_TokenPtr tok, - ::std::unique_ptr expr_to_cast, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_plus_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_minus_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_mult_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_div_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_mod_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_and_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_or_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_xor_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_left_shift_assig_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_right_shift_assig_expr( - const_TokenPtr tok, ::std::unique_ptr left, - ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_await_expr(const_TokenPtr tok, - ::std::unique_ptr expr_to_await, ::std::vector outer_attrs); - ::std::unique_ptr parse_method_call_expr(const_TokenPtr tok, - ::std::unique_ptr receiver_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_function_call_expr(const_TokenPtr tok, - ::std::unique_ptr function_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_led_range_exclusive_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_nud_range_exclusive_expr( - const_TokenPtr tok, ::std::vector outer_attrs); - ::std::unique_ptr parse_range_inclusive_expr(const_TokenPtr tok, - ::std::unique_ptr left, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_range_to_inclusive_expr( - const_TokenPtr tok, ::std::vector outer_attrs); - ::std::unique_ptr parse_tuple_index_expr(const_TokenPtr tok, - ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_field_access_expr(const_TokenPtr tok, - ::std::unique_ptr struct_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_index_expr(const_TokenPtr tok, - ::std::unique_ptr array_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr parse_macro_invocation_partial( - AST::PathInExpression path, ::std::vector outer_attrs); - ::std::unique_ptr parse_struct_expr_struct_partial( - AST::PathInExpression path, ::std::vector outer_attrs); - ::std::unique_ptr parse_struct_expr_tuple_partial( - AST::PathInExpression path, ::std::vector outer_attrs); - AST::PathInExpression parse_path_in_expression_pratt(const_TokenPtr tok); - ::std::unique_ptr parse_closure_expr_pratt(const_TokenPtr tok, - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_tuple_index_expr_float(const_TokenPtr tok, - ::std::unique_ptr tuple_expr, ::std::vector outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - - // Expression-related (non-Pratt parsed) - ::std::unique_ptr parse_expr_without_block( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_block_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_if_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_if_let_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_loop_expr( - ::std::vector outer_attrs = ::std::vector(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr parse_while_loop_expr( - ::std::vector outer_attrs = ::std::vector(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr parse_while_let_loop_expr( - ::std::vector outer_attrs = ::std::vector(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr parse_for_loop_expr( - ::std::vector outer_attrs = ::std::vector(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr parse_match_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - AST::MatchArm parse_match_arm(); - ::std::vector< ::std::unique_ptr > parse_match_arm_patterns( - TokenId end_token_id); - ::std::unique_ptr parse_labelled_loop_expr( - ::std::vector outer_attrs = ::std::vector()); - AST::LoopLabel parse_loop_label(); - ::std::unique_ptr parse_async_block_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_unsafe_block_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_grouped_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_closure_expr( - ::std::vector outer_attrs = ::std::vector()); - AST::ClosureParam parse_closure_param(); - ::std::unique_ptr parse_literal_expr( - ::std::vector outer_attrs = ::std::vector()); - ::std::unique_ptr parse_return_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_break_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_continue_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_array_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_grouped_or_tuple_expr( - ::std::vector outer_attrs = ::std::vector(), - bool pratt_parse = false); - ::std::unique_ptr parse_struct_expr_field(); - - // Type-related - ::std::unique_ptr parse_type(); - ::std::unique_ptr parse_type_no_bounds(); - ::std::unique_ptr parse_slice_or_array_type(); - ::std::unique_ptr parse_raw_pointer_type(); - ::std::unique_ptr parse_reference_type(); - ::std::unique_ptr parse_bare_function_type( - ::std::vector for_lifetimes); - ::std::unique_ptr parse_paren_prefixed_type(); - ::std::unique_ptr parse_paren_prefixed_type_no_bounds(); - ::std::unique_ptr parse_for_prefixed_type(); - AST::MaybeNamedParam parse_maybe_named_param(); - - // Statement-related - ::std::unique_ptr parse_stmt(); - ::std::unique_ptr parse_let_stmt(::std::vector outer_attrs); - ::std::unique_ptr parse_expr_stmt(::std::vector outer_attrs); - ::std::unique_ptr parse_expr_stmt_with_block( - ::std::vector outer_attrs); - ::std::unique_ptr parse_expr_stmt_without_block( - ::std::vector outer_attrs); - ExprOrStmt parse_stmt_or_expr_without_block(); - ExprOrStmt parse_macro_invocation_maybe_semi(::std::vector outer_attrs); - ExprOrStmt parse_path_based_stmt_or_expr(::std::vector outer_attrs); - - // Pattern-related - ::std::unique_ptr parse_pattern(); - ::std::unique_ptr parse_literal_or_range_pattern(); - ::std::unique_ptr parse_range_pattern_bound(); - ::std::unique_ptr parse_reference_pattern(); - ::std::unique_ptr parse_grouped_or_tuple_pattern(); - ::std::unique_ptr parse_slice_pattern(); - ::std::unique_ptr parse_identifier_pattern(); - ::std::unique_ptr parse_ident_leading_pattern(); - ::std::unique_ptr parse_tuple_struct_items(); - AST::StructPatternElements parse_struct_pattern_elems(); - ::std::unique_ptr parse_struct_pattern_field(); - - // void parse_crate(); - // AST::Module parse_module(); - // void parse_module_item(AST::Module module_for_items, AST::AttributeList - // item_outer_attributes); AST::Visibility parse_visibility(); - - bool done_end(); - bool done_end_or_else(); - bool done_end_of_file(); - - typedef Tree (Parser::*BinaryHandler)(const_TokenPtr, Tree); - BinaryHandler get_binary_handler(TokenId id); - - public: - // Construct parser with specified lexer reference. - Parser(Lexer& parLexer) : lexer(parLexer), printf_fn(), puts_fn(), scanf_fn() {} - - // (old) Main entry point for parser. - void parse_program(); - - // Main entry point for parser. - AST::Crate parse_crate(); - - Tree parse_statement(); - - Tree parse_variable_declaration(); - Tree parse_type_declaration(); - - // Tree parse_type(); - Tree parse_record(); - Tree parse_field_declaration(std::vector& field_names); - - Tree parse_assignment_statement(); - Tree parse_if_statement(); - Tree parse_while_statement(); - Tree parse_for_statement(); - Tree parse_read_statement(); - Tree parse_write_statement(); - - Tree parse_expression(); - Tree parse_expression_naming_variable(); - Tree parse_lhs_assignment_expression(); - Tree parse_boolean_expression(); - Tree parse_integer_expression(); - - // Dumps all lexer output. - void debug_dump_lex_output(); - void debug_dump_ast_output(); - - private: - // The lexer associated with the parser. - Lexer& lexer; - // The current scope. - Scope scope; - - // The simulated "main" function inside which the entire program lies. - tree main_fndecl; - - // Address to function declaration of printf. - Tree printf_fn; - // Address to function declaration of puts. - Tree puts_fn; - // Address to function declaration of scanf. - Tree scanf_fn; - - // The statement stack. - std::vector stack_stmt_list; - // The VAR_DECL stack. - std::vector stack_var_decl_chain; - - // The block stack. - std::vector stack_block_chain; - -// x-macro list for binary operators - only defined here to be inside Parser class -#define BINARY_HANDLER_LIST \ - BINARY_HANDLER(plus, PLUS) \ - BINARY_HANDLER(minus, MINUS) \ - BINARY_HANDLER(mult, ASTERISK) \ - BINARY_HANDLER(div, DIV) \ - BINARY_HANDLER(mod, PERCENT) \ - BINARY_HANDLER(bitwise_and, AMP) \ - BINARY_HANDLER(bitwise_or, PIPE) \ - BINARY_HANDLER(bitwise_xor, CARET) \ - BINARY_HANDLER(left_shift, LEFT_SHIFT) \ - BINARY_HANDLER(right_shift, RIGHT_SHIFT) \ - \ - BINARY_HANDLER(equal, EQUAL_EQUAL) \ - BINARY_HANDLER(not_equal, NOT_EQUAL) \ - BINARY_HANDLER(smaller_than, LEFT_ANGLE) \ - BINARY_HANDLER(smaller_equal, LESS_OR_EQUAL) \ - BINARY_HANDLER(greater_than, RIGHT_ANGLE) \ - BINARY_HANDLER(greater_equal, GREATER_OR_EQUAL) \ - \ - BINARY_HANDLER(logical_and, LOGICAL_AND) \ - BINARY_HANDLER(logical_or, OR) \ - \ - BINARY_HANDLER(as_cast, AS) \ - /* should this really be an operator? */ \ - \ - BINARY_HANDLER(array_index, LEFT_SQUARE) \ - \ - BINARY_HANDLER(field_ref, DOT) \ - /*BINARY_HANDLER(method_call, DOT)*/ \ - BINARY_HANDLER(error_propagation, QUESTION_MARK) \ - /* not a binary operator, technically, but still left denotation */ \ - BINARY_HANDLER(assignment_expr, EQUAL) \ - /* should this really be an operator? or a binary one? */ \ - /* if it should, also add all operation-assign below:*/ \ - BINARY_HANDLER(plus_assig, PLUS_EQ) \ - BINARY_HANDLER(minus_assig, MINUS_EQ) \ - BINARY_HANDLER(mult_assig, ASTERISK_EQ) \ - BINARY_HANDLER(div_assig, DIV_EQ) \ - BINARY_HANDLER(mod_assig, PERCENT_EQ) \ - BINARY_HANDLER(bitwise_and_assig, AMP_EQ) \ - BINARY_HANDLER(bitwise_or_assig, PIPE_EQ) \ - BINARY_HANDLER(bitwise_xor_assig, CARET_EQ) \ - BINARY_HANDLER(left_shift_assig, LEFT_SHIFT_EQ) \ - BINARY_HANDLER(right_shift_assig, RIGHT_SHIFT_EQ) \ - \ - BINARY_HANDLER(range_exclusive, DOT_DOT) \ - BINARY_HANDLER(range_inclusive, DOT_DOT_EQ) \ - \ - BINARY_HANDLER(path, SCOPE_RESOLUTION) \ - \ - BINARY_HANDLER(return, RETURN_TOK) \ - BINARY_HANDLER(break, BREAK) \ - BINARY_HANDLER(closure, MOVE) - -// create declarations for binary op handling -#define BINARY_HANDLER(name, _) Tree binary_##name(const_TokenPtr tok, Tree left); - BINARY_HANDLER_LIST -#undef BINARY_HANDLER - }; -} - -#endif // RUST_PARSE_H \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-scope.cc b/gcc/rust/test3/parse/rust-scope.cc deleted file mode 100644 index d38a078..0000000 --- a/gcc/rust/test3/parse/rust-scope.cc +++ /dev/null @@ -1,43 +0,0 @@ -#include "rust-scope.h" - -#include // for std::make_pair - -namespace Rust { - Scope::Scope() {} - - void SymbolMapping::insert(SymbolPtr s) { - gcc_assert(s != NULL); - std::pair p = map.insert(std::make_pair(s->get_name(), s)); - - gcc_assert(p.second); - } - - SymbolPtr SymbolMapping::get(const std::string& str) const { - Map::const_iterator it = map.find(str); - if (it != map.end()) { - return it->second; - } - - return SymbolPtr(); - } - - SymbolPtr Scope::lookup(const std::string& str) { - // Traverse stack from top (end of MapStack) to bottom, so use reverse_iterator. - for (MapStack::reverse_iterator map = map_stack.rbegin(); map != map_stack.rend(); map++) { - if (SymbolPtr sym = map->get(str)) { - return sym; - } - } - - return SymbolPtr(); - } - - void Scope::push_scope() { - map_stack.push_back(SymbolMapping()); - } - - void Scope::pop_scope() { - gcc_assert(!map_stack.empty()); - map_stack.pop_back(); - } -} \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-scope.h b/gcc/rust/test3/parse/rust-scope.h deleted file mode 100644 index 7ac38c9..0000000 --- a/gcc/rust/test3/parse/rust-scope.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef RUST_SCOPE_H -#define RUST_SCOPE_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -// order: config, system, coretypes, tree -// may not all be required - -#include -#include -#include - -#include "rust-tree.h" -#include "rust-symbol.h" - -// maybe split out scope into Symbol, SymbolMapping, and Scope headers - -namespace Rust { - // Map of strings (identifiers) to SymbolPtrs - struct SymbolMapping { - public: - // Inserts a new Symbol into the map using its name as the key. Also checks name is unique. - void insert(SymbolPtr s); - // Returns the mapped Symbol for the given string. May return a null Symbol. - SymbolPtr get(const std::string& str) const; - - private: - typedef std::map Map; - // SymbolMapping's map. - Map map; - }; - - // Scope class that holds mapping in it. - class Scope { - public: - // Gets current mapping (created in last push that hasn't been popped yet). - SymbolMapping& get_current_mapping() { - gcc_assert(!map_stack.empty()); - return map_stack.back(); - } - - // Create new mapping. - void push_scope(); - // Get rid of mapping? - void pop_scope(); - - Scope(); - - // Get the last mapping for a given string (or null if no such mapping exists). - SymbolPtr lookup(const std::string& str); - - private: - typedef std::vector MapStack; - // Scope's MapStack. - MapStack map_stack; - }; // TODO: have multiple scopes (for modules, function, etc) at once? -} - -#endif // RUST_SCOPE_H \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-symbol.h b/gcc/rust/test3/parse/rust-symbol.h deleted file mode 100644 index 439325b..0000000 --- a/gcc/rust/test3/parse/rust-symbol.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef RUST_SYMBOL_H -#define RUST_SYMBOL_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -// order: config, system, coretypes, tree - -#include -//#include // as shared_ptr is not available in std memory in c++03 -// replaced with proper memory in c++11 -#include - -namespace Rust { - // Kinds of symbols. - enum SymbolKind { INVALID, VARIABLE, TYPENAME /*change to STRUCT*/, FUNCTION }; - // TODO: possibly add typedef, struct, union, "enum" - - /* TODO: apparently Rust's type symbol table is separate to its identifier symbol table, so have a - * different symbol table for each? */ - - /* The symbol table(s) will be generated as a pass over the AST (the first, probably) and each - * scope, including module namespacing, will be a separate symbol table (with earlier ones still - * accessible but searched afterward). It will be preserved in later passes over the AST to type - * check and maybe bind identifiers together or something. - * It may have to be preserved, at least partially, for GENERIC lowering. */ - - // A symbol used for identifiers, etc. - TODO: extend to support namespacing (Rust paths?) - struct Symbol { - public: - // Constructs a new symbol of name with no declaration tree set. - Symbol(SymbolKind kind, const std::string& name_) : - kind(kind), name(name_), decl(error_mark_node) { - gcc_assert(name.size() > 0); - } - - // Gets symbol's kind. - SymbolKind get_kind() const { - return kind; - } - - // Gets symbol's name. - std::string get_name() const { - return name; - } - - // Sets symbol's declaration tree. - void set_tree_decl(Tree decl_) { - // Ensure declaration tree is a variable or type declaration. - gcc_assert((decl_.get_tree_code() == VAR_DECL) || (decl_.get_tree_code() == TYPE_DECL)); - decl = decl_; - } - - // Gets tree with the location of variable declaration. - Tree get_tree_decl() const { - return decl; - } - - private: - // Symbol's kind. - SymbolKind kind; - // Symbol's name. - std::string name; - // Symbol's declaration tree. - Tree decl; - - // Note: in other languages, other info about symbols would also be kept, e.g. "kind" - // Also would be able to store more than just variable declaration trees. - }; - - // Symbol shared pointer. - typedef std::shared_ptr SymbolPtr; - // Const symbol shared pointer (i.e. to const Symbol). - typedef std::shared_ptr const_SymbolPtr; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/parse/rust-tree.h b/gcc/rust/test3/parse/rust-tree.h deleted file mode 100644 index 6318a50..0000000 --- a/gcc/rust/test3/parse/rust-tree.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef RUST_TREE_H -#define RUST_TREE_H - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tree.h" -#include "tree-iterator.h" -#include "input.h" -// order: config, system, coretypes, tree, tree-iterator, input -// may not need all of them - -namespace Rust { - // Wrapper around tree to keep location and tree in one data structure. - struct Tree { - public: - Tree() : t(NULL_TREE), loc(UNKNOWN_LOCATION) {} - Tree(tree t_) : t(t_), loc(EXPR_LOCATION(t)) {} - Tree(tree t_, location_t loc_) : t(t_), loc(loc_) {} - Tree(Tree t_, location_t loc_) : t(t_.get_tree()), loc(loc_) {} - - // Get tree's location_t. - location_t get_locus() const { - return loc; - } - - // Sets tree's location_t. - void set_locus(location_t loc_) { - loc = loc_; - } - - // Gets tree's tree in GCC form. - tree get_tree() const { - return t; - } - - // Gets tree's GCC tree code. - tree_code get_tree_code() const { - return TREE_CODE(t); - } - - // Sets tree's GCC tree. - void set_tree(tree t_) { - t = t_; - } - - // Returns if tree is an error node? - bool is_error() const { - return error_operand_p(t); - } - - // Returns whether tree node is null. - bool is_null() { - return t == NULL_TREE; - } - - // Creates an error Tree. - static Tree error() { - return Tree(error_mark_node); - } - - // Gets tree's GCC type. - Tree get_type() const { - return TREE_TYPE(t); - } - - private: - // The tree object's gcc tree representation. - tree t; - // The tree's location. - location_t loc; - }; - - // Comparison by identity as tree is a pointer. - inline bool operator==(Tree t1, Tree t2) { - return t1.get_tree() == t2.get_tree(); - } - inline bool operator!=(Tree t1, Tree t2) { - return !(t1 == t2); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1) { - return build1_loc(loc, tc, type.get_tree(), t1.get_tree()); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2) { - return build2_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree()); - } - - inline Tree build_tree(tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3) { - return build3_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree()); - } - - inline Tree build_tree( - tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4) { - return build4_loc( - loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), t4.get_tree()); - } - - inline Tree build_tree( - tree_code tc, location_t loc, Tree type, Tree t1, Tree t2, Tree t3, Tree t4, Tree t5) { - return build5_loc(loc, tc, type.get_tree(), t1.get_tree(), t2.get_tree(), t3.get_tree(), - t4.get_tree(), t5.get_tree()); - } - - // Wrapper around STATEMENT_LIST, used to represent lists of statements. Adapter for TREE_LIST. - struct TreeStmtList { - public: - // Create new statement list from nothing. - TreeStmtList() : list(alloc_stmt_list()) {} - // Create new statement list from given tree. - TreeStmtList(Tree param_tree) : list(param_tree.get_tree()) {} - - // Append to statement list. - void append(Tree param_tree) { - append_to_statement_list(param_tree.get_tree(), &list); - } - - // Get the statement list. - tree get_tree() const { - return list; - } - - private: - // The statement list. - tree list; - }; - - // TODO: Check if already exists in GCC - template - struct TreeChainBase { - Tree first; - Tree last; - - TreeChainBase() : first(), last() {} - - void append(Tree t) { - gcc_assert(!t.is_null()); - if (first.is_null()) { - first = last = t; - } else { - Append()(last, t); - last = t; - } - } - }; - - struct tree_chain_append { - void operator()(Tree t, Tree a) { - TREE_CHAIN(t.get_tree()) = a.get_tree(); - } - }; - - // Single-linked list implemented with trees. Used for VAR_DECLs. - struct TreeChain : TreeChainBase {}; - - struct block_chain_append { - void operator()(Tree t, Tree a) { - BLOCK_CHAIN(t.get_tree()) = a.get_tree(); - } - }; - - // Single-linked list implemented with trees. Used for chains of blocks. - struct BlockChain : TreeChainBase {}; -} - -#endif // RUST_TREE_H \ No newline at end of file diff --git a/gcc/rust/test3/rsspec.cc b/gcc/rust/test3/rsspec.cc deleted file mode 100644 index 8f16e6c..0000000 --- a/gcc/rust/test3/rsspec.cc +++ /dev/null @@ -1,358 +0,0 @@ -/* Specific flags and argument handling of the Rust front-end. - -This file is part of GCC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -//#include "gcc.h" -#include "opts.h" - -#include "tm.h" -//#include "intl.h" - -// are gcc and intl includes required? - -/*#ifndef MATH_LIBRARY -#define MATH_LIBRARY "m" -#endif - -#ifndef RUST_LIBRARY -#define RUST_LIBRARY "grust" -#endif*/ - -/* The original argument list and related info is copied here. */ -/* static unsigned int grs_xargc; -static const struct cl_decoded_option* grs_x_decoded_options; -static void append_arg(const struct cl_decoded_option*);*/ - -/* The new argument list will be built here. */ -/* static unsigned int grs_newargc; -static struct cl_decoded_option* grs_new_decoded_options;*/ - -/* Return whether strings S1 and S2 are both NULL or both the same string. */ -/* static bool strings_same(const char* s1, const char* s2) { - return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0); -}*/ - -/* Return whether decoded option structures OPT1 and OPT2 are the same. */ -/* static bool options_same(const struct cl_decoded_option* opt1, const struct cl_decoded_option* opt2) { - return (opt1->opt_index == opt2->opt_index && strings_same(opt1->arg, opt2->arg) - && strings_same(opt1->orig_option_with_args_text, opt2->orig_option_with_args_text) - && strings_same(opt1->canonical_option[0], opt2->canonical_option[0]) - && strings_same(opt1->canonical_option[1], opt2->canonical_option[1]) - && strings_same(opt1->canonical_option[2], opt2->canonical_option[2]) - && strings_same(opt1->canonical_option[3], opt2->canonical_option[3]) - && (opt1->canonical_option_num_elements == opt2->canonical_option_num_elements) - && opt1->value == opt2->value && opt1->errors == opt2->errors); -}*/ - -/* Append another argument to the list being built. As long as it is identical to the corresponding - * arg in the original list, just increment the new arg count. Otherwise allocate a new list, etc. */ -/* static void append_arg(const struct cl_decoded_option* arg) { - static unsigned int newargsize; - -#if 0 - fprintf (stderr, "`%s'\n", arg); -#endif - - if (grs_new_decoded_options == grs_x_decoded_options && grs_newargc < grs_xargc - && options_same(arg, &grs_x_decoded_options[grs_newargc])) { - ++grs_newargc; - return; // Nothing new here. - } - - if (grs_new_decoded_options == grs_x_decoded_options) { // Make new arglist. - unsigned int i; - - newargsize = (grs_xargc << 2) + 20; // This should handle all. - grs_new_decoded_options = XNEWVEC(struct cl_decoded_option, newargsize); - - // Copy what has been done so far. - for (i = 0; i < grs_newargc; ++i) - grs_new_decoded_options[i] = grs_x_decoded_options[i]; - } - - if (grs_newargc == newargsize) - fatal_error("overflowed output arg list for %qs", arg->orig_option_with_args_text); - - grs_new_decoded_options[grs_newargc++] = *arg; -}*/ - -/* Append an option described by OPT_INDEX, ARG and VALUE to the list being built. */ -/* static void append_option(size_t opt_index, const char* arg, int value) { - struct cl_decoded_option decoded; - - generate_option(opt_index, arg, value, CL_DRIVER, &decoded); - append_arg(&decoded); -}*/ - -/* Append a librust argument to the list being built. If FORCE_STATIC, ensure the library is linked - * statically. */ -/* static void add_arg_libgrust(bool force_static ATTRIBUTE_UNUSED) { -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option(OPT_Wl_, "-Bstatic", 1); -#endif - append_option(OPT_l, RUST_LIBRARY, 1); -#ifdef HAVE_LD_STATIC_DYNAMIC - if (force_static) - append_option(OPT_Wl_, "-Bdynamic", 1); -#endif -}*/ - -/* Modeled closely of gcc/fortran/gfortranspec.c */ -// Presumably this is the "compiler driver", which runs the compiler -// Handle calling the compiler (i.e. options, libraries to use) -// Used to change flags before passing them to the driver -void lang_specific_driver(struct cl_decoded_option** in_decoded_options ATTRIBUTE_UNUSED, - unsigned int* in_decoded_options_count ATTRIBUTE_UNUSED, int* in_added_libraries ATTRIBUTE_UNUSED) { - // as of now, no options need changing, but they may in the future - - /* unsigned int i = 0; - unsigned int argc = *in_decoded_options_count; // argument list count - struct cl_decoded_option* decoded_options = *in_decoded_options; // argument list - - int verbose = 0;*/ - - /* This will be NULL if we encounter a situation where we should not - link in libf2c. */ - // const char* library = RUST_LIBRARY; - - /* 0 => -xnone in effect. - 1 => -xfoo in effect. */ - // int saw_speclang = 0; - - /* 0 => initial/reset state - 1 => last arg was -l - 2 => last two args were -l -lm. */ - // int saw_library = 0; - - // By default, we throw on the math library if we have one. - // int need_math = (MATH_LIBRARY[0] != '\0'); - - // Whether we should link a static libgrsthon. - // int static_lib = 0; - - // Whether we need to link statically. - // int static_linking = 0; - - // The number of input and output files in the incoming arg list. - // int n_infiles = 0; - // int n_outfiles = 0; - -/* #if 0 - fprintf (stderr, "Incoming:"); - for( i=0; i. - append_option(OPT_l, MATH_LIBRARY, 1); - -saw_library = 0; - -if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) { - append_arg(&decoded_options[i]); // "-" == Standard input. - continue; -} - -if (decoded_options[i].opt_index == OPT_x) { - // Track input language. - const char* lang = decoded_options[i].arg; - saw_speclang = (strcmp(lang, "none") != 0); -} -append_arg(&decoded_options[i]); -continue; -} - -// A filename/library, not an option. - -if (saw_speclang) -saw_library = 0; // -xfoo currently active. -else { // -lfoo or filename. -if (decoded_options[i].opt_index == OPT_l - && strcmp(decoded_options[i].arg, MATH_LIBRARY) == 0) { - if (saw_library == 1) - saw_library = 2; // -l -lm. - else - add_arg_libgrust(static_lib && !static_linking); -} else if (decoded_options[i].opt_index == OPT_l - && strcmp(decoded_options[i].arg, RUST_LIBRARY) == 0) { - saw_library = 1; // -l. - add_arg_libgrust(static_lib && !static_linking); - continue; -} else { // Other library, or filename. - if (saw_library == 1 && need_math) - append_option(OPT_l, MATH_LIBRARY, 1); - saw_library = 0; -} -} -append_arg(&decoded_options[i]); -}*/ - - // Append `-lrust -lm' as necessary. - - /* if (library) { // Doing a link and no -nostdlib. - if (saw_speclang) - append_option(OPT_x, "none", 1); - - switch (saw_library) { - case 0: - add_arg_libgrust(static_lib && !static_linking); - // Fall through. - case 1: - if (need_math) - append_option(OPT_l, MATH_LIBRARY, 1); - default: - break; - } - }*/ - - /* #ifdef ENABLE_SHARED_LIBGCC - if (library) { - unsigned int i; - - for (i = 1; i < grs_newargc; i++) - if (grs_new_decoded_options[i].opt_index == OPT_static_libgcc - || grs_new_decoded_options[i].opt_index == OPT_static) - break; - - if (i == grs_newargc) - append_option(OPT_shared_libgcc, NULL, 1); - } - - #endif*/ - - /* if (verbose && grs_new_decoded_options != grs_x_decoded_options) { - fprintf(stderr, _("Driving:")); - for (i = 0; i < grs_newargc; i++) - fprintf(stderr, " %s", grs_new_decoded_options[i].orig_option_with_args_text); - fprintf(stderr, "\n"); - } - - *in_decoded_options_count = grs_newargc; - *in_decoded_options = grs_new_decoded_options;*/ -} - -/* Called before linking - can be used to do some extra steps and abort if they fail. Returns 0 on - * success and -1 on failure. */ -int lang_specific_pre_link(void) { - // Not used for rust - return 0; -} - -/* Number of extra output files that lang_specific_pre_link may generate. Used to add extra outfiles - * to linking step. */ -int lang_specific_extra_outfiles = 0; // not used for rust diff --git a/gcc/rust/test3/rust-buffered-queue.h b/gcc/rust/test3/rust-buffered-queue.h deleted file mode 100644 index ac0ea1a..0000000 --- a/gcc/rust/test3/rust-buffered-queue.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef RUST_BUFFERED_QUEUE_H -#define RUST_BUFFERED_QUEUE_H - -#include - -#include "config.h" -#include "system.h" -// order: config, system - -namespace Rust { - // Buffered queue implementation. Items are of type T, queue source is of type Source. - template - class buffered_queue { - public: - // Construct empty queue from Source& src. - buffered_queue(Source& src) : source(src), start(0), end(0), buffer() {} - - // Returns token at position start + n (i.e. n tokens ahead). - T peek(int n) { - // n should not be behind - gcc_assert(n >= 0); - - int num_queued_items = end - start; - int num_items_required = n + 1; - - // if required items go past end of queue, add them to queue - if (num_items_required > num_queued_items) { - int num_items_to_read = num_items_required - num_queued_items; - - // if queue length + extra items is larger than buffer size, expand buffer - if (end + num_items_to_read > (int)buffer.size()) { - // Resize the buffer by 1.5x - int new_size = (buffer.size() + num_items_to_read); - new_size += (new_size >> 1); - - // create new queue buffer with new size - std::vector new_queue(new_size); - std::copy(buffer.begin() + start, buffer.begin() + end, new_queue.begin()); - start = 0; - end = num_queued_items; - - // swap member buffer and new queue buffer - std::swap(buffer, new_queue); - - // validate that buffer is large enough now - gcc_assert(end + num_queued_items < (int)buffer.size()); - } - - // iterate through buffer and invoke operator () on source on values past original end - for (int i = 0; i < num_items_to_read; i++) { - buffer[end + i] = source(); - } - - // move end based on additional items added - end += num_items_to_read; - } - - gcc_assert(0 <= start); - gcc_assert(start <= end); - gcc_assert(end <= (int)buffer.size()); - - gcc_assert(start + n < end); - - // return value at start + n in buffer - return buffer[start + n]; - } - - // TODO: add faster peek current token to remove overhead of conditional branches? - - // Advances start by n + 1. - void skip(int n) { - // Call peek to ensure requested n is actually in queue. - peek(n); - - // Clear values from start to n (inclusive). - for (int i = 0; i < (n + 1); i++) { - // Clear value at index - buffer[start + i] = T(); - } - - // Move start forward by n + 1. - start += (n + 1); - - // Ensure start is not impossible somehow - gcc_assert(0 <= start); - gcc_assert(start <= end); - - // Compact buffer if empty - if (start == end) { - start = end = 0; - } - } - - /* Inserts element at front of vector. Really dirty hack with terrible performance, only use - * when really needed. */ - void insert_at_front(T elem_to_insert) { - // TODO: test as this may not work properly - - // Insert actual element in buffer at start. - buffer.insert(buffer.begin(), 1, elem_to_insert); - - // Increase the end number since added element means all others have shifted one along - end++; - } - - // Replaces the current value in the buffer. Total HACK. - void replace_current_value(T replacement) { - // call peek to ensure value exists - peek(0); - - buffer[start] = replacement; - - // don't move start or end - } - - private: - // Source of tokens for queue. - Source& source; - - // Begin of range in buffer, inclusive. - int start; - // End of range in buffer, exclusive. - int end; - - // Queue buffer. - std::vector buffer; - }; -} - -#endif \ No newline at end of file diff --git a/gcc/rust/test3/rust-lang.cc b/gcc/rust/test3/rust-lang.cc deleted file mode 100644 index 5c47878..0000000 --- a/gcc/rust/test3/rust-lang.cc +++ /dev/null @@ -1,330 +0,0 @@ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "gimple-expr.h" -#include "diagnostic.h" -#include "opts.h" -#include "fold-const.h" -#include "gimplify.h" -#include "stor-layout.h" -#include "debug.h" -#include "convert.h" -#include "langhooks.h" -#include "langhooks-def.h" -#include "common/common-target.h" -// note: header files must be in this order or else forward declarations don't work properly. Kinda -// dumb system, but have to live with it. clang-format seems to mess it up -/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic, opts, fold-const, - * gimplify, stor-layout, debug, convert, langhooks, langhooks-def, common-target */ - -// FIXME: test saving intellisense -#include "options.h" - -// version check to stop compiling if c++ isn't c++11 or higher -#if __cplusplus < 201103 -#error \ - "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." -#endif -// TODO: is this best way to do it? Is it allowed? (should be) - -/* General TODOs: - * - maybe convert all raw pointer-returning/passing functions that conceptually return a unique - * pointer actually return a unique pointer. i.e. parse methods and constructors for AST objects. - * make_unique should probably be avoided to keep C++11 compatibility. - * - convert all copies of expensive-to-copy (deep copy) AST objects into moves, if possible. Don't - * remove clone functionality - it may be required for e.g. HIR conversion. */ - -#include "rust-parse.h" -#include "rust-session-manager.h" - -// Language-dependent contents of a type. GTY() mark used for garbage collector. -struct GTY(()) lang_type { - char dummy; -}; - -// Language-dependent contents of a decl. -struct GTY(()) lang_decl { - char dummy; -}; - -// Language-dependent contents of an identifier. This must include a tree_identifier. -struct GTY(()) lang_identifier { - struct tree_identifier common; -}; - -// The resulting tree type. -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next( - "CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " - "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node { - union tree_node GTY((tag("0"), desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; -}; - -// We don't use language_function. -struct GTY(()) language_function { - int dummy; -}; - -// Kinda HACK-ish - store parsing session as static variable -static Rust::Session session; - -/* Language hooks. */ - -/* Initial lang hook called (possibly), used for initialisation. - * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, and - * build_common_builtin_nodes, as well as set global variable void_list_node. - * Apparently called after option handling? */ -static bool grs_langhook_init(void) { - /* Something to do with this: - This allows the code in d-builtins.cc to not have to worry about - converting (C signed char *) to (D char *) for string arguments of - built-in functions. The parameter (signed_char = false) specifies - whether char is signed. */ - build_common_tree_nodes(false); - - // Creates a new TREE_LIST node with purpose NULL_TREE and value void_type_node - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - // Builds built-ins for middle-end after all front-end built-ins are already instantiated - build_common_builtin_nodes(); - - // mpfr_set_default_prec(128); - // using_eh_for_cleanups(); - - // rdot_init(); - - // initialise compiler session - session.init(); - - - - return true; -} - -/* The option mask (something to do with options for specific frontends or something). */ -static unsigned int grs_langhook_option_lang_mask(void) { - return CL_Rust; -} - -/* Initialize the options structure. */ -static void grs_langhook_init_options_struct(struct gcc_options* opts) { - // nothing yet - used by frontends to change specific options for the language - session.init_options(); -} - -/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and - * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. - * This function must create a complete parse tree in a global var, and then return. - * - * Some consider this the "start of compilation". */ -static void grs_langhook_parse_file(void) { - fprintf(stderr, "Preparing to parse files. \n"); - - // grs_parse_files(num_in_fnames, in_fnames); - session.parse_files(num_in_fnames, in_fnames); -} - -/* Seems to get the exact type for a specific type - e.g. for scalar float with 32-bit bitsize, it - * returns float, and for 64-bit bitsize, it returns double. Used to map RTL nodes to machine modes or - * something like that. */ -static tree grs_langhook_type_for_mode(machine_mode mode, int unsignedp) { - // TODO: change all this later to match rustc types - if (mode == TYPE_MODE(float_type_node)) - return float_type_node; - - if (mode == TYPE_MODE(double_type_node)) - return double_type_node; - - if (mode == TYPE_MODE(intQI_type_node)) // quarter integer mode - single byte treated as integer - return unsignedp ? unsigned_intQI_type_node : intQI_type_node; - if (mode == TYPE_MODE(intHI_type_node)) // half integer mode - two-byte integer - return unsignedp ? unsigned_intHI_type_node : intHI_type_node; - if (mode == TYPE_MODE(intSI_type_node)) // single integer mode - four-byte integer - return unsignedp ? unsigned_intSI_type_node : intSI_type_node; - if (mode == TYPE_MODE(intDI_type_node)) // double integer mode - eight-byte integer - return unsignedp ? unsigned_intDI_type_node : intDI_type_node; - if (mode == TYPE_MODE(intTI_type_node)) // tetra integer mode - 16-byte integer - return unsignedp ? unsigned_intTI_type_node : intTI_type_node; - - if (mode == TYPE_MODE(integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - - if (mode == TYPE_MODE(long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - - if (mode == TYPE_MODE(long_long_integer_type_node)) - return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; - - if (COMPLEX_MODE_P(mode)) { - if (mode == TYPE_MODE(complex_float_type_node)) - return complex_float_type_node; - if (mode == TYPE_MODE(complex_double_type_node)) - return complex_double_type_node; - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) - return complex_integer_type_node; - } - /* gcc_unreachable */ - return NULL; -} - -/* This appears to be used for creating different types for different bit sizes (e.g. int and long). - * Also, the Go frontend calls this from type_for_mode to determine the type from a specific bitsize - * for integer types. - * FIXME: change this when working on AST-GENERIC conversion to allow the full range of Rust type - * sizes. */ -static tree grs_langhook_type_for_size( - unsigned int bits ATTRIBUTE_UNUSED, int unsignedp ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL_TREE; - // nothing at the moment, but change later -} - -// Record a builtin function. We just ignore builtin functions. -static tree grs_langhook_builtin_function(tree decl ATTRIBUTE_UNUSED) { - return decl; -} - -/* Return true if we are in the global binding level (which is never, apparently). */ -static bool grs_langhook_global_bindings_p(void) { - // return current_function_decl == NULL_TREE; - // gcc_unreachable(); - // return true; - return false; -} - -/* Push a declaration into the current binding level. We can't - usefully implement this since we don't want to convert from tree - back to one of our internal data structures. I think the only way - this is used is to record a decl which is to be returned by - getdecls, and we could implement it for that purpose if - necessary. */ -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL; -} - -/* This hook is used to get the current list of declarations as trees. - We don't support that; instead we use the write_globals hook. This - can't simply crash because it is called by -gstabs. */ -static tree grs_langhook_getdecls(void) { - // gcc_unreachable(); - return NULL; -} - -// Handle Rust-specific options. Return false if nothing happened. -static bool grs_langhook_handle_option(size_t scode, const char* arg, HOST_WIDE_INT value, - int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, - const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - // Convert integer code to lang.opt enum codes with names. - enum opt_code code = (enum opt_code)scode; - // used to store whether results of various stuff are successful - // bool ret = true; - - // delegate to session manager - return session.handle_option(code, arg, value, kind, loc, handlers); - - // Handles options as listed in lang.opt. - /*switch (code) { - case OPT_I: - // TODO: add search path - break; - case OPT_L: - // TODO: add library link path or something - break; - case OPT_frust_dump: - // enable dump and return whether this was successful - ret = rust_enable_dump(arg) ? true : false; - break; - // no option handling for -o - default: - // return 1 to indicate option is valid - break; - } - - return ret;*/ -} - -/* Run after parsing options. */ -static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { - // can be used to override other options if required - - // satisfies an assert in init_excess_precision in toplev.c - if (flag_excess_precision/*_cmdline*/ == EXCESS_PRECISION_DEFAULT) - flag_excess_precision/*_cmdline*/ = EXCESS_PRECISION_STANDARD; - - /* Returning false means that the backend should be used. */ - return false; -} - -/* Rust-specific gimplification. May need to gimplify e.g. CALL_EXPR_STATIC_CHAIN */ -static int grs_langhook_gimplify_expr(tree* expr_p ATTRIBUTE_UNUSED, - gimple_seq* pre_p ATTRIBUTE_UNUSED, gimple_seq* post_p ATTRIBUTE_UNUSED) { - /*if (TREE_CODE (*expr_p) == CALL_EXPR - && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE) - gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, - is_gimple_val, fb_rvalue);*/ - return GS_UNHANDLED; -} - -/* Create an expression whose value is that of EXPR, - converted to type TYPE. The TREE_TYPE of the value - is always TYPE. This function implements all reasonable - conversions; callers should filter out those that are - not permitted by the language being compiled. */ -/* tree convert(tree type, tree expr) { // not implemented yet - seems to be needed for compilation - return NULL; -}*/ -// implemented in rust-misc-convert.cc - -/* The language hooks data structure. This is the main interface between the GCC front-end - * and the GCC middle-end/back-end. A list of language hooks could be found in - * /langhooks.h - */ -#undef LANG_HOOKS_NAME -#undef LANG_HOOKS_INIT -#undef LANG_HOOKS_OPTION_LANG_MASK -#undef LANG_HOOKS_INIT_OPTIONS_STRUCT -#undef LANG_HOOKS_HANDLE_OPTION -#undef LANG_HOOKS_POST_OPTIONS -#undef LANG_HOOKS_PARSE_FILE -#undef LANG_HOOKS_TYPE_FOR_MODE -#undef LANG_HOOKS_TYPE_FOR_SIZE -#undef LANG_HOOKS_BUILTIN_FUNCTION -#undef LANG_HOOKS_GLOBAL_BINDINGS_P -#undef LANG_HOOKS_PUSHDECL -#undef LANG_HOOKS_GETDECLS -//#undef LANG_HOOKS_WRITE_GLOBALS -#undef LANG_HOOKS_GIMPLIFY_EXPR -//#undef LANG_HOOKS_EH_PERSONALITY - -#define LANG_HOOKS_NAME "GNU Rust" -#define LANG_HOOKS_INIT grs_langhook_init -#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask -#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct -#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option -#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -/* Main lang-hook, apparently. Finds input file names in global vars in_fnames and num_in_fnames - * From this, frontend can take over and do actual parsing and initial compilation. - * This hook must create a complete parse tree in a global var, and then return. */ -#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file -#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode -#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size -#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function -#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p -#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl -#define LANG_HOOKS_GETDECLS grs_langhook_getdecls -//#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals -#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr -//#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality - -// Expands all LANG_HOOKS_x of GCC -struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -// These are for GCC's garbage collector to work properly or something -#include "gt-rust-rust-lang.h" -#include "gtype-rust.h" \ No newline at end of file diff --git a/gcc/rust/test3/rust-session-manager.cc b/gcc/rust/test3/rust-session-manager.cc deleted file mode 100644 index 443818c..0000000 --- a/gcc/rust/test3/rust-session-manager.cc +++ /dev/null @@ -1,654 +0,0 @@ -#include "rust-session-manager.h" - -#include "diagnostic.h" -#include "input.h" - -#include "rust-lex.h" -#include "rust-parse.h" - -#include - -namespace Rust { - // Simple wrapper for FILE* that simplifies destruction. - struct RAIIFile { - FILE* file; - - RAIIFile(const char* filename) : file(fopen(filename, "r")) {} - - ~RAIIFile() { - fclose(file); - } - }; - - // Implicitly enable a target_feature (and recursively enable dependencies). - void Session::implicitly_enable_feature(::std::string feature_name) { - // TODO: is this really required since features added would be complete via target spec? - - if (!options.target_data.has_key_value_pair("target_data", feature_name)) { - // if feature has dependencies, enable them - if (feature_name == "aes") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "avx") { - implicitly_enable_feature("sse4.2"); - } else if (feature_name == "avx2") { - implicitly_enable_feature("avx"); - } else if (feature_name == "fma") { - implicitly_enable_feature("avx"); - } else if (feature_name == "pclmulqdq") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sha") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sse2") { - implicitly_enable_feature("sse"); - } else if (feature_name == "sse3") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sse4.1") { - implicitly_enable_feature("sse3"); - } else if (feature_name == "sse4.2") { - implicitly_enable_feature("sse4.1"); - } else if (feature_name == "ssse3") { - implicitly_enable_feature("sse3"); - } - - options.target_data.insert_key_value_pair("target_feature", ::std::move(feature_name)); - } - } - - // Meant to enable all target features. As this will be done by target hook, this method's - // deprecated. - void Session::enable_features() { - bool has_target_crt_static = false; - const char* target = "PLACEHOLDER"; - - fprintf(stderr, "ERROR: Somewhere in call chain Session::enable_features is called.\n"); - - if (has_target_crt_static) { - // enable "crt-static" attribute - } - - /* TODO: do this via target hook. have one for each target that implicitly enables the - * features for that platform. Would probably have to make custom target hook. */ - - /* - if (target == "x86" || target == "x86_64") { - if (TARGET_ISA_AES) { - // enable aes, implicitly enable sse2 - implicitly_enable_feature("aes"); - } - - if (TARGET_ISA_AVX) { - // enable avx, implicitly enable sse4.2 - implicitly_enable_feature("sse4.2"); - } - - if (TARGET_ISA_AVX2) { - // enable avx2, implicitly enable avx - implicitly_enable_feature("avx"); - } - - if (TARGET_ISA_BMI) { - // enable bmi1 - implicitly_enable_feature("bmi1"); - } - - if (TARGET_ISA_BMI2) { - // enable bmi2 - implicitly_enable_feature("bmi2"); - } - - if (TARGET_ISA_FMA) { - // enable fma, implicitly enable avx - implicitly_enable_feature("fma"); - } - - if (TARGET_ISA_FXSR) { - // enable fxsr - implicitly_enable_feature("fxsr"); - } - - if (TARGET_ISA_LZCNT) { - // enable lzcnt - implicitly_enable_feature("lzcnt"); - } - - if (TARGET_ISA_VPCLMULQDQ) { - // enable pclmulqdq, implicitly enable sse2 - implicitly_enable_feature("pclmulqdq"); - } - - if (TARGET_ISA_POPCNT) { - // enable popcnt - implicitly_enable_feature("popcnt"); - } - - if (TARGET_ISA_RDRND) { - // enable rdrand - implicitly_enable_feature("rdrand"); - } - - if (TARGET_ISA_RDSEED) { - // enable rdseed - implicitly_enable_feature("rdseed"); - } - - if (TARGET_ISA_SHA) { - // enable sha, implicitly enable sse2 - implicitly_enable_feature("sha"); - } - - if (TARGET_ISA_SSE) { - // enable sse - implicitly_enable_feature("sse"); - } - - if (TARGET_ISA_SSE2) { - // enable sse2, implicitly enable sse - implicitly_enable_feature("sse2"); - } - - if (TARGET_ISA_SSE3) { - // enable sse3, implicitly enable sse2 - implicitly_enable_feature("sse3"); - } - - if (TARGET_ISA_SSE4_1) { - // enable sse4.1, implicitly enable sse3 - implicitly_enable_feature("sse4.1"); - } - - if (TARGET_ISA_SSE4_2) { - // enable sse4.2, implicitly enable sse4.1 - implicitly_enable_feature("sse4.2"); - } - - if (TARGET_ISA_SSSE3) { - // enable ssse3, implicitly enable sse3 - implicitly_enable_feature("ssse3"); - } - - if (TARGET_ISA_XSAVE) { - // enable xsave - implicitly_enable_feature("xsave"); - } - - if (TARGET_ISA_XSAVEC) { - // enable xsavec - implicitly_enable_feature("xsavec"); - } - - if (TARGET_ISA_XSAVEOPT) { - // enable xsaveopt - implicitly_enable_feature("xsaveopt"); - } - - if (TARGET_ISA_XSAVES) { - // enable xsaves - implicitly_enable_feature("xsaves"); - } - } - options.target_data.features.shrink_to_fit(); - ::std::sort(options.target_data.features.begin(), options.target_data.features.end());*/ - } - - void Session::init() { - // nothing yet - } - - // Initialise default options. Actually called before handle_option, unlike init itself. - void Session::init_options() { - options.dump_option = CompileOptions::NO_DUMP; - } - - // Handle option selection. - bool Session::handle_option(enum opt_code code, const char* arg, - HOST_WIDE_INT value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED, - location_t loc ATTRIBUTE_UNUSED, const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - // used to store whether results of various stuff are successful - bool ret = true; - - // Handles options as listed in lang.opt. - switch (code) { - case OPT_I: - // TODO: add search path - break; - case OPT_L: - // TODO: add library link path or something - break; - case OPT_frust_dump_: - // enable dump and return whether this was successful - if (arg != NULL) { - ret = enable_dump(::std::string(arg)); - } else { - ret = false; - } - break; - // no option handling for -o - default: - // return 1 to indicate option is valid - break; - } - - return ret; - } - - /* Enables a certain dump depending on the name passed in. Returns true if name is valid, false - * otherwise. */ - bool Session::enable_dump(::std::string arg) { - // FIXME: change dumping algorithm when new non-inhibiting dump system is created - if (arg == "all") { - error_at( - UNKNOWN_LOCATION, "dumping all is not supported as of now. choose 'lex' or 'parse'"); - return false; - } else if (arg == "lex") { - options.dump_option = CompileOptions::LEXER_DUMP; - } else if (arg == "parse") { - options.dump_option = CompileOptions::PARSER_AST_DUMP; - } else if (arg == "register_plugins") { - options.dump_option = CompileOptions::REGISTER_PLUGINS_DUMP; - } else if (arg == "injection") { - options.dump_option = CompileOptions::INJECTION_DUMP; - } else if (arg == "expansion") { - options.dump_option = CompileOptions::EXPANSION_DUMP; - } else if (arg == "name_resolution") { - options.dump_option = CompileOptions::NAME_RESOLUTION_DUMP; - } else if (arg == "") { - error_at(UNKNOWN_LOCATION, "dump option was not given a name. choose 'lex' or 'parse'"); - return false; - } else { - error_at(UNKNOWN_LOCATION, "dump option '%s' was unrecognised. choose 'lex' or 'parse'", - arg.c_str()); - return false; - } - return true; - } - - /* Actual main entry point for front-end. Called from langhook to parse files. */ - void Session::parse_files(int num_files, const char** files) { - for (int i = 0; i < num_files; i++) { - parse_file(files[i]); - } - // TODO: should semantic analysis be dealed with here? or per file? for now, per-file. - } - - // Parses a single file with filename filename. - void Session::parse_file(const char* filename) { - RAIIFile file_wrap(filename); - - if (file_wrap.file == NULL) { - fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); - } - - // parse file here - // create lexer and parser - these are file-specific and so aren't instance variables - Rust::Lexer lex(filename, file_wrap.file); - Rust::Parser parser(lex); - - // determine parsing method from options - /* FIXME: currently, the dump means that full compilation will not occur as of present. In - * future, dumps should not inhibit full compilation. */ - switch (options.dump_option) { - case CompileOptions::NO_DUMP: - fatal_error(UNKNOWN_LOCATION, "no-dump parsing has not been enabled yet"); - return; - case CompileOptions::LEXER_DUMP: - parser.debug_dump_lex_output(); - return; - case CompileOptions::PARSER_AST_DUMP: - parser.debug_dump_ast_output(); - return; - case CompileOptions::REGISTER_PLUGINS_DUMP: - case CompileOptions::INJECTION_DUMP: - case CompileOptions::EXPANSION_DUMP: - case CompileOptions::NAME_RESOLUTION_DUMP: - // will break later after more stages - break; - // semantic analysis when completed - default: - fatal_error(UNKNOWN_LOCATION, "unrecognised dump option: '%u'", options.dump_option); - return; - } - - /* basic pipeline: - * - lex - * - parse - * - register plugins (dummy stage for now) - attribute injection? what is this? - * (attribute injection is injecting attributes specified in command line into crate root) - * - injection (some lint checks or dummy, register builtin macros, crate injection) - * - expansion (expands all macros, maybe build test harness, AST validation, maybe macro - * crate) - * - name resolution (name resolution, maybe feature checking, maybe buffered lints) - * TODO not done */ - - // generate crate from parser - AST::Crate parsed_crate = parser.parse_crate(); - - fprintf(stderr, "\033[0;31mSUCCESSFULLY PARSED CRATE \n\033[0m"); - - // register plugins pipeline stage - register_plugins(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY REGISTERED PLUGINS \n\033[0m"); - - if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) { - // TODO: what do I dump here? - return; - } - - // injection pipeline stage - injection(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED INJECTION \n\033[0m"); - - if (options.dump_option == CompileOptions::INJECTION_DUMP) { - // TODO: what do I dump here? injected crate names? - return; - } - - // expansion pipeline stage - expansion(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED EXPANSION \n\033[0m"); - - if (options.dump_option == CompileOptions::EXPANSION_DUMP) { - // TODO: what do I dump here? expanded macros? AST with expanded macros? - return; - } - - // name resolution pipeline stage - name_resolution(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED NAME RESOLUTION \n\033[0m"); - - if (options.dump_option == CompileOptions::NAME_RESOLUTION_DUMP) { - // TODO: what do I dump here? resolved names? AST with resolved names? - return; - } - } - - // Checks whether 'cfg' attribute prevents compilation. - bool check_cfg(const AST::Attribute& attr ATTRIBUTE_UNUSED) { - // if "has sub items", and if 'cfg' attr, recursively call this on sub items? - - // TODO: actually implement. assume true for now - - return true; - } - // TODO: deprecated - don't use - - // Checks whether any 'cfg' attribute on the item prevents compilation of that item. - bool check_item_cfg(::std::vector attrs) { - for (const auto& attr : attrs) { - if (attr.get_path() == "cfg" && !check_cfg(attr)) { - return false; - } - } - - return true; - } - // TODO: deprecated - don't use - - // TODO: actually implement method - void load_extern_crate(::std::string crate_name ATTRIBUTE_UNUSED) {} - // TODO: deprecated - don't use - - // Parses up to the "load (external) crates" part of the frontend. - // TODO: lots of this code is probably actually useful outside of dumping, so maybe split off - // function - void Session::debug_dump_load_crates(Parser& parser) { - // parse crate as AST - AST::Crate crate = parser.parse_crate(); - - /* TODO: search through inner attrs and see whether any of those attr paths contain "no_core", - * "no_std", "compiler_builtins". If so/not, save certain crate names. In these names, insert - * items at beginning of crate items. This is crate injection. Also, inject prelude use decl - * at beginning (first name is assumed to be prelude - prelude is a use decl automatically - * generated to enable using Option and Copy without qualifying it or importing it via 'use' - * manually) */ - - ::std::vector< ::std::string> crate_names; - for (const auto& item : crate.items) { - // if item is extern crate, add name? to list of stuff ONLY IF config is checked - // if item is module, iterate this loop inside it as well (recursive?) ONLY IF config is - // checked - - // TODO: actually do the checks somewhere - probably in the items - - item->add_crate_name(crate_names); - } - - /* loop through list of crate names/paths/whatever, attempting to load each one. save loaded - * crates to a Session variable? Or save to current AST::Crate? */ - for (const auto& name : crate_names) { - load_extern_crate(name /*, basename = ""?*/); - } - // for each loaded crate, load dependencies of it as well - } - // TODO: deprecated - don't use - - void Session::register_plugins(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "ran register_plugins (with no body)\n"); - } - - // TODO: move somewhere else - bool contains_name(::std::vector attrs, ::std::string name) { - for (const auto& attr : attrs) { - if (attr.get_path() == name) { - return true; - } - } - - return false; - } - - void Session::injection(AST::Crate& crate) { - fprintf(stderr, "started injection\n"); - - // lint checks in future maybe? - - // register builtin macros - /* In rustc, builtin macros are divided into 3 categories depending on use - "bang" macros, - * "attr" macros, and "derive" macros. I think the meanings of these categories should be - * fairly obvious to anyone who has used rust. Builtin macro list by category: Bang - * - asm - * - assert - * - cfg - * - column - * - compile_error - * - concat_idents - * - concat - * - env - * - file - * - format_args_nl - * - format_args - * - global_asm - * - include_bytes - * - include_str - * - include - * - line - * - log_syntax - * - module_path - * - option_env - * - stringify - * - trace_macros - * Attr - * - bench - * - global_allocator - * - test - * - test_case - * Derive - * - Clone - * - Copy - * - Debug - * - Default - * - Eq - * - Hash - * - Ord - * - PartialEq - * - PartialOrd - * - RustcDecodable - * - RustcEncodable - * rustc also has a "quote" macro that is defined differently and is supposedly not stable so - * eh. */ - /* TODO: actually implement injection of these macros. In particular, derive macros, cfg, and - * test should be prioritised since they seem to be used the most. */ - - // crate injection - ::std::vector< ::std::string> names; - if (contains_name(crate.inner_attrs, "no_core")) { - // no prelude - injected_crate_name = ""; - } else if (contains_name(crate.inner_attrs, "no_std")) { - names.push_back("core"); - - if (!contains_name(crate.inner_attrs, "compiler_builtins")) { - names.push_back("compiler_builtins"); - } - - injected_crate_name = "core"; - } else { - names.push_back("std"); - - injected_crate_name = "std"; - } - - // reverse iterate through names to insert crate items in "forward" order at beginning of - // crate - for (auto it = names.rbegin(); it != names.rend(); ++it) { - // create "macro use" attribute for use on extern crate item to enable loading macros from - // it - AST::Attribute attr(AST::SimplePath::from_str("macro_use"), NULL); - - // create "extern crate" item with the name - ::std::unique_ptr extern_crate(new AST::ExternCrate( - *it, AST::Visibility::create_error(), { ::std::move(attr) }, UNKNOWN_LOCATION)); - - // insert at beginning - crate.items.insert(crate.items.begin(), ::std::move(extern_crate)); - } - - // create use tree path - // prelude is injected_crate_name - ::std::vector segments - = { AST::SimplePathSegment(injected_crate_name), AST::SimplePathSegment("prelude"), - AST::SimplePathSegment("v1") }; - // create use tree and decl - ::std::unique_ptr use_tree(new AST::UseTreeGlob( - AST::UseTreeGlob::PATH_PREFIXED, AST::SimplePath(::std::move(segments)), UNKNOWN_LOCATION)); - AST::Attribute prelude_attr(AST::SimplePath::from_str("prelude_import"), NULL); - ::std::unique_ptr use_decl(new AST::UseDeclaration(::std::move(use_tree), - AST::Visibility::create_error(), { ::std::move(prelude_attr) }, UNKNOWN_LOCATION)); - - crate.items.insert(crate.items.begin(), ::std::move(use_decl)); - - /* TODO: potentially add checking attribute crate type? I can't figure out what this does - * currently comment says "Unconditionally collect crate types from attributes to make them - * used", which presumably refers to checking the linkage info by "crate_type". It also seems - * to ensure that an invalid crate type is not specified, so maybe just do that. Valid crate - * types: bin lib dylib staticlib cdylib rlib proc-macro */ - - fprintf(stderr, "finished injection\n"); - } - - void Session::expansion(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "started expansion\n"); - - // rustc has a modification to windows PATH temporarily here, which may end up being required - - // create macro expansion config? - // if not, would at least have to configure recursion_limit - - // create extctxt? from parse session, cfg, and resolver? - // expand by calling cxtctxt object's monotonic_expander's expand_crate method. - - // error reporting - check unused macros, get missing fragment specifiers - - // build test harness - - // ast validation (also with proc macro decls) - - // maybe create macro crate if not rustdoc - - fprintf(stderr, "finished expansion\n"); - } - - void Session::name_resolution(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "started name resolution\n"); - - fprintf(stderr, "finished name resolution\n"); - } - - // NOTEs: - /* mrustc compile pipeline: - * - target load (pass target spec to parser?) - * - parse (convert source to AST) - * - load crates (load any explicitly mentioned extern crates [not all of them]) - * - expand (AST transformations from attributes and macros, loads remaining extern crates - * [std/core and any triggered by macro expansion]) - * - implicit crates (test harness, allocator crate, panic crate) - * - resolve use (annotate every 'use' item with source [supposedly handles nasty recursion]) - * - resolve index (generate index of visible items for every module [avoids recursion in next - * pass]) - * - resolve absolute (resolve all paths into either variable names [types/values] or absolute - * paths) - * - HIR lower (convert modified AST to simpler HIR [both expressions and module tree]) - * - resolve type aliases (replace any usages of type aliases with actual type [except associated - * types]) - * - resolve bind (iterate HIR tree and set binding annotations on all concrete types [avoids - * path lookups later]) - * - resolve HIR markings (generate "markings" [e.g. for Copy/Send/Sync/...] for all types - * - sort impls (small pass - sort impls into groups) - * - resolve UFCS outer (determine source trait for all top-level ::Type [qualified] paths) - * - resolve UFCS paths (do the same, but include for exprs this time. also normalises results of - * previous pass [expanding known associated types]) - * - constant evaluate (evaluate all constants) - * - typecheck outer (checks impls are sane) - * - typecheck expressions (resolve and check types for all exprs) - * - expand HIR annotate (annotate how exprs are used - used for closure extractions and - * reborrows) - * - expand HIR closures (extract closures into structs implementing Fn* traits) - * - expand HIR vtables (generate vtables for types with dyn dispatch) - * - expand HIR calls (converts method and callable calls into explicit function calls) - * - expand HIR reborrows (apply reborrow rules [taking '&mut *v' instead of 'v']) - * - expand HIR erasedtype (replace all erased types 'impl Trait' with the true type) - * - typecheck expressions (validate - double check that previous passes haven't broke type - * system rules) - * - lower MIR (convert HIR exprs into a control-flow graph [MIR]) - * - MIR validate (check that the generated MIR is consistent) - * - MIR cleanup (perform various transformations on MIR - replace reads of const items with the - * item itself; convert casts to unsized types into 'MakeDst' operations) - * - MIR optimise (perform various simple optimisations on the MIR - constant propagation, dead - * code elimination, borrow elimination, some inlining) - * - MIR validate PO (re-validate the MIR) - * - MIR validate full (optionally: perform expensive state-tracking validation on MIR) - * - trans enumerate (enumerate all items needed for code generation, primarily types used for - * generics) - * - trans auto impls (create magic trait impls as enumerated in previous pass) - * - trans monomorph (generate monomorphised copies of all functions [with generics replaced with - * real types]) - * - MIR optimise inline (run optimisation again, this time with full type info [primarily for - * inlining]) - * - HIR serialise (write out HIR dump [module tree and generic/inline MIR]) - * - trans codegen (generate final output file: emit C source file and call C compiler) */ - - /* rustc compile pipeline (basic, in way less detail): - * - parse input (parse .rs to AST) - * - name resolution, macro expansion, and configuration (process AST recursively, resolving - * paths, expanding macros, processing #[cfg] nodes [i.e. maybe stripping stuff from AST]) - * - lower to HIR - * - type check and other analyses (e.g. privacy checking) - * - lower to MIR and post-processing (and do stuff like borrow checking) - * - translation to LLVM IR and LLVM optimisations (produce the .o files) - * - linking (link together .o files) */ - - /* Pierced-together rustc compile pipeline (from source): - * - parse input (parse file to crate) - * - register plugins (attributes injection, set various options, register lints, load plugins) - * - expansion/configure and expand (initial 'cfg' processing, 'loading compiler plugins', - * syntax expansion, secondary 'cfg' expansion, synthesis of a test harness if required, - * injection of any std lib dependency and prelude, and name resolution) - actually documented - * inline - * - seeming pierced-together order: pre-AST expansion lint checks, registering builtin - * macros, crate injection, then expand all macros, then maybe build test harness, AST validation, - * maybe create a macro crate (if not rustdoc), name resolution, complete gated feature - * checking, add all buffered lints - * - create global context (lower to HIR) - * - analysis on global context (HIR optimisations? create MIR?) - * - code generation - * - link */ -} \ No newline at end of file diff --git a/gcc/rust/test3/rust-session-manager.h b/gcc/rust/test3/rust-session-manager.h deleted file mode 100644 index c268453..0000000 --- a/gcc/rust/test3/rust-session-manager.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef RUST_SESSION_MANAGER_H -#define RUST_SESSION_MANAGER_H -// Session manager - controls compiler session. - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "options.h" -// order: config, system, coretypes, options - -#include -#include -#include -#include -#include - -namespace Rust { - // parser forward decl - class Parser; - // crate forward decl - namespace AST { - struct Crate; - } - - // Data related to target, most useful for conditional compilation and whatever. - struct TargetOptions { - // TODO: maybe make private and access through helpers to allow changes to impl - std::unordered_map> features; - - public: - // Returns whether a key is defined in the feature set. - bool has_key(std::string key) const { - return features.find(key) != features.end(); - } - - // Returns whether a key exists with the given value in the feature set. - bool has_key_value_pair(std::string key, std::string value) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - auto it2 = set.find(value); - if (it2 != set.end()) - return true; - } - return false; - } - - // Returns the singular value from the key, or if the key has multiple, an empty string. - std::string get_singular_value(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - if (set.size() == 1) - return *set.begin(); - } - return ""; - } - - // Returns all values associated with a key (including none), or an empty set if no key is found. - std::unordered_set< ::std::string> get_values_for_key(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - return it->second; - } - return {}; - } - - /* Inserts a key (no value) into the feature set. This will do nothing if the key already exists. - * This returns whether the insertion was successful (i.e. whether key already existed). */ - bool insert_key(std::string key) { - return features.insert(std::make_pair(key, std::unordered_set())).second; - } - - // Inserts a key-value pair into the feature set. - void insert_key_value_pair(std::string key, std::string value) { - auto existing_set = get_values_for_key(key); - existing_set.insert(std::move(value)); - features[std::move(key)] = std::move(existing_set); - } - - /* According to reference, Rust uses either multi-map key-values or just values (although - * values may be aliases for a key-value value). This seems like overkill. Thus, depending on - * whether the attributes used in cfg are fixed or not, I think I'll either put each - * non-multimap "key-value" as a separate field and have the multimap "key-values" in a - * regular map for that one key, or actually use a multimap. - * - * rustc itself uses a set of key-value tuples where the second tuple element is optional. - * This gets rid of the requirement to make a multi-map, I guess, but seems like it might make - * search slow (unless all "is defined"-only ones have empty string as second element). */ - /* cfg attributes: - * - target_arch: single value - * - target_feature: multiple values possible - * - target_os: single value - * - target_family: single value (or no value?) - * - unix: set when target_family = "unix" - * - windows: set when target_family = "windows" - * - if these are just syntactic sugar, then maybe have a separate set or map for this kind - * of stuff - * - target_env: set when needed for disambiguation about ABI - usually empty string for GNU, - * complicated - * - seems to be a single value (if any) - * - target_endian: single value; "little" or "big" - * - target_pointer_width: single value, "32" for 32-bit pointers, etc. - * - target_vendor, single value - * - test: set when testing is being done - * - again, seems similar to a "is defined" rather than "is equal to" like unix - * - debug_assertions: seems to "is defined" - * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" */ - }; - - // Defines compiler options (e.g. dump, etc.). - struct CompileOptions { - // TODO: use bitfield for smaller memory requirements? - - // FIXME: this is set up for "instead of" dumping - in future, dumps should not inhibit - // compilation - enum DumpOptions { - NO_DUMP, - LEXER_DUMP, - PARSER_AST_DUMP, - REGISTER_PLUGINS_DUMP, - INJECTION_DUMP, - EXPANSION_DUMP, - NAME_RESOLUTION_DUMP, - // TODO: add more? - } dump_option; - - // configuration options - actually useful for conditional compilation and whatever - // data related to target arch, features, os, family, env, endian, pointer width, vendor - TargetOptions target_data; - bool enable_test = false; - bool debug_assertions = false; - bool proc_macro = false; - }; - - /* Defines a compiler session. This is for a single compiler invocation, so potentially includes - * parsing multiple crates. */ - struct Session { - CompileOptions options; - // This should really be in a per-crate storage area but it is wiped with every file so eh. - ::std::string injected_crate_name; - - public: - /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). Note that this is - * called after option handling. */ - void init(); - bool handle_option(enum opt_code code, const char* arg, HOST_WIDE_INT value, int kind, - location_t loc, const struct cl_option_handlers* handlers); - void parse_files(int num_files, const char** files); - void init_options(); - - private: - // TODO: should this be private or public? - void parse_file(const char* filename); - bool enable_dump(::std::string arg); - - void debug_dump_load_crates(Parser& parser); - - void implicitly_enable_feature(::std::string feature_name); - void enable_features(); - - // pipeline stages - TODO maybe move? - /* Register plugins pipeline stage. TODO maybe move to another object? Currently dummy stage. - * In future will handle attribute injection (top-level inner attribute creation from command - * line arguments), setting options maybe, registering lints maybe, loading plugins maybe. */ - void register_plugins(AST::Crate& crate); - /* Injection pipeline stage. TODO maybe move to another object? Maybe have some lint checks - * (in future, obviously), register builtin macros, crate injection. */ - void injection(AST::Crate& crate); - /* Expansion pipeline stage. TODO maybe move to another object? Expands all macros, maybe - * build test harness in future, AST validation, maybe create macro crate (if not rustdoc).*/ - void expansion(AST::Crate& crate); - /* Name resolution pipeline stage. TODO maybe move to another object. Performs name - * resolution, maybe complete gated feature checking, maybe create buffered lints in future. - */ - void name_resolution(AST::Crate& crate); - }; -} - -#endif \ No newline at end of file diff --git a/gcc/testsuite/rust.test/alias-uninit-value.rs b/gcc/testsuite/rust.test/alias-uninit-value.rs deleted file mode 100644 index ab39546..0000000 --- a/gcc/testsuite/rust.test/alias-uninit-value.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// Regression test for issue #374 - -enum sty { ty_nil, } - -struct RawT {struct_: sty, cname: Option<~str>, hash: uint} - -fn mk_raw_ty(st: sty, cname: Option<~str>) -> RawT { - return RawT {struct_: st, cname: cname, hash: 0u}; -} - -pub fn main() { mk_raw_ty(ty_nil, None::<~str>); } diff --git a/gcc/testsuite/rust.test/alignment-gep-tup-like-1.rs b/gcc/testsuite/rust.test/alignment-gep-tup-like-1.rs deleted file mode 100644 index 873eb66..0000000 --- a/gcc/testsuite/rust.test/alignment-gep-tup-like-1.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct pair { - a: A, b: B -} - -trait Invokable { - fn f(&self) -> (A, u16); -} - -struct Invoker { - a: A, - b: u16, -} - -impl Invokable for Invoker { - fn f(&self) -> (A, u16) { - (self.a.clone(), self.b) - } -} - -fn f(a: A, b: u16) -> @Invokable { - @Invoker { - a: a, - b: b, - } as @Invokable -} - -pub fn main() { - let (a, b) = f(22_u64, 44u16).f(); - info2!("a={:?} b={:?}", a, b); - assert_eq!(a, 22u64); - assert_eq!(b, 44u16); -} diff --git a/gcc/testsuite/rust.test/alignment-gep-tup-like-2.rs b/gcc/testsuite/rust.test/alignment-gep-tup-like-2.rs deleted file mode 100644 index 7c43385..0000000 --- a/gcc/testsuite/rust.test/alignment-gep-tup-like-2.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair { - a: A, b: B -} - -struct RecEnum(Rec); -struct Rec { - val: A, - rec: Option<@mut RecEnum> -} - -fn make_cycle(a: A) { - let g: @mut RecEnum = @mut RecEnum(Rec {val: a, rec: None}); - g.rec = Some(g); -} - -struct Invoker { - a: A, - b: B, -} - -trait Invokable { - fn f(&self) -> (A, B); -} - -impl Invokable for Invoker { - fn f(&self) -> (A, B) { - (self.a.clone(), self.b.clone()) - } -} - -fn f( - a: A, - b: B) - -> @Invokable { - @Invoker { - a: a, - b: b, - } as @Invokable -} - -pub fn main() { - let x = 22_u8; - let y = 44_u64; - let z = f(~x, y); - make_cycle(z); - let (a, b) = z.f(); - info2!("a={} b={}", *a as uint, b as uint); - assert_eq!(*a, x); - assert_eq!(b, y); -} diff --git a/gcc/testsuite/rust.test/alloca-from-derived-tydesc.rs b/gcc/testsuite/rust.test/alloca-from-derived-tydesc.rs deleted file mode 100644 index ddaa382..0000000 --- a/gcc/testsuite/rust.test/alloca-from-derived-tydesc.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum option { some(T), none, } - -struct R {v: ~[option]} - -fn f() -> ~[T] { return ~[]; } - -pub fn main() { let mut r: R = R {v: ~[]}; r.v = f(); } diff --git a/gcc/testsuite/rust.test/anon-extern-mod-cross-crate-2.rs b/gcc/testsuite/rust.test/anon-extern-mod-cross-crate-2.rs deleted file mode 100644 index 45e544c..0000000 --- a/gcc/testsuite/rust.test/anon-extern-mod-cross-crate-2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:anon-extern-mod-cross-crate-1.rs -extern mod anonexternmod; - -use anonexternmod::rust_get_test_int; - -#[fixed_stack_segment] -pub fn main() { - unsafe { - rust_get_test_int(); - } -} diff --git a/gcc/testsuite/rust.test/anon-extern-mod.rs b/gcc/testsuite/rust.test/anon-extern-mod.rs deleted file mode 100644 index 343e9b9..0000000 --- a/gcc/testsuite/rust.test/anon-extern-mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -#[link_name = "rustrt"] -extern { - fn rust_get_test_int() -> libc::intptr_t; -} - -#[fixed_stack_segment] -pub fn main() { - unsafe { - let _ = rust_get_test_int(); - } -} diff --git a/gcc/testsuite/rust.test/anon-trait-static-method.rs b/gcc/testsuite/rust.test/anon-trait-static-method.rs deleted file mode 100644 index 843e943..0000000 --- a/gcc/testsuite/rust.test/anon-trait-static-method.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int -} - -impl Foo { - pub fn new() -> Foo { - Foo { x: 3 } - } -} - -pub fn main() { - let x = Foo::new(); - println(x.x.to_str()); -} diff --git a/gcc/testsuite/rust.test/anon_trait_static_method_exe.rs b/gcc/testsuite/rust.test/anon_trait_static_method_exe.rs deleted file mode 100644 index 5780a4e..0000000 --- a/gcc/testsuite/rust.test/anon_trait_static_method_exe.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:anon_trait_static_method_lib.rs - -extern mod anon_trait_static_method_lib; -use anon_trait_static_method_lib::Foo; - -pub fn main() { - let x = Foo::new(); - println(x.x.to_str()); -} diff --git a/gcc/testsuite/rust.test/argument-passing.rs b/gcc/testsuite/rust.test/argument-passing.rs deleted file mode 100644 index 6d6ae3d..0000000 --- a/gcc/testsuite/rust.test/argument-passing.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -struct X { - x: int -} - -fn f1(a: &mut X, b: &mut int, c: int) -> int { - let r = a.x + *b + c; - a.x = 0; - *b = 10; - return r; -} - -fn f2(a: int, f: &fn(int)) -> int { f(1); return a; } - -pub fn main() { - let mut a = X {x: 1}; - let mut b = 2; - let c = 3; - assert_eq!(f1(&mut a, &mut b, c), 6); - assert_eq!(a.x, 0); - assert_eq!(b, 10); - assert_eq!(f2(a.x, |_| a.x = 50), 0); - assert_eq!(a.x, 50); -} diff --git a/gcc/testsuite/rust.test/arith-0.rs b/gcc/testsuite/rust.test/arith-0.rs deleted file mode 100644 index 9944241..0000000 --- a/gcc/testsuite/rust.test/arith-0.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let a: int = 10; - info2!("{}", a); - assert_eq!(a * (a - 1), 90); -} diff --git a/gcc/testsuite/rust.test/arith-1.rs b/gcc/testsuite/rust.test/arith-1.rs deleted file mode 100644 index db8f0ea..0000000 --- a/gcc/testsuite/rust.test/arith-1.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let i32_a: int = 10; - assert_eq!(i32_a, 10); - assert_eq!(i32_a - 10, 0); - assert_eq!(i32_a / 10, 1); - assert_eq!(i32_a - 20, -10); - assert_eq!(i32_a << 10, 10240); - assert_eq!(i32_a << 16, 655360); - assert_eq!(i32_a * 16, 160); - assert_eq!(i32_a * i32_a * i32_a, 1000); - assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000); - assert_eq!(i32_a * i32_a / i32_a * i32_a, 100); - assert_eq!(i32_a * (i32_a - 1) << 2 + i32_a, 368640); - let i32_b: int = 0x10101010; - assert_eq!(i32_b + 1 - 1, i32_b); - assert_eq!(i32_b << 1, i32_b << 1); - assert_eq!(i32_b >> 1, i32_b >> 1); - assert_eq!(i32_b & i32_b << 1, 0); - info2!("{}", i32_b | i32_b << 1); - assert_eq!(i32_b | i32_b << 1, 0x30303030); -} diff --git a/gcc/testsuite/rust.test/arith-2.rs b/gcc/testsuite/rust.test/arith-2.rs deleted file mode 100644 index 70df6e4..0000000 --- a/gcc/testsuite/rust.test/arith-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let i32_c: int = 0x10101010; - assert!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3) == - i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3)); -} diff --git a/gcc/testsuite/rust.test/arith-unsigned.rs b/gcc/testsuite/rust.test/arith-unsigned.rs deleted file mode 100644 index ae94ad3..0000000 --- a/gcc/testsuite/rust.test/arith-unsigned.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(type_limits)]; - -// Unsigned integer operations -pub fn main() { - assert!((0u8 < 255u8)); - assert!((0u8 <= 255u8)); - assert!((255u8 > 0u8)); - assert!((255u8 >= 0u8)); - assert_eq!(250u8 / 10u8, 25u8); - assert_eq!(255u8 % 10u8, 5u8); - assert!((0u16 < 60000u16)); - assert!((0u16 <= 60000u16)); - assert!((60000u16 > 0u16)); - assert!((60000u16 >= 0u16)); - assert_eq!(60000u16 / 10u16, 6000u16); - assert_eq!(60005u16 % 10u16, 5u16); - assert!((0u32 < 4000000000u32)); - assert!((0u32 <= 4000000000u32)); - assert!((4000000000u32 > 0u32)); - assert!((4000000000u32 >= 0u32)); - assert_eq!(4000000000u32 / 10u32, 400000000u32); - assert_eq!(4000000005u32 % 10u32, 5u32); - // 64-bit numbers have some flakiness yet. Not tested - -} diff --git a/gcc/testsuite/rust.test/artificial-block.rs b/gcc/testsuite/rust.test/artificial-block.rs deleted file mode 100644 index 7bc1354..0000000 --- a/gcc/testsuite/rust.test/artificial-block.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() -> int { { return 3; } } - -pub fn main() { assert!((f() == 3)); } diff --git a/gcc/testsuite/rust.test/asm-out-assign.rs b/gcc/testsuite/rust.test/asm-out-assign.rs deleted file mode 100644 index 2e1fc65..0000000 --- a/gcc/testsuite/rust.test/asm-out-assign.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] -pub fn main() { - let x: int; - unsafe { - // Treat the output as initialization. - asm!("mov $1, $0" : "=r"(x) : "r"(5u)); - } - assert_eq!(x, 5); - - let mut x = x + 1; - assert_eq!(x, 6); - - unsafe { - // Assignment to mutable. - asm!("mov $1, $0" : "=r"(x) : "r"(x + 7)); - } - assert_eq!(x, 13); -} - -#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))] -pub fn main() {} diff --git a/gcc/testsuite/rust.test/assert-approx-eq-macro-success.rs b/gcc/testsuite/rust.test/assert-approx-eq-macro-success.rs deleted file mode 100644 index 3ea1f89..0000000 --- a/gcc/testsuite/rust.test/assert-approx-eq-macro-success.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - assert_approx_eq!(1.0f64, 1.0); - assert_approx_eq!(1.0000001f64, 1.0); - assert_approx_eq!(1.0000001f64, 1.0, 1.0e-6); - assert_approx_eq!(1.000001f64, 1.0, 1.0e-5); -} diff --git a/gcc/testsuite/rust.test/assert-eq-macro-success.rs b/gcc/testsuite/rust.test/assert-eq-macro-success.rs deleted file mode 100644 index 047c339..0000000 --- a/gcc/testsuite/rust.test/assert-eq-macro-success.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Point { x : int } - -pub fn main() { - assert_eq!(14,14); - assert_eq!(~"abc",~"abc"); - assert_eq!(~Point{x:34},~Point{x:34}); - assert_eq!(&Point{x:34},&Point{x:34}); - assert_eq!(@Point{x:34},@Point{x:34}); -} diff --git a/gcc/testsuite/rust.test/assign-assign.rs b/gcc/testsuite/rust.test/assign-assign.rs deleted file mode 100644 index 0f5d270..0000000 --- a/gcc/testsuite/rust.test/assign-assign.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue 483 - Assignment expressions result in nil -fn test_assign() { - let mut x: int; - let y: () = x = 10; - assert_eq!(x, 10); - assert_eq!(y, ()); - let mut z = x = 11; - assert_eq!(x, 11); - assert_eq!(z, ()); - z = x = 12; - assert_eq!(x, 12); - assert_eq!(z, ()); -} - -fn test_assign_op() { - let mut x: int = 0; - let y: () = x += 10; - assert_eq!(x, 10); - assert_eq!(y, ()); - let mut z = x += 11; - assert_eq!(x, 21); - assert_eq!(z, ()); - z = x += 12; - assert_eq!(x, 33); - assert_eq!(z, ()); -} - -pub fn main() { test_assign(); test_assign_op(); } diff --git a/gcc/testsuite/rust.test/assignability-trait.rs b/gcc/testsuite/rust.test/assignability-trait.rs deleted file mode 100644 index 5269f7d..0000000 --- a/gcc/testsuite/rust.test/assignability-trait.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that type assignability is used to search for instances when -// making method calls, but only if there aren't any matches without -// it. - -trait iterable { - fn iterate(&self, blk: &fn(x: &A) -> bool) -> bool; -} - -impl<'self,A> iterable for &'self [A] { - fn iterate(&self, f: &fn(x: &A) -> bool) -> bool { - self.iter().advance(f) - } -} - -impl iterable for ~[A] { - fn iterate(&self, f: &fn(x: &A) -> bool) -> bool { - self.iter().advance(f) - } -} - -fn length>(x: T) -> uint { - let mut len = 0; - do x.iterate() |_y| { len += 1; true }; - return len; -} - -pub fn main() { - let x = ~[0,1,2,3]; - // Call a method - do x.iterate() |y| { assert!(x[*y] == *y); true }; - // Call a parameterized function - assert_eq!(length(x.clone()), x.len()); - // Call a parameterized function, with type arguments that require - // a borrow - assert_eq!(length::(x), x.len()); - - // Now try it with a type that *needs* to be borrowed - let z = [0,1,2,3]; - // Call a method - do z.iterate() |y| { assert!(z[*y] == *y); true }; - // Call a parameterized function - assert_eq!(length::(z), z.len()); -} diff --git a/gcc/testsuite/rust.test/attr-before-view-item.rs b/gcc/testsuite/rust.test/attr-before-view-item.rs deleted file mode 100644 index 316f8fa..0000000 --- a/gcc/testsuite/rust.test/attr-before-view-item.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:expected item - -#[foo = "bar"] -extern mod extra; - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/attr-before-view-item2.rs b/gcc/testsuite/rust.test/attr-before-view-item2.rs deleted file mode 100644 index 0721544..0000000 --- a/gcc/testsuite/rust.test/attr-before-view-item2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:expected item - -mod m { - #[foo = "bar"] - extern mod extra; -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/attr-main-2.rs b/gcc/testsuite/rust.test/attr-main-2.rs deleted file mode 100644 index 6078698..0000000 --- a/gcc/testsuite/rust.test/attr-main-2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -pub fn main() { - fail2!() -} - -#[main] -fn foo() { -} diff --git a/gcc/testsuite/rust.test/attr-main.rs b/gcc/testsuite/rust.test/attr-main.rs deleted file mode 100644 index 10de96c..0000000 --- a/gcc/testsuite/rust.test/attr-main.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -#[main] -fn foo() { -} diff --git a/gcc/testsuite/rust.test/attr-no-drop-flag-size.rs b/gcc/testsuite/rust.test/attr-no-drop-flag-size.rs deleted file mode 100644 index 48768a1..0000000 --- a/gcc/testsuite/rust.test/attr-no-drop-flag-size.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem::size_of; - -#[unsafe_no_drop_flag] -struct Test { - a: T -} - -#[unsafe_destructor] -impl Drop for Test { - fn drop(&mut self) { } -} - -pub fn main() { - assert_eq!(size_of::(), size_of::>()); -} diff --git a/gcc/testsuite/rust.test/attr-start.rs b/gcc/testsuite/rust.test/attr-start.rs deleted file mode 100644 index ca75af9..0000000 --- a/gcc/testsuite/rust.test/attr-start.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//xfail-fast - -#[start] -fn start(_argc: int, _argv: **u8) -> int { - return 0; -} diff --git a/gcc/testsuite/rust.test/auto-encode.rs b/gcc/testsuite/rust.test/auto-encode.rs deleted file mode 100644 index c162985..0000000 --- a/gcc/testsuite/rust.test/auto-encode.rs +++ /dev/null @@ -1,185 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #6122 - -extern mod extra; - -// These tests used to be separate files, but I wanted to refactor all -// the common code. - -use std::hashmap::{HashMap, HashSet}; - -use EBReader = extra::ebml::reader; -use EBWriter = extra::ebml::writer; -use std::cmp::Eq; -use std::cmp; -use std::io; -use extra::serialize::{Decodable, Encodable}; -use extra::time; - -fn test_ebml + - Decodable ->(a1: &A) { - let bytes = do io::with_bytes_writer |wr| { - let mut ebml_w = EBWriter::Encoder(wr); - a1.encode(&mut ebml_w) - }; - let d = EBReader::Doc(@bytes); - let mut decoder = EBReader::Decoder(d); - let a2: A = Decodable::decode(&mut decoder); - if !(*a1 == a2) { - ::std::sys::FailWithCause::fail_with(~"explicit failure" + "foo", - "auto-encode.rs", 43u); - } - assert!(*a1 == a2); -} - -#[deriving(Decodable, Encodable)] -enum Expr { - Val(uint), - Plus(@Expr, @Expr), - Minus(@Expr, @Expr) -} - -impl cmp::Eq for Expr { - fn eq(&self, other: &Expr) -> bool { - match *self { - Val(e0a) => { - match *other { - Val(e0b) => e0a == e0b, - _ => false - } - } - Plus(e0a, e1a) => { - match *other { - Plus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - Minus(e0a, e1a) => { - match *other { - Minus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - } - } - fn ne(&self, other: &Expr) -> bool { !(*self).eq(other) } -} - -impl cmp::Eq for Point { - fn eq(&self, other: &Point) -> bool { - self.x == other.x && self.y == other.y - } - fn ne(&self, other: &Point) -> bool { !(*self).eq(other) } -} - -impl cmp::Eq for Quark { - fn eq(&self, other: &Quark) -> bool { - match *self { - Top(ref q) => { - match *other { - Top(ref r) => q == r, - Bottom(_) => false - } - }, - Bottom(ref q) => { - match *other { - Top(_) => false, - Bottom(ref r) => q == r - } - }, - } - } - fn ne(&self, other: &Quark) -> bool { !(*self).eq(other) } -} - -impl cmp::Eq for CLike { - fn eq(&self, other: &CLike) -> bool { - (*self) as int == *other as int - } - fn ne(&self, other: &CLike) -> bool { !self.eq(other) } -} - -#[deriving(Decodable, Encodable, Eq)] -struct Spanned { - lo: uint, - hi: uint, - node: T, -} - -#[deriving(Decodable, Encodable)] -struct SomeStruct { v: ~[uint] } - -#[deriving(Decodable, Encodable)] -struct Point {x: uint, y: uint} - -#[deriving(Decodable, Encodable)] -enum Quark { - Top(T), - Bottom(T) -} - -#[deriving(Decodable, Encodable)] -enum CLike { A, B, C } - -pub fn main() { - let a = &Plus(@Minus(@Val(3u), @Val(10u)), @Plus(@Val(22u), @Val(5u))); - test_ebml(a); - -// let a = &Spanned {lo: 0u, hi: 5u, node: 22u}; -// test_ebml(a); - -// let a = &Point {x: 3u, y: 5u}; -// test_ebml(a); -// -// let a = &@[1u, 2u, 3u]; -// test_ebml(a); -// -// let a = &Top(22u); -// test_ebml(a); -// -// let a = &Bottom(222u); -// test_ebml(a); -// -// let a = &A; -// test_ebml(a); -// -// let a = &B; -// test_ebml(a); - - println("Hi1"); - let a = &time::now(); - test_ebml(a); - - println("Hi2"); -// test_ebml(&1.0f32); -// test_ebml(&1.0f64); - test_ebml(&1.0f); -// println("Hi3"); -// test_ebml(&'a'); - - println("Hi4"); - let mut a = HashMap::new(); - test_ebml(&a); - a.insert(1, 2); - println("Hi4"); - test_ebml(&a); - -// let mut a = HashSet::new(); -// test_ebml(&a); -// a.insert(1); -// test_ebml(&a); -} diff --git a/gcc/testsuite/rust.test/auto-instantiate.rs b/gcc/testsuite/rust.test/auto-instantiate.rs deleted file mode 100644 index d839984..0000000 --- a/gcc/testsuite/rust.test/auto-instantiate.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -struct Pair { a: T, b: U } -struct Triple { x: int, y: int, z: int } - -fn f(x: T, y: U) -> Pair { return Pair {a: x, b: y}; } - -pub fn main() { - info2!("{:?}", f(Triple {x: 3, y: 4, z: 5}, 4).a.x); - info2!("{:?}", f(5, 6).a); -} diff --git a/gcc/testsuite/rust.test/auto-loop.rs b/gcc/testsuite/rust.test/auto-loop.rs deleted file mode 100644 index 33aee55..0000000 --- a/gcc/testsuite/rust.test/auto-loop.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut sum = 0; - let xs = ~[1, 2, 3, 4, 5]; - for x in xs.iter() { - sum += *x; - } - assert_eq!(sum, 15); -} diff --git a/gcc/testsuite/rust.test/auto-ref-bounded-ty-param.rs b/gcc/testsuite/rust.test/auto-ref-bounded-ty-param.rs deleted file mode 100644 index bb01c27..0000000 --- a/gcc/testsuite/rust.test/auto-ref-bounded-ty-param.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io; - -trait Foo { - fn f(&self); -} - -struct Bar { - x: int -} - -trait Baz { - fn g(&self); -} - -impl Foo for T { - fn f(&self) { - self.g(); - } -} - -impl Baz for Bar { - fn g(&self) { - io::println(self.x.to_str()); - } -} - -pub fn main() { - let y = Bar { x: 42 }; - y.f(); -} diff --git a/gcc/testsuite/rust.test/auto-ref-newtype.rs b/gcc/testsuite/rust.test/auto-ref-newtype.rs deleted file mode 100644 index 8adc2cf..0000000 --- a/gcc/testsuite/rust.test/auto-ref-newtype.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that we can define inherent methods on newtype enums that use -// an auto-ref'd receiver. - -struct Foo(uint); - -impl Foo { - pub fn len(&self) -> uint { **self } -} - -pub fn main() { - let m = Foo(3); - assert_eq!(m.len(), 3); -} diff --git a/gcc/testsuite/rust.test/auto-ref-slice-plus-ref.rs b/gcc/testsuite/rust.test/auto-ref-slice-plus-ref.rs deleted file mode 100644 index d353415..0000000 --- a/gcc/testsuite/rust.test/auto-ref-slice-plus-ref.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing that method lookup automatically both borrows vectors to slices -// and also references them to create the &self pointer - -trait MyIter { - fn test_imm(&self); -} - -impl<'self> MyIter for &'self [int] { - fn test_imm(&self) { assert_eq!(self[0], 1) } -} - -impl<'self> MyIter for &'self str { - fn test_imm(&self) { assert_eq!(*self, "test") } -} - -pub fn main() { - // NB: Associativity of ~, etc. in this context is surprising. These must be parenthesized - - ([1]).test_imm(); - (~[1]).test_imm(); - (@[1]).test_imm(); - (&[1]).test_imm(); - ("test").test_imm(); - (~"test").test_imm(); - (@"test").test_imm(); - (&"test").test_imm(); - - // XXX: Other types of mutable vecs don't currently exist - - // NB: We don't do this double autoreffing for &mut self because that would - // allow creating a mutable pointer to a temporary, which would be a source - // of confusion -} diff --git a/gcc/testsuite/rust.test/auto-ref-sliceable.rs b/gcc/testsuite/rust.test/auto-ref-sliceable.rs deleted file mode 100644 index 8e2b3b5..0000000 --- a/gcc/testsuite/rust.test/auto-ref-sliceable.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Pushable { - fn push_val(&mut self, t: T); -} - -impl Pushable for ~[T] { - fn push_val(&mut self, t: T) { - self.push(t); - } -} - -pub fn main() { - let mut v = ~[1]; - v.push_val(2); - v.push_val(3); - assert_eq!(v, ~[1, 2, 3]); -} diff --git a/gcc/testsuite/rust.test/auto-ref.rs b/gcc/testsuite/rust.test/auto-ref.rs deleted file mode 100644 index 6dc6790..0000000 --- a/gcc/testsuite/rust.test/auto-ref.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int, -} - -trait Stuff { - fn printme(&self); -} - -impl Stuff for Foo { - fn printme(&self) { - println!("{}", self.x); - } -} - -pub fn main() { - let x = Foo { x: 3 }; - x.printme(); -} diff --git a/gcc/testsuite/rust.test/autobind.rs b/gcc/testsuite/rust.test/autobind.rs deleted file mode 100644 index 440ad72..0000000 --- a/gcc/testsuite/rust.test/autobind.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(x: ~[T]) -> T { return x[0]; } - -fn g(act: &fn(~[int]) -> int) -> int { return act(~[1, 2, 3]); } - -pub fn main() { - assert_eq!(g(f), 1); - let f1: &fn(~[~str]) -> ~str = f; - assert_eq!(f1(~[~"x", ~"y", ~"z"]), ~"x"); -} diff --git a/gcc/testsuite/rust.test/autoderef-and-borrow-method-receiver.rs b/gcc/testsuite/rust.test/autoderef-and-borrow-method-receiver.rs deleted file mode 100644 index fc643ec..0000000 --- a/gcc/testsuite/rust.test/autoderef-and-borrow-method-receiver.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int, -} - -impl Foo { - pub fn f(&self) {} -} - -fn g(x: &mut Foo) { - x.f(); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/autoderef-method-newtype.rs b/gcc/testsuite/rust.test/autoderef-method-newtype.rs deleted file mode 100644 index e3a19b2..0000000 --- a/gcc/testsuite/rust.test/autoderef-method-newtype.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(&self) -> uint; -} - -impl double for uint { - fn double(&self) -> uint { *self * 2u } -} - -struct foo(uint); - -pub fn main() { - let x = foo(3u); - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoderef-method-on-trait.rs b/gcc/testsuite/rust.test/autoderef-method-on-trait.rs deleted file mode 100644 index 9bc7151..0000000 --- a/gcc/testsuite/rust.test/autoderef-method-on-trait.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(@self) -> uint; -} - -impl double for uint { - fn double(@self) -> uint { *self * 2u } -} - -pub fn main() { - let x = @(@3u as @double); - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoderef-method-priority.rs b/gcc/testsuite/rust.test/autoderef-method-priority.rs deleted file mode 100644 index f9f78aa..0000000 --- a/gcc/testsuite/rust.test/autoderef-method-priority.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(self) -> uint; -} - -impl double for uint { - fn double(self) -> uint { self } -} - -impl double for @uint { - fn double(self) -> uint { *self * 2u } -} - -pub fn main() { - let x = @3u; - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoderef-method-twice-but-not-thrice.rs b/gcc/testsuite/rust.test/autoderef-method-twice-but-not-thrice.rs deleted file mode 100644 index 2997602..0000000 --- a/gcc/testsuite/rust.test/autoderef-method-twice-but-not-thrice.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(@self) -> uint; -} - -impl double for @uint { - fn double(@self) -> uint { **self * 2u } -} - -pub fn main() { - let x = @@@@@3u; - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoderef-method-twice.rs b/gcc/testsuite/rust.test/autoderef-method-twice.rs deleted file mode 100644 index f93f060..0000000 --- a/gcc/testsuite/rust.test/autoderef-method-twice.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(@self) -> uint; -} - -impl double for uint { - fn double(@self) -> uint { *self * 2u } -} - -pub fn main() { - let x = @@3u; - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoderef-method.rs b/gcc/testsuite/rust.test/autoderef-method.rs deleted file mode 100644 index eb173e3..0000000 --- a/gcc/testsuite/rust.test/autoderef-method.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait double { - fn double(@self) -> uint; -} - -impl double for uint { - fn double(@self) -> uint { *self * 2u } -} - -pub fn main() { - let x = @3u; - assert_eq!(x.double(), 6u); -} diff --git a/gcc/testsuite/rust.test/autoref-intermediate-types-issue-3585.rs b/gcc/testsuite/rust.test/autoref-intermediate-types-issue-3585.rs deleted file mode 100644 index 096e437..0000000 --- a/gcc/testsuite/rust.test/autoref-intermediate-types-issue-3585.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn foo(&self) -> ~str; -} - -impl Foo for @T { - fn foo(&self) -> ~str { - format!("@{}", (**self).foo()) - } -} - -impl Foo for uint { - fn foo(&self) -> ~str { - format!("{}", *self) - } -} - -pub fn main() { - let x = @3u; - assert_eq!(x.foo(), ~"@3"); -} diff --git a/gcc/testsuite/rust.test/bare-static-string.rs b/gcc/testsuite/rust.test/bare-static-string.rs deleted file mode 100644 index 9b2855d..0000000 --- a/gcc/testsuite/rust.test/bare-static-string.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x: &'static str = "foo"; - println(x); -} diff --git a/gcc/testsuite/rust.test/big-literals.rs b/gcc/testsuite/rust.test/big-literals.rs deleted file mode 100644 index 96615b7..0000000 --- a/gcc/testsuite/rust.test/big-literals.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-pretty - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - assert_eq!(0xffffffffu32, (-1 as u32)); - assert_eq!(4294967295u32, (-1 as u32)); - assert_eq!(0xffffffffffffffffu64, (-1 as u64)); - assert_eq!(18446744073709551615u64, (-1 as u64)); - - assert_eq!(-2147483648i32 - 1i32, 2147483647i32); - assert_eq!(-9223372036854775808i64 - 1i64, 9223372036854775807i64); -} diff --git a/gcc/testsuite/rust.test/binary-minus-without-space.rs b/gcc/testsuite/rust.test/binary-minus-without-space.rs deleted file mode 100644 index f312cda..0000000 --- a/gcc/testsuite/rust.test/binary-minus-without-space.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that issue #954 stays fixed - -pub fn main() { - match -1 { -1 => {}, _ => fail2!("wat") } - assert_eq!(1-1, 0); -} diff --git a/gcc/testsuite/rust.test/bind-by-move.rs b/gcc/testsuite/rust.test/bind-by-move.rs deleted file mode 100644 index ad55738..0000000 --- a/gcc/testsuite/rust.test/bind-by-move.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -extern mod extra; -use extra::arc; -fn dispose(_x: arc::Arc) { } - -pub fn main() { - let p = arc::Arc::new(true); - let x = Some(p); - match x { - Some(z) => { dispose(z); }, - None => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/binops.rs b/gcc/testsuite/rust.test/binops.rs deleted file mode 100644 index 10a7355..0000000 --- a/gcc/testsuite/rust.test/binops.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Binop corner cases - -fn test_nil() { - assert_eq!((), ()); - assert!((!(() != ()))); - assert!((!(() < ()))); - assert!((() <= ())); - assert!((!(() > ()))); - assert!((() >= ())); -} - -fn test_bool() { - assert!((!(true < false))); - assert!((!(true <= false))); - assert!((true > false)); - assert!((true >= false)); - - assert!((false < true)); - assert!((false <= true)); - assert!((!(false > true))); - assert!((!(false >= true))); - - // Bools support bitwise binops - assert_eq!(false & false, false); - assert_eq!(true & false, false); - assert_eq!(true & true, true); - assert_eq!(false | false, false); - assert_eq!(true | false, true); - assert_eq!(true | true, true); - assert_eq!(false ^ false, false); - assert_eq!(true ^ false, true); - assert_eq!(true ^ true, false); -} - -fn test_box() { - assert_eq!(@10, @10); -} - -fn test_ptr() { - unsafe { - let p1: *u8 = ::std::cast::transmute(0); - let p2: *u8 = ::std::cast::transmute(0); - let p3: *u8 = ::std::cast::transmute(1); - - assert_eq!(p1, p2); - assert!(p1 != p3); - assert!(p1 < p3); - assert!(p1 <= p3); - assert!(p3 > p1); - assert!(p3 >= p3); - assert!(p1 <= p2); - assert!(p1 >= p2); - } -} - -#[deriving(Eq)] -struct p { - x: int, - y: int, -} - -fn p(x: int, y: int) -> p { - p { - x: x, - y: y - } -} - -fn test_class() { - let q = p(1, 2); - let mut r = p(1, 2); - - unsafe { - error2!("q = {:x}, r = {:x}", - (::std::cast::transmute::<*p, uint>(&q)), - (::std::cast::transmute::<*p, uint>(&r))); - } - assert_eq!(q, r); - r.y = 17; - assert!((r.y != q.y)); - assert_eq!(r.y, 17); - assert!((q != r)); -} - -pub fn main() { - test_nil(); - test_bool(); - test_box(); - test_ptr(); - test_class(); -} diff --git a/gcc/testsuite/rust.test/bitv-perf-test.rs b/gcc/testsuite/rust.test/bitv-perf-test.rs deleted file mode 100644 index dcdab0e..0000000 --- a/gcc/testsuite/rust.test/bitv-perf-test.rs +++ /dev/null @@ -1,24 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; -use extra::bitv::Bitv; - -fn bitv_test() { - let mut v1 = ~Bitv::new(31, false); - let v2 = ~Bitv::new(31, true); - v1.union(v2); -} - -pub fn main() { - do 10000.times || {bitv_test()}; -} diff --git a/gcc/testsuite/rust.test/bitwise.rs b/gcc/testsuite/rust.test/bitwise.rs deleted file mode 100644 index b990674..0000000 --- a/gcc/testsuite/rust.test/bitwise.rs +++ /dev/null @@ -1,45 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "arm")] -fn target() { - assert_eq!(-1000 as uint >> 3u, 536870787u); -} - -#[cfg(target_arch = "x86_64")] -fn target() { - assert_eq!(-1000 as uint >> 3u, 2305843009213693827u); -} - -fn general() { - let mut a: int = 1; - let mut b: int = 2; - a ^= b; - b ^= a; - a = a ^ b; - info2!("{}", a); - info2!("{}", b); - assert_eq!(b, 1); - assert_eq!(a, 2); - assert_eq!(!0xf0 & 0xff, 0xf); - assert_eq!(0xf0 | 0xf, 0xff); - assert_eq!(0xf << 4, 0xf0); - assert_eq!(0xf0 >> 4, 0xf); - assert_eq!(-16 >> 2, -4); - assert_eq!(0b1010_1010 | 0b0101_0101, 0xff); -} - -pub fn main() { - general(); - target(); -} diff --git a/gcc/testsuite/rust.test/block-arg-call-as.rs b/gcc/testsuite/rust.test/block-arg-call-as.rs deleted file mode 100644 index 6a59278..0000000 --- a/gcc/testsuite/rust.test/block-arg-call-as.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -fn asSendfn( f : ~fn()->uint ) -> uint { - return f(); -} - -fn asBlock( f : &fn()->uint ) -> uint { - return f(); -} - -pub fn main() { - let x = asSendfn(|| 22u); - assert_eq!(x, 22u); - let x = asBlock(|| 22u); - assert_eq!(x, 22u); -} diff --git a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-binop.rs b/gcc/testsuite/rust.test/block-arg-can-be-followed-by-binop.rs deleted file mode 100644 index e65116f..0000000 --- a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-binop.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let v = ~[-1.0, 0.0, 1.0, 2.0, 3.0]; - - // Trailing expressions don't require parentheses: - let y = do v.iter().fold(0.0) |x, y| { x + *y } + 10.0; - - assert_eq!(y, 15.0); -} diff --git a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-block-arg.rs b/gcc/testsuite/rust.test/block-arg-can-be-followed-by-block-arg.rs deleted file mode 100644 index ed8641e..0000000 --- a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-block-arg.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - fn f(i: &fn() -> uint) -> uint { i() } - let v = ~[-1.0, 0.0, 1.0, 2.0, 3.0]; - let z = do do v.iter().fold(f) |x, _y| { x } { 22u }; - assert_eq!(z, 22u); -} diff --git a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-call.rs b/gcc/testsuite/rust.test/block-arg-can-be-followed-by-call.rs deleted file mode 100644 index 1bb16f6..0000000 --- a/gcc/testsuite/rust.test/block-arg-can-be-followed-by-call.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - fn f(i: uint) -> uint { i } - let v = ~[-1.0, 0.0, 1.0, 2.0, 3.0]; - let z = do v.iter().fold(f) |x, _y| { x } (22u); - assert_eq!(z, 22u); -} diff --git a/gcc/testsuite/rust.test/block-arg-in-parentheses.rs b/gcc/testsuite/rust.test/block-arg-in-parentheses.rs deleted file mode 100644 index fcd6a8d..0000000 --- a/gcc/testsuite/rust.test/block-arg-in-parentheses.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn w_semi(v: ~[int]) -> int { - // the semicolon causes compiler not to - // complain about the ignored return value: - do v.iter().fold(0) |x,y| { x+*y }; - -10 -} - -fn w_paren1(v: ~[int]) -> int { - (do v.iter().fold(0) |x,y| { x+*y }) - 10 -} - -fn w_paren2(v: ~[int]) -> int { - (do v.iter().fold(0) |x,y| { x+*y} - 10) -} - -fn w_ret(v: ~[int]) -> int { - return do v.iter().fold(0) |x,y| { x+*y } - 10; -} - -pub fn main() { - assert_eq!(w_semi(~[0, 1, 2, 3]), -10); - assert_eq!(w_paren1(~[0, 1, 2, 3]), -4); - assert_eq!(w_paren2(~[0, 1, 2, 3]), -4); - assert_eq!(w_ret(~[0, 1, 2, 3]), -4); -} diff --git a/gcc/testsuite/rust.test/block-arg-used-as-any.rs b/gcc/testsuite/rust.test/block-arg-used-as-any.rs deleted file mode 100644 index 7ee9d9e..0000000 --- a/gcc/testsuite/rust.test/block-arg-used-as-any.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn call_any(f: &fn() -> uint) -> uint { - return f(); -} - -pub fn main() { - let x_r = do call_any { 22u }; - assert_eq!(x_r, 22u); -} diff --git a/gcc/testsuite/rust.test/block-arg.rs b/gcc/testsuite/rust.test/block-arg.rs deleted file mode 100644 index c296a37..0000000 --- a/gcc/testsuite/rust.test/block-arg.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check usage and precedence of block arguments in expressions: -pub fn main() { - let v = ~[-1.0f64, 0.0, 1.0, 2.0, 3.0]; - - // Statement form does not require parentheses: - for i in v.iter() { - info2!("{:?}", *i); - } - - // Usable at all: - let mut any_negative = do v.iter().any |e| { e.is_negative() }; - assert!(any_negative); - - // Higher precedence than assignments: - any_negative = do v.iter().any |e| { e.is_negative() }; - assert!(any_negative); - - // Higher precedence than unary operations: - let abs_v = do v.iter().map |e| { e.abs() }.collect::<~[f64]>(); - assert!(do abs_v.iter().all |e| { e.is_positive() }); - assert!(!do abs_v.iter().any |e| { e.is_negative() }); - - // Usable in funny statement-like forms: - if !do v.iter().any |e| { e.is_positive() } { - assert!(false); - } - match do v.iter().all |e| { e.is_negative() } { - true => { fail2!("incorrect answer."); } - false => { } - } - match 3 { - _ if do v.iter().any |e| { e.is_negative() } => { - } - _ => { - fail2!("wrong answer."); - } - } - - - // Lower precedence than binary operations: - let w = do v.iter().fold(0.0) |x, y| { x + *y } + 10.0; - let y = do v.iter().fold(0.0) |x, y| { x + *y } + 10.0; - let z = 10.0 + do v.iter().fold(0.0) |x, y| { x + *y }; - assert_eq!(w, y); - assert_eq!(y, z); - - // In the tail of a block - let w = - if true { do abs_v.iter().any |e| { e.is_positive() } } - else { false }; - assert!(w); -} diff --git a/gcc/testsuite/rust.test/block-explicit-types.rs b/gcc/testsuite/rust.test/block-explicit-types.rs deleted file mode 100644 index 1931ec5..0000000 --- a/gcc/testsuite/rust.test/block-explicit-types.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - fn as_buf(s: ~str, f: &fn(~str) -> T) -> T { f(s) } - as_buf(~"foo", |foo: ~str| -> () error2!("{}", foo) ); -} diff --git a/gcc/testsuite/rust.test/block-expr-precedence.rs b/gcc/testsuite/rust.test/block-expr-precedence.rs deleted file mode 100644 index ace372d..0000000 --- a/gcc/testsuite/rust.test/block-expr-precedence.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test has some extra semis in it that the pretty-printer won't -// reproduce so we don't want to automatically reformat it - -// no-reformat - -/* - * - * When you write a block-expression thing followed by - * a lone unary operator, you can get a surprising parse: - * - * if (...) { ... } - * -num; - * - * for example, or: - * - * if (...) { ... } - * *box; - * - * These will parse as subtraction and multiplication binops. - * To get them to parse "the way you want" you need to brace - * the leading unops: - - * if (...) { ... } - * {-num}; - * - * or alternatively, semi-separate them: - * - * if (...) { ... }; - * -num; - * - * This seems a little wonky, but the alternative is to lower - * precedence of such block-like exprs to the point where - * you have to parenthesize them to get them to occur in the - * RHS of a binop. For example, you'd have to write: - * - * 12 + (if (foo) { 13 } else { 14 }); - * - * rather than: - * - * 12 + if (foo) { 13 } else { 14 }; - * - * Since we want to maintain the ability to write the latter, - * we leave the parens-burden on the trailing unop case. - * - */ - -pub fn main() { - - let num = 12; - - assert_eq!(if (true) { 12 } else { 12 } - num, 0); - assert_eq!(12 - if (true) { 12 } else { 12 }, 0); - if (true) { 12; } {-num}; - if (true) { 12; }; {-num}; - if (true) { 12; };;; -num; -} diff --git a/gcc/testsuite/rust.test/block-fn-coerce.rs b/gcc/testsuite/rust.test/block-fn-coerce.rs deleted file mode 100644 index 19e1fd4..0000000 --- a/gcc/testsuite/rust.test/block-fn-coerce.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn force(f: &fn() -> int) -> int { return f(); } -pub fn main() { - fn f() -> int { return 7; } - assert_eq!(force(f), 7); - let g = {||force(f)}; - assert_eq!(g(), 7); -} diff --git a/gcc/testsuite/rust.test/block-iter-1.rs b/gcc/testsuite/rust.test/block-iter-1.rs deleted file mode 100644 index 806ed03..0000000 --- a/gcc/testsuite/rust.test/block-iter-1.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn iter_vec(v: ~[T], f: &fn(&T)) { for x in v.iter() { f(x); } } - -pub fn main() { - let v = ~[1, 2, 3, 4, 5, 6, 7]; - let mut odds = 0; - iter_vec(v, |i| { - if *i % 2 == 1 { - odds += 1; - } - }); - error2!("{:?}", odds); - assert_eq!(odds, 4); -} diff --git a/gcc/testsuite/rust.test/block-iter-2.rs b/gcc/testsuite/rust.test/block-iter-2.rs deleted file mode 100644 index c84033e..0000000 --- a/gcc/testsuite/rust.test/block-iter-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn iter_vec(v: ~[T], f: &fn(&T)) { for x in v.iter() { f(x); } } - -pub fn main() { - let v = ~[1, 2, 3, 4, 5]; - let mut sum = 0; - iter_vec(v.clone(), |i| { - iter_vec(v.clone(), |j| { - sum += *i * *j; - }); - }); - error2!("{:?}", sum); - assert_eq!(sum, 225); -} diff --git a/gcc/testsuite/rust.test/bool-not.rs b/gcc/testsuite/rust.test/bool-not.rs deleted file mode 100644 index 3d659d5..0000000 --- a/gcc/testsuite/rust.test/bool-not.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - if !false { assert!((true)); } else { assert!((false)); } - if !true { assert!((false)); } else { assert!((true)); } -} diff --git a/gcc/testsuite/rust.test/borrow-by-val-method-receiver.rs b/gcc/testsuite/rust.test/borrow-by-val-method-receiver.rs deleted file mode 100644 index fb4316c..0000000 --- a/gcc/testsuite/rust.test/borrow-by-val-method-receiver.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn foo(self); -} - -impl<'self> Foo for &'self [int] { - fn foo(self) {} -} - -pub fn main() { - let items = ~[ 3, 5, 1, 2, 4 ]; - items.foo(); -} diff --git a/gcc/testsuite/rust.test/borrowck-binding-mutbl.rs b/gcc/testsuite/rust.test/borrowck-binding-mutbl.rs deleted file mode 100644 index 377ed26..0000000 --- a/gcc/testsuite/rust.test/borrowck-binding-mutbl.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct F { f: ~[int] } - -fn impure(_v: &[int]) { -} - -pub fn main() { - let mut x = F {f: ~[3]}; - - match x { - F {f: ref mut v} => { - impure(*v); - } - } -} diff --git a/gcc/testsuite/rust.test/borrowck-borrow-from-at-vec.rs b/gcc/testsuite/rust.test/borrowck-borrow-from-at-vec.rs deleted file mode 100644 index 8ec1b59..0000000 --- a/gcc/testsuite/rust.test/borrowck-borrow-from-at-vec.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn sum_slice(x: &[int]) -> int { - let mut sum = 0; - for i in x.iter() { sum += *i; } - return sum; -} - -pub fn main() { - let x = @[1, 2, 3]; - assert_eq!(sum_slice(x), 6); -} diff --git a/gcc/testsuite/rust.test/borrowck-borrow-from-expr-block.rs b/gcc/testsuite/rust.test/borrowck-borrow-from-expr-block.rs deleted file mode 100644 index d6d4407..0000000 --- a/gcc/testsuite/rust.test/borrowck-borrow-from-expr-block.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow; -use std::ptr; - -fn borrow(x: &int, f: &fn(x: &int)) { - f(x) -} - -fn test1(x: @~int) { - do borrow(&*(*x).clone()) |p| { - let x_a = ptr::to_unsafe_ptr(&**x); - assert!((x_a as uint) != borrow::to_uint(p)); - assert_eq!(unsafe{*x_a}, *p); - } -} - -pub fn main() { - test1(@~22); -} diff --git a/gcc/testsuite/rust.test/borrowck-fixed-length-vecs.rs b/gcc/testsuite/rust.test/borrowck-fixed-length-vecs.rs deleted file mode 100644 index ee561fd..0000000 --- a/gcc/testsuite/rust.test/borrowck-fixed-length-vecs.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = [22]; - let y = &x[0]; - assert_eq!(*y, 22); -} diff --git a/gcc/testsuite/rust.test/borrowck-lend-args.rs b/gcc/testsuite/rust.test/borrowck-lend-args.rs deleted file mode 100644 index a912e1e..0000000 --- a/gcc/testsuite/rust.test/borrowck-lend-args.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn borrow(_v: &int) {} - -fn borrow_from_arg_imm_ref(v: ~int) { - borrow(v); -} - -fn borrow_from_arg_mut_ref(v: &mut ~int) { - borrow(*v); -} - -fn borrow_from_arg_copy(v: ~int) { - borrow(v); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/borrowck-macro-interaction-issue-6304.rs b/gcc/testsuite/rust.test/borrowck-macro-interaction-issue-6304.rs deleted file mode 100644 index 2c4d007..0000000 --- a/gcc/testsuite/rust.test/borrowck-macro-interaction-issue-6304.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Check that we do not ICE when compiling this -// macro, which reuses the expression `$id` - -#[feature(macro_rules)]; - -struct Foo { - a: int -} - -pub enum Bar { - Bar1, Bar2(int, ~Bar), -} - -impl Foo { - fn elaborate_stm(&mut self, s: ~Bar) -> ~Bar { - macro_rules! declare( - ($id:expr, $rest:expr) => ({ - self.check_id($id); - ~Bar2($id, $rest) - }) - ); - match s { - ~Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)), - _ => fail2!() - } - } - - fn check_id(&mut self, s: int) { fail2!() } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/borrowck-move-by-capture-ok.rs b/gcc/testsuite/rust.test/borrowck-move-by-capture-ok.rs deleted file mode 100644 index f6328c8..0000000 --- a/gcc/testsuite/rust.test/borrowck-move-by-capture-ok.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn main() { - let bar = ~3; - let h: ~fn() -> int = || *bar; - assert_eq!(h(), 3); -} diff --git a/gcc/testsuite/rust.test/borrowck-mut-uniq.rs b/gcc/testsuite/rust.test/borrowck-mut-uniq.rs deleted file mode 100644 index 8ff326e..0000000 --- a/gcc/testsuite/rust.test/borrowck-mut-uniq.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; - -struct Ints {sum: ~int, values: ~[int]} - -fn add_int(x: &mut Ints, v: int) { - *x.sum += v; - let mut values = ~[]; - util::swap(&mut values, &mut x.values); - values.push(v); - util::swap(&mut values, &mut x.values); -} - -fn iter_ints(x: &Ints, f: &fn(x: &int) -> bool) -> bool { - let l = x.values.len(); - range(0u, l).advance(|i| f(&x.values[i])) -} - -pub fn main() { - let mut ints = ~Ints {sum: ~0, values: ~[]}; - add_int(ints, 22); - add_int(ints, 44); - - do iter_ints(ints) |i| { - error2!("int = {}", *i); - true - }; - - error2!("ints={:?}", ints); -} diff --git a/gcc/testsuite/rust.test/borrowck-mut-vec-as-imm-slice.rs b/gcc/testsuite/rust.test/borrowck-mut-vec-as-imm-slice.rs deleted file mode 100644 index 1ca94d6..0000000 --- a/gcc/testsuite/rust.test/borrowck-mut-vec-as-imm-slice.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn want_slice(v: &[int]) -> int { - let mut sum = 0; - for i in v.iter() { sum += *i; } - sum -} - -fn has_mut_vec(v: ~[int]) -> int { - want_slice(v) -} - -pub fn main() { - assert_eq!(has_mut_vec(~[1, 2, 3]), 6); -} diff --git a/gcc/testsuite/rust.test/borrowck-nested-calls.rs b/gcc/testsuite/rust.test/borrowck-nested-calls.rs deleted file mode 100644 index 50e9b6d..0000000 --- a/gcc/testsuite/rust.test/borrowck-nested-calls.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #5074 nested method calls - -// Test that (safe) nested calls with `&mut` receivers are permitted. - -struct Foo {a: uint, b: uint} - -impl Foo { - pub fn inc_a(&mut self, v: uint) { self.a += v; } - - pub fn next_b(&mut self) -> uint { - let b = self.b; - self.b += 1; - b - } -} - -fn main() { - let mut f = Foo {a: 22, b: 23}; - f.inc_a(f.next_b()); - assert_eq!(f.a, 22+23); - assert_eq!(f.b, 24); -} diff --git a/gcc/testsuite/rust.test/borrowck-pat-enum.rs b/gcc/testsuite/rust.test/borrowck-pat-enum.rs deleted file mode 100644 index 79cad64..0000000 --- a/gcc/testsuite/rust.test/borrowck-pat-enum.rs +++ /dev/null @@ -1,47 +0,0 @@ -// xfail-pretty - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn match_ref(v: Option) -> int { - match v { - Some(ref i) => { - *i - } - None => {0} - } -} - -fn match_ref_unused(v: Option) { - match v { - Some(_) => {} - None => {} - } -} - -fn impure(_i: int) { -} - -fn match_imm_reg(v: &Option) { - match *v { - Some(ref i) => {impure(*i)} // OK because immutable - None => {} - } -} - -fn match_mut_reg(v: &mut Option) { - match *v { - Some(ref i) => {impure(*i)} // OK, frozen - None => {} - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/borrowck-pat-reassign-no-binding.rs b/gcc/testsuite/rust.test/borrowck-pat-reassign-no-binding.rs deleted file mode 100644 index 4ccbf6b..0000000 --- a/gcc/testsuite/rust.test/borrowck-pat-reassign-no-binding.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut x = None; - match x { - None => { - // It is ok to reassign x here, because there is in - // fact no outstanding loan of x! - x = Some(0); - } - Some(_) => { } - } - assert_eq!(x, Some(0)); -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-in-arm-not-taken.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-in-arm-not-taken.rs deleted file mode 100644 index a8e14b5..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-in-arm-not-taken.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -pub fn main() { - let x: @mut @Option<~int> = @mut @None; - match x { - @@Some(ref _y) => { - // here, the refcount of `*x` is bumped so - // `_y` remains valid even if `*x` is modified. - *x = @None; - } - @@None => { - // here, no bump of the ref count of `*x` is needed, but in - // fact a bump occurs anyway because of how pattern marching - // works. - } - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-in-discr.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-in-discr.rs deleted file mode 100644 index 4be38df..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-in-discr.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -struct F { f: ~int } - -pub fn main() { - let mut x = @F {f: ~3}; - match x { - @F {f: ref b_x} => { - assert_eq!(**b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(**b_x))); - - x = @F {f: ~4}; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(**b_x)) as uint); - assert_eq!(**b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x))); - } - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-in-field.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-in-field.rs deleted file mode 100644 index ddc1d61..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-in-field.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -fn borrow(x: &int, f: &fn(x: &int)) { - let before = *x; - f(x); - let after = *x; - assert_eq!(before, after); -} - -struct F { f: ~int } - -pub fn main() { - let mut x = @F {f: ~3}; - do borrow(x.f) |b_x| { - assert_eq!(*b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); - x = @F {f: ~4}; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert_eq!(*b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-in-pat.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-in-pat.rs deleted file mode 100644 index dc389ed..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-in-pat.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -struct F { f: ~int } - -pub fn main() { - let x = @mut @F {f: ~3}; - match x { - @@F{f: ref b_x} => { - assert_eq!(**b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(x.f)), ptr::to_unsafe_ptr(b_x)); - - *x = @F {f: ~4}; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(**b_x)) as uint); - assert_eq!(**b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x))); - } - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-in-uniq.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-in-uniq.rs deleted file mode 100644 index 139466b..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-in-uniq.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -fn borrow(x: &int, f: &fn(x: &int)) { - let before = *x; - f(x); - let after = *x; - assert_eq!(before, after); -} - -struct F { f: ~int } - -pub fn main() { - let mut x = ~@F{f: ~3}; - do borrow(x.f) |b_x| { - assert_eq!(*b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); - *x = @F{f: ~4}; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert_eq!(*b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box-sometimes-needed.rs b/gcc/testsuite/rust.test/borrowck-preserve-box-sometimes-needed.rs deleted file mode 100644 index 3f3534c..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box-sometimes-needed.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -fn switcher(x: Option<@int>) { - let mut x = x; - match x { - Some(@y) => { y.clone(); x = None; } - None => { } - } - assert_eq!(x, None); -} - -pub fn main() { - switcher(None); - switcher(Some(@3)); -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-box.rs b/gcc/testsuite/rust.test/borrowck-preserve-box.rs deleted file mode 100644 index f852f36..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-box.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -fn borrow(x: &int, f: &fn(x: &int)) { - let before = *x; - f(x); - let after = *x; - assert_eq!(before, after); -} - -pub fn main() { - let mut x = @3; - do borrow(x) |b_x| { - assert_eq!(*b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(*x)), ptr::to_unsafe_ptr(&(*b_x))); - x = @22; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert_eq!(*b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x)) != ptr::to_unsafe_ptr(&(*b_x))); - } -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-cond-box.rs b/gcc/testsuite/rust.test/borrowck-preserve-cond-box.rs deleted file mode 100644 index b9428da..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-cond-box.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -fn testfn(cond: bool) { - let mut x = @3; - let mut y = @4; - - // borrow x and y - let r_x = &*x; - let r_y = &*y; - let mut r = r_x; - let mut exp = 3; - - if cond { - r = r_y; - exp = 4; - } - - info2!("*r = {}, exp = {}", *r, exp); - assert_eq!(*r, exp); - - x = @5; - y = @6; - - info2!("*r = {}, exp = {}", *r, exp); - assert_eq!(*r, exp); - assert_eq!(x, @5); - assert_eq!(y, @6); -} - -pub fn main() { - testfn(true); - testfn(false); -} diff --git a/gcc/testsuite/rust.test/borrowck-preserve-expl-deref.rs b/gcc/testsuite/rust.test/borrowck-preserve-expl-deref.rs deleted file mode 100644 index fec8575..0000000 --- a/gcc/testsuite/rust.test/borrowck-preserve-expl-deref.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exec-env:RUST_POISON_ON_FREE=1 - -use std::ptr; - -fn borrow(x: &int, f: &fn(x: &int)) { - let before = *x; - f(x); - let after = *x; - assert_eq!(before, after); -} - -struct F { f: ~int } - -pub fn main() { - let mut x = @F {f: ~3}; - do borrow((*x).f) |b_x| { - assert_eq!(*b_x, 3); - assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); - x = @F {f: ~4}; - - info2!("ptr::to_unsafe_ptr(*b_x) = {:x}", - ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert_eq!(*b_x, 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); - } -} diff --git a/gcc/testsuite/rust.test/borrowck-root-while-cond-2.rs b/gcc/testsuite/rust.test/borrowck-root-while-cond-2.rs deleted file mode 100644 index ea165e5..0000000 --- a/gcc/testsuite/rust.test/borrowck-root-while-cond-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct F { f: @G } -struct G { g: ~[int] } - -pub fn main() { - let rec = @mut F {f: @G {g: ~[1, 2, 3]}}; - while rec.f.g.len() == 23 {} -} diff --git a/gcc/testsuite/rust.test/borrowck-root-while-cond.rs b/gcc/testsuite/rust.test/borrowck-root-while-cond.rs deleted file mode 100644 index 77e4f51..0000000 --- a/gcc/testsuite/rust.test/borrowck-root-while-cond.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn borrow<'r,T>(x: &'r T) -> &'r T {x} - -struct Rec { f: @int } - -pub fn main() { - let rec = @mut Rec {f: @22}; - while *borrow(rec.f) == 23 {} -} diff --git a/gcc/testsuite/rust.test/borrowck-rvalues-mutable.rs b/gcc/testsuite/rust.test/borrowck-rvalues-mutable.rs deleted file mode 100644 index cf5a934..0000000 --- a/gcc/testsuite/rust.test/borrowck-rvalues-mutable.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Counter { - value: uint -} - -impl Counter { - fn new(v: uint) -> Counter { - Counter {value: v} - } - - fn get_and_inc(&mut self) -> uint { - let v = self.value; - self.value += 1; - v - } -} - -pub fn main() { - let v = Counter::new(22).get_and_inc(); - assert_eq!(v, 22); -} diff --git a/gcc/testsuite/rust.test/borrowck-scope-of-deref-issue-4666.rs b/gcc/testsuite/rust.test/borrowck-scope-of-deref-issue-4666.rs deleted file mode 100644 index 0e75722..0000000 --- a/gcc/testsuite/rust.test/borrowck-scope-of-deref-issue-4666.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that the scope of the pointer returned from `get()` is -// limited to the deref operation itself, and does not infect the -// block as a whole. - -struct Box { - x: uint -} - -impl Box { - fn get<'a>(&'a self) -> &'a uint { - &self.x - } - fn set(&mut self, x: uint) { - self.x = x; - } -} - -fn fun1() { - // in the past, borrow checker behaved differently when - // init and decl of `v` were distinct - let v; - let mut box = Box {x: 0}; - box.set(22); - v = *box.get(); - box.set(v+1); - assert_eq!(23, *box.get()); -} - -fn fun2() { - let mut box = Box {x: 0}; - box.set(22); - let v = *box.get(); - box.set(v+1); - assert_eq!(23, *box.get()); -} - -pub fn main() { - fun1(); - fun2(); -} diff --git a/gcc/testsuite/rust.test/borrowck-static-item-in-fn.rs b/gcc/testsuite/rust.test/borrowck-static-item-in-fn.rs deleted file mode 100644 index 366752f..0000000 --- a/gcc/testsuite/rust.test/borrowck-static-item-in-fn.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #7740 - -pub fn main() { - static A: &'static char = &'A'; -} diff --git a/gcc/testsuite/rust.test/borrowck-unary-move-2.rs b/gcc/testsuite/rust.test/borrowck-unary-move-2.rs deleted file mode 100644 index 6d16fd8..0000000 --- a/gcc/testsuite/rust.test/borrowck-unary-move-2.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct noncopyable { - i: (), -} - -impl Drop for noncopyable { - fn drop(&mut self) { - error2!("dropped"); - } -} - -fn noncopyable() -> noncopyable { - noncopyable { - i: () - } -} - -struct wrapper(noncopyable); - -pub fn main() { - let x1 = wrapper(noncopyable()); - let _x2 = *x1; -} diff --git a/gcc/testsuite/rust.test/borrowck-uniq-via-ref.rs b/gcc/testsuite/rust.test/borrowck-uniq-via-ref.rs deleted file mode 100644 index d50b4f1..0000000 --- a/gcc/testsuite/rust.test/borrowck-uniq-via-ref.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Rec { - f: ~int, -} - -struct Outer { - f: Inner -} - -struct Inner { - g: Innermost -} - -struct Innermost { - h: ~int, -} - -fn borrow(_v: &int) {} - -fn box_mut(v: &mut ~int) { - borrow(*v); // OK: &mut -> &imm -} - -fn box_mut_rec(v: &mut Rec) { - borrow(v.f); // OK: &mut -> &imm -} - -fn box_mut_recs(v: &mut Outer) { - borrow(v.f.g.h); // OK: &mut -> &imm -} - -fn box_imm(v: &~int) { - borrow(*v); // OK -} - -fn box_imm_rec(v: &Rec) { - borrow(v.f); // OK -} - -fn box_imm_recs(v: &Outer) { - borrow(v.f.g.h); // OK -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/borrowck-univariant-enum.rs b/gcc/testsuite/rust.test/borrowck-univariant-enum.rs deleted file mode 100644 index bb8710a..0000000 --- a/gcc/testsuite/rust.test/borrowck-univariant-enum.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum newtype { - newtype(int) -} - -pub fn main() { - - // Test that borrowck treats enums with a single variant - // specially. - - let x = @mut 5; - let y = @mut newtype(3); - let z = match *y { - newtype(b) => { - *x += 1; - *x * b - } - }; - assert_eq!(z, 18); -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs b/gcc/testsuite/rust.test/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs deleted file mode 100644 index 4ee0d42..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Issue #6272. Tests that freezing correctly accounts for all the -// implicit derefs that can occur. -// -// In this particular case, the expression: -// -// let x: &mut [int] = c[0]; -// -// is seen by borrowck as this sequence of derefs -// and pointer offsets: -// -// &*((**c)[0]) -// -// or, written using `x.*` for `*x` (so that everything -// is a postfix operation): -// -// &c.*.*.[0].* -// ^ ^ -// | | -// b a -// -// Here I also indicated where the evaluation yields the boxes `a` and -// `b`. It is important then that we only freeze the innermost box -// (`a`), and not the other ones (`b`, `c`). -// -// Also see the companion test: -// -// run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs - - -pub fn main() { - let a = @mut 3i; - let b = @mut [a]; - let c = @mut [3]; - - // this should freeze `a` only - let _x: &mut int = a; - - // hence these writes should not fail: - b[0] = b[0]; - c[0] = c[0]; -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-2.rs b/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-2.rs deleted file mode 100644 index d721704..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -struct Cat; - -fn bar(_: &Cat) { -} - -fn foo(cat: &mut Cat) { - bar(&*cat); -} - -pub fn main() { - let mut mimi = ~Cat; - foo(mimi); -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-3.rs b/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-3.rs deleted file mode 100644 index dcf497e..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm-3.rs +++ /dev/null @@ -1,18 +0,0 @@ -struct Wizard { - spells: ~[&'static str] -} - -impl Wizard { - pub fn cast(&mut self) { - for &spell in self.spells.iter() { - println(spell); - } - } -} - -pub fn main() { - let mut harry = Wizard { - spells: ~[ "expelliarmus", "expecto patronum", "incendio" ] - }; - harry.cast(); -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm.rs b/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm.rs deleted file mode 100644 index 668f602..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-borrow-mut-to-imm.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn g(x: &Option) { - println(x.unwrap().to_str()); -} - -fn f(x: &mut Option) { - g(&*x); -} - -pub fn main() { - let mut x = ~Some(3); - f(x); -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-simple.rs b/gcc/testsuite/rust.test/borrowck-wg-simple.rs deleted file mode 100644 index c07962e..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-simple.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn f(x: &int) { - println(x.to_str()); -} - -pub fn main() { - let x = @mut 3; - f(x); -} diff --git a/gcc/testsuite/rust.test/borrowck-wg-two-imm-borrows.rs b/gcc/testsuite/rust.test/borrowck-wg-two-imm-borrows.rs deleted file mode 100644 index 3d29882..0000000 --- a/gcc/testsuite/rust.test/borrowck-wg-two-imm-borrows.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Test that we can borrow the same @mut box twice, so long as both are imm. - -fn add(x:&int, y:&int) -{ - *x + *y; -} - -pub fn main() -{ - let z = @mut [1,2,3]; - let z2 = z; - add(&z[0], &z2[0]); - println!("{}", z[0]); -} diff --git a/gcc/testsuite/rust.test/borrowed-ptr-pattern-2.rs b/gcc/testsuite/rust.test/borrowed-ptr-pattern-2.rs deleted file mode 100644 index b15f9e7..0000000 --- a/gcc/testsuite/rust.test/borrowed-ptr-pattern-2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(s: &~str) -> bool { - match s { - &~"kitty" => true, - _ => false - } -} - -pub fn main() { - assert!(foo(&~"kitty")); - assert!(!foo(&~"gata")); -} diff --git a/gcc/testsuite/rust.test/borrowed-ptr-pattern-3.rs b/gcc/testsuite/rust.test/borrowed-ptr-pattern-3.rs deleted file mode 100644 index 030e055..0000000 --- a/gcc/testsuite/rust.test/borrowed-ptr-pattern-3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo<'r>(s: &'r uint) -> bool { - match s { - &3 => true, - _ => false - } -} - -pub fn main() { - assert!(foo(&3)); - assert!(!foo(&4)); -} diff --git a/gcc/testsuite/rust.test/borrowed-ptr-pattern-infallible.rs b/gcc/testsuite/rust.test/borrowed-ptr-pattern-infallible.rs deleted file mode 100644 index 4e9ba6d..0000000 --- a/gcc/testsuite/rust.test/borrowed-ptr-pattern-infallible.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let (&x, &y, &z) = (&3, &'a', &@"No pets!"); - assert_eq!(x, 3); - assert_eq!(y, 'a'); - assert_eq!(z, @"No pets!"); -} diff --git a/gcc/testsuite/rust.test/borrowed-ptr-pattern-option.rs b/gcc/testsuite/rust.test/borrowed-ptr-pattern-option.rs deleted file mode 100644 index 9f17b9d..0000000 --- a/gcc/testsuite/rust.test/borrowed-ptr-pattern-option.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn select<'r>(x: &'r Option, y: &'r Option) -> &'r Option { - match (x, y) { - (&None, &None) => x, - (&Some(_), _) => x, - (&None, &Some(_)) => y - } -} - -pub fn main() { - let x = None; - let y = Some(3); - assert_eq!(select(&x, &y).unwrap(), 3); -} diff --git a/gcc/testsuite/rust.test/borrowed-ptr-pattern.rs b/gcc/testsuite/rust.test/borrowed-ptr-pattern.rs deleted file mode 100644 index 11751ed..0000000 --- a/gcc/testsuite/rust.test/borrowed-ptr-pattern.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &T) -> T{ - match x { - &ref a => (*a).clone() - } -} - -pub fn main() { - assert_eq!(foo(&3), 3); - assert_eq!(foo(&'a'), 'a'); - assert_eq!(foo(&@"Dogs rule, cats drool"), @"Dogs rule, cats drool"); -} diff --git a/gcc/testsuite/rust.test/box-compare.rs b/gcc/testsuite/rust.test/box-compare.rs deleted file mode 100644 index b68ecd3..0000000 --- a/gcc/testsuite/rust.test/box-compare.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - assert!((@1 < @3)); - assert!((@@~"hello " > @@~"hello")); - assert!((@@@~"hello" != @@@~"there")); -} diff --git a/gcc/testsuite/rust.test/box-in-tup.rs b/gcc/testsuite/rust.test/box-in-tup.rs deleted file mode 100644 index 315b69f..0000000 --- a/gcc/testsuite/rust.test/box-in-tup.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let i: (@int, int) = (@10, 10); - let (_a, _) = i; -} diff --git a/gcc/testsuite/rust.test/box-inside-if.rs b/gcc/testsuite/rust.test/box-inside-if.rs deleted file mode 100644 index 249e9a4..0000000 --- a/gcc/testsuite/rust.test/box-inside-if.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- - -fn some_box(x: int) -> @int { return @x; } - -fn is_odd(_n: int) -> bool { return true; } - -fn length_is_even(_vs: @int) -> bool { return true; } - -fn foo(_acc: int, n: int) { - if is_odd(n) && length_is_even(some_box(1)) { error2!("bloop"); } -} - -pub fn main() { foo(67, 5); } diff --git a/gcc/testsuite/rust.test/box-inside-if2.rs b/gcc/testsuite/rust.test/box-inside-if2.rs deleted file mode 100644 index a4563c3..0000000 --- a/gcc/testsuite/rust.test/box-inside-if2.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- - -fn some_box(x: int) -> @int { return @x; } - -fn is_odd(_n: int) -> bool { return true; } - -fn length_is_even(_vs: @int) -> bool { return true; } - -fn foo(_acc: int, n: int) { - if is_odd(n) || length_is_even(some_box(1)) { error2!("bloop"); } -} - -pub fn main() { foo(67, 5); } diff --git a/gcc/testsuite/rust.test/box-pattern.rs b/gcc/testsuite/rust.test/box-pattern.rs deleted file mode 100644 index 89f62ad..0000000 --- a/gcc/testsuite/rust.test/box-pattern.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo {a: int, b: uint} -enum bar { u(@Foo), w(int), } - -pub fn main() { - assert!(match u(@Foo{a: 10, b: 40u}) { - u(@Foo{a: a, b: b}) => { a + (b as int) } - _ => { 66 } - } == 50); -} diff --git a/gcc/testsuite/rust.test/box-unbox.rs b/gcc/testsuite/rust.test/box-unbox.rs deleted file mode 100644 index f5d5224..0000000 --- a/gcc/testsuite/rust.test/box-unbox.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -struct Box {c: @T} - -fn unbox(b: Box) -> T { return (*b.c).clone(); } - -pub fn main() { - let foo: int = 17; - let bfoo: Box = Box {c: @foo}; - info2!("see what's in our box"); - assert_eq!(unbox::(bfoo), foo); -} diff --git a/gcc/testsuite/rust.test/box.rs b/gcc/testsuite/rust.test/box.rs deleted file mode 100644 index 4c394a6..0000000 --- a/gcc/testsuite/rust.test/box.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { let x: @int = @10; assert!((*x == 10)); } diff --git a/gcc/testsuite/rust.test/boxed-class-type-substitution.rs b/gcc/testsuite/rust.test/boxed-class-type-substitution.rs deleted file mode 100644 index e9be090..0000000 --- a/gcc/testsuite/rust.test/boxed-class-type-substitution.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test that rustc doesn't recurse infinitely substituting -// the boxed type parameter - -struct Tree { - parent: Option -} - -fn empty() -> Tree { fail2!() } - -struct Box { - tree: Tree<@Box> -} - -fn Box() -> Box { - Box { - tree: empty() - } -} - -struct LayoutData { - box: Option<@Box> -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/boxed-trait-with-vstore.rs b/gcc/testsuite/rust.test/boxed-trait-with-vstore.rs deleted file mode 100644 index 1d901d4..0000000 --- a/gcc/testsuite/rust.test/boxed-trait-with-vstore.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn foo(@self); -} - -impl Foo for int { - fn foo(@self) { - println("Hello world!"); - } -} - -pub fn main() { - let x = @3 as @Foo; - x.foo(); -} diff --git a/gcc/testsuite/rust.test/break-value.rs b/gcc/testsuite/rust.test/break-value.rs deleted file mode 100644 index efc3ab3..0000000 --- a/gcc/testsuite/rust.test/break-value.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn int_id(x: int) -> int { return x; } - -pub fn main() { loop { int_id(break); } } diff --git a/gcc/testsuite/rust.test/break.rs b/gcc/testsuite/rust.test/break.rs deleted file mode 100644 index 1ae77bc..0000000 --- a/gcc/testsuite/rust.test/break.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let mut i = 0; - while i < 20 { i += 1; if i == 10 { break; } } - assert_eq!(i, 10); - loop { i += 1; if i == 20 { break; } } - assert_eq!(i, 20); - let xs = [1, 2, 3, 4, 5, 6]; - for x in xs.iter() { - if *x == 3 { break; } assert!((*x <= 3)); - } - i = 0; - while i < 10 { i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); } - i = 0; - loop { - i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); - if i >= 10 { break; } - } - let ys = ~[1, 2, 3, 4, 5, 6]; - for x in ys.iter() { - if *x % 2 == 0 { continue; } - assert!((*x % 2 != 0)); - } -} diff --git a/gcc/testsuite/rust.test/bug-7183-generics.rs b/gcc/testsuite/rust.test/bug-7183-generics.rs deleted file mode 100644 index 3e89ac8..0000000 --- a/gcc/testsuite/rust.test/bug-7183-generics.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Speak { - fn say(&self, s:&str) -> ~str; - fn hi(&self) -> ~str { hello(self) } -} - -fn hello(s:&S) -> ~str{ - s.say("hello") -} - -impl Speak for int { - fn say(&self, s:&str) -> ~str { - format!("{}: {}", s, *self) - } -} - -impl Speak for Option { - fn say(&self, s:&str) -> ~str { - match *self { - None => format!("{} - none", s), - Some(ref x) => { ~"something!" + x.say(s) } - } - } -} - - -pub fn main() { - assert_eq!(3.hi(), ~"hello: 3"); - assert_eq!(Some(Some(3)).hi(), ~"something!something!hello: 3"); - assert_eq!(None::.hi(), ~"hello - none"); - - assert_eq!(Some(None::).hi(), ~"something!hello - none"); - assert_eq!(Some(3).hi(), ~"something!hello: 3"); -} diff --git a/gcc/testsuite/rust.test/bug-7295.rs b/gcc/testsuite/rust.test/bug-7295.rs deleted file mode 100644 index ea711d7..0000000 --- a/gcc/testsuite/rust.test/bug-7295.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait Foo { - fn func1(&self, t: U); - - fn func2(&self, t: U) { - self.func1(t); - } -} - -pub fn main() { - -} diff --git a/gcc/testsuite/rust.test/builtin-superkinds-capabilities-transitive.rs b/gcc/testsuite/rust.test/builtin-superkinds-capabilities-transitive.rs deleted file mode 100644 index ec5af69..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-capabilities-transitive.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests "transitivity" of super-builtin-kinds on traits. Here, if -// we have a Foo, we know we have a Bar, and if we have a Bar, we -// know we have a Send. So if we have a Foo we should know we have -// a Send. Basically this just makes sure rustc is using -// each_bound_trait_and_supertraits in type_contents correctly. - -use std::comm; - -trait Bar : Send { } -trait Foo : Bar { } - -impl Foo for T { } -impl Bar for T { } - -fn foo(val: T, chan: comm::Chan) { - chan.send(val); -} - -pub fn main() { - let (p,c) = comm::stream(); - foo(31337, c); - assert!(p.recv() == 31337); -} diff --git a/gcc/testsuite/rust.test/builtin-superkinds-capabilities-xc.rs b/gcc/testsuite/rust.test/builtin-superkinds-capabilities-xc.rs deleted file mode 100644 index ea61b91..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-capabilities-xc.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -// aux-build:trait_superkinds_in_metadata.rs - -// Tests "capabilities" granted by traits with super-builtin-kinds, -// even when using them cross-crate. - -extern mod trait_superkinds_in_metadata; -use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; -use std::comm; - -#[deriving(Eq)] -struct X(T); - -impl RequiresFreeze for X { } -impl RequiresRequiresFreezeAndSend for X { } - -fn foo(val: T, chan: comm::Chan) { - chan.send(val); -} - -fn main() { - let (p,c) = comm::stream(); - foo(X(31337), c); - assert!(p.recv() == X(31337)); -} diff --git a/gcc/testsuite/rust.test/builtin-superkinds-capabilities.rs b/gcc/testsuite/rust.test/builtin-superkinds-capabilities.rs deleted file mode 100644 index 148fb5a..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-capabilities.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests "capabilities" granted by traits that inherit from super- -// builtin-kinds, e.g., if a trait requires Send to implement, then -// at usage site of that trait, we know we have the Send capability. - -use std::comm; - -trait Foo : Send { } - -impl Foo for T { } - -fn foo(val: T, chan: comm::Chan) { - chan.send(val); -} - -pub fn main() { - let (p,c) = comm::stream(); - foo(31337, c); - assert!(p.recv() == 31337); -} diff --git a/gcc/testsuite/rust.test/builtin-superkinds-in-metadata.rs b/gcc/testsuite/rust.test/builtin-superkinds-in-metadata.rs deleted file mode 100644 index e2fc6cc..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-in-metadata.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -// aux-build:trait_superkinds_in_metadata.rs - -// Tests (correct) usage of trait super-builtin-kinds cross-crate. - -extern mod trait_superkinds_in_metadata; -use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; - -struct X(T); - -impl RequiresFreeze for X { } - -impl RequiresRequiresFreezeAndSend for X { } - -fn main() { } diff --git a/gcc/testsuite/rust.test/builtin-superkinds-phantom-typaram.rs b/gcc/testsuite/rust.test/builtin-superkinds-phantom-typaram.rs deleted file mode 100644 index 740b8c2..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-phantom-typaram.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that even when a type paramenter doesn't implement a required -// super-builtin-kind of a trait, if the type parameter is never used, -// the type can implement the trait anyway. - -trait Foo : Send { } - -struct X(()); - -impl Foo for X { } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/builtin-superkinds-self-type.rs b/gcc/testsuite/rust.test/builtin-superkinds-self-type.rs deleted file mode 100644 index a8f5f27..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-self-type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests the ability for the Self type in default methods to use -// capabilities granted by builtin kinds as supertraits. - -use std::comm; - -trait Foo : Send { - fn foo(self, chan: comm::Chan) { - chan.send(self); - } -} - -impl Foo for T { } - -pub fn main() { - let (p,c) = comm::stream(); - 1193182.foo(c); - assert!(p.recv() == 1193182); -} diff --git a/gcc/testsuite/rust.test/builtin-superkinds-simple.rs b/gcc/testsuite/rust.test/builtin-superkinds-simple.rs deleted file mode 100644 index 9643e29..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-simple.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Simple test case of implementing a trait with super-builtin-kinds. - -trait Foo : Send { } - -impl Foo for int { } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/builtin-superkinds-typaram.rs b/gcc/testsuite/rust.test/builtin-superkinds-typaram.rs deleted file mode 100644 index d96679c..0000000 --- a/gcc/testsuite/rust.test/builtin-superkinds-typaram.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests correct implementation of traits with super-builtin-kinds -// using a bounded type parameter. - -trait Foo : Send { } - -impl Foo for T { } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/c-stack-as-value.rs b/gcc/testsuite/rust.test/c-stack-as-value.rs deleted file mode 100644 index f8d30a9..0000000 --- a/gcc/testsuite/rust.test/c-stack-as-value.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rustrt { - use std::libc; - - extern { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -pub fn main() { - let _foo = rustrt::rust_get_test_int; -} diff --git a/gcc/testsuite/rust.test/c-stack-returning-int64.rs b/gcc/testsuite/rust.test/c-stack-returning-int64.rs deleted file mode 100644 index 866dd6b..0000000 --- a/gcc/testsuite/rust.test/c-stack-returning-int64.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod libc { - use std::libc::{c_char, c_long, c_longlong}; - - #[nolink] - extern { - pub fn atol(x: *c_char) -> c_long; - pub fn atoll(x: *c_char) -> c_longlong; - } -} - -#[fixed_stack_segment] -fn atol(s: ~str) -> int { - s.with_c_str(|x| unsafe { libc::atol(x) as int }) -} - -#[fixed_stack_segment] -fn atoll(s: ~str) -> i64 { - s.with_c_str(|x| unsafe { libc::atoll(x) as i64 }) -} - -pub fn main() { - assert_eq!(atol(~"1024") * 10, atol(~"10240")); - assert!((atoll(~"11111111111111111") * 10) == atoll(~"111111111111111110")); -} diff --git a/gcc/testsuite/rust.test/call-closure-from-overloaded-op.rs b/gcc/testsuite/rust.test/call-closure-from-overloaded-op.rs deleted file mode 100644 index 16728df..0000000 --- a/gcc/testsuite/rust.test/call-closure-from-overloaded-op.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo() -> int { 22 } - -pub fn main() { - let mut x: ~[extern "Rust" fn() -> int] = ~[]; - x.push(foo); - assert_eq!((x[0])(), 22); -} diff --git a/gcc/testsuite/rust.test/cancel-clean-via-immediate-rvalue-ref.rs b/gcc/testsuite/rust.test/cancel-clean-via-immediate-rvalue-ref.rs deleted file mode 100644 index 2b9e97b..0000000 --- a/gcc/testsuite/rust.test/cancel-clean-via-immediate-rvalue-ref.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(x: &mut ~u8) { - *x = ~5; -} - -pub fn main() { - foo(&mut ~4); -} diff --git a/gcc/testsuite/rust.test/cap-clause-move.rs b/gcc/testsuite/rust.test/cap-clause-move.rs deleted file mode 100644 index 64be8da..0000000 --- a/gcc/testsuite/rust.test/cap-clause-move.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; - -pub fn main() { - let x = ~3; - let y = ptr::to_unsafe_ptr(&(*x)) as uint; - let snd_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert_eq!(snd_move(), y); - - let x = ~4; - let y = ptr::to_unsafe_ptr(&(*x)) as uint; - let lam_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert_eq!(lam_move(), y); -} diff --git a/gcc/testsuite/rust.test/capture_nil.rs b/gcc/testsuite/rust.test/capture_nil.rs deleted file mode 100644 index edd1a9c..0000000 --- a/gcc/testsuite/rust.test/capture_nil.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-Z no-opt - -// This test has to be setup just so to trigger -// the condition which was causing us a crash. -// The situation is that we are capturing a -// () value by ref. We generally feel free, -// however, to substitute NULL pointers and -// undefined values for values of () type, and -// so this caused a segfault when we copied into -// the closure. -// -// The fix is just to not emit any actual loads -// or stores for copies of () type (which is of -// course preferable, as the value itself is -// irrelevant). - -use std::task; - -fn foo(x: ()) -> Port<()> { - let (p, c) = stream::<()>(); - do task::spawn() { - c.send(x); - } - p -} - -pub fn main() { - foo(()).recv() -} diff --git a/gcc/testsuite/rust.test/cast-mutable-trait.rs b/gcc/testsuite/rust.test/cast-mutable-trait.rs deleted file mode 100644 index ce026d3..0000000 --- a/gcc/testsuite/rust.test/cast-mutable-trait.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait T { - fn foo(@mut self); -} - -struct S { - unused: int -} - -impl T for S { - fn foo(@mut self) { - } -} - -fn bar(t: @mut T) { - t.foo(); -} - -pub fn main() { - let s = @mut S { unused: 0 }; - let s2 = s as @mut T; - s2.foo(); - bar(s2); - bar(s as @mut T); -} diff --git a/gcc/testsuite/rust.test/cast-region-to-uint.rs b/gcc/testsuite/rust.test/cast-region-to-uint.rs deleted file mode 100644 index 69ca158..0000000 --- a/gcc/testsuite/rust.test/cast-region-to-uint.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow; - -pub fn main() { - let x = 3; - info2!("&x={:x}", borrow::to_uint(&x)); -} diff --git a/gcc/testsuite/rust.test/cast.rs b/gcc/testsuite/rust.test/cast.rs deleted file mode 100644 index 8cf7c2e..0000000 --- a/gcc/testsuite/rust.test/cast.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// -*- rust -*- -pub fn main() { - let i: int = 'Q' as int; - assert_eq!(i, 0x51); - let u: u32 = i as u32; - assert_eq!(u, 0x51 as u32); - assert_eq!(u, 'Q' as u32); - assert_eq!(i as u8, 'Q' as u8); - assert_eq!(i as u8 as i8, 'Q' as u8 as i8); - assert_eq!(0x51u8 as char, 'Q'); - assert_eq!(0 as u32, false as u32); -} diff --git a/gcc/testsuite/rust.test/cci_borrow.rs b/gcc/testsuite/rust.test/cci_borrow.rs deleted file mode 100644 index 3db000a..0000000 --- a/gcc/testsuite/rust.test/cci_borrow.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_borrow_lib.rs - -extern mod cci_borrow_lib; -use cci_borrow_lib::foo; - -pub fn main() { - let p = @22u; - let r = foo(p); - info2!("r={}", r); - assert_eq!(r, 22u); -} diff --git a/gcc/testsuite/rust.test/cci_capture_clause.rs b/gcc/testsuite/rust.test/cci_capture_clause.rs deleted file mode 100644 index bb74065..0000000 --- a/gcc/testsuite/rust.test/cci_capture_clause.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:cci_capture_clause.rs -// xfail-fast - -// This test makes sure we can do cross-crate inlining on functions -// that use capture clauses. - -extern mod cci_capture_clause; - -pub fn main() { - cci_capture_clause::foo(()).recv() -} diff --git a/gcc/testsuite/rust.test/cci_impl_exe.rs b/gcc/testsuite/rust.test/cci_impl_exe.rs deleted file mode 100644 index b85d539..0000000 --- a/gcc/testsuite/rust.test/cci_impl_exe.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_impl_lib.rs - -extern mod cci_impl_lib; -use cci_impl_lib::uint_helpers; - -pub fn main() { - //let bt0 = sys::frame_address(); - //info!("%?", bt0); - - do 3u.to(10u) |i| { - println!("{}", i); - - //let bt1 = sys::frame_address(); - //info!("%?", bt1); - //assert!(bt0 == bt1); - } -} diff --git a/gcc/testsuite/rust.test/cci_iter_exe.rs b/gcc/testsuite/rust.test/cci_iter_exe.rs deleted file mode 100644 index ea313a4..0000000 --- a/gcc/testsuite/rust.test/cci_iter_exe.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_iter_lib.rs - -extern mod cci_iter_lib; - -pub fn main() { - //let bt0 = sys::rusti::frame_address(1u32); - //info!("%?", bt0); - do cci_iter_lib::iter([1, 2, 3]) |i| { - println!("{}", *i); - //assert!(bt0 == sys::rusti::frame_address(2u32)); - } -} diff --git a/gcc/testsuite/rust.test/cci_nested_exe.rs b/gcc/testsuite/rust.test/cci_nested_exe.rs deleted file mode 100644 index 8664102..0000000 --- a/gcc/testsuite/rust.test/cci_nested_exe.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_nested_lib.rs - -#[feature(globs)]; - -extern mod cci_nested_lib; -use cci_nested_lib::*; - -pub fn main() { - let lst = new_int_alist(); - alist_add(&lst, 22, ~"hi"); - alist_add(&lst, 44, ~"ho"); - assert_eq!(alist_get(&lst, 22), ~"hi"); - assert_eq!(alist_get(&lst, 44), ~"ho"); - - let lst = new_int_alist_2(); - alist_add(&lst, 22, ~"hi"); - alist_add(&lst, 44, ~"ho"); - assert_eq!(alist_get(&lst, 22), ~"hi"); - assert_eq!(alist_get(&lst, 44), ~"ho"); -} diff --git a/gcc/testsuite/rust.test/cci_no_inline_exe.rs b/gcc/testsuite/rust.test/cci_no_inline_exe.rs deleted file mode 100644 index 53c67e4..0000000 --- a/gcc/testsuite/rust.test/cci_no_inline_exe.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - check-fast doesn't understand aux-build -// aux-build:cci_no_inline_lib.rs - -extern mod cci_no_inline_lib; -use cci_no_inline_lib::iter; - -pub fn main() { - // Check that a cross-crate call function not marked as inline - // does not, in fact, get inlined. Also, perhaps more - // importantly, checks that our scheme of using - // sys::frame_address() to determine if we are inlining is - // actually working. - //let bt0 = sys::frame_address(); - //info!("%?", bt0); - do iter(~[1u, 2u, 3u]) |i| { - println!("{}", i); - - //let bt1 = sys::frame_address(); - //info!("%?", bt1); - - //assert!(bt0 != bt1); - } -} diff --git a/gcc/testsuite/rust.test/cfg-family.rs b/gcc/testsuite/rust.test/cfg-family.rs deleted file mode 100644 index 24120b6..0000000 --- a/gcc/testsuite/rust.test/cfg-family.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(windows)] -pub fn main() { -} - -#[cfg(unix)] -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/cfg-macros-foo.rs b/gcc/testsuite/rust.test/cfg-macros-foo.rs deleted file mode 100644 index 224df80..0000000 --- a/gcc/testsuite/rust.test/cfg-macros-foo.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast compile-flags directive doesn't work for check-fast -// compile-flags: --cfg foo - -// check that cfg correctly chooses between the macro impls (see also -// cfg-macros-notfoo.rs) - -#[feature(macro_rules)]; - -#[cfg(foo)] -#[macro_escape] -mod foo { - macro_rules! bar { - () => { true } - } -} - -#[cfg(not(foo))] -#[macro_escape] -mod foo { - macro_rules! bar { - () => { false } - } -} - -fn main() { - assert!(bar!()) -} diff --git a/gcc/testsuite/rust.test/cfg-macros-notfoo.rs b/gcc/testsuite/rust.test/cfg-macros-notfoo.rs deleted file mode 100644 index 5aa94bb..0000000 --- a/gcc/testsuite/rust.test/cfg-macros-notfoo.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast compile-flags directive doesn't work for check-fast -// compile-flags: - -// check that cfg correctly chooses between the macro impls (see also -// cfg-macros-foo.rs) - -#[feature(macro_rules)]; - -#[cfg(foo)] -#[macro_escape] -mod foo { - macro_rules! bar { - () => { true } - } -} - -#[cfg(not(foo))] -#[macro_escape] -mod foo { - macro_rules! bar { - () => { false } - } -} - -fn main() { - assert!(!bar!()) -} diff --git a/gcc/testsuite/rust.test/cfg-target-family.rs b/gcc/testsuite/rust.test/cfg-target-family.rs deleted file mode 100644 index 784c932..0000000 --- a/gcc/testsuite/rust.test/cfg-target-family.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(target_family = "windows")] -pub fn main() { -} - -#[cfg(target_family = "unix")] -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/cfg_inner_static.rs b/gcc/testsuite/rust.test/cfg_inner_static.rs deleted file mode 100644 index 2d06a10..0000000 --- a/gcc/testsuite/rust.test/cfg_inner_static.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:cfg_inner_static.rs -// xfail-fast - -extern mod cfg_inner_static; - -fn main() { - cfg_inner_static::foo(); -} diff --git a/gcc/testsuite/rust.test/cfgs-on-items.rs b/gcc/testsuite/rust.test/cfgs-on-items.rs deleted file mode 100644 index 237fa3f..0000000 --- a/gcc/testsuite/rust.test/cfgs-on-items.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// compile-flags: --cfg fooA --cfg fooB - -// fooA AND !bar -#[cfg(fooA, not(bar))] -fn foo1() -> int { 1 } - -// !fooA AND !bar -#[cfg(not(fooA, bar))] -fn foo2() -> int { 2 } - -// fooC OR (fooB AND !bar) -#[cfg(fooC)] -#[cfg(fooB, not(bar))] -fn foo2() -> int { 3 } - - -fn main() { - assert_eq!(1, foo1()); - assert_eq!(3, foo2()); -} diff --git a/gcc/testsuite/rust.test/char.rs b/gcc/testsuite/rust.test/char.rs deleted file mode 100644 index f982d37..0000000 --- a/gcc/testsuite/rust.test/char.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let c: char = 'x'; - let d: char = 'x'; - assert_eq!(c, 'x'); - assert_eq!('x', c); - assert_eq!(c, c); - assert_eq!(c, d); - assert_eq!(d, c); - assert_eq!(d, 'x'); - assert_eq!('x', d); -} diff --git a/gcc/testsuite/rust.test/child-outlives-parent.rs b/gcc/testsuite/rust.test/child-outlives-parent.rs deleted file mode 100644 index 233a431..0000000 --- a/gcc/testsuite/rust.test/child-outlives-parent.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Reported as issue #126, child leaks the string. - -use std::task; - -fn child2(_s: ~str) { } - -pub fn main() { - let _x = task::spawn(|| child2(~"hi")); -} diff --git a/gcc/testsuite/rust.test/class-attributes-1.rs b/gcc/testsuite/rust.test/class-attributes-1.rs deleted file mode 100644 index 3e7cae3..0000000 --- a/gcc/testsuite/rust.test/class-attributes-1.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact - Make sure we actually print the attributes - -struct cat { - name: ~str, -} - -impl Drop for cat { - #[cat_dropper] - fn drop(&mut self) { error2!("{} landed on hir feet" , self . name); } -} - - -#[cat_maker] -fn cat(name: ~str) -> cat { cat{name: name,} } - -pub fn main() { let _kitty = cat(~"Spotty"); } diff --git a/gcc/testsuite/rust.test/class-attributes-2.rs b/gcc/testsuite/rust.test/class-attributes-2.rs deleted file mode 100644 index 0a3f153..0000000 --- a/gcc/testsuite/rust.test/class-attributes-2.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - name: ~str, -} - -impl Drop for cat { - #[cat_dropper] - /** - Actually, cats don't always land on their feet when you drop them. - */ - fn drop(&mut self) { - error2!("{} landed on hir feet", self.name); - } -} - -#[cat_maker] -/** -Maybe it should technically be a kitten_maker. -*/ -fn cat(name: ~str) -> cat { - cat { - name: name - } -} - -pub fn main() { - let _kitty = cat(~"Spotty"); -} diff --git a/gcc/testsuite/rust.test/class-cast-to-trait-cross-crate-2.rs b/gcc/testsuite/rust.test/class-cast-to-trait-cross-crate-2.rs deleted file mode 100644 index bdba6a4..0000000 --- a/gcc/testsuite/rust.test/class-cast-to-trait-cross-crate-2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_cast.rs -extern mod cci_class_cast; -use std::to_str::ToStr; -use cci_class_cast::kitty::cat; - -fn print_out(thing: @ToStr, expected: ~str) { - let actual = thing.to_str(); - info2!("{}", actual); - assert_eq!(actual, expected); -} - -pub fn main() { - let nyan : @ToStr = @cat(0u, 2, ~"nyan") as @ToStr; - print_out(nyan, ~"nyan"); -} diff --git a/gcc/testsuite/rust.test/class-cast-to-trait-multiple-types.rs b/gcc/testsuite/rust.test/class-cast-to-trait-multiple-types.rs deleted file mode 100644 index 3828fbd..0000000 --- a/gcc/testsuite/rust.test/class-cast-to-trait-multiple-types.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait noisy { - fn speak(&self) -> int; -} - -struct dog { - priv barks : @mut uint, - - volume : @mut int, -} - -impl dog { - fn bark(&self) -> int { - info2!("Woof {} {}", *self.barks, *self.volume); - *self.barks += 1u; - if *self.barks % 3u == 0u { - *self.volume += 1; - } - if *self.barks % 10u == 0u { - *self.volume -= 2; - } - info2!("Grrr {} {}", *self.barks, *self.volume); - *self.volume - } -} - -impl noisy for dog { - fn speak(&self) -> int { self.bark() } -} - -fn dog() -> dog { - dog { - volume: @mut 0, - barks: @mut 0u - } -} - -#[deriving(Clone)] -struct cat { - priv meows : @mut uint, - - how_hungry : @mut int, - name : ~str, -} - -impl noisy for cat { - fn speak(&self) -> int { self.meow() as int } -} - -impl cat { - pub fn meow_count(&self) -> uint { *self.meows } -} - -impl cat { - fn meow(&self) -> uint { - info2!("Meow"); - *self.meows += 1u; - if *self.meows % 5u == 0u { - *self.how_hungry += 1; - } - *self.meows - } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: @mut in_x, - how_hungry: @mut in_y, - name: in_name - } -} - - -fn annoy_neighbors(critter: @noisy) { - for _i in range(0u, 10) { critter.speak(); } -} - -pub fn main() { - let nyan : cat = cat(0u, 2, ~"nyan"); - let whitefang : dog = dog(); - annoy_neighbors(@nyan.clone() as @noisy); - annoy_neighbors(@whitefang as @noisy); - assert_eq!(nyan.meow_count(), 10u); - assert_eq!(*whitefang.volume, 1); -} diff --git a/gcc/testsuite/rust.test/class-cast-to-trait.rs b/gcc/testsuite/rust.test/class-cast-to-trait.rs deleted file mode 100644 index 69a94e0..0000000 --- a/gcc/testsuite/rust.test/class-cast-to-trait.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait noisy { - fn speak(&mut self); -} - -struct cat { - priv meows: uint, - how_hungry: int, - name: ~str, -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - error2!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - error2!("Meow"); - self.meows += 1u; - if self.meows % 5u == 0u { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - - -pub fn main() { - let nyan: @mut noisy = @mut cat(0u, 2, ~"nyan") as @mut noisy; - nyan.speak(); -} diff --git a/gcc/testsuite/rust.test/class-dtor.rs b/gcc/testsuite/rust.test/class-dtor.rs deleted file mode 100644 index 8ee382e..0000000 --- a/gcc/testsuite/rust.test/class-dtor.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - done : extern fn(uint), - meows : uint, -} - -impl Drop for cat { - fn drop(&mut self) { - (self.done)(self.meows); - } -} - -fn cat(done: extern fn(uint)) -> cat { - cat { - meows: 0u, - done: done - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/class-exports.rs b/gcc/testsuite/rust.test/class-exports.rs deleted file mode 100644 index d801da4..0000000 --- a/gcc/testsuite/rust.test/class-exports.rs +++ /dev/null @@ -1,38 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* Test that exporting a class also exports its - public fields and methods */ - -use kitty::cat; - -mod kitty { - pub struct cat { - meows: uint, - name: ~str, - } - - impl cat { - pub fn get_name(&self) -> ~str { self.name.clone() } - } - - pub fn cat(in_name: ~str) -> cat { - cat { - name: in_name, - meows: 0u - } - } -} - -pub fn main() { - assert_eq!(cat(~"Spreckles").get_name(), ~"Spreckles"); -} diff --git a/gcc/testsuite/rust.test/class-impl-very-parameterized-trait.rs b/gcc/testsuite/rust.test/class-impl-very-parameterized-trait.rs deleted file mode 100644 index baa82db..0000000 --- a/gcc/testsuite/rust.test/class-impl-very-parameterized-trait.rs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -use std::cmp; - -enum cat_type { tuxedo, tabby, tortoiseshell } - -impl cmp::Eq for cat_type { - fn eq(&self, other: &cat_type) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &cat_type) -> bool { !(*self).eq(other) } -} - -// Very silly -- this just returns the value of the name field -// for any int value that's less than the meows field - -// ok: T should be in scope when resolving the trait ref for map -struct cat { - // Yes, you can have negative meows - priv meows : int, - - how_hungry : int, - name : T, -} - -impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - error2!("Not hungry!"); - return false; - } - } -} - -impl Container for cat { - fn len(&self) -> uint { self.meows as uint } - fn is_empty(&self) -> bool { self.meows == 0 } -} - -impl Mutable for cat { - fn clear(&mut self) {} -} - -impl Map for cat { - fn contains_key(&self, k: &int) -> bool { *k <= self.meows } - - fn find<'a>(&'a self, k: &int) -> Option<&'a T> { - if *k <= self.meows { - Some(&self.name) - } else { - None - } - } -} - -impl MutableMap for cat { - fn insert(&mut self, k: int, _: T) -> bool { - self.meows += k; - true - } - - fn find_mut<'a>(&'a mut self, _k: &int) -> Option<&'a mut T> { fail2!() } - - fn remove(&mut self, k: &int) -> bool { - if self.find(k).is_some() { - self.meows -= *k; true - } else { - false - } - } - - fn pop(&mut self, _k: &int) -> Option { fail2!() } - - fn swap(&mut self, _k: int, _v: T) -> Option { fail2!() } -} - -impl cat { - pub fn get<'a>(&'a self, k: &int) -> &'a T { - match self.find(k) { - Some(v) => { v } - None => { fail2!("epic fail"); } - } - } - - pub fn new(in_x: int, in_y: int, in_name: T) -> cat { - cat{meows: in_x, how_hungry: in_y, name: in_name } - } -} - -impl cat { - fn meow(&mut self) { - self.meows += 1; - error2!("Meow {}", self.meows); - if self.meows % 5 == 0 { - self.how_hungry += 1; - } - } -} - -pub fn main() { - let mut nyan: cat<~str> = cat::new(0, 2, ~"nyan"); - for _ in range(1u, 5) { nyan.speak(); } - assert!(*nyan.find(&1).unwrap() == ~"nyan"); - assert_eq!(nyan.find(&10), None); - let mut spotty: cat = cat::new(2, 57, tuxedo); - for _ in range(0u, 6) { spotty.speak(); } - assert_eq!(spotty.len(), 8); - assert!((spotty.contains_key(&2))); - assert_eq!(spotty.get(&3), &tuxedo); -} diff --git a/gcc/testsuite/rust.test/class-implement-trait-cross-crate.rs b/gcc/testsuite/rust.test/class-implement-trait-cross-crate.rs deleted file mode 100644 index d6477d2..0000000 --- a/gcc/testsuite/rust.test/class-implement-trait-cross-crate.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_trait.rs -extern mod cci_class_trait; -use cci_class_trait::animals::noisy; - -struct cat { - priv meows: uint, - - how_hungry : int, - name : ~str, -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - error2!("Not hungry!"); - return false; - } - } -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -impl cat { - fn meow(&mut self) { - error2!("Meow"); - self.meows += 1u; - if self.meows % 5u == 0u { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - - -pub fn main() { - let mut nyan = cat(0u, 2, ~"nyan"); - nyan.eat(); - assert!((!nyan.eat())); - for _ in range(1u, 10u) { nyan.speak(); }; - assert!((nyan.eat())); -} diff --git a/gcc/testsuite/rust.test/class-implement-traits.rs b/gcc/testsuite/rust.test/class-implement-traits.rs deleted file mode 100644 index 1433b5a..0000000 --- a/gcc/testsuite/rust.test/class-implement-traits.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -trait noisy { - fn speak(&mut self); -} - -#[deriving(Clone)] -struct cat { - priv meows : uint, - - how_hungry : int, - name : ~str, -} - -impl cat { - fn meow(&mut self) { - error2!("Meow"); - self.meows += 1u; - if self.meows % 5u == 0u { - self.how_hungry += 1; - } - } -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - error2!("Not hungry!"); - return false; - } - } -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name.clone() - } -} - - -fn make_speak(mut c: C) { - c.speak(); -} - -pub fn main() { - let mut nyan = cat(0u, 2, ~"nyan"); - nyan.eat(); - assert!((!nyan.eat())); - for _ in range(1u, 10u) { - make_speak(nyan.clone()); - } -} diff --git a/gcc/testsuite/rust.test/class-method-cross-crate.rs b/gcc/testsuite/rust.test/class-method-cross-crate.rs deleted file mode 100644 index b0e96ad..0000000 --- a/gcc/testsuite/rust.test/class-method-cross-crate.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_2.rs -extern mod cci_class_2; -use cci_class_2::kitties::cat; - -pub fn main() { - let nyan : cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); -} diff --git a/gcc/testsuite/rust.test/class-methods-cross-crate.rs b/gcc/testsuite/rust.test/class-methods-cross-crate.rs deleted file mode 100644 index 86a529a..0000000 --- a/gcc/testsuite/rust.test/class-methods-cross-crate.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_3.rs -extern mod cci_class_3; -use cci_class_3::kitties::cat; - -pub fn main() { - let mut nyan : cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); - assert_eq!(nyan.meow_count(), 53u); -} diff --git a/gcc/testsuite/rust.test/class-methods.rs b/gcc/testsuite/rust.test/class-methods.rs deleted file mode 100644 index f5fa72e..0000000 --- a/gcc/testsuite/rust.test/class-methods.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn speak(&mut self) { self.meows += 1u; } - pub fn meow_count(&mut self) -> uint { self.meows } -} - -fn cat(in_x: uint, in_y: int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan: cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); - assert_eq!(nyan.meow_count(), 53u); -} diff --git a/gcc/testsuite/rust.test/class-poly-methods-cross-crate.rs b/gcc/testsuite/rust.test/class-poly-methods-cross-crate.rs deleted file mode 100644 index 9aac6a0..0000000 --- a/gcc/testsuite/rust.test/class-poly-methods-cross-crate.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_6.rs -extern mod cci_class_6; -use cci_class_6::kitties::cat; - -pub fn main() { - let mut nyan : cat = cat::(52u, 99, ~['p']); - let mut kitty = cat(1000u, 2, ~[~"tabby"]); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(~[1u,2u,3u]); - assert_eq!(nyan.meow_count(), 55u); - kitty.speak(~[~"meow", ~"mew", ~"purr", ~"chirp"]); - assert_eq!(kitty.meow_count(), 1004u); -} diff --git a/gcc/testsuite/rust.test/class-poly-methods.rs b/gcc/testsuite/rust.test/class-poly-methods.rs deleted file mode 100644 index 0201501..0000000 --- a/gcc/testsuite/rust.test/class-poly-methods.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv info : ~[U], - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn speak(&mut self, stuff: ~[T]) { - self.meows += stuff.len(); - } - pub fn meow_count(&mut self) -> uint { self.meows } -} - -fn cat(in_x : uint, in_y : int, in_info: ~[U]) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - info: in_info - } -} - -pub fn main() { - let mut nyan : cat = cat::(52u, 99, ~[9]); - let mut kitty = cat(1000u, 2, ~[~"tabby"]); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(~[1,2,3]); - assert_eq!(nyan.meow_count(), 55u); - kitty.speak(~[~"meow", ~"mew", ~"purr", ~"chirp"]); - assert_eq!(kitty.meow_count(), 1004u); -} diff --git a/gcc/testsuite/rust.test/class-separate-impl.rs b/gcc/testsuite/rust.test/class-separate-impl.rs deleted file mode 100644 index 5ef0569..0000000 --- a/gcc/testsuite/rust.test/class-separate-impl.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -struct cat { - priv meows : uint, - - how_hungry : int, - name : ~str, -} - -impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - error2!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - error2!("Meow"); - self.meows += 1u; - if self.meows % 5u == 0u { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - -impl ToStr for cat { - fn to_str(&self) -> ~str { - self.name.clone() - } -} - -fn print_out(thing: @ToStr, expected: ~str) { - let actual = thing.to_str(); - info2!("{}", actual); - assert_eq!(actual, expected); -} - -pub fn main() { - let nyan : @ToStr = @cat(0u, 2, ~"nyan") as @ToStr; - print_out(nyan, ~"nyan"); -} diff --git a/gcc/testsuite/rust.test/class-str-field.rs b/gcc/testsuite/rust.test/class-str-field.rs deleted file mode 100644 index 452242d..0000000 --- a/gcc/testsuite/rust.test/class-str-field.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - - name : ~str, - -} - -fn cat(in_name: ~str) -> cat { - cat { - name: in_name - } -} - -pub fn main() { - let _nyan = cat(~"nyan"); -} diff --git a/gcc/testsuite/rust.test/class-typarams.rs b/gcc/testsuite/rust.test/class-typarams.rs deleted file mode 100644 index ab6a8b1..0000000 --- a/gcc/testsuite/rust.test/class-typarams.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn speak(&mut self) { self.meows += 1u; } - pub fn meow_count(&mut self) -> uint { self.meows } -} - -fn cat(in_x : uint, in_y : int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - - -pub fn main() { - let _nyan : cat = cat::(52u, 99); - // let mut kitty = cat(1000u, 2); -} diff --git a/gcc/testsuite/rust.test/classes-cross-crate.rs b/gcc/testsuite/rust.test/classes-cross-crate.rs deleted file mode 100644 index 96d9434..0000000 --- a/gcc/testsuite/rust.test/classes-cross-crate.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class_4.rs -extern mod cci_class_4; -use cci_class_4::kitties::cat; - -pub fn main() { - let mut nyan = cat(0u, 2, ~"nyan"); - nyan.eat(); - assert!((!nyan.eat())); - for _ in range(1u, 10u) { nyan.speak(); }; - assert!((nyan.eat())); -} diff --git a/gcc/testsuite/rust.test/classes-self-referential.rs b/gcc/testsuite/rust.test/classes-self-referential.rs deleted file mode 100644 index 4f2499e..0000000 --- a/gcc/testsuite/rust.test/classes-self-referential.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct kitten { - cat: Option, -} - -fn kitten(cat: Option) -> kitten { - kitten { - cat: cat - } -} - -type cat = @kitten; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/classes-simple-cross-crate.rs b/gcc/testsuite/rust.test/classes-simple-cross-crate.rs deleted file mode 100644 index 519cca2..0000000 --- a/gcc/testsuite/rust.test/classes-simple-cross-crate.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_class.rs -extern mod cci_class; -use cci_class::kitties::cat; - -pub fn main() { - let nyan : cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); -} diff --git a/gcc/testsuite/rust.test/classes-simple-method.rs b/gcc/testsuite/rust.test/classes-simple-method.rs deleted file mode 100644 index 6e08a4d..0000000 --- a/gcc/testsuite/rust.test/classes-simple-method.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -impl cat { - pub fn speak(&mut self) {} -} - -fn cat(in_x : uint, in_y : int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan : cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); -} diff --git a/gcc/testsuite/rust.test/classes-simple.rs b/gcc/testsuite/rust.test/classes-simple.rs deleted file mode 100644 index 49e8f5c..0000000 --- a/gcc/testsuite/rust.test/classes-simple.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, -} - -fn cat(in_x : uint, in_y : int) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let nyan : cat = cat(52u, 99); - let kitty = cat(1000u, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); -} diff --git a/gcc/testsuite/rust.test/classes.rs b/gcc/testsuite/rust.test/classes.rs deleted file mode 100644 index 14acd1c..0000000 --- a/gcc/testsuite/rust.test/classes.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct cat { - priv meows : uint, - - how_hungry : int, - name : ~str, -} - -impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - error2!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - error2!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - error2!("Meow"); - self.meows += 1u; - if self.meows % 5u == 0u { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - -pub fn main() { - let mut nyan = cat(0u, 2, ~"nyan"); - nyan.eat(); - assert!((!nyan.eat())); - for _ in range(1u, 10u) { nyan.speak(); }; - assert!((nyan.eat())); -} diff --git a/gcc/testsuite/rust.test/cleanup-copy-mode.rs b/gcc/testsuite/rust.test/cleanup-copy-mode.rs deleted file mode 100644 index 6381a40..0000000 --- a/gcc/testsuite/rust.test/cleanup-copy-mode.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -fn adder(x: @int, y: @int) -> int { return *x + *y; } -fn failer() -> @int { fail2!(); } -pub fn main() { - assert!(task::try(|| { - adder(@2, failer()); () - }).is_err()); -} diff --git a/gcc/testsuite/rust.test/clone-with-exterior.rs b/gcc/testsuite/rust.test/clone-with-exterior.rs deleted file mode 100644 index f6a7856..0000000 --- a/gcc/testsuite/rust.test/clone-with-exterior.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; -use std::task::spawn; - -struct Pair { - a: int, - b: int -} - -pub fn main() { - let z = ~Pair { a : 10, b : 12}; - - let f: ~fn() = || { - assert_eq!(z.a, 10); - assert_eq!(z.b, 12); - }; - - spawn(f); -} diff --git a/gcc/testsuite/rust.test/close-over-big-then-small-data.rs b/gcc/testsuite/rust.test/close-over-big-then-small-data.rs deleted file mode 100644 index 4b6b3cc..0000000 --- a/gcc/testsuite/rust.test/close-over-big-then-small-data.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// If we use GEPi rathern than GEP_tup_like when -// storing closure data (as we used to do), the u64 would -// overwrite the u16. - -struct Pair { - a: A, b: B -} - -struct Invoker { - a: A, - b: u16, -} - -trait Invokable { - fn f(&self) -> (A, u16); -} - -impl Invokable for Invoker { - fn f(&self) -> (A, u16) { - (self.a.clone(), self.b) - } -} - -fn f(a: A, b: u16) -> @Invokable { - @Invoker { - a: a, - b: b, - } as @Invokable -} - -pub fn main() { - let (a, b) = f(22_u64, 44u16).f(); - info2!("a={:?} b={:?}", a, b); - assert_eq!(a, 22u64); - assert_eq!(b, 44u16); -} diff --git a/gcc/testsuite/rust.test/closure-bounds-can-capture-chan.rs b/gcc/testsuite/rust.test/closure-bounds-can-capture-chan.rs deleted file mode 100644 index d35d6d9..0000000 --- a/gcc/testsuite/rust.test/closure-bounds-can-capture-chan.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::comm; - -fn foo(blk: ~fn:Send()) { - blk(); -} - -pub fn main() { - let (p,c) = comm::stream(); - do foo { - c.send(()); - } - p.recv(); -} diff --git a/gcc/testsuite/rust.test/closure-inference.rs b/gcc/testsuite/rust.test/closure-inference.rs deleted file mode 100644 index 167fbdf..0000000 --- a/gcc/testsuite/rust.test/closure-inference.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn foo(i: int) -> int { i + 1 } - -fn apply(f: &fn(A) -> A, v: A) -> A { f(v) } - -pub fn main() { - let f = {|i| foo(i)}; - assert_eq!(apply(f, 2), 3); -} diff --git a/gcc/testsuite/rust.test/closure-inference2.rs b/gcc/testsuite/rust.test/closure-inference2.rs deleted file mode 100644 index fa16ea0..0000000 --- a/gcc/testsuite/rust.test/closure-inference2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a rather underspecified example: - -pub fn main() { - let f = {|i| i}; - assert_eq!(f(2), 2); - assert_eq!(f(5), 5); -} diff --git a/gcc/testsuite/rust.test/cmp-default.rs b/gcc/testsuite/rust.test/cmp-default.rs deleted file mode 100644 index 92b14dc..0000000 --- a/gcc/testsuite/rust.test/cmp-default.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test default methods in Ord and Eq -// -struct Fool(bool); - -impl Eq for Fool { - fn eq(&self, other: &Fool) -> bool { - **self != **other - } -} - -struct Int(int); - -impl Ord for Int { - fn lt(&self, other: &Int) -> bool { - **self < **other - } -} - -struct RevInt(int); - -impl Ord for RevInt { - fn lt(&self, other: &RevInt) -> bool { - **self > **other - } -} - -pub fn main() { - assert!(Int(2) > Int(1)); - assert!(Int(2) >= Int(1)); - assert!(Int(1) >= Int(1)); - assert!(Int(1) < Int(2)); - assert!(Int(1) <= Int(2)); - assert!(Int(1) <= Int(1)); - - assert!(RevInt(2) < RevInt(1)); - assert!(RevInt(2) <= RevInt(1)); - assert!(RevInt(1) <= RevInt(1)); - assert!(RevInt(1) > RevInt(2)); - assert!(RevInt(1) >= RevInt(2)); - assert!(RevInt(1) >= RevInt(1)); - - assert!(Fool(true) == Fool(false)); - assert!(Fool(true) != Fool(true)); - assert!(Fool(false) != Fool(false)); - assert!(Fool(false) == Fool(true)); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-arg.rs b/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-arg.rs deleted file mode 100644 index e40272b..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-arg.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn negate(x: &int) -> int { - -*x -} - -fn negate_mut(y: &mut int) -> int { - negate(y) -} - -fn negate_imm(y: &int) -> int { - negate(y) -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-rcvr.rs b/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-rcvr.rs deleted file mode 100644 index 52fa139..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-imm-ptr-rcvr.rs +++ /dev/null @@ -1,16 +0,0 @@ -struct SpeechMaker { - speeches: uint -} - -impl SpeechMaker { - pub fn how_many(&self) -> uint { self.speeches } -} - -fn foo(speaker: &SpeechMaker) -> uint { - speaker.how_many() + 33 -} - -pub fn main() { - let lincoln = SpeechMaker {speeches: 22}; - assert_eq!(foo(&lincoln), 55); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-arg.rs b/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-arg.rs deleted file mode 100644 index b31f0ea..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn sum(x: &[int]) -> int { - let mut sum = 0; - for y in x.iter() { sum += *y; } - return sum; -} - -fn sum_mut(y: &mut [int]) -> int { - sum(y) -} - -fn sum_imm(y: &[int]) -> int { - sum(y) -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-rcvr.rs b/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-rcvr.rs deleted file mode 100644 index 8a271a4..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-imm-vec-rcvr.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn bar(v: &mut [uint]) -> ~[uint] { - v.to_owned() -} - -fn bip(v: &[uint]) -> ~[uint] { - v.to_owned() -} - -pub fn main() { - let mut the_vec = ~[1u, 2, 3, 100]; - assert_eq!(the_vec.clone(), bar(the_vec)); - assert_eq!(the_vec.clone(), bip(the_vec)); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-arg.rs b/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-arg.rs deleted file mode 100644 index f8650c8..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-arg.rs +++ /dev/null @@ -1,22 +0,0 @@ -struct SpeechMaker { - speeches: uint -} - -fn talk(x: &mut SpeechMaker) { - x.speeches += 1; -} - -fn give_a_few_speeches(speaker: &mut SpeechMaker) { - - // Here speaker is reborrowed for each call, so we don't get errors - // about speaker being moved. - - talk(speaker); - talk(speaker); - talk(speaker); -} - -pub fn main() { - let mut lincoln = SpeechMaker {speeches: 22}; - give_a_few_speeches(&mut lincoln); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-rcvr.rs b/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-rcvr.rs deleted file mode 100644 index 3adb805..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-mut-ptr-rcvr.rs +++ /dev/null @@ -1,24 +0,0 @@ -struct SpeechMaker { - speeches: uint -} - -impl SpeechMaker { - pub fn talk(&mut self) { - self.speeches += 1; - } -} - -fn give_a_few_speeches(speaker: &mut SpeechMaker) { - - // Here speaker is reborrowed for each call, so we don't get errors - // about speaker being moved. - - speaker.talk(); - speaker.talk(); - speaker.talk(); -} - -pub fn main() { - let mut lincoln = SpeechMaker {speeches: 22}; - give_a_few_speeches(&mut lincoln); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-arg.rs b/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-arg.rs deleted file mode 100644 index 356c159..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn reverse(v: &mut [uint]) { - v.reverse(); -} - -fn bar(v: &mut [uint]) { - reverse(v); - reverse(v); - reverse(v); -} - -pub fn main() { - let mut the_vec = ~[1, 2, 3, 100]; - bar(the_vec); - assert_eq!(the_vec, ~[100, 3, 2, 1]); -} diff --git a/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-rcvr.rs b/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-rcvr.rs deleted file mode 100644 index 556d70f..0000000 --- a/gcc/testsuite/rust.test/coerce-reborrow-mut-vec-rcvr.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn bar(v: &mut [uint]) { - v.reverse(); - v.reverse(); - v.reverse(); -} - -pub fn main() { - let mut the_vec = ~[1, 2, 3, 100]; - bar(the_vec); - assert_eq!(the_vec, ~[100, 3, 2, 1]); -} diff --git a/gcc/testsuite/rust.test/coherence-impl-in-fn.rs b/gcc/testsuite/rust.test/coherence-impl-in-fn.rs deleted file mode 100644 index 707a7bf..0000000 --- a/gcc/testsuite/rust.test/coherence-impl-in-fn.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - enum x { foo } - impl ::std::cmp::Eq for x { - fn eq(&self, other: &x) -> bool { - (*self) as int == (*other) as int - } - fn ne(&self, other: &x) -> bool { !(*self).eq(other) } - } -} diff --git a/gcc/testsuite/rust.test/comm.rs b/gcc/testsuite/rust.test/comm.rs deleted file mode 100644 index 63c1f4e..0000000 --- a/gcc/testsuite/rust.test/comm.rs +++ /dev/null @@ -1,27 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::task; - -pub fn main() { - let (p, ch) = stream(); - let _t = task::spawn(|| child(&ch) ); - let y = p.recv(); - error2!("received"); - error2!("{:?}", y); - assert_eq!(y, 10); -} - -fn child(c: &Chan) { - error2!("sending"); - c.send(10); - error2!("value sent"); -} diff --git a/gcc/testsuite/rust.test/compare-generic-enums.rs b/gcc/testsuite/rust.test/compare-generic-enums.rs deleted file mode 100644 index c6f4fec..0000000 --- a/gcc/testsuite/rust.test/compare-generic-enums.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -type an_int = int; - -fn cmp(x: Option, y: Option) -> bool { - x == y -} - -pub fn main() { - assert!(!cmp(Some(3), None)); - assert!(!cmp(Some(3), Some(4))); - assert!(cmp(Some(3), Some(3))); - assert!(cmp(None, None)); -} diff --git a/gcc/testsuite/rust.test/complex.rs b/gcc/testsuite/rust.test/complex.rs deleted file mode 100644 index f395c6b..0000000 --- a/gcc/testsuite/rust.test/complex.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -type t = int; - -fn nothing() { } - -fn putstr(_s: ~str) { } - -fn putint(_i: int) { - let mut i: int = 33; - while i < 36 { putstr(~"hi"); i = i + 1; } -} - -fn zerg(i: int) -> int { return i; } - -fn foo(x: int) -> int { - let mut y: t = x + 2; - putstr(~"hello"); - while y < 10 { putint(y); if y * 3 == 4 { y = y + 2; nothing(); } } - let mut z: t; - z = 0x55; - foo(z); - return 0; -} - -pub fn main() { - let x: int = 2 + 2; - info2!("{}", x); - info2!("hello, world"); - info2!("{}", 10); -} diff --git a/gcc/testsuite/rust.test/conditional-compile-arch.rs b/gcc/testsuite/rust.test/conditional-compile-arch.rs deleted file mode 100644 index 106f59d..0000000 --- a/gcc/testsuite/rust.test/conditional-compile-arch.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(target_arch = "x86")] -pub fn main() { } - -#[cfg(target_arch = "x86_64")] -pub fn main() { } - -#[cfg(target_arch = "arm")] -pub fn main() { } diff --git a/gcc/testsuite/rust.test/conditional-compile.rs b/gcc/testsuite/rust.test/conditional-compile.rs deleted file mode 100644 index 89f4440..0000000 --- a/gcc/testsuite/rust.test/conditional-compile.rs +++ /dev/null @@ -1,151 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Crate use statements -#[cfg(bogus)] -use flippity; - -#[cfg(bogus)] -static b: bool = false; - -static b: bool = true; - -mod rustrt { - #[cfg(bogus)] - extern { - // This symbol doesn't exist and would be a link error if this - // module was translated - pub fn bogus(); - } - - extern {} -} - -#[cfg(bogus)] -type t = int; - -type t = bool; - -#[cfg(bogus)] -enum tg { foo, } - -enum tg { bar, } - -#[cfg(bogus)] -struct r { - i: int, -} - -#[cfg(bogus)] -fn r(i:int) -> r { - r { - i: i - } -} - -struct r { - i: int, -} - -fn r(i:int) -> r { - r { - i: i - } -} - -#[cfg(bogus)] -mod m { - // This needs to parse but would fail in typeck. Since it's not in - // the current config it should not be typechecked. - pub fn bogus() { return 0; } -} - -mod m { - // Submodules have slightly different code paths than the top-level - // module, so let's make sure this jazz works here as well - #[cfg(bogus)] - pub fn f() { } - - pub fn f() { } -} - -// Since the bogus configuration isn't defined main will just be -// parsed, but nothing further will be done with it -#[cfg(bogus)] -pub fn main() { fail!() } - -pub fn main() { - // Exercise some of the configured items in ways that wouldn't be possible - // if they had the bogus definition - assert!((b)); - let _x: t = true; - let _y: tg = bar; - - test_in_fn_ctxt(); -} - -fn test_in_fn_ctxt() { - #[cfg(bogus)] - fn f() { fail!() } - fn f() { } - f(); - - #[cfg(bogus)] - static i: int = 0; - static i: int = 1; - assert_eq!(i, 1); -} - -mod test_foreign_items { - pub mod rustrt { - extern { - #[cfg(bogus)] - pub fn rust_get_stdin() -> ~str; - pub fn rust_get_stdin() -> ~str; - } - } -} - -mod test_use_statements { - #[cfg(bogus)] - use flippity_foo; -} - -mod test_methods { - struct Foo { - bar: uint - } - - impl Fooable for Foo { - #[cfg(bogus)] - fn what(&self) { } - - fn what(&self) { } - - #[cfg(bogus)] - fn the(&self) { } - - fn the(&self) { } - } - - trait Fooable { - #[cfg(bogus)] - fn what(&self); - - fn what(&self); - - #[cfg(bogus)] - fn the(&self); - - fn the(&self); - } -} diff --git a/gcc/testsuite/rust.test/conditional-debug-macro-off.rs b/gcc/testsuite/rust.test/conditional-debug-macro-off.rs deleted file mode 100644 index 1706275..0000000 --- a/gcc/testsuite/rust.test/conditional-debug-macro-off.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast exec-env directive doesn't work for check-fast -// compile-flags: --cfg ndebug -// exec-env:RUST_LOG=conditional-debug-macro-off=4 - -fn main() { - // only fails if debug! evaluates its argument. - debug2!("{:?}", { if true { fail2!() } }); -} diff --git a/gcc/testsuite/rust.test/conditional-debug-macro-on.rs b/gcc/testsuite/rust.test/conditional-debug-macro-on.rs deleted file mode 100644 index dec79f0..0000000 --- a/gcc/testsuite/rust.test/conditional-debug-macro-on.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast compile-flags directive doesn't work for check-fast -// exec-env:RUST_LOG=conditional-debug-macro-on=4 - -fn main() { - // exits early if debug! evaluates its arguments, otherwise it - // will hit the fail. - debug2!("{:?}", { if true { return; } }); - - fail2!(); -} diff --git a/gcc/testsuite/rust.test/const-autoderef-newtype.rs b/gcc/testsuite/rust.test/const-autoderef-newtype.rs deleted file mode 100644 index 19dea65..0000000 --- a/gcc/testsuite/rust.test/const-autoderef-newtype.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S(&'static [int]); -static C0: S = S([3]); -static C1: int = C0[0]; - -pub fn main() { - assert_eq!(C1, 3); -} diff --git a/gcc/testsuite/rust.test/const-autoderef.rs b/gcc/testsuite/rust.test/const-autoderef.rs deleted file mode 100644 index e80ed7c..0000000 --- a/gcc/testsuite/rust.test/const-autoderef.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static A: [u8, ..1] = ['h' as u8]; -static B: u8 = (&A)[0]; -static C: &'static &'static &'static &'static [u8, ..1] = & & & &A; -static D: u8 = (&C)[0]; - -pub fn main() { - assert_eq!(B, A[0]); - assert_eq!(D, A[0]); -} diff --git a/gcc/testsuite/rust.test/const-big-enum.rs b/gcc/testsuite/rust.test/const-big-enum.rs deleted file mode 100644 index 0a5a421..0000000 --- a/gcc/testsuite/rust.test/const-big-enum.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Foo { - Bar(u32), - Baz, - Quux(u64, u16) -} - -static X: Foo = Baz; - -pub fn main() { - match X { - Baz => {} - _ => fail2!() - } - match Y { - Bar(s) => assert!(s == 2654435769), - _ => fail2!() - } - match Z { - Quux(d,h) => { - assert_eq!(d, 0x123456789abcdef0); - assert_eq!(h, 0x1234); - } - _ => fail2!() - } -} - -static Y: Foo = Bar(2654435769); -static Z: Foo = Quux(0x123456789abcdef0, 0x1234); diff --git a/gcc/testsuite/rust.test/const-binops.rs b/gcc/testsuite/rust.test/const-binops.rs deleted file mode 100644 index 8ccfd9f..0000000 --- a/gcc/testsuite/rust.test/const-binops.rs +++ /dev/null @@ -1,116 +0,0 @@ -static a: int = -4 + 3; -static a2: uint = 3 + 3; -static b: f64 = 3.0 + 2.7; - -static c: int = 3 - 4; -static d: uint = 3 - 3; -static e: f64 = 3.0 - 2.7; - -static e2: int = -3 * 3; -static f: uint = 3 * 3; -static g: f64 = 3.3 * 3.3; - -static h: int = 3 / -1; -static i: uint = 3 / 3; -static j: f64 = 3.3 / 3.3; - -static n: bool = true && false; - -static o: bool = true || false; - -static p: int = 3 & 1; -static q: uint = 1 & 3; - -static r: int = 3 | 1; -static s: uint = 1 | 3; - -static t: int = 3 ^ 1; -static u: uint = 1 ^ 3; - -static v: int = 1 << 3; - -// NOTE: better shr coverage -static w: int = 1024 >> 4; -static x: uint = 1024 >> 4; - -static y: bool = 1 == 1; -static z: bool = 1.0 == 1.0; - -static aa: bool = 1 <= 2; -static ab: bool = -1 <= 2; -static ac: bool = 1.0 <= 2.0; - -static ad: bool = 1 < 2; -static ae: bool = -1 < 2; -static af: bool = 1.0 < 2.0; - -static ag: bool = 1 != 2; -static ah: bool = -1 != 2; -static ai: bool = 1.0 != 2.0; - -static aj: bool = 2 >= 1; -static ak: bool = 2 >= -2; -static al: bool = 1.0 >= -2.0; - -static am: bool = 2 > 1; -static an: bool = 2 > -2; -static ao: bool = 1.0 > -2.0; - -pub fn main() { - assert_eq!(a, -1); - assert_eq!(a2, 6); - assert_approx_eq!(b, 5.7); - - assert_eq!(c, -1); - assert_eq!(d, 0); - assert_approx_eq!(e, 0.3); - - assert_eq!(e2, -9); - assert_eq!(f, 9); - assert_approx_eq!(g, 10.89); - - assert_eq!(h, -3); - assert_eq!(i, 1); - assert_approx_eq!(j, 1.0); - - assert_eq!(n, false); - - assert_eq!(o, true); - - assert_eq!(p, 1); - assert_eq!(q, 1); - - assert_eq!(r, 3); - assert_eq!(s, 3); - - assert_eq!(t, 2); - assert_eq!(u, 2); - - assert_eq!(v, 8); - - assert_eq!(w, 64); - assert_eq!(x, 64); - - assert_eq!(y, true); - assert_eq!(z, true); - - assert_eq!(aa, true); - assert_eq!(ab, true); - assert_eq!(ac, true); - - assert_eq!(ad, true); - assert_eq!(ae, true); - assert_eq!(af, true); - - assert_eq!(ag, true); - assert_eq!(ah, true); - assert_eq!(ai, true); - - assert_eq!(aj, true); - assert_eq!(ak, true); - assert_eq!(al, true); - - assert_eq!(am, true); - assert_eq!(an, true); - assert_eq!(ao, true); -} diff --git a/gcc/testsuite/rust.test/const-bound.rs b/gcc/testsuite/rust.test/const-bound.rs deleted file mode 100644 index 635ae70..0000000 --- a/gcc/testsuite/rust.test/const-bound.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure const bounds work on things, and test that a few types -// are const. - - -fn foo(x: T) -> T { x } - -struct F { field: int } - -pub fn main() { - /*foo(1); - foo(~"hi"); - foo(~[1, 2, 3]); - foo(F{field: 42}); - foo((1, 2u)); - foo(@1);*/ - foo(~1); -} diff --git a/gcc/testsuite/rust.test/const-cast-ptr-int.rs b/gcc/testsuite/rust.test/const-cast-ptr-int.rs deleted file mode 100644 index 88ab70f..0000000 --- a/gcc/testsuite/rust.test/const-cast-ptr-int.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; - -static a: *u8 = 0 as *u8; - -pub fn main() { - assert_eq!(a, ptr::null()); -} diff --git a/gcc/testsuite/rust.test/const-cast.rs b/gcc/testsuite/rust.test/const-cast.rs deleted file mode 100644 index d511930..0000000 --- a/gcc/testsuite/rust.test/const-cast.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -extern fn foo() {} - -static x: extern "C" fn() = foo; -static y: *libc::c_void = x as *libc::c_void; -static a: &'static int = &10; -static b: *int = a as *int; - -pub fn main() { - assert_eq!(x as *libc::c_void, y); - assert_eq!(a as *int, b); -} diff --git a/gcc/testsuite/rust.test/const-const.rs b/gcc/testsuite/rust.test/const-const.rs deleted file mode 100644 index bdb2b3d..0000000 --- a/gcc/testsuite/rust.test/const-const.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static a: int = 1; -static b: int = a + 2; - -pub fn main() { - assert_eq!(b, 3); -} diff --git a/gcc/testsuite/rust.test/const-contents.rs b/gcc/testsuite/rust.test/const-contents.rs deleted file mode 100644 index 616826f..0000000 --- a/gcc/testsuite/rust.test/const-contents.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #570 - -static lsl : int = 1 << 2; -static add : int = 1 + 2; -static addf : f64 = 1.0 + 2.0; -static not : int = !0; -static notb : bool = !true; -static neg : int = -(1); - -pub fn main() { - assert_eq!(lsl, 4); - assert_eq!(add, 3); - assert_eq!(addf, 3.0); - assert_eq!(not, -1); - assert_eq!(notb, false); - assert_eq!(neg, -1); -} diff --git a/gcc/testsuite/rust.test/const-cross-crate-const.rs b/gcc/testsuite/rust.test/const-cross-crate-const.rs deleted file mode 100644 index 607d0c7..0000000 --- a/gcc/testsuite/rust.test/const-cross-crate-const.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_const.rs - -extern mod cci_const; -static foo: &'static str = cci_const::foopy; -static a: uint = cci_const::uint_val; -static b: uint = cci_const::uint_expr + 5; - -fn main() { - assert_eq!(a, 12); - let foo2 = a; - assert_eq!(foo2, cci_const::uint_val); - assert_eq!(b, cci_const::uint_expr + 5); - assert_eq!(foo, cci_const::foopy); -} diff --git a/gcc/testsuite/rust.test/const-cross-crate-extern.rs b/gcc/testsuite/rust.test/const-cross-crate-extern.rs deleted file mode 100644 index 5ded736..0000000 --- a/gcc/testsuite/rust.test/const-cross-crate-extern.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_const.rs - -extern mod cci_const; -use cci_const::bar; -static foo: extern "C" fn() = bar; - -pub fn main() { - assert_eq!(foo, bar); -} diff --git a/gcc/testsuite/rust.test/const-deref.rs b/gcc/testsuite/rust.test/const-deref.rs deleted file mode 100644 index b179785..0000000 --- a/gcc/testsuite/rust.test/const-deref.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static C: &'static int = &1000; -static D: int = *C; -struct S(&'static int); -static E: &'static S = &S(C); -static F: int = ***E; - -pub fn main() { - assert_eq!(D, 1000); - assert_eq!(F, 1000); -} diff --git a/gcc/testsuite/rust.test/const-enum-byref-self.rs b/gcc/testsuite/rust.test/const-enum-byref-self.rs deleted file mode 100644 index 25e4b71..0000000 --- a/gcc/testsuite/rust.test/const-enum-byref-self.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V, VV(int) } -static C: E = V; - -impl E { - pub fn method(&self) { - match *self { - V => {} - VV(*) => fail2!() - } - } -} - -pub fn main() { - C.method() -} diff --git a/gcc/testsuite/rust.test/const-enum-byref.rs b/gcc/testsuite/rust.test/const-enum-byref.rs deleted file mode 100644 index 22ec61f..0000000 --- a/gcc/testsuite/rust.test/const-enum-byref.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V, VV(int) } -static C: E = V; - -fn f(a: &E) { - match *a { - V => {} - VV(*) => fail2!() - } -} - -pub fn main() { - f(&C) -} diff --git a/gcc/testsuite/rust.test/const-enum-cast.rs b/gcc/testsuite/rust.test/const-enum-cast.rs deleted file mode 100644 index 75e942c..0000000 --- a/gcc/testsuite/rust.test/const-enum-cast.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum A { A1, A2 } -enum B { B1=0, B2=2 } - -pub fn main () { - static c1: int = A2 as int; - static c2: int = B2 as int; - static c3: f64 = A2 as f64; - static c4: f64 = B2 as f64; - let a1 = A2 as int; - let a2 = B2 as int; - let a3 = A2 as f64; - let a4 = B2 as f64; - assert_eq!(c1, 1); - assert_eq!(c2, 2); - assert_eq!(c3, 1.0); - assert_eq!(c4, 2.0); - assert_eq!(a1, 1); - assert_eq!(a2, 2); - assert_eq!(a3, 1.0); - assert_eq!(a4, 2.0); -} diff --git a/gcc/testsuite/rust.test/const-enum-ptr.rs b/gcc/testsuite/rust.test/const-enum-ptr.rs deleted file mode 100644 index c75d172..0000000 --- a/gcc/testsuite/rust.test/const-enum-ptr.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V0, V1(int) } -static C: &'static E = &V0; - -pub fn main() { - match *C { - V0 => (), - _ => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/const-enum-struct.rs b/gcc/testsuite/rust.test/const-enum-struct.rs deleted file mode 100644 index 3229293..0000000 --- a/gcc/testsuite/rust.test/const-enum-struct.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V16(u16), V32(u32) } -struct S { a: E, b: u16, c: u16 } -static C: S = S { a: V16(0xDEAD), b: 0x600D, c: 0xBAD }; - -pub fn main() { - let n = C.b; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-struct2.rs b/gcc/testsuite/rust.test/const-enum-struct2.rs deleted file mode 100644 index 4530a65..0000000 --- a/gcc/testsuite/rust.test/const-enum-struct2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V0, V16(u16) } -struct S { a: E, b: u16, c: u16 } -static C: S = S { a: V0, b: 0x600D, c: 0xBAD }; - -pub fn main() { - let n = C.b; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-structlike.rs b/gcc/testsuite/rust.test/const-enum-structlike.rs deleted file mode 100644 index 95ba635..0000000 --- a/gcc/testsuite/rust.test/const-enum-structlike.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -enum E { - S0 { s: ~str }, - S1 { u: uint } -} - -static C: E = S1 { u: 23 }; - -pub fn main() { - match C { - S0 { _ } => fail2!(), - S1 { u } => assert!(u == 23) - } -} diff --git a/gcc/testsuite/rust.test/const-enum-tuple.rs b/gcc/testsuite/rust.test/const-enum-tuple.rs deleted file mode 100644 index 17d8341..0000000 --- a/gcc/testsuite/rust.test/const-enum-tuple.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V16(u16), V32(u32) } -static C: (E, u16, u16) = (V16(0xDEAD), 0x600D, 0xBAD); - -pub fn main() { - let (_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-tuple2.rs b/gcc/testsuite/rust.test/const-enum-tuple2.rs deleted file mode 100644 index 5d7a161..0000000 --- a/gcc/testsuite/rust.test/const-enum-tuple2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V0, V16(u16) } -static C: (E, u16, u16) = (V0, 0x600D, 0xBAD); - -pub fn main() { - let (_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-tuplestruct.rs b/gcc/testsuite/rust.test/const-enum-tuplestruct.rs deleted file mode 100644 index 40137af..0000000 --- a/gcc/testsuite/rust.test/const-enum-tuplestruct.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V16(u16), V32(u32) } -struct S(E, u16, u16); -static C: S = S(V16(0xDEAD), 0x600D, 0xBAD); - -pub fn main() { - let S(_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-tuplestruct2.rs b/gcc/testsuite/rust.test/const-enum-tuplestruct2.rs deleted file mode 100644 index f6345ef..0000000 --- a/gcc/testsuite/rust.test/const-enum-tuplestruct2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V0, V16(u16) } -struct S(E, u16, u16); -static C: S = S(V0, 0x600D, 0xBAD); - -pub fn main() { - let S(_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/gcc/testsuite/rust.test/const-enum-vec-index.rs b/gcc/testsuite/rust.test/const-enum-vec-index.rs deleted file mode 100644 index 5b4ce1b..0000000 --- a/gcc/testsuite/rust.test/const-enum-vec-index.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V1(int), V0 } -static C: &'static [E] = &[V0, V1(0xDEADBEE)]; -static C0: E = C[0]; -static C1: E = C[1]; - -pub fn main() { - match C0 { - V0 => (), - _ => fail2!() - } - match C1 { - V1(n) => assert!(n == 0xDEADBEE), - _ => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/const-enum-vec-ptr.rs b/gcc/testsuite/rust.test/const-enum-vec-ptr.rs deleted file mode 100644 index 8b90504..0000000 --- a/gcc/testsuite/rust.test/const-enum-vec-ptr.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V1(int), V0 } -static C: &'static [E] = &[V0, V1(0xDEADBEE), V0]; - -pub fn main() { - match C[1] { - V1(n) => assert!(n == 0xDEADBEE), - _ => fail2!() - } - match C[2] { - V0 => (), - _ => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/const-enum-vector.rs b/gcc/testsuite/rust.test/const-enum-vector.rs deleted file mode 100644 index cff5d46..0000000 --- a/gcc/testsuite/rust.test/const-enum-vector.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum E { V1(int), V0 } -static C: [E, ..3] = [V0, V1(0xDEADBEE), V0]; - -pub fn main() { - match C[1] { - V1(n) => assert!(n == 0xDEADBEE), - _ => fail2!() - } - match C[2] { - V0 => (), - _ => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/const-expr-in-fixed-length-vec.rs b/gcc/testsuite/rust.test/const-expr-in-fixed-length-vec.rs deleted file mode 100644 index 48b41d0..0000000 --- a/gcc/testsuite/rust.test/const-expr-in-fixed-length-vec.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that constant expressions can be used for declaring the -// type of a fixed length vector. - -pub fn main() { - - static FOO: int = 2; - let _v: [int, ..FOO*3]; - -} diff --git a/gcc/testsuite/rust.test/const-expr-in-vec-repeat.rs b/gcc/testsuite/rust.test/const-expr-in-vec-repeat.rs deleted file mode 100644 index f10cef52..0000000 --- a/gcc/testsuite/rust.test/const-expr-in-vec-repeat.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that constant expressions can be used in vec repeat syntax. - -pub fn main() { - - static FOO: int = 2; - let _v = [0, ..FOO*3*2/2]; - -} diff --git a/gcc/testsuite/rust.test/const-extern-function.rs b/gcc/testsuite/rust.test/const-extern-function.rs deleted file mode 100644 index 501a879..0000000 --- a/gcc/testsuite/rust.test/const-extern-function.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern fn foopy() {} - -static f: extern "C" fn() = foopy; -static s: S = S { f: foopy }; - -struct S { - f: extern "C" fn() -} - -pub fn main() { - assert_eq!(foopy, f); - assert_eq!(f, s.f); -} diff --git a/gcc/testsuite/rust.test/const-fields-and-indexing.rs b/gcc/testsuite/rust.test/const-fields-and-indexing.rs deleted file mode 100644 index e99b0ed..0000000 --- a/gcc/testsuite/rust.test/const-fields-and-indexing.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static x : [int, ..4] = [1,2,3,4]; -static p : int = x[2]; -static y : &'static [int] = &[1,2,3,4]; -static q : int = y[2]; - -struct S {a: int, b: int} - -static s : S = S {a: 10, b: 20}; -static t : int = s.b; - -struct K {a: int, b: int, c: D} -struct D { d: int, e: int } - -static k : K = K {a: 10, b: 20, c: D {d: 30, e: 40}}; -static m : int = k.c.e; - -pub fn main() { - println!("{:?}", p); - println!("{:?}", q); - println!("{:?}", t); - assert_eq!(p, 3); - assert_eq!(q, 3); - assert_eq!(t, 20); -} diff --git a/gcc/testsuite/rust.test/const-fn-val.rs b/gcc/testsuite/rust.test/const-fn-val.rs deleted file mode 100644 index dfcfb30..0000000 --- a/gcc/testsuite/rust.test/const-fn-val.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo() -> int { - return 0xca7f000d; -} - -struct Bar<'self> { f: &'self fn() -> int } - -static b : Bar<'static> = Bar { f: foo }; - -pub fn main() { - assert_eq!((b.f)(), 0xca7f000d); -} diff --git a/gcc/testsuite/rust.test/const-negative.rs b/gcc/testsuite/rust.test/const-negative.rs deleted file mode 100644 index 4e2be01..0000000 --- a/gcc/testsuite/rust.test/const-negative.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #358 - -static toplevel_mod: int = -1; - -pub fn main() { - assert_eq!(toplevel_mod, -1); -} diff --git a/gcc/testsuite/rust.test/const-nullary-enum.rs b/gcc/testsuite/rust.test/const-nullary-enum.rs deleted file mode 100644 index ac9a7fa..0000000 --- a/gcc/testsuite/rust.test/const-nullary-enum.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Foo { - Bar, - Baz, - Boo, -} - -static X: Foo = Bar; - -pub fn main() { - match X { - Bar => {} - Baz | Boo => fail2!() - } - match Y { - Baz => {} - Bar | Boo => fail2!() - } -} - -static Y: Foo = Baz; diff --git a/gcc/testsuite/rust.test/const-nullary-univariant-enum.rs b/gcc/testsuite/rust.test/const-nullary-univariant-enum.rs deleted file mode 100644 index 30fbe38..0000000 --- a/gcc/testsuite/rust.test/const-nullary-univariant-enum.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Foo { - Bar = 0xDEADBEE -} - -static X: Foo = Bar; - -pub fn main() { - assert_eq!((X as uint), 0xDEADBEE); - assert_eq!((Y as uint), 0xDEADBEE); -} - -static Y: Foo = Bar; diff --git a/gcc/testsuite/rust.test/const-rec-and-tup.rs b/gcc/testsuite/rust.test/const-rec-and-tup.rs deleted file mode 100644 index e6680fe..0000000 --- a/gcc/testsuite/rust.test/const-rec-and-tup.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair { a: f64, b: f64 } - -struct AnotherPair { x: (i64, i64), y: Pair } - -static x : (i32,i32) = (0xfeedf00dd,0xca11ab1e); -static y : AnotherPair = AnotherPair{ x: (0xf0f0f0f0_f0f0f0f0, - 0xabababab_abababab), - y: Pair { a: 3.14159265358979323846, - b: 2.7182818284590452354 }}; - -pub fn main() { - let (p, _) = y.x; - assert_eq!(p, - 1085102592571150096); - println!("{:#x}", p); -} diff --git a/gcc/testsuite/rust.test/const-region-ptrs-noncopy.rs b/gcc/testsuite/rust.test/const-region-ptrs-noncopy.rs deleted file mode 100644 index 3eaf733..0000000 --- a/gcc/testsuite/rust.test/const-region-ptrs-noncopy.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::ptr; - -type Big = [u64, ..8]; -struct Pair<'self> { a: int, b: &'self Big } -static x: &'static Big = &([13, 14, 10, 13, 11, 14, 14, 15]); -static y: &'static Pair<'static> = &Pair {a: 15, b: x}; - -pub fn main() { - assert_eq!(ptr::to_unsafe_ptr(x), ptr::to_unsafe_ptr(y.b)); -} diff --git a/gcc/testsuite/rust.test/const-region-ptrs.rs b/gcc/testsuite/rust.test/const-region-ptrs.rs deleted file mode 100644 index c5884ae..0000000 --- a/gcc/testsuite/rust.test/const-region-ptrs.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair<'self> { a: int, b: &'self int } - -static x: &'static int = &10; - -static y: &'static Pair<'static> = &Pair {a: 15, b: x}; - -pub fn main() { - println!("x = {}", *x); - println!("y = \\{a: {}, b: {}\\}", y.a, *(y.b)); - assert_eq!(*x, 10); - assert_eq!(*(y.b), 10); -} diff --git a/gcc/testsuite/rust.test/const-str-ptr.rs b/gcc/testsuite/rust.test/const-str-ptr.rs deleted file mode 100644 index d12a0ab..0000000 --- a/gcc/testsuite/rust.test/const-str-ptr.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::str; - -static A: [u8, ..2] = ['h' as u8, 'i' as u8]; -static B: &'static [u8, ..2] = &A; -static C: *u8 = B as *u8; - -pub fn main() { - unsafe { - let foo = &A as *u8; - assert_eq!(str::raw::from_utf8(A), ~"hi"); - assert_eq!(str::raw::from_buf_len(foo, A.len()), ~"hi"); - assert_eq!(str::raw::from_buf_len(C, B.len()), ~"hi"); - assert!(*C == A[0]); - assert!(*(&B[0] as *u8) == A[0]); - - let bar = str::raw::from_utf8(A).to_c_str(); - assert_eq!(bar.with_ref(|buf| str::raw::from_c_str(buf)), ~"hi"); - } -} diff --git a/gcc/testsuite/rust.test/const-struct-offsets.rs b/gcc/testsuite/rust.test/const-struct-offsets.rs deleted file mode 100644 index 2bb0516..0000000 --- a/gcc/testsuite/rust.test/const-struct-offsets.rs +++ /dev/null @@ -1,13 +0,0 @@ -enum Foo { - IntVal(i32), - Int64Val(i64) -} - -struct Bar { - i: i32, - v: Foo -} - -static bar: Bar = Bar { i: 0, v: IntVal(0) }; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/const-struct.rs b/gcc/testsuite/rust.test/const-struct.rs deleted file mode 100644 index af6dd40..0000000 --- a/gcc/testsuite/rust.test/const-struct.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp; - -struct foo { a: int, b: int, c: int } - -impl cmp::Eq for foo { - fn eq(&self, other: &foo) -> bool { - (*self).a == (*other).a && - (*self).b == (*other).b && - (*self).c == (*other).c - } - fn ne(&self, other: &foo) -> bool { !(*self).eq(other) } -} - -static x : foo = foo { a:1, b:2, c: 3 }; -static y : foo = foo { b:2, c:3, a: 1 }; -static z : &'static foo = &foo { a: 10, b: 22, c: 12 }; -static w : foo = foo { a:5, ..x }; - -pub fn main() { - assert_eq!(x.b, 2); - assert_eq!(x, y); - assert_eq!(z.b, 22); - assert_eq!(w.a, 5); - assert_eq!(w.c, 3); - println!("{:#x}", x.b); - println!("{:#x}", z.c); -} diff --git a/gcc/testsuite/rust.test/const-tuple-struct.rs b/gcc/testsuite/rust.test/const-tuple-struct.rs deleted file mode 100644 index 54116dd..0000000 --- a/gcc/testsuite/rust.test/const-tuple-struct.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Bar(int, int); - -static X: Bar = Bar(1, 2); - -pub fn main() { - match X { - Bar(x, y) => { - assert_eq!(x, 1); - assert_eq!(y, 2); - } - } -} diff --git a/gcc/testsuite/rust.test/const-unit-struct.rs b/gcc/testsuite/rust.test/const-unit-struct.rs deleted file mode 100644 index 7e6d9f0..0000000 --- a/gcc/testsuite/rust.test/const-unit-struct.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo; - -static X: Foo = Foo; - -pub fn main() { - match X { - Foo => {} - } -} diff --git a/gcc/testsuite/rust.test/const-vec-of-fns.rs b/gcc/testsuite/rust.test/const-vec-of-fns.rs deleted file mode 100644 index 6117ea9..0000000 --- a/gcc/testsuite/rust.test/const-vec-of-fns.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// FIXME: #7385: hits a codegen bug on OS X x86_64 - -/*! - * Try to double-check that static fns have the right size (with or - * without dummy env ptr, as appropriate) by iterating a size-2 array. - * If the static size differs from the runtime size, the second element - * should be read as a null or otherwise wrong pointer and crash. - */ - -fn f() { } -static bare_fns: &'static [extern fn()] = &[f, f]; -struct S<'self>(&'self fn()); -static closures: &'static [S<'static>] = &[S(f), S(f)]; - -pub fn main() { - for &bare_fn in bare_fns.iter() { bare_fn() } - for &closure in closures.iter() { (*closure)() } -} diff --git a/gcc/testsuite/rust.test/const-vec-syntax.rs b/gcc/testsuite/rust.test/const-vec-syntax.rs deleted file mode 100644 index 84ee54c..0000000 --- a/gcc/testsuite/rust.test/const-vec-syntax.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(_: &[int]) {} - -pub fn main() { - let v = [ 1, 2, 3 ]; - f(v); -} diff --git a/gcc/testsuite/rust.test/const-vecs-and-slices.rs b/gcc/testsuite/rust.test/const-vecs-and-slices.rs deleted file mode 100644 index 3935bb2..0000000 --- a/gcc/testsuite/rust.test/const-vecs-and-slices.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static x : [int, ..4] = [1,2,3,4]; -static y : &'static [int] = &[1,2,3,4]; - -pub fn main() { - println!("{:?}", x[1]); - println!("{:?}", y[1]); - assert_eq!(x[1], 2); - assert_eq!(x[3], 4); - assert_eq!(x[3], y[3]); -} diff --git a/gcc/testsuite/rust.test/const.rs b/gcc/testsuite/rust.test/const.rs deleted file mode 100644 index 5696c16..0000000 --- a/gcc/testsuite/rust.test/const.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -static i: int = 10; - -pub fn main() { info2!("{}", i); } diff --git a/gcc/testsuite/rust.test/consts-in-patterns.rs b/gcc/testsuite/rust.test/consts-in-patterns.rs deleted file mode 100644 index 788c305..0000000 --- a/gcc/testsuite/rust.test/consts-in-patterns.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static FOO: int = 10; -static BAR: int = 3; - -pub fn main() { - let x: int = 3; - let y = match x { - FOO => 1, - BAR => 2, - _ => 3 - }; - assert_eq!(y, 2); -} diff --git a/gcc/testsuite/rust.test/core-rt-smoke.rs b/gcc/testsuite/rust.test/core-rt-smoke.rs deleted file mode 100644 index 0260edf..0000000 --- a/gcc/testsuite/rust.test/core-rt-smoke.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -// A simple test of starting the runtime manually - -#[start] -fn start(argc: int, argv: **u8) -> int { - do std::rt::start(argc, argv) { - info2!("creating my own runtime is joy"); - } -} diff --git a/gcc/testsuite/rust.test/core-run-destroy.rs b/gcc/testsuite/rust.test/core-run-destroy.rs deleted file mode 100644 index 0e0e52c..0000000 --- a/gcc/testsuite/rust.test/core-run-destroy.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// compile-flags:--test - -// NB: These tests kill child processes. Valgrind sees these children as leaking -// memory, which makes for some *confusing* logs. That's why these are here -// instead of in std. - -use std::libc; -use std::run; -use std::str; - -#[test] -fn test_destroy_once() { - let mut p = run::Process::new("echo", [], run::ProcessOptions::new()); - p.destroy(); // this shouldn't crash (and nor should the destructor) -} - -#[test] -fn test_destroy_twice() { - let mut p = run::Process::new("echo", [], run::ProcessOptions::new()); - p.destroy(); // this shouldnt crash... - p.destroy(); // ...and nor should this (and nor should the destructor) -} - -fn test_destroy_actually_kills(force: bool) { - - #[cfg(unix)] - static BLOCK_COMMAND: &'static str = "cat"; - - #[cfg(windows)] - static BLOCK_COMMAND: &'static str = "cmd"; - - #[cfg(unix,not(target_os="android"))] - fn process_exists(pid: libc::pid_t) -> bool { - let run::ProcessOutput {output, _} = run::process_output("ps", [~"-p", pid.to_str()]); - str::from_utf8(output).contains(pid.to_str()) - } - - #[cfg(unix,target_os="android")] - fn process_exists(pid: libc::pid_t) -> bool { - let run::ProcessOutput {output, _} = run::process_output("/system/bin/ps", [pid.to_str()]); - str::from_utf8(output).contains(~"root") - } - - #[cfg(windows)] - fn process_exists(pid: libc::pid_t) -> bool { - #[fixed_stack_segment]; - - use std::libc::types::os::arch::extra::DWORD; - use std::libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess}; - use std::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE }; - - unsafe { - let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); - if proc.is_null() { - return false; - } - // proc will be non-null if the process is alive, or if it died recently - let mut status = 0; - GetExitCodeProcess(proc, &mut status); - CloseHandle(proc); - return status == STILL_ACTIVE; - } - } - - // this process will stay alive indefinitely trying to read from stdin - let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new()); - - assert!(process_exists(p.get_id())); - - if force { - p.force_destroy(); - } else { - p.destroy(); - } - - assert!(!process_exists(p.get_id())); -} - -#[test] -fn test_unforced_destroy_actually_kills() { - test_destroy_actually_kills(false); -} - -#[test] -fn test_forced_destroy_actually_kills() { - test_destroy_actually_kills(true); -} diff --git a/gcc/testsuite/rust.test/crate-method-reexport-grrrrrrr.rs b/gcc/testsuite/rust.test/crate-method-reexport-grrrrrrr.rs deleted file mode 100644 index ac79a22..0000000 --- a/gcc/testsuite/rust.test/crate-method-reexport-grrrrrrr.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This is a regression test that the metadata for the -// name_pool::methods impl in the other crate is reachable from this -// crate. - -// xfail-fast -// aux-build:crate-method-reexport-grrrrrrr2.rs - -extern mod crate_method_reexport_grrrrrrr2; - -pub fn main() { - use crate_method_reexport_grrrrrrr2::rust::add; - use crate_method_reexport_grrrrrrr2::rust::cx; - let x = @(); - x.cx(); - let y = (); - y.add(~"hi"); -} diff --git a/gcc/testsuite/rust.test/crateresolve1.rs b/gcc/testsuite/rust.test/crateresolve1.rs deleted file mode 100644 index 737a604..0000000 --- a/gcc/testsuite/rust.test/crateresolve1.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve1-1.rs -// aux-build:crateresolve1-2.rs -// aux-build:crateresolve1-3.rs - -extern mod crateresolve1(vers = "0.2"); - -pub fn main() { - assert_eq!(crateresolve1::f(), 20); -} diff --git a/gcc/testsuite/rust.test/crateresolve2.rs b/gcc/testsuite/rust.test/crateresolve2.rs deleted file mode 100644 index 1ffbf83..0000000 --- a/gcc/testsuite/rust.test/crateresolve2.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve2-1.rs -// aux-build:crateresolve2-2.rs -// aux-build:crateresolve2-3.rs - -mod a { - extern mod crateresolve2(vers = "0.1"); - pub fn f() { assert!(crateresolve2::f() == 10); } -} - -mod b { - extern mod crateresolve2(vers = "0.2"); - pub fn f() { assert!(crateresolve2::f() == 20); } -} - -mod c { - extern mod crateresolve2(vers = "0.3"); - pub fn f() { assert!(crateresolve2::f() == 30); } -} - -pub fn main() { - a::f(); - b::f(); - c::f(); -} diff --git a/gcc/testsuite/rust.test/crateresolve3.rs b/gcc/testsuite/rust.test/crateresolve3.rs deleted file mode 100644 index 519e67a..0000000 --- a/gcc/testsuite/rust.test/crateresolve3.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve3-1.rs -// aux-build:crateresolve3-2.rs - -// verify able to link with crates with same name but different versions -// as long as no name collision on invoked functions. - -mod a { - extern mod crateresolve3(vers = "0.1"); - pub fn f() { assert!(crateresolve3::f() == 10); } -} - -mod b { - extern mod crateresolve3(vers = "0.2"); - pub fn f() { assert!(crateresolve3::g() == 20); } -} - -pub fn main() { - a::f(); - b::f(); -} diff --git a/gcc/testsuite/rust.test/crateresolve4.rs b/gcc/testsuite/rust.test/crateresolve4.rs deleted file mode 100644 index ead2a21..0000000 --- a/gcc/testsuite/rust.test/crateresolve4.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve4a-1.rs -// aux-build:crateresolve4a-2.rs -// aux-build:crateresolve4b-1.rs -// aux-build:crateresolve4b-2.rs - -pub mod a { - extern mod crateresolve4b(vers = "0.1"); - pub fn f() { assert!(crateresolve4b::f() == 20); } -} - -pub mod b { - extern mod crateresolve4b(vers = "0.2"); - pub fn f() { assert!(crateresolve4b::g() == 10); } -} - -pub fn main() { - a::f(); - b::f(); -} diff --git a/gcc/testsuite/rust.test/crateresolve5.rs b/gcc/testsuite/rust.test/crateresolve5.rs deleted file mode 100644 index 688853d..0000000 --- a/gcc/testsuite/rust.test/crateresolve5.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve5-1.rs -// aux-build:crateresolve5-2.rs - -extern mod cr5_1 (name = "crateresolve5", vers = "0.1"); -extern mod cr5_2 (name = "crateresolve5", vers = "0.2"); - -pub fn main() { - // Structural types can be used between two versions of the same crate - assert!(cr5_1::struct_nameval().name == cr5_2::struct_nameval().name); - assert!(cr5_1::struct_nameval().val == cr5_2::struct_nameval().val); - // Make sure these are actually two different crates - assert!(cr5_1::f() == 10 && cr5_2::f() == 20); -} diff --git a/gcc/testsuite/rust.test/crateresolve6.rs b/gcc/testsuite/rust.test/crateresolve6.rs deleted file mode 100644 index 883f486..0000000 --- a/gcc/testsuite/rust.test/crateresolve6.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve_calories-1.rs -// aux-build:crateresolve_calories-2.rs -// error-pattern:mismatched types - -// These both have the same version but differ in other metadata -extern mod cr6_1 (name = "crateresolve_calories", vers = "0.1", calories="100"); -extern mod cr6_2 (name = "crateresolve_calories", vers = "0.1", calories="200"); - -pub fn main() { - assert_eq!(cr6_1::f(), 100); - assert_eq!(cr6_2::f(), 200); -} diff --git a/gcc/testsuite/rust.test/crateresolve7.rs b/gcc/testsuite/rust.test/crateresolve7.rs deleted file mode 100644 index 86fc72a..0000000 --- a/gcc/testsuite/rust.test/crateresolve7.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:crateresolve_calories-1.rs -// aux-build:crateresolve_calories-2.rs -// aux-build:crateresolve7x.rs - -extern mod crateresolve7x; - -pub fn main() { - assert_eq!(crateresolve7x::a::f(), 100); - assert_eq!(crateresolve7x::b::f(), 200); -} diff --git a/gcc/testsuite/rust.test/cross-crate-const-pat.rs b/gcc/testsuite/rust.test/cross-crate-const-pat.rs deleted file mode 100644 index 0a0e235..0000000 --- a/gcc/testsuite/rust.test/cross-crate-const-pat.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:cci_const.rs - -extern mod cci_const; - -fn main() { - let x = cci_const::uint_val; - match x { - cci_const::uint_val => {} - _ => {} - } -} diff --git a/gcc/testsuite/rust.test/cross-crate-newtype-struct-pat.rs b/gcc/testsuite/rust.test/cross-crate-newtype-struct-pat.rs deleted file mode 100644 index 37d5c5c..0000000 --- a/gcc/testsuite/rust.test/cross-crate-newtype-struct-pat.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:newtype_struct_xc.rs - -extern mod newtype_struct_xc; - -fn main() { - let x = newtype_struct_xc::Au(21); - match x { - newtype_struct_xc::Au(n) => assert_eq!(n, 21) - } -} diff --git a/gcc/testsuite/rust.test/cycle-collection.rs b/gcc/testsuite/rust.test/cycle-collection.rs deleted file mode 100644 index 0e9be02..0000000 --- a/gcc/testsuite/rust.test/cycle-collection.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum taggy { - cons(@mut taggy), - nil, -} - -fn f() { - let box = @mut nil; - *box = cons(box); -} - -pub fn main() { - f(); -} diff --git a/gcc/testsuite/rust.test/cycle-collection2.rs b/gcc/testsuite/rust.test/cycle-collection2.rs deleted file mode 100644 index 46c0c52..0000000 --- a/gcc/testsuite/rust.test/cycle-collection2.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct foo { - z: Option<@Invokable>, -} - -struct Thing { - w: @mut foo, -} - -trait Invokable { - fn f(&self); -} - -impl Invokable for Thing { - fn f(&self) { - nop_foo(self.w); - } -} - -fn nop() { } -fn nop_foo(_x : @mut foo) { } - -pub fn main() { - let w = @mut foo { - z: None, - }; - let x = @Thing { - w: w, - } as @Invokable; - w.z = Some(x); -} diff --git a/gcc/testsuite/rust.test/dead-code-one-arm-if.rs b/gcc/testsuite/rust.test/dead-code-one-arm-if.rs deleted file mode 100644 index 9a2819c..0000000 --- a/gcc/testsuite/rust.test/dead-code-one-arm-if.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { if 1 == 1 { return; } info2!("Paul is dead"); } diff --git a/gcc/testsuite/rust.test/deep-vector.rs b/gcc/testsuite/rust.test/deep-vector.rs deleted file mode 100644 index e6ae892..0000000 --- a/gcc/testsuite/rust.test/deep-vector.rs +++ /dev/null @@ -1,2012 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x = ~[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ]; -} diff --git a/gcc/testsuite/rust.test/deep-vector2.rs b/gcc/testsuite/rust.test/deep-vector2.rs deleted file mode 100644 index b644d1a..0000000 --- a/gcc/testsuite/rust.test/deep-vector2.rs +++ /dev/null @@ -1,8012 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x = ~[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ]; -} diff --git a/gcc/testsuite/rust.test/deep.rs b/gcc/testsuite/rust.test/deep.rs deleted file mode 100644 index ebb033d..0000000 --- a/gcc/testsuite/rust.test/deep.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn f(x: int) -> int { - if x == 1 { return 1; } else { let y: int = 1 + f(x - 1); return y; } -} - -pub fn main() { assert!((f(5000) == 5000)); } diff --git a/gcc/testsuite/rust.test/default-method-parsing.rs b/gcc/testsuite/rust.test/default-method-parsing.rs deleted file mode 100644 index 639ea59..0000000 --- a/gcc/testsuite/rust.test/default-method-parsing.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn m(&self, _:int) { } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/default-method-simple.rs b/gcc/testsuite/rust.test/default-method-simple.rs deleted file mode 100644 index 4072d1d..0000000 --- a/gcc/testsuite/rust.test/default-method-simple.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -trait Foo { - fn f(&self) { - println("Hello!"); - self.g(); - } - fn g(&self); -} - -struct A { - x: int -} - -impl Foo for A { - fn g(&self) { - println("Goodbye!"); - } -} - -pub fn main() { - let a = A { x: 1 }; - a.f(); -} diff --git a/gcc/testsuite/rust.test/default-method-supertrait-vtable.rs b/gcc/testsuite/rust.test/default-method-supertrait-vtable.rs deleted file mode 100644 index 2bcf264..0000000 --- a/gcc/testsuite/rust.test/default-method-supertrait-vtable.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// Tests that we can call a function bounded over a supertrait from -// a default method - -fn require_y(x: T) -> int { x.y() } - -trait Y { - fn y(self) -> int; -} - - -trait Z: Y { - fn x(self) -> int { - require_y(self) - } -} - -impl Y for int { - fn y(self) -> int { self } -} - -impl Z for int {} - -pub fn main() { - assert_eq!(12.x(), 12); -} diff --git a/gcc/testsuite/rust.test/deref-lval.rs b/gcc/testsuite/rust.test/deref-lval.rs deleted file mode 100644 index bc0b51c..0000000 --- a/gcc/testsuite/rust.test/deref-lval.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { let x = @mut 5; *x = 1000; info2!("{:?}", *x); } diff --git a/gcc/testsuite/rust.test/deref.rs b/gcc/testsuite/rust.test/deref.rs deleted file mode 100644 index 9951531..0000000 --- a/gcc/testsuite/rust.test/deref.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let x: @int = @10; - let _y: int = *x; -} diff --git a/gcc/testsuite/rust.test/deriving-clone-enum.rs b/gcc/testsuite/rust.test/deriving-clone-enum.rs deleted file mode 100644 index 9ce965a..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-enum.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone, DeepClone)] -enum E { - A, - B(()), - C -} - -pub fn main() { - let _ = A.clone(); - let _ = B(()).deep_clone(); -} diff --git a/gcc/testsuite/rust.test/deriving-clone-generic-enum.rs b/gcc/testsuite/rust.test/deriving-clone-generic-enum.rs deleted file mode 100644 index 61696c2..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-generic-enum.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone, DeepClone)] -enum E { - A(T), - B(T,U), - C -} - -pub fn main() { - let _ = A::(1i).clone(); - let _ = B(1i, 1.234).deep_clone(); -} diff --git a/gcc/testsuite/rust.test/deriving-clone-generic-struct.rs b/gcc/testsuite/rust.test/deriving-clone-generic-struct.rs deleted file mode 100644 index fd300cb..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-generic-struct.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone, DeepClone)] -struct S { - foo: (), - bar: (), - baz: T, -} - -pub fn main() { - let _ = S { foo: (), bar: (), baz: 1i }.clone().deep_clone(); -} diff --git a/gcc/testsuite/rust.test/deriving-clone-generic-tuple-struct.rs b/gcc/testsuite/rust.test/deriving-clone-generic-tuple-struct.rs deleted file mode 100644 index 02043b5..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-generic-tuple-struct.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone, DeepClone)] -struct S(T, ()); - -pub fn main() { - let _ = S(1i, ()).clone().deep_clone(); -} diff --git a/gcc/testsuite/rust.test/deriving-clone-struct.rs b/gcc/testsuite/rust.test/deriving-clone-struct.rs deleted file mode 100644 index 52858a4..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone, DeepClone)] -struct S { - _int: int, - _i8: i8, - _i16: i16, - _i32: i32, - _i64: i64, - - _uint: uint, - _u8: u8, - _u16: u16, - _u32: u32, - _u64: u64, - - _f32: f32, - _f64: f64, - - _bool: bool, - _char: char, - _nil: () -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/deriving-clone-tuple-struct.rs b/gcc/testsuite/rust.test/deriving-clone-tuple-struct.rs deleted file mode 100644 index 1e5c8c8..0000000 --- a/gcc/testsuite/rust.test/deriving-clone-tuple-struct.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Clone)] -struct S((), ()); - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/deriving-cmp-generic-enum.rs b/gcc/testsuite/rust.test/deriving-cmp-generic-enum.rs deleted file mode 100644 index 094d17c..0000000 --- a/gcc/testsuite/rust.test/deriving-cmp-generic-enum.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -enum E { - E0, - E1(T), - E2(T,T) -} - -pub fn main() { - let e0 = E0; - let e11 = E1(1); - let e12 = E1(2); - let e21 = E2(1, 1); - let e22 = E2(1, 2); - - // in order for both Ord and TotalOrd - let es = [e0, e11, e12, e21, e22]; - - for (i, e1) in es.iter().enumerate() { - for (j, e2) in es.iter().enumerate() { - let ord = i.cmp(&j); - - let eq = i == j; - let lt = i < j; - let le = i <= j; - let gt = i > j; - let ge = i >= j; - - // Eq - assert_eq!(*e1 == *e2, eq); - assert_eq!(*e1 != *e2, !eq); - - // TotalEq - assert_eq!(e1.equals(e2), eq); - - // Ord - assert_eq!(*e1 < *e2, lt); - assert_eq!(*e1 > *e2, gt); - - assert_eq!(*e1 <= *e2, le); - assert_eq!(*e1 >= *e2, ge); - - // TotalOrd - assert_eq!(e1.cmp(e2), ord); - } - } -} diff --git a/gcc/testsuite/rust.test/deriving-cmp-generic-struct-enum.rs b/gcc/testsuite/rust.test/deriving-cmp-generic-struct-enum.rs deleted file mode 100644 index aedf473..0000000 --- a/gcc/testsuite/rust.test/deriving-cmp-generic-struct-enum.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -enum ES { - ES1 { x: T }, - ES2 { x: T, y: T } -} - - -pub fn main() { - let (es11, es12, es21, es22) = (ES1 {x: 1}, ES1 {x: 2}, ES2 {x: 1, y: 1}, ES2 {x: 1, y: 2}); - - // in order for both Ord and TotalOrd - let ess = [es11, es12, es21, es22]; - - for (i, es1) in ess.iter().enumerate() { - for (j, es2) in ess.iter().enumerate() { - let ord = i.cmp(&j); - - let eq = i == j; - let (lt, le) = (i < j, i <= j); - let (gt, ge) = (i > j, i >= j); - - // Eq - assert_eq!(*es1 == *es2, eq); - assert_eq!(*es1 != *es2, !eq); - - // TotalEq - assert_eq!(es1.equals(es2), eq); - - // Ord - assert_eq!(*es1 < *es2, lt); - assert_eq!(*es1 > *es2, gt); - - assert_eq!(*es1 <= *es2, le); - assert_eq!(*es1 >= *es2, ge); - - // TotalOrd - assert_eq!(es1.cmp(es2), ord); - } - } -} diff --git a/gcc/testsuite/rust.test/deriving-cmp-generic-struct.rs b/gcc/testsuite/rust.test/deriving-cmp-generic-struct.rs deleted file mode 100644 index d04bdee..0000000 --- a/gcc/testsuite/rust.test/deriving-cmp-generic-struct.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -struct S { - x: T, - y: T -} - -pub fn main() { - let s1 = S {x: 1, y: 1}; - let s2 = S {x: 1, y: 2}; - - // in order for both Ord and TotalOrd - let ss = [s1, s2]; - - for (i, s1) in ss.iter().enumerate() { - for (j, s2) in ss.iter().enumerate() { - let ord = i.cmp(&j); - - let eq = i == j; - let lt = i < j; - let le = i <= j; - let gt = i > j; - let ge = i >= j; - - // Eq - assert_eq!(*s1 == *s2, eq); - assert_eq!(*s1 != *s2, !eq); - - // TotalEq - assert_eq!(s1.equals(s2), eq); - - // Ord - assert_eq!(*s1 < *s2, lt); - assert_eq!(*s1 > *s2, gt); - - assert_eq!(*s1 <= *s2, le); - assert_eq!(*s1 >= *s2, ge); - - // TotalOrd - assert_eq!(s1.cmp(s2), ord); - } - } -} diff --git a/gcc/testsuite/rust.test/deriving-cmp-generic-tuple-struct.rs b/gcc/testsuite/rust.test/deriving-cmp-generic-tuple-struct.rs deleted file mode 100644 index 5d4cf7c..0000000 --- a/gcc/testsuite/rust.test/deriving-cmp-generic-tuple-struct.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -struct TS(T,T); - - -pub fn main() { - let ts1 = TS(1, 1); - let ts2 = TS(1, 2); - - // in order for both Ord and TotalOrd - let tss = [ts1, ts2]; - - for (i, ts1) in tss.iter().enumerate() { - for (j, ts2) in tss.iter().enumerate() { - let ord = i.cmp(&j); - - let eq = i == j; - let lt = i < j; - let le = i <= j; - let gt = i > j; - let ge = i >= j; - - // Eq - assert_eq!(*ts1 == *ts2, eq); - assert_eq!(*ts1 != *ts2, !eq); - - // TotalEq - assert_eq!(ts1.equals(ts2), eq); - - // Ord - assert_eq!(*ts1 < *ts2, lt); - assert_eq!(*ts1 > *ts2, gt); - - assert_eq!(*ts1 <= *ts2, le); - assert_eq!(*ts1 >= *ts2, ge); - - // TotalOrd - assert_eq!(ts1.cmp(ts2), ord); - } - } -} diff --git a/gcc/testsuite/rust.test/deriving-cmp-shortcircuit.rs b/gcc/testsuite/rust.test/deriving-cmp-shortcircuit.rs deleted file mode 100644 index 940ddc3..0000000 --- a/gcc/testsuite/rust.test/deriving-cmp-shortcircuit.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// check that the derived impls for the comparison traits shortcircuit -// where possible, by having a type that fails when compared as the -// second element, so this passes iff the instances shortcircuit. - -pub struct FailCmp; -impl Eq for FailCmp { - fn eq(&self, _: &FailCmp) -> bool { fail2!("eq") } -} - -impl Ord for FailCmp { - fn lt(&self, _: &FailCmp) -> bool { fail2!("lt") } -} - -impl TotalEq for FailCmp { - fn equals(&self, _: &FailCmp) -> bool { fail2!("equals") } -} - -impl TotalOrd for FailCmp { - fn cmp(&self, _: &FailCmp) -> Ordering { fail2!("cmp") } -} - -#[deriving(Eq,Ord,TotalEq,TotalOrd)] -struct ShortCircuit { - x: int, - y: FailCmp -} - -pub fn main() { - let a = ShortCircuit { x: 1, y: FailCmp }; - let b = ShortCircuit { x: 2, y: FailCmp }; - - assert!(a != b); - assert!(a < b); - assert!(!a.equals(&b)); - assert_eq!(a.cmp(&b), ::std::cmp::Less); -} diff --git a/gcc/testsuite/rust.test/deriving-encodable-decodable.rs b/gcc/testsuite/rust.test/deriving-encodable-decodable.rs deleted file mode 100644 index b1c5f2f..0000000 --- a/gcc/testsuite/rust.test/deriving-encodable-decodable.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This actually tests a lot more than just encodable/decodable, but it gets the -// job done at least - -// xfail-fast - -#[feature(struct_variant)]; - -extern mod extra; - -use std::io; -use std::rand::{random, Rand}; -use extra::serialize::{Encodable, Decodable}; -use extra::ebml; -use extra::ebml::writer::Encoder; -use extra::ebml::reader::Decoder; - -#[deriving(Encodable, Decodable, Eq, Rand)] -struct A; -#[deriving(Encodable, Decodable, Eq, Rand)] -struct B(int); -#[deriving(Encodable, Decodable, Eq, Rand)] -struct C(int, int, uint); - -#[deriving(Encodable, Decodable, Eq, Rand)] -struct D { - a: int, - b: uint, -} - -#[deriving(Encodable, Decodable, Eq, Rand)] -enum E { - E1, - E2(uint), - E3(D), - E4{ x: uint }, -} - -#[deriving(Encodable, Decodable, Eq, Rand)] -enum F { F1 } - -#[deriving(Encodable, Decodable, Eq, Rand)] -struct G { - t: T -} - -fn roundtrip + Decodable>() { - let obj: T = random(); - let bytes = do io::with_bytes_writer |w| { - let mut e = Encoder(w); - obj.encode(&mut e); - }; - let doc = ebml::reader::Doc(@bytes); - let mut dec = Decoder(doc); - let obj2 = Decodable::decode(&mut dec); - assert!(obj == obj2); -} - -pub fn main() { - roundtrip::(); - roundtrip::(); - roundtrip::(); - roundtrip::(); - - do 20.times { - roundtrip::(); - roundtrip::(); - roundtrip::>(); - } -} diff --git a/gcc/testsuite/rust.test/deriving-enum-single-variant.rs b/gcc/testsuite/rust.test/deriving-enum-single-variant.rs deleted file mode 100644 index ebbdc15..0000000 --- a/gcc/testsuite/rust.test/deriving-enum-single-variant.rs +++ /dev/null @@ -1,8 +0,0 @@ -type task_id = int; - -#[deriving(Eq)] -pub enum Task { - TaskHandle(task_id) -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/deriving-global.rs b/gcc/testsuite/rust.test/deriving-global.rs deleted file mode 100644 index 7804ce4..0000000 --- a/gcc/testsuite/rust.test/deriving-global.rs +++ /dev/null @@ -1,42 +0,0 @@ -// xfail-fast #7103 `extern mod` does not work on windows -// xfail-pretty - does not converge - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; // {En,De}codable -mod submod { - // if any of these are implemented without global calls for any - // function calls, then being in a submodule will (correctly) - // cause errors about unrecognised module `std` (or `extra`) - #[deriving(Eq, Ord, TotalEq, TotalOrd, - IterBytes, - Clone, DeepClone, - ToStr, Rand, - Encodable, Decodable)] - enum A { A1(uint), A2(int) } - - #[deriving(Eq, Ord, TotalEq, TotalOrd, - IterBytes, - Clone, DeepClone, - ToStr, Rand, - Encodable, Decodable)] - struct B { x: uint, y: int } - - #[deriving(Eq, Ord, TotalEq, TotalOrd, - IterBytes, - Clone, DeepClone, - ToStr, Rand, - Encodable, Decodable)] - struct C(uint, int); - -} - -fn main() {} diff --git a/gcc/testsuite/rust.test/deriving-meta-empty-trait-list.rs b/gcc/testsuite/rust.test/deriving-meta-empty-trait-list.rs deleted file mode 100644 index 955e02d..0000000 --- a/gcc/testsuite/rust.test/deriving-meta-empty-trait-list.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-pretty - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -#[deriving] //~ WARNING empty trait list in `deriving` -struct Foo; - -#[deriving()] //~ WARNING empty trait list in `deriving` -struct Bar; - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/deriving-meta-multiple.rs b/gcc/testsuite/rust.test/deriving-meta-multiple.rs deleted file mode 100644 index 85b8f55..0000000 --- a/gcc/testsuite/rust.test/deriving-meta-multiple.rs +++ /dev/null @@ -1,27 +0,0 @@ -// xfail-fast - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -#[deriving(Clone)] -#[deriving(IterBytes)] -struct Foo { - bar: uint, - baz: int -} - -pub fn main() { - let a = Foo {bar: 4, baz: -3}; - - a == a; // check for Eq impl w/o testing its correctness - a.clone(); // check for Clone impl w/o testing its correctness - a.hash(); // check for IterBytes impl w/o testing its correctness -} diff --git a/gcc/testsuite/rust.test/deriving-meta.rs b/gcc/testsuite/rust.test/deriving-meta.rs deleted file mode 100644 index 04e0dbb..0000000 --- a/gcc/testsuite/rust.test/deriving-meta.rs +++ /dev/null @@ -1,25 +0,0 @@ -// xfail-fast - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq, Clone, IterBytes)] -struct Foo { - bar: uint, - baz: int -} - -pub fn main() { - let a = Foo {bar: 4, baz: -3}; - - a == a; // check for Eq impl w/o testing its correctness - a.clone(); // check for Clone impl w/o testing its correctness - a.hash(); // check for IterBytes impl w/o testing its correctness -} diff --git a/gcc/testsuite/rust.test/deriving-primitive.rs b/gcc/testsuite/rust.test/deriving-primitive.rs deleted file mode 100644 index f82d77b..0000000 --- a/gcc/testsuite/rust.test/deriving-primitive.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::num::FromPrimitive; -use std::int; - -#[deriving(Eq, FromPrimitive)] -enum A { - Foo = int::max_value, - Bar = 1, - Baz = 3, - Qux, -} - -pub fn main() { - let x: Option = FromPrimitive::from_int(int::max_value); - assert_eq!(x, Some(Foo)); - - let x: Option = FromPrimitive::from_int(1); - assert_eq!(x, Some(Bar)); - - let x: Option = FromPrimitive::from_int(3); - assert_eq!(x, Some(Baz)); - - let x: Option = FromPrimitive::from_int(4); - assert_eq!(x, Some(Qux)); - - let x: Option = FromPrimitive::from_int(5); - assert_eq!(x, None); -} diff --git a/gcc/testsuite/rust.test/deriving-rand.rs b/gcc/testsuite/rust.test/deriving-rand.rs deleted file mode 100644 index 39a86c0..0000000 --- a/gcc/testsuite/rust.test/deriving-rand.rs +++ /dev/null @@ -1,43 +0,0 @@ -// xfail-fast #6330 -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -use std::rand; - -#[deriving(Rand)] -struct A; - -#[deriving(Rand)] -struct B(int, int); - -#[deriving(Rand)] -struct C { - x: f64, - y: (u8, u8) -} - -#[deriving(Rand)] -enum D { - D0, - D1(uint), - D2 { x: (), y: () } -} - -fn main() { - // check there's no segfaults - do 20.times { - rand::random::(); - rand::random::(); - rand::random::(); - rand::random::(); - } -} diff --git a/gcc/testsuite/rust.test/deriving-self-lifetime-totalord-totaleq.rs b/gcc/testsuite/rust.test/deriving-self-lifetime-totalord-totaleq.rs deleted file mode 100644 index 2d42088..0000000 --- a/gcc/testsuite/rust.test/deriving-self-lifetime-totalord-totaleq.rs +++ /dev/null @@ -1,32 +0,0 @@ -// xfail-test FIXME #6257 - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::{Less,Equal,Greater}; - -#[deriving(TotalEq,TotalOrd)] -struct A<'self> { - x: &'self int -} - -fn main() { - let a = A { x: &1 }, b = A { x: &2 }; - - assert!(a.equals(&a)); - assert!(b.equals(&b)); - - - assert_eq!(a.cmp(&a), Equal); - assert_eq!(b.cmp(&b), Equal); - - assert_eq!(a.cmp(&b), Less); - assert_eq!(b.cmp(&a), Greater); -} diff --git a/gcc/testsuite/rust.test/deriving-self-lifetime.rs b/gcc/testsuite/rust.test/deriving-self-lifetime.rs deleted file mode 100644 index 2b0245f..0000000 --- a/gcc/testsuite/rust.test/deriving-self-lifetime.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq,Ord)] -struct A<'self> { - x: &'self int -} - -pub fn main() { - let a = A { x: &1 }; - let b = A { x: &2 }; - - assert_eq!(a, a); - assert_eq!(b, b); - - - assert!(a < b); - assert!(b > a); - - assert!(a <= b); - assert!(a <= a); - assert!(b <= b); - - assert!(b >= a); - assert!(b >= b); - assert!(a >= a); -} diff --git a/gcc/testsuite/rust.test/deriving-to-str.rs b/gcc/testsuite/rust.test/deriving-to-str.rs deleted file mode 100644 index d9f69bd..0000000 --- a/gcc/testsuite/rust.test/deriving-to-str.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[feature(struct_variant)]; - -#[deriving(ToStr)] -enum A {} -#[deriving(ToStr)] -enum B { B1, B2, B3 } -#[deriving(ToStr)] -enum C { C1(int), C2(B), C3(~str) } -#[deriving(ToStr)] -enum D { D1{ a: int } } -#[deriving(ToStr)] -struct E; -#[deriving(ToStr)] -struct F(int); -#[deriving(ToStr)] -struct G(int, int); -#[deriving(ToStr)] -struct H { a: int } -#[deriving(ToStr)] -struct I { a: int, b: int } -#[deriving(ToStr)] -struct J(Custom); - -struct Custom; -impl ToStr for Custom { - fn to_str(&self) -> ~str { ~"yay" } -} - -pub fn main() { - assert_eq!(B1.to_str(), ~"B1"); - assert_eq!(B2.to_str(), ~"B2"); - assert_eq!(C1(3).to_str(), ~"C1(3)"); - assert_eq!(C2(B2).to_str(), ~"C2(B2)"); - assert_eq!(D1{ a: 2 }.to_str(), ~"D1{a: 2}"); - assert_eq!(E.to_str(), ~"E"); - assert_eq!(F(3).to_str(), ~"F(3)"); - assert_eq!(G(3, 4).to_str(), ~"G(3, 4)"); - assert_eq!(G(3, 4).to_str(), ~"G(3, 4)"); - assert_eq!(I{ a: 2, b: 4 }.to_str(), ~"I{a: 2, b: 4}"); - assert_eq!(J(Custom).to_str(), ~"J(yay)"); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-c-enum.rs b/gcc/testsuite/rust.test/deriving-via-extension-c-enum.rs deleted file mode 100644 index 3c4fb6c..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-c-enum.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -enum Foo { - Bar, - Baz, - Boo -} - -pub fn main() { - let a = Bar; - let b = Bar; - assert_eq!(a, b); - assert!(!(a != b)); - assert!(a.eq(&b)); - assert!(!a.ne(&b)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-enum.rs b/gcc/testsuite/rust.test/deriving-via-extension-enum.rs deleted file mode 100644 index b2974b4..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-enum.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -enum Foo { - Bar(int, int), - Baz(f64, f64) -} - -pub fn main() { - let a = Bar(1, 2); - let b = Bar(1, 2); - assert_eq!(a, b); - assert!(!(a != b)); - assert!(a.eq(&b)); - assert!(!a.ne(&b)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-enum.rs b/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-enum.rs deleted file mode 100644 index b08117b..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-enum.rs +++ /dev/null @@ -1,27 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(IterBytes)] -enum Foo { - Bar(int, char), - Baz(char, int) -} - -#[deriving(IterBytes)] -enum A { - B, - C, - D, - E -} - -pub fn main(){} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-struct.rs b/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-struct.rs deleted file mode 100644 index 8369d12..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-iter-bytes-struct.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(IterBytes)] -struct Foo { - x: int, - y: int, - z: int -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-struct-empty.rs b/gcc/testsuite/rust.test/deriving-via-extension-struct-empty.rs deleted file mode 100644 index 74698b9..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-struct-empty.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Foo; - -pub fn main() { - assert_eq!(Foo, Foo); - assert!(!(Foo != Foo)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-struct-like-enum-variant.rs b/gcc/testsuite/rust.test/deriving-via-extension-struct-like-enum-variant.rs deleted file mode 100644 index 83c8679..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-struct-like-enum-variant.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[feature(struct_variant)]; - -#[deriving(Eq)] -enum S { - X { x: int, y: int }, - Y -} - -pub fn main() { - let x = X { x: 1, y: 2 }; - assert_eq!(x, x); - assert!(!(x != x)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-struct-tuple.rs b/gcc/testsuite/rust.test/deriving-via-extension-struct-tuple.rs deleted file mode 100644 index cc76751..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-struct-tuple.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Foo(int, int, ~str); - -pub fn main() { - let a1 = Foo(5, 6, ~"abc"); - let a2 = Foo(5, 6, ~"abc"); - let b = Foo(5, 7, ~"def"); - - assert!(a1 == a1); - assert!(a2 == a1); - assert!(!(a1 == b)); - - assert!(a1 != b); - assert!(!(a1 != a1)); - assert!(!(a2 != a1)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-struct.rs b/gcc/testsuite/rust.test/deriving-via-extension-struct.rs deleted file mode 100644 index 44aca59..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-struct.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -struct Foo { - x: int, - y: int, - z: int, -} - -pub fn main() { - let a = Foo { x: 1, y: 2, z: 3 }; - let b = Foo { x: 1, y: 2, z: 3 }; - assert_eq!(a, b); - assert!(!(a != b)); - assert!(a.eq(&b)); - assert!(!a.ne(&b)); -} diff --git a/gcc/testsuite/rust.test/deriving-via-extension-type-params.rs b/gcc/testsuite/rust.test/deriving-via-extension-type-params.rs deleted file mode 100644 index ecc3055..0000000 --- a/gcc/testsuite/rust.test/deriving-via-extension-type-params.rs +++ /dev/null @@ -1,28 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq)] -#[deriving(IterBytes)] -struct Foo { - x: int, - y: T, - z: int -} - -pub fn main() { - let a = Foo { x: 1, y: 2.0, z: 3 }; - let b = Foo { x: 1, y: 2.0, z: 3 }; - assert_eq!(a, b); - assert!(!(a != b)); - assert!(a.eq(&b)); - assert!(!a.ne(&b)); -} diff --git a/gcc/testsuite/rust.test/deriving-zero.rs b/gcc/testsuite/rust.test/deriving-zero.rs deleted file mode 100644 index 2c8271d..0000000 --- a/gcc/testsuite/rust.test/deriving-zero.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::util; -use std::num::Zero; - -#[deriving(Zero)] -struct A; -#[deriving(Zero)] -struct B(int); -#[deriving(Zero)] -struct C(int, int); -#[deriving(Zero)] -struct D { a: int } -#[deriving(Zero)] -struct E { a: int, b: int } - -#[deriving(Zero)] -struct Lots { - d: u8, - e: char, - f: f64, - g: (f32, char), - h: @mut (int, int), - i: bool, - j: (), -} - -pub fn main() { - let lots: Lots = Zero::zero(); - assert!(lots.is_zero()); -} diff --git a/gcc/testsuite/rust.test/die-macro.rs b/gcc/testsuite/rust.test/die-macro.rs deleted file mode 100644 index ade0114..0000000 --- a/gcc/testsuite/rust.test/die-macro.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Just testing that fail!() type checks in statement or expr - -#[allow(unreachable_code)]; - -fn f() { - fail2!(); - - let _x: int = fail2!(); -} - -pub fn main() { - -} diff --git a/gcc/testsuite/rust.test/div-mod.rs b/gcc/testsuite/rust.test/div-mod.rs deleted file mode 100644 index 3aeaef0..0000000 --- a/gcc/testsuite/rust.test/div-mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let x: int = 15; - let y: int = 5; - assert_eq!(x / 5, 3); - assert_eq!(x / 4, 3); - assert_eq!(x / 3, 5); - assert_eq!(x / y, 3); - assert_eq!(15 / y, 3); - assert_eq!(x % 5, 0); - assert_eq!(x % 4, 3); - assert_eq!(x % 3, 0); - assert_eq!(x % y, 0); - assert_eq!(15 % y, 0); -} diff --git a/gcc/testsuite/rust.test/do-empty-args.rs b/gcc/testsuite/rust.test/do-empty-args.rs deleted file mode 100644 index 485d59d..0000000 --- a/gcc/testsuite/rust.test/do-empty-args.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// no-reformat -// Testing various forms of `do` with empty arg lists - -fn f(_f: &fn() -> bool) -> bool { - true -} - -pub fn main() { - do f() || { true }; - do f() { true }; - do f || { true }; - do f { true }; -} diff --git a/gcc/testsuite/rust.test/do-no-args.rs b/gcc/testsuite/rust.test/do-no-args.rs deleted file mode 100644 index 1f725ff..0000000 --- a/gcc/testsuite/rust.test/do-no-args.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Testing that we can drop the || in do exprs - -fn f(_f: &fn() -> bool) -> bool { true } - -fn d(_f: &fn()) { } - -pub fn main() { - do d { } -} diff --git a/gcc/testsuite/rust.test/do-pure.rs b/gcc/testsuite/rust.test/do-pure.rs deleted file mode 100644 index 8a0509c..0000000 --- a/gcc/testsuite/rust.test/do-pure.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(_f: &fn()) { -} - -fn g() { - // `f || { }` is considered pure, so `do f { }` should be too - do f { } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/do-stack.rs b/gcc/testsuite/rust.test/do-stack.rs deleted file mode 100644 index 0444b26..0000000 --- a/gcc/testsuite/rust.test/do-stack.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(f: &fn(int)) { f(10) } - -pub fn main() { - do f() |i| { assert!(i == 10) } -} diff --git a/gcc/testsuite/rust.test/do1.rs b/gcc/testsuite/rust.test/do1.rs deleted file mode 100644 index 0444b26..0000000 --- a/gcc/testsuite/rust.test/do1.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(f: &fn(int)) { f(10) } - -pub fn main() { - do f() |i| { assert!(i == 10) } -} diff --git a/gcc/testsuite/rust.test/do2.rs b/gcc/testsuite/rust.test/do2.rs deleted file mode 100644 index 9feeded..0000000 --- a/gcc/testsuite/rust.test/do2.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(f: &fn(int) -> int) -> int { f(10) } - -pub fn main() { - assert_eq!(do f() |i| { i }, 10); -} diff --git a/gcc/testsuite/rust.test/do3.rs b/gcc/testsuite/rust.test/do3.rs deleted file mode 100644 index eeb983b..0000000 --- a/gcc/testsuite/rust.test/do3.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(f: &fn(int) -> int) -> int { f(10) } - -pub fn main() { - assert_eq!(do f |i| { i }, 10); -} diff --git a/gcc/testsuite/rust.test/double-unbox.rs b/gcc/testsuite/rust.test/double-unbox.rs deleted file mode 100644 index c6ea32b..0000000 --- a/gcc/testsuite/rust.test/double-unbox.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Quux { - bar: int -} - -fn g(_i: int) { } -fn f(foo: @@Quux) { g(foo.bar); } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/drop-on-empty-block-exit.rs b/gcc/testsuite/rust.test/drop-on-empty-block-exit.rs deleted file mode 100644 index 07a73e0..0000000 --- a/gcc/testsuite/rust.test/drop-on-empty-block-exit.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum t { foo(@int), } - -pub fn main() { - let tt = foo(@10); - match tt { foo(_z) => { } } -} diff --git a/gcc/testsuite/rust.test/drop-on-ret.rs b/gcc/testsuite/rust.test/drop-on-ret.rs deleted file mode 100644 index afc9e53..0000000 --- a/gcc/testsuite/rust.test/drop-on-ret.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn f() -> int { - if true { - let _s: ~str = ~"should not leak"; - return 1; - } - return 0; -} - -pub fn main() { f(); } diff --git a/gcc/testsuite/rust.test/drop-trait-generic.rs b/gcc/testsuite/rust.test/drop-trait-generic.rs deleted file mode 100644 index 39453af8..0000000 --- a/gcc/testsuite/rust.test/drop-trait-generic.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S { - x: T -} - -#[unsafe_destructor] -impl ::std::ops::Drop for S { - fn drop(&mut self) { - println("bye"); - } -} - -pub fn main() { - let _x = S { x: 1 }; -} diff --git a/gcc/testsuite/rust.test/drop-trait.rs b/gcc/testsuite/rust.test/drop-trait.rs deleted file mode 100644 index e363792..0000000 --- a/gcc/testsuite/rust.test/drop-trait.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int -} - -impl Drop for Foo { - fn drop(&mut self) { - println("bye"); - } -} - -pub fn main() { - let _x: Foo = Foo { x: 3 }; -} diff --git a/gcc/testsuite/rust.test/duplicate-use.rs b/gcc/testsuite/rust.test/duplicate-use.rs deleted file mode 100644 index 35d5d2f..0000000 --- a/gcc/testsuite/rust.test/duplicate-use.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -extern mod extra; - -use list = extra::oldmap::chained; -use extra::list; - -pub fn main() { - let _x: list::T = list::mk(); -} diff --git a/gcc/testsuite/rust.test/early-ret-binop-add.rs b/gcc/testsuite/rust.test/early-ret-binop-add.rs deleted file mode 100644 index 97e873e..0000000 --- a/gcc/testsuite/rust.test/early-ret-binop-add.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn wsucc(n: int) -> int { 0 + { return n + 1 } } -pub fn main() { } diff --git a/gcc/testsuite/rust.test/early-vtbl-resolution.rs b/gcc/testsuite/rust.test/early-vtbl-resolution.rs deleted file mode 100644 index 89fee73..0000000 --- a/gcc/testsuite/rust.test/early-vtbl-resolution.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait thing { - fn foo(&self) -> Option; -} -impl thing for int { - fn foo(&self) -> Option { None } -} -fn foo_func>(x: B) -> Option { x.foo() } - -struct A { a: int } - -pub fn main() { - let _x: Option = foo_func(0); -} diff --git a/gcc/testsuite/rust.test/else-if.rs b/gcc/testsuite/rust.test/else-if.rs deleted file mode 100644 index 476d3f4..0000000 --- a/gcc/testsuite/rust.test/else-if.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - if 1 == 2 { - assert!((false)); - } else if 2 == 3 { - assert!((false)); - } else if 3 == 4 { assert!((false)); } else { assert!((true)); } - if 1 == 2 { assert!((false)); } else if 2 == 2 { assert!((true)); } - if 1 == 2 { - assert!((false)); - } else if 2 == 2 { - if 1 == 1 { - assert!((true)); - } else { if 2 == 1 { assert!((false)); } else { assert!((false)); } } - } - if 1 == 2 { - assert!((false)); - } else { if 1 == 2 { assert!((false)); } else { assert!((true)); } } -} diff --git a/gcc/testsuite/rust.test/empty-mutable-vec.rs b/gcc/testsuite/rust.test/empty-mutable-vec.rs deleted file mode 100644 index 6c90e01..0000000 --- a/gcc/testsuite/rust.test/empty-mutable-vec.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_mut)]; - -pub fn main() { let mut _v: ~[int] = ~[]; } diff --git a/gcc/testsuite/rust.test/empty-tag.rs b/gcc/testsuite/rust.test/empty-tag.rs deleted file mode 100644 index 7b90463..0000000 --- a/gcc/testsuite/rust.test/empty-tag.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum chan { chan_t, } - -impl Eq for chan { - fn eq(&self, other: &chan) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &chan) -> bool { !(*self).eq(other) } -} - -fn wrapper3(i: chan) { - assert_eq!(i, chan_t); -} - -pub fn main() { - let wrapped = {||wrapper3(chan_t)}; - wrapped(); -} diff --git a/gcc/testsuite/rust.test/enum-alignment.rs b/gcc/testsuite/rust.test/enum-alignment.rs deleted file mode 100644 index 4c60cfb..0000000 --- a/gcc/testsuite/rust.test/enum-alignment.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; -use std::ptr; -use std::mem; - -fn addr_of(ptr: &T) -> uint { - let ptr = ptr::to_unsafe_ptr(ptr); - ptr as uint -} - -fn is_aligned(ptr: &T) -> bool { - unsafe { - let addr: uint = cast::transmute(ptr); - (addr % mem::min_align_of::()) == 0 - } -} - -pub fn main() { - let x = Some(0u64); - match x { - None => fail2!(), - Some(ref y) => assert!(is_aligned(y)) - } -} diff --git a/gcc/testsuite/rust.test/enum-discr.rs b/gcc/testsuite/rust.test/enum-discr.rs deleted file mode 100644 index 28f3882..0000000 --- a/gcc/testsuite/rust.test/enum-discr.rs +++ /dev/null @@ -1,20 +0,0 @@ -enum Animal { - Cat = 0u, - Dog = 1u, - Horse = 2u, - Snake = 3u -} - -enum Hero { - Batman = -1, - Superman = -2, - Ironman = -3, - Spiderman = -4 -} - -pub fn main() { - let pet: Animal = Snake; - let hero: Hero = Superman; - assert!(pet as uint == 3); - assert!(hero as int == -2); -} diff --git a/gcc/testsuite/rust.test/enum-discrim-range-overflow.rs b/gcc/testsuite/rust.test/enum-discrim-range-overflow.rs deleted file mode 100644 index 37e457d..0000000 --- a/gcc/testsuite/rust.test/enum-discrim-range-overflow.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub enum E64 { - H64 = 0x7FFF_FFFF_FFFF_FFFF, - L64 = 0x8000_0000_0000_0000 -} -pub enum E32 { - H32 = 0x7FFF_FFFF, - L32 = 0x8000_0000 -} - -pub fn f(e64: E64, e32: E32) -> (bool,bool) { - (match e64 { - H64 => true, - L64 => false - }, - match e32 { - H32 => true, - L32 => false - }) -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/enum-discrim-width-stuff.rs b/gcc/testsuite/rust.test/enum-discrim-width-stuff.rs deleted file mode 100644 index 65f93b1..0000000 --- a/gcc/testsuite/rust.test/enum-discrim-width-stuff.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -pub fn main() { - enum E { V = 0x1717171717171717 } - static C: E = V; - let expected: u64 = if mem::size_of::() < 8 { - 0x17171717 - } else { - 0x1717171717171717 - }; - assert_eq!(expected, V as u64); - assert_eq!(expected, C as u64); - assert_eq!(format!("{:?}", V), ~"V"); - assert_eq!(format!("{:?}", C), ~"V"); -} diff --git a/gcc/testsuite/rust.test/enum-disr-val-pretty.rs b/gcc/testsuite/rust.test/enum-disr-val-pretty.rs deleted file mode 100644 index ee2c1ff..0000000 --- a/gcc/testsuite/rust.test/enum-disr-val-pretty.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact - -enum color { red = 1, green, blue, imaginary = -1, } - -pub fn main() { - test_color(red, 1, ~"red"); - test_color(green, 2, ~"green"); - test_color(blue, 3, ~"blue"); - test_color(imaginary, -1, ~"imaginary"); -} - -fn test_color(color: color, val: int, _name: ~str) { - assert!(color as int == val); - assert!(color as f64 == val as f64); -} diff --git a/gcc/testsuite/rust.test/enum-export-inheritance.rs b/gcc/testsuite/rust.test/enum-export-inheritance.rs deleted file mode 100644 index 0983426..0000000 --- a/gcc/testsuite/rust.test/enum-export-inheritance.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod a { - pub enum Foo { - Bar, - Baz, - Boo - } -} - -pub fn main() { - let _x = a::Bar; -} diff --git a/gcc/testsuite/rust.test/enum-nullable-simplifycfg-misopt.rs b/gcc/testsuite/rust.test/enum-nullable-simplifycfg-misopt.rs deleted file mode 100644 index 334047d..0000000 --- a/gcc/testsuite/rust.test/enum-nullable-simplifycfg-misopt.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * This is a regression test for a bug in LLVM, fixed in upstream r179587, - * where the switch instructions generated for destructuring enums - * represented with nullable pointers could be misoptimized in some cases. - */ - -enum List { Nil, Cons(X, @List) } -pub fn main() { - match Cons(10, @Nil) { - Cons(10, _) => {} - Nil => {} - _ => fail2!() - } -} diff --git a/gcc/testsuite/rust.test/enum-variants.rs b/gcc/testsuite/rust.test/enum-variants.rs deleted file mode 100644 index 69f3c88..0000000 --- a/gcc/testsuite/rust.test/enum-variants.rs +++ /dev/null @@ -1,15 +0,0 @@ -#[allow(dead_assignment)]; -#[allow(unused_variable)]; -#[feature(struct_variant)]; - -enum Animal { - Dog (~str, f64), - Cat { name: ~str, weight: f64 } -} - -pub fn main() { - let mut a: Animal = Dog(~"Cocoa", 37.2); - a = Cat{ name: ~"Spotty", weight: 2.7 }; - // permuting the fields should work too - let _c = Cat { weight: 3.1, name: ~"Spreckles" }; -} diff --git a/gcc/testsuite/rust.test/enum-vec-initializer.rs b/gcc/testsuite/rust.test/enum-vec-initializer.rs deleted file mode 100644 index a55b5ee..0000000 --- a/gcc/testsuite/rust.test/enum-vec-initializer.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Flopsy { - Bunny = 2 -} - -static BAR:uint = Bunny as uint; -static BAR2:uint = BAR; - -pub fn main() { - let _v = [0, .. Bunny as uint]; - let _v = [0, .. BAR]; - let _v = [0, .. BAR2]; - static BAR3:uint = BAR2; - let _v = [0, .. BAR3]; -} diff --git a/gcc/testsuite/rust.test/estr-shared.rs b/gcc/testsuite/rust.test/estr-shared.rs deleted file mode 100644 index 20698a3..0000000 --- a/gcc/testsuite/rust.test/estr-shared.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let _x : @str = @"hello"; -} diff --git a/gcc/testsuite/rust.test/estr-slice.rs b/gcc/testsuite/rust.test/estr-slice.rs deleted file mode 100644 index 145f040..0000000 --- a/gcc/testsuite/rust.test/estr-slice.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -pub fn main() { - let x = &"hello"; - let v = &"hello"; - let y : &str = &"there"; - - info2!("{}", x); - info2!("{}", y); - - assert_eq!(x[0], 'h' as u8); - assert_eq!(x[4], 'o' as u8); - - let z : &str = &"thing"; - assert_eq!(v, x); - assert!(x != z); - - let a = &"aaaa"; - let b = &"bbbb"; - - let c = &"cccc"; - let cc = &"ccccc"; - - info2!("{}", a); - - assert!(a < b); - assert!(a <= b); - assert!(a != b); - assert!(b >= a); - assert!(b > a); - - info2!("{}", b); - - assert!(a < c); - assert!(a <= c); - assert!(a != c); - assert!(c >= a); - assert!(c > a); - - info2!("{}", c); - - assert!(c < cc); - assert!(c <= cc); - assert!(c != cc); - assert!(cc >= c); - assert!(cc > c); - - info2!("{}", cc); -} diff --git a/gcc/testsuite/rust.test/estr-uniq.rs b/gcc/testsuite/rust.test/estr-uniq.rs deleted file mode 100644 index 7935886..0000000 --- a/gcc/testsuite/rust.test/estr-uniq.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let x : ~str = ~"hello"; - let _y : ~str = ~"there"; - let mut z = ~"thing"; - z = x; - assert_eq!(z[0], ('h' as u8)); - assert_eq!(z[4], ('o' as u8)); -} diff --git a/gcc/testsuite/rust.test/evec-internal-boxes.rs b/gcc/testsuite/rust.test/evec-internal-boxes.rs deleted file mode 100644 index c872ee5..0000000 --- a/gcc/testsuite/rust.test/evec-internal-boxes.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let x : [@int, ..5] = [@1,@2,@3,@4,@5]; - let _y : [@int, ..5] = [@1,@2,@3,@4,@5]; - let mut z = [@1,@2,@3,@4,@5]; - z = x; - assert_eq!(*z[0], 1); - assert_eq!(*z[4], 5); -} diff --git a/gcc/testsuite/rust.test/evec-internal.rs b/gcc/testsuite/rust.test/evec-internal.rs deleted file mode 100644 index 6c3dfb2..0000000 --- a/gcc/testsuite/rust.test/evec-internal.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// xfail-fast - -// Doesn't work; needs a design decision. - -pub fn main() { - let x : [int, ..5] = [1,2,3,4,5]; - let _y : [int, ..5] = [1,2,3,4,5]; - let mut z = [1,2,3,4,5]; - z = x; - assert_eq!(z[0], 1); - assert_eq!(z[4], 5); - - let a : [int, ..5] = [1,1,1,1,1]; - let b : [int, ..5] = [2,2,2,2,2]; - let c : [int, ..5] = [2,2,2,2,3]; - - log(debug, a); - - assert!(a < b); - assert!(a <= b); - assert!(a != b); - assert!(b >= a); - assert!(b > a); - - log(debug, b); - - assert!(b < c); - assert!(b <= c); - assert!(b != c); - assert!(c >= b); - assert!(c > b); - - assert!(a < c); - assert!(a <= c); - assert!(a != c); - assert!(c >= a); - assert!(c > a); - - log(debug, c); - - -} diff --git a/gcc/testsuite/rust.test/evec-slice.rs b/gcc/testsuite/rust.test/evec-slice.rs deleted file mode 100644 index 32de1ad..0000000 --- a/gcc/testsuite/rust.test/evec-slice.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -pub fn main() { - let x : &[int] = &[1,2,3,4,5]; - let mut z = &[1,2,3,4,5]; - z = x; - assert_eq!(z[0], 1); - assert_eq!(z[4], 5); - - let a : &[int] = &[1,1,1,1,1]; - let b : &[int] = &[2,2,2,2,2]; - let c : &[int] = &[2,2,2,2,3]; - let cc : &[int] = &[2,2,2,2,2,2]; - - info2!("{:?}", a); - - assert!(a < b); - assert!(a <= b); - assert!(a != b); - assert!(b >= a); - assert!(b > a); - - info2!("{:?}", b); - - assert!(b < c); - assert!(b <= c); - assert!(b != c); - assert!(c >= b); - assert!(c > b); - - assert!(a < c); - assert!(a <= c); - assert!(a != c); - assert!(c >= a); - assert!(c > a); - - info2!("{:?}", c); - - assert!(a < cc); - assert!(a <= cc); - assert!(a != cc); - assert!(cc >= a); - assert!(cc > a); - - info2!("{:?}", cc); -} diff --git a/gcc/testsuite/rust.test/exec-env.rs b/gcc/testsuite/rust.test/exec-env.rs deleted file mode 100644 index 735891b..0000000 --- a/gcc/testsuite/rust.test/exec-env.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast (exec-env not supported in fast mode) -// exec-env:TEST_EXEC_ENV=22 - -use std::os; - -pub fn main() { - assert_eq!(os::getenv("TEST_EXEC_ENV"), Some(~"22")); -} diff --git a/gcc/testsuite/rust.test/explicit-i-suffix.rs b/gcc/testsuite/rust.test/explicit-i-suffix.rs deleted file mode 100644 index 45cfee7..0000000 --- a/gcc/testsuite/rust.test/explicit-i-suffix.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x: int = 8i; - let y = 9i; - x + y; - - let q: int = -8i; - let r = -9i; - q + r; -} diff --git a/gcc/testsuite/rust.test/explicit-self-closures.rs b/gcc/testsuite/rust.test/explicit-self-closures.rs deleted file mode 100644 index ce662ba..0000000 --- a/gcc/testsuite/rust.test/explicit-self-closures.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test to make sure that explicit self params work inside closures - -struct Box { - x: uint -} - -impl Box { - pub fn set_many(&mut self, xs: &[uint]) { - for x in xs.iter() { self.x = *x; } - } - pub fn set_many2(@mut self, xs: &[uint]) { - for x in xs.iter() { self.x = *x; } - } -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/explicit-self-generic.rs b/gcc/testsuite/rust.test/explicit-self-generic.rs deleted file mode 100644 index 80e16af..0000000 --- a/gcc/testsuite/rust.test/explicit-self-generic.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -/** - * A function that returns a hash of a value - * - * The hash should concentrate entropy in the lower bits. - */ -type HashFn = ~fn(K) -> uint; -type EqFn = ~fn(K, K) -> bool; - -struct LM { resize_at: uint, size: uint } - -enum HashMap { - HashMap_(LM) -} - -fn linear_map() -> HashMap { - HashMap_(LM{ - resize_at: 32, - size: 0}) -} - -impl HashMap { - pub fn len(&mut self) -> uint { - self.size - } -} - -pub fn main() { - let mut m = ~linear_map::<(),()>(); - assert_eq!(m.len(), 0); -} diff --git a/gcc/testsuite/rust.test/explicit-self-objects-box.rs b/gcc/testsuite/rust.test/explicit-self-objects-box.rs deleted file mode 100644 index 9010dd3..0000000 --- a/gcc/testsuite/rust.test/explicit-self-objects-box.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn f(@self); -} - -struct S { - x: int -} - -impl Foo for S { - fn f(@self) { - assert_eq!(self.x, 3); - } -} - -pub fn main() { - let x = @S { x: 3 }; - let y = x as @Foo; - y.f(); - y.f(); - y.f(); - y.f(); -} diff --git a/gcc/testsuite/rust.test/explicit-self-objects-simple.rs b/gcc/testsuite/rust.test/explicit-self-objects-simple.rs deleted file mode 100644 index 6092c38..0000000 --- a/gcc/testsuite/rust.test/explicit-self-objects-simple.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn f(&self); -} - -struct S { - x: int -} - -impl Foo for S { - fn f(&self) { - assert_eq!(self.x, 3); - } -} - -pub fn main() { - let x = @S { x: 3 }; - let y = x as @Foo; - y.f(); -} diff --git a/gcc/testsuite/rust.test/explicit-self-objects-uniq.rs b/gcc/testsuite/rust.test/explicit-self-objects-uniq.rs deleted file mode 100644 index 69ca98e..0000000 --- a/gcc/testsuite/rust.test/explicit-self-objects-uniq.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn f(~self); -} - -struct S { - x: int -} - -impl Foo for S { - fn f(~self) { - assert_eq!(self.x, 3); - } -} - -pub fn main() { - let x = ~S { x: 3 }; - let y = x as ~Foo; - y.f(); -} diff --git a/gcc/testsuite/rust.test/explicit-self.rs b/gcc/testsuite/rust.test/explicit-self.rs deleted file mode 100644 index c090ca3..0000000 --- a/gcc/testsuite/rust.test/explicit-self.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -static tau: f64 = 2.0*3.14159265358979323; - -struct Point {x: f64, y: f64} -struct Size {w: f64, h: f64} -enum shape { - circle(Point, f64), - rectangle(Point, Size) -} - - -fn compute_area(shape: &shape) -> f64 { - match *shape { - circle(_, radius) => 0.5 * tau * radius * radius, - rectangle(_, ref size) => size.w * size.h - } -} - -impl shape { - // self is in the implicit self region - pub fn select<'r, T>(&self, threshold: f64, a: &'r T, b: &'r T) - -> &'r T { - if compute_area(self) > threshold {a} else {b} - } -} - -fn select_based_on_unit_circle<'r, T>( - threshold: f64, a: &'r T, b: &'r T) -> &'r T { - - let shape = &circle(Point{x: 0.0, y: 0.0}, 1.0); - shape.select(threshold, a, b) -} - -#[deriving(Clone)] -struct thing { - x: A -} - -#[deriving(Clone)] -struct A { - a: @int -} - -fn thing(x: A) -> thing { - thing { - x: x - } -} - -impl thing { - pub fn foo(@self) -> int { *self.x.a } - pub fn bar(~self) -> int { *self.x.a } - pub fn quux(&self) -> int { *self.x.a } - pub fn baz<'a>(&'a self) -> &'a A { &self.x } - pub fn spam(self) -> int { *self.x.a } -} - -trait Nus { fn f(&self); } -impl Nus for thing { fn f(&self) {} } - -pub fn main() { - - let x = @thing(A {a: @10}); - assert_eq!(x.foo(), 10); - assert_eq!(x.quux(), 10); - - let y = ~thing(A {a: @10}); - assert_eq!(y.clone().bar(), 10); - assert_eq!(y.quux(), 10); - - let z = thing(A {a: @11}); - assert_eq!(z.spam(), 11); -} diff --git a/gcc/testsuite/rust.test/explicit_self_xcrate_exe.rs b/gcc/testsuite/rust.test/explicit_self_xcrate_exe.rs deleted file mode 100644 index 6f6520e..0000000 --- a/gcc/testsuite/rust.test/explicit_self_xcrate_exe.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// aux-build:explicit_self_xcrate.rs - -extern mod explicit_self_xcrate; -use explicit_self_xcrate::{Foo, Bar}; - -pub fn main() { - let x = Bar { x: ~"hello" }; - x.f(); -} diff --git a/gcc/testsuite/rust.test/export-abstract-tag.rs b/gcc/testsuite/rust.test/export-abstract-tag.rs deleted file mode 100644 index adc4b55..0000000 --- a/gcc/testsuite/rust.test/export-abstract-tag.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// We can export tags without exporting the variants to create a simple -// sort of ADT. - -mod foo { - pub enum t { t1, } - - pub fn f() -> t { return t1; } -} - -pub fn main() { let _v: foo::t = foo::f(); } diff --git a/gcc/testsuite/rust.test/export-glob-imports-target.rs b/gcc/testsuite/rust.test/export-glob-imports-target.rs deleted file mode 100644 index 16f4754..0000000 --- a/gcc/testsuite/rust.test/export-glob-imports-target.rs +++ /dev/null @@ -1,30 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that a glob-export functions as an import -// when referenced within its own local scope. - -// Modified to not use export since it's going away. --pcw - -#[feature(globs)]; - -mod foo { - use foo::bar::*; - pub mod bar { - pub static a : int = 10; - } - pub fn zum() { - let _b = a; - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/export-multi.rs b/gcc/testsuite/rust.test/export-multi.rs deleted file mode 100644 index 396e4e6..0000000 --- a/gcc/testsuite/rust.test/export-multi.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use m::f; -use m::g; - -mod m { - pub fn f() { } - pub fn g() { } -} - -pub fn main() { f(); g(); m::f(); m::g(); } diff --git a/gcc/testsuite/rust.test/export-non-interference.rs b/gcc/testsuite/rust.test/export-non-interference.rs deleted file mode 100644 index 67f8191..0000000 --- a/gcc/testsuite/rust.test/export-non-interference.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -enum list_cell { cons(@list_cell), nil } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/export-non-interference2.rs b/gcc/testsuite/rust.test/export-non-interference2.rs deleted file mode 100644 index 8fdc9c5..0000000 --- a/gcc/testsuite/rust.test/export-non-interference2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod foo { - pub mod bar { - pub fn y() { super::super::foo::x(); } - } - - pub fn x() { info2!("x"); } -} - -pub fn main() { self::foo::bar::y(); } diff --git a/gcc/testsuite/rust.test/export-non-interference3.rs b/gcc/testsuite/rust.test/export-non-interference3.rs deleted file mode 100644 index b063237..0000000 --- a/gcc/testsuite/rust.test/export-non-interference3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub mod foo { - pub fn x() { ::bar::x(); } -} - -pub mod bar { - pub fn x() { info2!("x"); } -} - -pub fn main() { foo::x(); } diff --git a/gcc/testsuite/rust.test/export-tag-variant.rs b/gcc/testsuite/rust.test/export-tag-variant.rs deleted file mode 100644 index d0aa23e..0000000 --- a/gcc/testsuite/rust.test/export-tag-variant.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod foo { - pub enum t { t1, } -} - -pub fn main() { let _v = foo::t1; } diff --git a/gcc/testsuite/rust.test/export-unexported-dep.rs b/gcc/testsuite/rust.test/export-unexported-dep.rs deleted file mode 100644 index 0047614..0000000 --- a/gcc/testsuite/rust.test/export-unexported-dep.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This tests that exports can have visible dependencies on things -// that are not exported, allowing for a sort of poor-man's ADT - -mod foo { - // not exported - enum t { t1, t2, } - - impl Eq for t { - fn eq(&self, other: &t) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } - } - - pub fn f() -> t { return t1; } - - pub fn g(v: t) { assert!((v == t1)); } -} - -pub fn main() { foo::g(foo::f()); } diff --git a/gcc/testsuite/rust.test/expr-block-box.rs b/gcc/testsuite/rust.test/expr-block-box.rs deleted file mode 100644 index 8385c95..0000000 --- a/gcc/testsuite/rust.test/expr-block-box.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { let x = { @100 }; assert!((*x == 100)); } diff --git a/gcc/testsuite/rust.test/expr-block-fn.rs b/gcc/testsuite/rust.test/expr-block-fn.rs deleted file mode 100644 index 63e5c76..0000000 --- a/gcc/testsuite/rust.test/expr-block-fn.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn test_fn() { - type t = &'static fn() -> int; - fn ten() -> int { return 10; } - let rs: t = { ten }; - assert!((rs() == 10)); -} - -pub fn main() { test_fn(); } diff --git a/gcc/testsuite/rust.test/expr-block-generic-box1.rs b/gcc/testsuite/rust.test/expr-block-generic-box1.rs deleted file mode 100644 index 710cab5..0000000 --- a/gcc/testsuite/rust.test/expr-block-generic-box1.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -type compare = &'static fn(@T, @T) -> bool; - -fn test_generic(expected: @T, eq: compare) { - let actual: @T = { expected }; - assert!((eq(expected, actual))); -} - -fn test_box() { - fn compare_box(b1: @bool, b2: @bool) -> bool { - info2!("{}", *b1); - info2!("{}", *b2); - return *b1 == *b2; - } - test_generic::(@true, compare_box); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-block-generic-box2.rs b/gcc/testsuite/rust.test/expr-block-generic-box2.rs deleted file mode 100644 index cfa59d6..0000000 --- a/gcc/testsuite/rust.test/expr-block-generic-box2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -type compare<'self, T> = &'self fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = { expected.clone() }; - assert!((eq(expected, actual))); -} - -fn test_vec() { - fn compare_vec(v1: @int, v2: @int) -> bool { return v1 == v2; } - test_generic::<@int>(@1, compare_vec); -} - -pub fn main() { test_vec(); } diff --git a/gcc/testsuite/rust.test/expr-block-generic-unique1.rs b/gcc/testsuite/rust.test/expr-block-generic-unique1.rs deleted file mode 100644 index f22ef21..0000000 --- a/gcc/testsuite/rust.test/expr-block-generic-unique1.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- -type compare<'self, T> = &'self fn(~T, ~T) -> bool; - -fn test_generic(expected: ~T, eq: compare) { - let actual: ~T = { expected.clone() }; - assert!((eq(expected, actual))); -} - -fn test_box() { - fn compare_box(b1: ~bool, b2: ~bool) -> bool { - info2!("{}", *b1); - info2!("{}", *b2); - return *b1 == *b2; - } - test_generic::(~true, compare_box); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-block-generic-unique2.rs b/gcc/testsuite/rust.test/expr-block-generic-unique2.rs deleted file mode 100644 index 3484a4f..0000000 --- a/gcc/testsuite/rust.test/expr-block-generic-unique2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -type compare<'self, T> = &'self fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = { expected.clone() }; - assert!((eq(expected, actual))); -} - -fn test_vec() { - fn compare_vec(v1: ~int, v2: ~int) -> bool { return v1 == v2; } - test_generic::<~int>(~1, compare_vec); -} - -pub fn main() { test_vec(); } diff --git a/gcc/testsuite/rust.test/expr-block-generic.rs b/gcc/testsuite/rust.test/expr-block-generic.rs deleted file mode 100644 index 2f37960..0000000 --- a/gcc/testsuite/rust.test/expr-block-generic.rs +++ /dev/null @@ -1,41 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// xfail-fast - -// Tests for standalone blocks as expressions with dynamic type sizes -type compare<'self, T> = &'self fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = { expected.clone() }; - assert!((eq(expected, actual))); -} - -fn test_bool() { - fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } - test_generic::(true, compare_bool); -} - -#[deriving(Clone)] -struct Pair { - a: int, - b: int, -} - -fn test_rec() { - fn compare_rec(t1: Pair, t2: Pair) -> bool { - t1.a == t2.a && t1.b == t2.b - } - test_generic::(Pair {a: 1, b: 2}, compare_rec); -} - -pub fn main() { test_bool(); test_rec(); } diff --git a/gcc/testsuite/rust.test/expr-block-ref.rs b/gcc/testsuite/rust.test/expr-block-ref.rs deleted file mode 100644 index c77cad8..0000000 --- a/gcc/testsuite/rust.test/expr-block-ref.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #388 -pub fn main() { let _x = { { @10 } }; } diff --git a/gcc/testsuite/rust.test/expr-block-slot.rs b/gcc/testsuite/rust.test/expr-block-slot.rs deleted file mode 100644 index cfb764e..0000000 --- a/gcc/testsuite/rust.test/expr-block-slot.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #377 - -struct A { a: int } -struct V { v: int } - -pub fn main() { - let a = { let b = A {a: 3}; b }; - assert_eq!(a.a, 3); - let c = { let d = V {v: 3}; d }; - assert_eq!(c.v, 3); -} diff --git a/gcc/testsuite/rust.test/expr-block-unique.rs b/gcc/testsuite/rust.test/expr-block-unique.rs deleted file mode 100644 index 72151f7..0000000 --- a/gcc/testsuite/rust.test/expr-block-unique.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { let x = { ~100 }; assert!((*x == 100)); } diff --git a/gcc/testsuite/rust.test/expr-block.rs b/gcc/testsuite/rust.test/expr-block.rs deleted file mode 100644 index e43377c..0000000 --- a/gcc/testsuite/rust.test/expr-block.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for standalone blocks as expressions -fn test_basic() { let rs: bool = { true }; assert!((rs)); } - -struct RS { v1: int, v2: int } - -fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert!((rs.v2 == 20)); } - -fn test_filled_with_stuff() { - let rs = { let mut a = 0; while a < 10 { a += 1; } a }; - assert_eq!(rs, 10); -} - -pub fn main() { test_basic(); test_rec(); test_filled_with_stuff(); } diff --git a/gcc/testsuite/rust.test/expr-copy.rs b/gcc/testsuite/rust.test/expr-copy.rs deleted file mode 100644 index 4bc8d1f..0000000 --- a/gcc/testsuite/rust.test/expr-copy.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn f(arg: &mut A) { - arg.a = 100; -} - -struct A { a: int } - -pub fn main() { - let mut x = A {a: 10}; - f(&mut x); - assert_eq!(x.a, 100); - x.a = 20; - let mut y = x; - f(&mut y); - assert_eq!(x.a, 20); -} diff --git a/gcc/testsuite/rust.test/expr-elseif-ref.rs b/gcc/testsuite/rust.test/expr-elseif-ref.rs deleted file mode 100644 index 669acf1..0000000 --- a/gcc/testsuite/rust.test/expr-elseif-ref.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure we drop the refs of the temporaries needed to return the -// values from the else if branch -pub fn main() { - let y: @uint = @10u; - let _x = if false { y } else if true { y } else { y }; - assert_eq!(*y, 10u); -} diff --git a/gcc/testsuite/rust.test/expr-elseif-ref2.rs b/gcc/testsuite/rust.test/expr-elseif-ref2.rs deleted file mode 100644 index 96acaf4..0000000 --- a/gcc/testsuite/rust.test/expr-elseif-ref2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #388 -pub fn main() { - let _x = if false { - @0u - } else if true { - @10u - } else { - @0u - }; -} diff --git a/gcc/testsuite/rust.test/expr-empty-ret.rs b/gcc/testsuite/rust.test/expr-empty-ret.rs deleted file mode 100644 index afc7dfa..0000000 --- a/gcc/testsuite/rust.test/expr-empty-ret.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Issue #521 - -fn f() { - let _x = match true { - true => { 10 } - false => { return } - }; -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/expr-fn.rs b/gcc/testsuite/rust.test/expr-fn.rs deleted file mode 100644 index cba1bab..0000000 --- a/gcc/testsuite/rust.test/expr-fn.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test_int() { - fn f() -> int { 10 } - assert_eq!(f(), 10); -} - -fn test_vec() { - fn f() -> ~[int] { ~[10, 11] } - assert_eq!(f()[1], 11); -} - -fn test_generic() { - fn f(t: T) -> T { t } - assert_eq!(f(10), 10); -} - -fn test_alt() { - fn f() -> int { match true { false => { 10 } true => { 20 } } } - assert_eq!(f(), 20); -} - -fn test_if() { - fn f() -> int { if true { 10 } else { 20 } } - assert_eq!(f(), 10); -} - -fn test_block() { - fn f() -> int { { 10 } } - assert_eq!(f(), 10); -} - -fn test_ret() { - fn f() -> int { - return 10 // no semi - - } - assert_eq!(f(), 10); -} - - -// From issue #372 -fn test_372() { - fn f() -> int { let x = { 3 }; x } - assert_eq!(f(), 3); -} - -fn test_nil() { () } - -pub fn main() { - test_int(); - test_vec(); - test_generic(); - test_alt(); - test_if(); - test_block(); - test_ret(); - test_372(); - test_nil(); -} diff --git a/gcc/testsuite/rust.test/expr-if-box.rs b/gcc/testsuite/rust.test/expr-if-box.rs deleted file mode 100644 index e560da2..0000000 --- a/gcc/testsuite/rust.test/expr-if-box.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for if as expressions returning boxed types -fn test_box() { - let rs = if true { @100 } else { @101 }; - assert_eq!(*rs, 100); -} - -fn test_str() { - let rs = if true { ~"happy" } else { ~"sad" }; - assert_eq!(rs, ~"happy"); -} - -pub fn main() { test_box(); test_str(); } diff --git a/gcc/testsuite/rust.test/expr-if-fail-all.rs b/gcc/testsuite/rust.test/expr-if-fail-all.rs deleted file mode 100644 index b19b9ce..0000000 --- a/gcc/testsuite/rust.test/expr-if-fail-all.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// When all branches of an if expression result in fail, the entire if -// expression results in fail. -pub fn main() { - let _x = if true { - 10 - } else { - if true { fail2!() } else { fail2!() } - }; -} diff --git a/gcc/testsuite/rust.test/expr-if-fail.rs b/gcc/testsuite/rust.test/expr-if-fail.rs deleted file mode 100644 index 966a1db..0000000 --- a/gcc/testsuite/rust.test/expr-if-fail.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test_if_fail() { let x = if false { fail2!() } else { 10 }; assert!((x == 10)); } - -fn test_else_fail() { - let x = if true { 10 } else { fail2!() }; - assert_eq!(x, 10); -} - -fn test_elseif_fail() { - let x = if false { 0 } else if false { fail2!() } else { 10 }; - assert_eq!(x, 10); -} - -pub fn main() { test_if_fail(); test_else_fail(); test_elseif_fail(); } diff --git a/gcc/testsuite/rust.test/expr-if-generic-box1.rs b/gcc/testsuite/rust.test/expr-if-generic-box1.rs deleted file mode 100644 index 8bf6e65..0000000 --- a/gcc/testsuite/rust.test/expr-if-generic-box1.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -type compare = &'static fn(@T, @T) -> bool; - -fn test_generic(expected: @T, not_expected: @T, eq: compare) { - let actual: @T = if true { expected } else { not_expected }; - assert!((eq(expected, actual))); -} - -fn test_box() { - fn compare_box(b1: @bool, b2: @bool) -> bool { return *b1 == *b2; } - test_generic::(@true, @false, compare_box); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-if-generic-box2.rs b/gcc/testsuite/rust.test/expr-if-generic-box2.rs deleted file mode 100644 index 2c4707a..0000000 --- a/gcc/testsuite/rust.test/expr-if-generic-box2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -type compare = &'static fn(T, T) -> bool; - -fn test_generic(expected: T, not_expected: T, eq: compare) { - let actual: T = if true { expected.clone() } else { not_expected }; - assert!((eq(expected, actual))); -} - -fn test_vec() { - fn compare_box(v1: @int, v2: @int) -> bool { return v1 == v2; } - test_generic::<@int>(@1, @2, compare_box); -} - -pub fn main() { test_vec(); } diff --git a/gcc/testsuite/rust.test/expr-if-generic.rs b/gcc/testsuite/rust.test/expr-if-generic.rs deleted file mode 100644 index 1bbf3a5..0000000 --- a/gcc/testsuite/rust.test/expr-if-generic.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -// Tests for if as expressions with dynamic type sizes -type compare = &'static fn(T, T) -> bool; - -fn test_generic(expected: T, not_expected: T, eq: compare) { - let actual: T = if true { expected.clone() } else { not_expected }; - assert!((eq(expected, actual))); -} - -fn test_bool() { - fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } - test_generic::(true, false, compare_bool); -} - -#[deriving(Clone)] -struct Pair { - a: int, - b: int, -} - -fn test_rec() { - fn compare_rec(t1: Pair, t2: Pair) -> bool { - t1.a == t2.a && t1.b == t2.b - } - test_generic::(Pair{a: 1, b: 2}, Pair{a: 2, b: 3}, compare_rec); -} - -pub fn main() { test_bool(); test_rec(); } diff --git a/gcc/testsuite/rust.test/expr-if-struct.rs b/gcc/testsuite/rust.test/expr-if-struct.rs deleted file mode 100644 index 00e0fe1..0000000 --- a/gcc/testsuite/rust.test/expr-if-struct.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for if as expressions returning nominal types - -struct I { i: int } - -fn test_rec() { - let rs = if true { I {i: 100} } else { I {i: 101} }; - assert_eq!(rs.i, 100); -} - -enum mood { happy, sad, } - -impl Eq for mood { - fn eq(&self, other: &mood) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } -} - -fn test_tag() { - let rs = if true { happy } else { sad }; - assert_eq!(rs, happy); -} - -pub fn main() { test_rec(); test_tag(); } diff --git a/gcc/testsuite/rust.test/expr-if-unique.rs b/gcc/testsuite/rust.test/expr-if-unique.rs deleted file mode 100644 index 2271461..0000000 --- a/gcc/testsuite/rust.test/expr-if-unique.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for if as expressions returning boxed types -fn test_box() { - let rs = if true { ~100 } else { ~101 }; - assert_eq!(*rs, 100); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-if.rs b/gcc/testsuite/rust.test/expr-if.rs deleted file mode 100644 index 54f831e..0000000 --- a/gcc/testsuite/rust.test/expr-if.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for if as expressions -fn test_if() { let rs: bool = if true { true } else { false }; assert!((rs)); } - -fn test_else() { - let rs: bool = if false { false } else { true }; - assert!((rs)); -} - -fn test_elseif1() { - let rs: bool = if true { true } else if true { false } else { false }; - assert!((rs)); -} - -fn test_elseif2() { - let rs: bool = if false { false } else if true { true } else { false }; - assert!((rs)); -} - -fn test_elseif3() { - let rs: bool = if false { false } else if false { false } else { true }; - assert!((rs)); -} - -fn test_inferrence() { - let rs = if true { true } else { false }; - assert!((rs)); -} - -fn test_if_as_if_condition() { - let rs1 = if if false { false } else { true } { true } else { false }; - assert!((rs1)); - let rs2 = if if true { false } else { true } { false } else { true }; - assert!((rs2)); -} - -fn test_if_as_block_result() { - let rs = if true { if false { false } else { true } } else { false }; - assert!((rs)); -} - -pub fn main() { - test_if(); - test_else(); - test_elseif1(); - test_elseif2(); - test_elseif3(); - test_inferrence(); - test_if_as_if_condition(); - test_if_as_block_result(); -} diff --git a/gcc/testsuite/rust.test/expr-match-box.rs b/gcc/testsuite/rust.test/expr-match-box.rs deleted file mode 100644 index 6f63875..0000000 --- a/gcc/testsuite/rust.test/expr-match-box.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for match as expressions resulting in boxed types -fn test_box() { - let res = match true { true => { @100 } _ => fail2!("wat") }; - assert_eq!(*res, 100); -} - -fn test_str() { - let res = match true { true => { ~"happy" }, - _ => fail2!("not happy at all") }; - assert_eq!(res, ~"happy"); -} - -pub fn main() { test_box(); test_str(); } diff --git a/gcc/testsuite/rust.test/expr-match-fail-all.rs b/gcc/testsuite/rust.test/expr-match-fail-all.rs deleted file mode 100644 index 4180312..0000000 --- a/gcc/testsuite/rust.test/expr-match-fail-all.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// When all branches of an match expression result in fail, the entire -// match expression results in fail. -pub fn main() { - let _x = - match true { - true => { 10 } - false => { match true { true => { fail2!() } false => { fail2!() } } } - }; -} diff --git a/gcc/testsuite/rust.test/expr-match-fail.rs b/gcc/testsuite/rust.test/expr-match-fail.rs deleted file mode 100644 index c108156..0000000 --- a/gcc/testsuite/rust.test/expr-match-fail.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn test_simple() { - let r = match true { true => { true } false => { fail2!() } }; - assert_eq!(r, true); -} - -fn test_box() { - let r = match true { true => { ~[10] } false => { fail2!() } }; - assert_eq!(r[0], 10); -} - -pub fn main() { test_simple(); test_box(); } diff --git a/gcc/testsuite/rust.test/expr-match-generic-box1.rs b/gcc/testsuite/rust.test/expr-match-generic-box1.rs deleted file mode 100644 index e70a18a..0000000 --- a/gcc/testsuite/rust.test/expr-match-generic-box1.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -type compare = &'static fn(@T, @T) -> bool; - -fn test_generic(expected: @T, eq: compare) { - let actual: @T = match true { true => { expected }, _ => fail2!() }; - assert!((eq(expected, actual))); -} - -fn test_box() { - fn compare_box(b1: @bool, b2: @bool) -> bool { return *b1 == *b2; } - test_generic::(@true, compare_box); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-match-generic-box2.rs b/gcc/testsuite/rust.test/expr-match-generic-box2.rs deleted file mode 100644 index 92e13e3..0000000 --- a/gcc/testsuite/rust.test/expr-match-generic-box2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -type compare = &'static fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = match true { true => { expected.clone() }, _ => fail2!("wat") }; - assert!((eq(expected, actual))); -} - -fn test_vec() { - fn compare_box(v1: @int, v2: @int) -> bool { return v1 == v2; } - test_generic::<@int>(@1, compare_box); -} - -pub fn main() { test_vec(); } diff --git a/gcc/testsuite/rust.test/expr-match-generic-unique1.rs b/gcc/testsuite/rust.test/expr-match-generic-unique1.rs deleted file mode 100644 index e4a6fa5..0000000 --- a/gcc/testsuite/rust.test/expr-match-generic-unique1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -// -*- rust -*- -type compare = &'static fn(~T, ~T) -> bool; - -fn test_generic(expected: ~T, eq: compare) { - let actual: ~T = match true { - true => { expected.clone() }, - _ => fail2!("wat") - }; - assert!((eq(expected, actual))); -} - -fn test_box() { - fn compare_box(b1: ~bool, b2: ~bool) -> bool { return *b1 == *b2; } - test_generic::(~true, compare_box); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-match-generic-unique2.rs b/gcc/testsuite/rust.test/expr-match-generic-unique2.rs deleted file mode 100644 index 09278fa..0000000 --- a/gcc/testsuite/rust.test/expr-match-generic-unique2.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -type compare<'self, T> = &'self fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = match true { - true => expected.clone(), - _ => fail2!("wat") - }; - assert!((eq(expected, actual))); -} - -fn test_vec() { - fn compare_box(v1: ~int, v2: ~int) -> bool { return v1 == v2; } - test_generic::<~int>(~1, compare_box); -} - -pub fn main() { test_vec(); } diff --git a/gcc/testsuite/rust.test/expr-match-generic.rs b/gcc/testsuite/rust.test/expr-match-generic.rs deleted file mode 100644 index d98cd13..0000000 --- a/gcc/testsuite/rust.test/expr-match-generic.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// -*- rust -*- - -type compare = extern "Rust" fn(T, T) -> bool; - -fn test_generic(expected: T, eq: compare) { - let actual: T = match true { true => { expected.clone() }, _ => fail2!("wat") }; - assert!((eq(expected, actual))); -} - -fn test_bool() { - fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } - test_generic::(true, compare_bool); -} - -#[deriving(Clone)] -struct Pair { - a: int, - b: int, -} - -fn test_rec() { - fn compare_rec(t1: Pair, t2: Pair) -> bool { - t1.a == t2.a && t1.b == t2.b - } - test_generic::(Pair {a: 1, b: 2}, compare_rec); -} - -pub fn main() { test_bool(); test_rec(); } diff --git a/gcc/testsuite/rust.test/expr-match-struct.rs b/gcc/testsuite/rust.test/expr-match-struct.rs deleted file mode 100644 index 7fa58a5..0000000 --- a/gcc/testsuite/rust.test/expr-match-struct.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for match as expressions resulting in struct types -struct R { i: int } - -fn test_rec() { - let rs = match true { true => R {i: 100}, _ => fail2!() }; - assert_eq!(rs.i, 100); -} - -enum mood { happy, sad, } - -impl Eq for mood { - fn eq(&self, other: &mood) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } -} - -fn test_tag() { - let rs = match true { true => { happy } false => { sad } }; - assert_eq!(rs, happy); -} - -pub fn main() { test_rec(); test_tag(); } diff --git a/gcc/testsuite/rust.test/expr-match-unique.rs b/gcc/testsuite/rust.test/expr-match-unique.rs deleted file mode 100644 index 7f610d1..0000000 --- a/gcc/testsuite/rust.test/expr-match-unique.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for match as expressions resulting in boxed types -fn test_box() { - let res = match true { true => { ~100 }, _ => fail2!() }; - assert_eq!(*res, 100); -} - -pub fn main() { test_box(); } diff --git a/gcc/testsuite/rust.test/expr-match.rs b/gcc/testsuite/rust.test/expr-match.rs deleted file mode 100644 index 1e9ad52..0000000 --- a/gcc/testsuite/rust.test/expr-match.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Tests for using match as an expression -fn test_basic() { - let mut rs: bool = match true { true => { true } false => { false } }; - assert!((rs)); - rs = match false { true => { false } false => { true } }; - assert!((rs)); -} - -fn test_inferrence() { - let rs = match true { true => { true } false => { false } }; - assert!((rs)); -} - -fn test_alt_as_alt_head() { - // Yeah, this is kind of confusing ... - - let rs = - match match false { true => { true } false => { false } } { - true => { false } - false => { true } - }; - assert!((rs)); -} - -fn test_alt_as_block_result() { - let rs = - match false { - true => { false } - false => { match true { true => { true } false => { false } } } - }; - assert!((rs)); -} - -pub fn main() { - test_basic(); - test_inferrence(); - test_alt_as_alt_head(); - test_alt_as_block_result(); -} diff --git a/gcc/testsuite/rust.test/expr-repeat-vstore.rs b/gcc/testsuite/rust.test/expr-repeat-vstore.rs deleted file mode 100644 index 48bce39..0000000 --- a/gcc/testsuite/rust.test/expr-repeat-vstore.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::io::println; - -pub fn main() { - let v: ~[int] = ~[ 1, ..5 ]; - println(v[0].to_str()); - println(v[1].to_str()); - println(v[2].to_str()); - println(v[3].to_str()); - println(v[4].to_str()); - let v: @[int] = @[ 2, ..5 ]; - println(v[0].to_str()); - println(v[1].to_str()); - println(v[2].to_str()); - println(v[3].to_str()); - println(v[4].to_str()); - let v: @mut [int] = @mut [ 3, ..5 ]; - println((v[0]).to_str()); - println((v[1]).to_str()); - println((v[2]).to_str()); - println((v[3]).to_str()); - println((v[4]).to_str()); -} diff --git a/gcc/testsuite/rust.test/expr-scope.rs b/gcc/testsuite/rust.test/expr-scope.rs deleted file mode 100644 index 942147f..0000000 --- a/gcc/testsuite/rust.test/expr-scope.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Regression test for issue #762 -// xfail-fast - -pub fn f() { } -pub fn main() { return ::f(); } diff --git a/gcc/testsuite/rust.test/exterior.rs b/gcc/testsuite/rust.test/exterior.rs deleted file mode 100644 index 43f14b7..0000000 --- a/gcc/testsuite/rust.test/exterior.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -struct Point {x: int, y: int, z: int} - -fn f(p: @mut Point) { assert!((p.z == 12)); p.z = 13; assert!((p.z == 13)); } - -pub fn main() { - let a: Point = Point {x: 10, y: 11, z: 12}; - let b: @mut Point = @mut a; - assert_eq!(b.z, 12); - f(b); - assert_eq!(a.z, 12); - assert_eq!(b.z, 13); -} diff --git a/gcc/testsuite/rust.test/extern-1.rs b/gcc/testsuite/rust.test/extern-1.rs deleted file mode 100644 index e4b9b9d..0000000 --- a/gcc/testsuite/rust.test/extern-1.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern fn f() { -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/extern-call-deep.rs b/gcc/testsuite/rust.test/extern-call-deep.rs deleted file mode 100644 index 41ae128..0000000 --- a/gcc/testsuite/rust.test/extern-call-deep.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - count(data - 1u) + 1u - } -} - -#[fixed_stack_segment] -fn count(n: uint) -> uint { - unsafe { - info2!("n = {}", n); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - let result = count(1000u); - info2!("result = {}", result); - assert_eq!(result, 1000u); -} diff --git a/gcc/testsuite/rust.test/extern-call-deep2.rs b/gcc/testsuite/rust.test/extern-call-deep2.rs deleted file mode 100644 index 0490949..0000000 --- a/gcc/testsuite/rust.test/extern-call-deep2.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; -use std::task; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - count(data - 1u) + 1u - } -} - -#[fixed_stack_segment] #[inline(never)] -fn count(n: uint) -> uint { - unsafe { - info2!("n = {}", n); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - // Make sure we're on a task with small Rust stacks (main currently - // has a large stack) - do task::spawn { - let result = count(1000u); - info2!("result = {}", result); - assert_eq!(result, 1000u); - }; -} diff --git a/gcc/testsuite/rust.test/extern-call-direct.rs b/gcc/testsuite/rust.test/extern-call-direct.rs deleted file mode 100644 index 925ec8e..0000000 --- a/gcc/testsuite/rust.test/extern-call-direct.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test direct calls to extern fns. - -extern fn f(x: uint) -> uint { x * 2 } - -pub fn main() { - #[fixed_stack_segment]; - - let x = f(22); - assert_eq!(x, 44); -} diff --git a/gcc/testsuite/rust.test/extern-call-indirect.rs b/gcc/testsuite/rust.test/extern-call-indirect.rs deleted file mode 100644 index 733625f..0000000 --- a/gcc/testsuite/rust.test/extern-call-indirect.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - fact(data - 1u) * data - } -} - -#[fixed_stack_segment] #[inline(never)] -fn fact(n: uint) -> uint { - unsafe { - info2!("n = {}", n); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - let result = fact(10u); - info2!("result = {}", result); - assert_eq!(result, 3628800u); -} diff --git a/gcc/testsuite/rust.test/extern-call-scrub.rs b/gcc/testsuite/rust.test/extern-call-scrub.rs deleted file mode 100644 index 74b1ed9..0000000 --- a/gcc/testsuite/rust.test/extern-call-scrub.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This time we're testing repeatedly going up and down both stacks to -// make sure the stack pointers are maintained properly in both -// directions - -use std::libc; -use std::task; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - count(data - 1u) + count(data - 1u) - } -} - -#[fixed_stack_segment] #[inline(never)] -fn count(n: uint) -> uint { - unsafe { - info2!("n = {}", n); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - // Make sure we're on a task with small Rust stacks (main currently - // has a large stack) - do task::spawn { - let result = count(12u); - info2!("result = {}", result); - assert_eq!(result, 2048u); - }; -} diff --git a/gcc/testsuite/rust.test/extern-compare-with-return-type.rs b/gcc/testsuite/rust.test/extern-compare-with-return-type.rs deleted file mode 100644 index 53a5d3e..0000000 --- a/gcc/testsuite/rust.test/extern-compare-with-return-type.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that we can compare various kinds of extern fn signatures. - -extern fn voidret1() {} -extern fn voidret2() {} - -extern fn uintret() -> uint { 22 } - -extern fn uintvoidret(_x: uint) {} - -extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z } - -pub fn main() { - assert_eq!(voidret1, voidret1); - assert!(voidret1 != voidret2); - - assert_eq!(uintret, uintret); - - assert_eq!(uintvoidret, uintvoidret); - - assert_eq!(uintuintuintuintret, uintuintuintuintret); -} - diff --git a/gcc/testsuite/rust.test/extern-crosscrate.rs b/gcc/testsuite/rust.test/extern-crosscrate.rs deleted file mode 100644 index 3367b79..0000000 --- a/gcc/testsuite/rust.test/extern-crosscrate.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -//aux-build:extern-crosscrate-source.rs - -extern mod externcallback(vers = "0.1"); - -#[fixed_stack_segment] #[inline(never)] -fn fact(n: uint) -> uint { - unsafe { - info2!("n = {}", n); - externcallback::rustrt::rust_dbg_call(externcallback::cb, n) - } -} - -pub fn main() { - let result = fact(10u); - info2!("result = {}", result); - assert_eq!(result, 3628800u); -} diff --git a/gcc/testsuite/rust.test/extern-mod-abi.rs b/gcc/testsuite/rust.test/extern-mod-abi.rs deleted file mode 100644 index 84fd1b4..0000000 --- a/gcc/testsuite/rust.test/extern-mod-abi.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern "C" { - fn pow(x: f64, y: f64) -> f64; -} - -pub fn main() {} diff --git a/gcc/testsuite/rust.test/extern-mod-ordering-exe.rs b/gcc/testsuite/rust.test/extern-mod-ordering-exe.rs deleted file mode 100644 index 5836245..0000000 --- a/gcc/testsuite/rust.test/extern-mod-ordering-exe.rs +++ /dev/null @@ -1,10 +0,0 @@ -// aux-build:extern_mod_ordering_lib.rs -// xfail-fast - -extern mod extern_mod_ordering_lib; - -use extern_mod_ordering_lib::extern_mod_ordering_lib; - -fn main() { - extern_mod_ordering_lib::f(); -} diff --git a/gcc/testsuite/rust.test/extern-mod-syntax.rs b/gcc/testsuite/rust.test/extern-mod-syntax.rs deleted file mode 100644 index 4643c80..0000000 --- a/gcc/testsuite/rust.test/extern-mod-syntax.rs +++ /dev/null @@ -1,20 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_imports)]; - -extern mod extra; -use extra::json::Object; - -pub fn main() { - println("Hello world!"); -} diff --git a/gcc/testsuite/rust.test/extern-pass-TwoU16s.rs b/gcc/testsuite/rust.test/extern-pass-TwoU16s.rs deleted file mode 100644 index eadb01d..0000000 --- a/gcc/testsuite/rust.test/extern-pass-TwoU16s.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #5744 fails on 32 bit - -// Test a foreign function that accepts and returns a struct -// by value. - -#[deriving(Eq)] -struct TwoU16s { - one: u16, two: u16 -} - -extern { - pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let x = TwoU16s {one: 22, two: 23}; - let y = rust_dbg_extern_identity_TwoU16s(x); - assert_eq!(x, y); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-TwoU32s.rs b/gcc/testsuite/rust.test/extern-pass-TwoU32s.rs deleted file mode 100644 index 147db0c..0000000 --- a/gcc/testsuite/rust.test/extern-pass-TwoU32s.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a foreign function that accepts and returns a struct -// by value. - -#[deriving(Eq)] -struct TwoU32s { - one: u32, two: u32 -} - -extern { - pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let x = TwoU32s {one: 22, two: 23}; - let y = rust_dbg_extern_identity_TwoU32s(x); - assert_eq!(x, y); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-TwoU64s-ref.rs b/gcc/testsuite/rust.test/extern-pass-TwoU64s-ref.rs deleted file mode 100644 index ed9871b..0000000 --- a/gcc/testsuite/rust.test/extern-pass-TwoU64s-ref.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that we ignore modes when calling extern functions. -// xfail-fast #9205 - -#[deriving(Eq)] -struct TwoU64s { - one: u64, two: u64 -} - -extern { - pub fn rust_dbg_extern_identity_TwoU64s(u: TwoU64s) -> TwoU64s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let x = TwoU64s {one: 22, two: 23}; - let y = rust_dbg_extern_identity_TwoU64s(x); - assert_eq!(x, y); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-TwoU64s.rs b/gcc/testsuite/rust.test/extern-pass-TwoU64s.rs deleted file mode 100644 index 772970c..0000000 --- a/gcc/testsuite/rust.test/extern-pass-TwoU64s.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a foreign function that accepts and returns a struct -// by value. - -// xfail-fast This works standalone on windows but not with check-fast. -// possibly because there is another test that uses this extern fn but gives it -// a different signature -// xfail-fast #9205 - -#[deriving(Eq)] -struct TwoU64s { - one: u64, two: u64 -} - -extern { - pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let x = TwoU64s {one: 22, two: 23}; - let y = rust_dbg_extern_identity_TwoU64s(x); - assert_eq!(x, y); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-TwoU8s.rs b/gcc/testsuite/rust.test/extern-pass-TwoU8s.rs deleted file mode 100644 index 868c40d..0000000 --- a/gcc/testsuite/rust.test/extern-pass-TwoU8s.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #5744 fails on 32 bit - -// Test a foreign function that accepts and returns a struct -// by value. - -#[deriving(Eq)] -struct TwoU8s { - one: u8, two: u8 -} - -extern { - pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let x = TwoU8s {one: 22, two: 23}; - let y = rust_dbg_extern_identity_TwoU8s(x); - assert_eq!(x, y); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-char.rs b/gcc/testsuite/rust.test/extern-pass-char.rs deleted file mode 100644 index f255746..0000000 --- a/gcc/testsuite/rust.test/extern-pass-char.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a function that takes/returns a u8. - -extern { - pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - assert_eq!(22_u8, rust_dbg_extern_identity_u8(22_u8)); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-double.rs b/gcc/testsuite/rust.test/extern-pass-double.rs deleted file mode 100644 index c80a0cd..0000000 --- a/gcc/testsuite/rust.test/extern-pass-double.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern { - pub fn rust_dbg_extern_identity_double(v: f64) -> f64; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64)); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-u32.rs b/gcc/testsuite/rust.test/extern-pass-u32.rs deleted file mode 100644 index c6fdabe..0000000 --- a/gcc/testsuite/rust.test/extern-pass-u32.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a function that takes/returns a u32. - -extern { - pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - assert_eq!(22_u32, rust_dbg_extern_identity_u32(22_u32)); - } -} diff --git a/gcc/testsuite/rust.test/extern-pass-u64.rs b/gcc/testsuite/rust.test/extern-pass-u64.rs deleted file mode 100644 index 09babc1..0000000 --- a/gcc/testsuite/rust.test/extern-pass-u64.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test a call to a function that takes/returns a u64. - -extern { - pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - assert_eq!(22_u64, rust_dbg_extern_identity_u64(22_u64)); - } -} diff --git a/gcc/testsuite/rust.test/extern-pub.rs b/gcc/testsuite/rust.test/extern-pub.rs deleted file mode 100644 index b146f32..0000000 --- a/gcc/testsuite/rust.test/extern-pub.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern { - pub fn free(p: *u8); -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/extern-return-TwoU16s.rs b/gcc/testsuite/rust.test/extern-return-TwoU16s.rs deleted file mode 100644 index 2b9f99c..0000000 --- a/gcc/testsuite/rust.test/extern-return-TwoU16s.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct TwoU16s { - one: u16, two: u16 -} - -extern { - pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let y = rust_dbg_extern_return_TwoU16s(); - assert_eq!(y.one, 10); - assert_eq!(y.two, 20); - } -} diff --git a/gcc/testsuite/rust.test/extern-return-TwoU32s.rs b/gcc/testsuite/rust.test/extern-return-TwoU32s.rs deleted file mode 100644 index f93a15b..0000000 --- a/gcc/testsuite/rust.test/extern-return-TwoU32s.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct TwoU32s { - one: u32, two: u32 -} - -extern { - pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let y = rust_dbg_extern_return_TwoU32s(); - assert_eq!(y.one, 10); - assert_eq!(y.two, 20); - } -} diff --git a/gcc/testsuite/rust.test/extern-return-TwoU64s.rs b/gcc/testsuite/rust.test/extern-return-TwoU64s.rs deleted file mode 100644 index 7fcbe36..0000000 --- a/gcc/testsuite/rust.test/extern-return-TwoU64s.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast #9205 - -struct TwoU64s { - one: u64, two: u64 -} - -extern { - pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let y = rust_dbg_extern_return_TwoU64s(); - assert_eq!(y.one, 10); - assert_eq!(y.two, 20); - } -} diff --git a/gcc/testsuite/rust.test/extern-return-TwoU8s.rs b/gcc/testsuite/rust.test/extern-return-TwoU8s.rs deleted file mode 100644 index aae8b8a..0000000 --- a/gcc/testsuite/rust.test/extern-return-TwoU8s.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct TwoU8s { - one: u8, two: u8 -} - -extern { - pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - let y = rust_dbg_extern_return_TwoU8s(); - assert_eq!(y.one, 10); - assert_eq!(y.two, 20); - } -} diff --git a/gcc/testsuite/rust.test/extern-stress.rs b/gcc/testsuite/rust.test/extern-stress.rs deleted file mode 100644 index 2323567..0000000 --- a/gcc/testsuite/rust.test/extern-stress.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This creates a bunch of descheduling tasks that run concurrently -// while holding onto C stacks - -use std::libc; -use std::task; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - task::deschedule(); - count(data - 1u) + count(data - 1u) - } -} - -#[fixed_stack_segment] #[inline(never)] -fn count(n: uint) -> uint { - unsafe { - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - do 100u.times { - do task::spawn { - assert_eq!(count(5u), 16u); - }; - } -} diff --git a/gcc/testsuite/rust.test/extern-take-value.rs b/gcc/testsuite/rust.test/extern-take-value.rs deleted file mode 100644 index b883fbd..0000000 --- a/gcc/testsuite/rust.test/extern-take-value.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern fn f() { -} - -extern fn g() { -} - -pub fn main() { - let a: extern "C" fn() = f; - let b: extern "C" fn() = f; - let c: extern "C" fn() = g; - - assert_eq!(a, b); - assert!(a != c); -} diff --git a/gcc/testsuite/rust.test/extern-yield.rs b/gcc/testsuite/rust.test/extern-yield.rs deleted file mode 100644 index 7e71d41..0000000 --- a/gcc/testsuite/rust.test/extern-yield.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::libc; -use std::task; - -mod rustrt { - use std::libc; - - extern { - pub fn rust_dbg_call(cb: extern "C" fn (libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1u { - data - } else { - count(data - 1u) + count(data - 1u) - } -} - -#[fixed_stack_segment] #[inline(never)] -fn count(n: uint) -> uint { - unsafe { - task::deschedule(); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - do 10u.times { - do task::spawn { - let result = count(5u); - info2!("result = {}", result); - assert_eq!(result, 16u); - }; - } -} diff --git a/gcc/testsuite/rust.test/extoption_env-not-defined.rs b/gcc/testsuite/rust.test/extoption_env-not-defined.rs deleted file mode 100644 index 891133c..0000000 --- a/gcc/testsuite/rust.test/extoption_env-not-defined.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - assert!(option_env!("__HOPEFULLY_DOESNT_EXIST__").is_none()); -} diff --git a/gcc/testsuite/rust.test/fact.rs b/gcc/testsuite/rust.test/fact.rs deleted file mode 100644 index f0379e1..0000000 --- a/gcc/testsuite/rust.test/fact.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn f(x: int) -> int { - // info!("in f:"); - - info2!("{}", x); - if x == 1 { - // info!("bottoming out"); - - return 1; - } else { - // info!("recurring"); - - let y: int = x * f(x - 1); - // info!("returned"); - - info2!("{}", y); - return y; - } -} - -pub fn main() { - assert_eq!(f(5), 120); - // info!("all done"); - -} diff --git a/gcc/testsuite/rust.test/fat-arrow-match.rs b/gcc/testsuite/rust.test/fat-arrow-match.rs deleted file mode 100644 index be945e9..0000000 --- a/gcc/testsuite/rust.test/fat-arrow-match.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -enum color { - red, - green, - blue -} - -pub fn main() { - error2!("{}", match red { - red => { 1 } - green => { 2 } - blue => { 3 } - }); -} diff --git a/gcc/testsuite/rust.test/filter-block-view-items.rs b/gcc/testsuite/rust.test/filter-block-view-items.rs deleted file mode 100644 index 34272b1..0000000 --- a/gcc/testsuite/rust.test/filter-block-view-items.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - // Make sure that this view item is filtered out because otherwise it would - // trigger a compilation error - #[cfg(not_present)] use foo = bar; -} diff --git a/gcc/testsuite/rust.test/fixed_length_copy.rs b/gcc/testsuite/rust.test/fixed_length_copy.rs deleted file mode 100644 index bbd7b91..0000000 --- a/gcc/testsuite/rust.test/fixed_length_copy.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let arr = [1,2,3]; - let arr2 = arr; - assert_eq!(arr[1], 2); - assert_eq!(arr2[2], 3); -} diff --git a/gcc/testsuite/rust.test/fixed_length_vec_glue.rs b/gcc/testsuite/rust.test/fixed_length_vec_glue.rs deleted file mode 100644 index ab34245..0000000 --- a/gcc/testsuite/rust.test/fixed_length_vec_glue.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast: check-fast screws up repr paths - -use std::sys; - -struct Struc { a: u8, b: [int, ..3], c: int } - -pub fn main() { - let arr = [1,2,3]; - let struc = Struc {a: 13u8, b: arr, c: 42}; - let s = sys::log_str(&struc); - assert_eq!(s, ~"Struc{a: 13u8, b: [1, 2, 3], c: 42}"); -} diff --git a/gcc/testsuite/rust.test/float-literal-inference.rs b/gcc/testsuite/rust.test/float-literal-inference.rs deleted file mode 100644 index b80cdf9..0000000 --- a/gcc/testsuite/rust.test/float-literal-inference.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S { - z: f64 -} - -pub fn main() { - let x: f32 = 4.0; - println(x.to_str()); - let y: f64 = 64.0; - println(y.to_str()); - let z = S { z: 1.0 }; - println(z.z.to_str()); -} diff --git a/gcc/testsuite/rust.test/float-nan.rs b/gcc/testsuite/rust.test/float-nan.rs deleted file mode 100644 index 9035176..0000000 --- a/gcc/testsuite/rust.test/float-nan.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use std::num::Float; - -pub fn main() { - let nan: f64 = Float::nan(); - assert!((nan).is_nan()); - - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - assert_eq!(-inf, neg_inf); - - assert!( nan != nan); - assert!( nan != -nan); - assert!(-nan != -nan); - assert!(-nan != nan); - - assert!( nan != 1.); - assert!( nan != 0.); - assert!( nan != inf); - assert!( nan != -inf); - - assert!( 1. != nan); - assert!( 0. != nan); - assert!( inf != nan); - assert!(-inf != nan); - - assert!(!( nan == nan)); - assert!(!( nan == -nan)); - assert!(!( nan == 1.)); - assert!(!( nan == 0.)); - assert!(!( nan == inf)); - assert!(!( nan == -inf)); - assert!(!( 1. == nan)); - assert!(!( 0. == nan)); - assert!(!( inf == nan)); - assert!(!(-inf == nan)); - assert!(!(-nan == nan)); - assert!(!(-nan == -nan)); - - assert!(!( nan > nan)); - assert!(!( nan > -nan)); - assert!(!( nan > 0.)); - assert!(!( nan > inf)); - assert!(!( nan > -inf)); - assert!(!( 0. > nan)); - assert!(!( inf > nan)); - assert!(!(-inf > nan)); - assert!(!(-nan > nan)); - - assert!(!(nan < 0.)); - assert!(!(nan < 1.)); - assert!(!(nan < -1.)); - assert!(!(nan < inf)); - assert!(!(nan < -inf)); - assert!(!(nan < nan)); - assert!(!(nan < -nan)); - - assert!(!( 0. < nan)); - assert!(!( 1. < nan)); - assert!(!( -1. < nan)); - assert!(!( inf < nan)); - assert!(!(-inf < nan)); - assert!(!(-nan < nan)); - - assert!((nan + inf).is_nan()); - assert!((nan + -inf).is_nan()); - assert!((nan + 0.).is_nan()); - assert!((nan + 1.).is_nan()); - assert!((nan * 1.).is_nan()); - assert!((nan / 1.).is_nan()); - assert!((nan / 0.).is_nan()); - assert!((0.0/0.0f64).is_nan()); - assert!((-inf + inf).is_nan()); - assert!((inf - inf).is_nan()); - - assert!(!(-1.0f64).is_nan()); - assert!(!(0.0f64).is_nan()); - assert!(!(0.1f64).is_nan()); - assert!(!(1.0f64).is_nan()); - assert!(!(inf).is_nan()); - assert!(!(-inf).is_nan()); - assert!(!(1./-inf).is_nan()); -} diff --git a/gcc/testsuite/rust.test/float-signature.rs b/gcc/testsuite/rust.test/float-signature.rs deleted file mode 100644 index dae41d3..0000000 --- a/gcc/testsuite/rust.test/float-signature.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - fn foo(n: f64) -> f64 { return n + 0.12345; } - let n: f64 = 0.1; - let m: f64 = foo(n); - info2!("{}", m); -} diff --git a/gcc/testsuite/rust.test/float.rs b/gcc/testsuite/rust.test/float.rs deleted file mode 100644 index 1418255..0000000 --- a/gcc/testsuite/rust.test/float.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let pi = 3.1415927; - info2!("{:?}", -pi * (pi + 2.0 / pi) - pi * 5.0); - if pi == 5.0 || pi < 10.0 || pi <= 2.0 || pi != 22.0 / 7.0 || pi >= 10.0 - || pi > 1.0 { - info2!("yes"); - } -} diff --git a/gcc/testsuite/rust.test/float2.rs b/gcc/testsuite/rust.test/float2.rs deleted file mode 100644 index 713d863..0000000 --- a/gcc/testsuite/rust.test/float2.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let a = 1.5e6; - let b = 1.5E6; - let c = 1e6; - let d = 1E6; - let e = 3.0f32; - let f = 5.9f64; - let g = 1e6f32; - let h = 1.0e7f64; - let i = 1.0E7f64; - let j = 3.1e+9; - let k = 3.2e-10; - assert_eq!(a, b); - assert!((c < b)); - assert_eq!(c, d); - assert!((e < g)); - assert!((f < h)); - assert_eq!(g, 1000000.0f32); - assert_eq!(h, i); - assert!((j > k)); - assert!((k < a)); -} diff --git a/gcc/testsuite/rust.test/floatlits.rs b/gcc/testsuite/rust.test/floatlits.rs deleted file mode 100644 index d1300e7..0000000 --- a/gcc/testsuite/rust.test/floatlits.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -pub fn main() { - let f = 4.999999999999; - assert!((f > 4.90)); - assert!((f < 5.0)); - let g = 4.90000000001e-10; - assert!((g > 5e-11)); - assert!((g < 5e-9)); -} diff --git a/gcc/testsuite/rust.test/fn-bare-assign.rs b/gcc/testsuite/rust.test/fn-bare-assign.rs deleted file mode 100644 index 7c8fbd2..0000000 --- a/gcc/testsuite/rust.test/fn-bare-assign.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(i: int, called: &mut bool) { - assert_eq!(i, 10); - *called = true; -} - -fn g(f: extern fn(int, v: &mut bool), called: &mut bool) { - f(10, called); -} - -pub fn main() { - let mut called = false; - let h = f; - g(h, &mut called); - assert_eq!(called, true); -} diff --git a/gcc/testsuite/rust.test/fn-bare-coerce-to-block.rs b/gcc/testsuite/rust.test/fn-bare-coerce-to-block.rs deleted file mode 100644 index db7604d..0000000 --- a/gcc/testsuite/rust.test/fn-bare-coerce-to-block.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn bare() {} - -fn likes_block(f: &fn()) { f() } - -pub fn main() { - likes_block(bare); -} diff --git a/gcc/testsuite/rust.test/fn-bare-item.rs b/gcc/testsuite/rust.test/fn-bare-item.rs deleted file mode 100644 index be0f686..0000000 --- a/gcc/testsuite/rust.test/fn-bare-item.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() { - info2!("This is a bare function"); -} - -pub fn main() { - f(); -} diff --git a/gcc/testsuite/rust.test/fn-bare-size.rs b/gcc/testsuite/rust.test/fn-bare-size.rs deleted file mode 100644 index cdde983..0000000 --- a/gcc/testsuite/rust.test/fn-bare-size.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -pub fn main() { - // Bare functions should just be a pointer - assert_eq!(mem::size_of::(), mem::size_of::()); -} diff --git a/gcc/testsuite/rust.test/fn-bare-spawn.rs b/gcc/testsuite/rust.test/fn-bare-spawn.rs deleted file mode 100644 index e9954be..0000000 --- a/gcc/testsuite/rust.test/fn-bare-spawn.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This is what the signature to spawn should look like with bare functions - -fn spawn(val: T, f: extern fn(T)) { - f(val); -} - -fn f(i: int) { - assert_eq!(i, 100); -} - -pub fn main() { - spawn(100, f); -} diff --git a/gcc/testsuite/rust.test/fn-coerce-field.rs b/gcc/testsuite/rust.test/fn-coerce-field.rs deleted file mode 100644 index ae2e353..0000000 --- a/gcc/testsuite/rust.test/fn-coerce-field.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct r<'self> { - field: &'self fn() -} - -pub fn main() { - fn f() {} - let _i: r = r {field: f}; -} diff --git a/gcc/testsuite/rust.test/fn-lval.rs b/gcc/testsuite/rust.test/fn-lval.rs deleted file mode 100644 index b19708a..0000000 --- a/gcc/testsuite/rust.test/fn-lval.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn foo(_f: extern fn(int) -> int) { } - -fn id(x: int) -> int { return x; } - -pub fn main() { foo(id); } diff --git a/gcc/testsuite/rust.test/fn-pattern-expected-type-2.rs b/gcc/testsuite/rust.test/fn-pattern-expected-type-2.rs deleted file mode 100644 index 8102673..0000000 --- a/gcc/testsuite/rust.test/fn-pattern-expected-type-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let v : &[(int,int)] = &[ (1, 2), (3, 4), (5, 6) ]; - for &(x, y) in v.iter() { - println(y.to_str()); - println(x.to_str()); - } -} diff --git a/gcc/testsuite/rust.test/fn-pattern-expected-type.rs b/gcc/testsuite/rust.test/fn-pattern-expected-type.rs deleted file mode 100644 index 450e2a7..0000000 --- a/gcc/testsuite/rust.test/fn-pattern-expected-type.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let f: &fn((int,int)) = |(x, y)| { - assert_eq!(x, 1); - assert_eq!(y, 2); - }; - f((1, 2)); -} diff --git a/gcc/testsuite/rust.test/fn-type-infer.rs b/gcc/testsuite/rust.test/fn-type-infer.rs deleted file mode 100644 index 09e7aba..0000000 --- a/gcc/testsuite/rust.test/fn-type-infer.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(unused_variable)]; - -pub fn main() { - // We should be able to type infer inside of &fns. - let _f = || { - let i = 10; - }; -} diff --git a/gcc/testsuite/rust.test/for-destruct.rs b/gcc/testsuite/rust.test/for-destruct.rs deleted file mode 100644 index dd1cda2..0000000 --- a/gcc/testsuite/rust.test/for-destruct.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test: #3511: does not currently compile, due to rvalue issues - -use std::vec; - -struct Pair { x: int, y: int } -pub fn main() { - for vec::each(~[Pair {x: 10, y: 20}, Pair {x: 30, y: 0}]) |elt| { - assert_eq!(elt.x + elt.y, 30); - } -} diff --git a/gcc/testsuite/rust.test/for-loop-fail.rs b/gcc/testsuite/rust.test/for-loop-fail.rs deleted file mode 100644 index 9599c58..0000000 --- a/gcc/testsuite/rust.test/for-loop-fail.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { let x: ~[int] = ~[]; for _ in x.iter() { fail2!("moop"); } } diff --git a/gcc/testsuite/rust.test/foreach-external-iterators-break.rs b/gcc/testsuite/rust.test/foreach-external-iterators-break.rs deleted file mode 100644 index 87ed782..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators-break.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = [1,..100]; - let mut y = 0; - for i in x.iter() { - if y > 10 { - break; - } - y += *i; - } - assert!(y == 11); -} diff --git a/gcc/testsuite/rust.test/foreach-external-iterators-hashmap-break-restart.rs b/gcc/testsuite/rust.test/foreach-external-iterators-hashmap-break-restart.rs deleted file mode 100644 index 34ce8c4..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators-hashmap-break-restart.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -// This is a fancy one: it uses an external iterator established -// outside the loop, breaks, then _picks back up_ and continues -// iterating with it. - -pub fn main() { - let mut h = HashMap::new(); - let kvs = [(1, 10), (2, 20), (3, 30)]; - for &(k,v) in kvs.iter() { - h.insert(k,v); - } - let mut x = 0; - let mut y = 0; - - let mut i = h.iter(); - - for (&k,&v) in i { - x += k; - y += v; - break; - } - - for (&k,&v) in i { - x += k; - y += v; - } - - assert_eq!(x, 6); - assert_eq!(y, 60); -} diff --git a/gcc/testsuite/rust.test/foreach-external-iterators-hashmap.rs b/gcc/testsuite/rust.test/foreach-external-iterators-hashmap.rs deleted file mode 100644 index 365cde3..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators-hashmap.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::hashmap::HashMap; - -pub fn main() { - let mut h = HashMap::new(); - let kvs = [(1, 10), (2, 20), (3, 30)]; - for &(k,v) in kvs.iter() { - h.insert(k,v); - } - let mut x = 0; - let mut y = 0; - for (&k,&v) in h.iter() { - x += k; - y += v; - } - assert_eq!(x, 6); - assert_eq!(y, 60); -} diff --git a/gcc/testsuite/rust.test/foreach-external-iterators-loop.rs b/gcc/testsuite/rust.test/foreach-external-iterators-loop.rs deleted file mode 100644 index 3757687..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators-loop.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = [1,..100]; - let mut y = 0; - for (n,i) in x.iter().enumerate() { - if n < 10 { - continue; - } - y += *i; - } - assert_eq!(y, 90); -} diff --git a/gcc/testsuite/rust.test/foreach-external-iterators-nested.rs b/gcc/testsuite/rust.test/foreach-external-iterators-nested.rs deleted file mode 100644 index 78aba77..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators-nested.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = [1,..100]; - let y = [2,..100]; - let mut p = 0; - let mut q = 0; - for i in x.iter() { - for j in y.iter() { - p += *j; - } - q += *i + p; - } - assert!(q == 1010100); -} diff --git a/gcc/testsuite/rust.test/foreach-external-iterators.rs b/gcc/testsuite/rust.test/foreach-external-iterators.rs deleted file mode 100644 index 593a996..0000000 --- a/gcc/testsuite/rust.test/foreach-external-iterators.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - let x = [1,..100]; - let mut y = 0; - for i in x.iter() { - y += *i - } - assert!(y == 100); -} diff --git a/gcc/testsuite/rust.test/foreach-nested.rs b/gcc/testsuite/rust.test/foreach-nested.rs deleted file mode 100644 index 6987e2c..0000000 --- a/gcc/testsuite/rust.test/foreach-nested.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn two(it: &fn(int)) { it(0); it(1); } - -pub fn main() { - let mut a: ~[int] = ~[-1, -1, -1, -1]; - let mut p: int = 0; - do two |i| { - do two |j| { a[p] = 10 * i + j; p += 1; } - } - assert_eq!(a[0], 0); - assert_eq!(a[1], 1); - assert_eq!(a[2], 10); - assert_eq!(a[3], 11); -} diff --git a/gcc/testsuite/rust.test/foreach-put-structured.rs b/gcc/testsuite/rust.test/foreach-put-structured.rs deleted file mode 100644 index 6e20bb2..0000000 --- a/gcc/testsuite/rust.test/foreach-put-structured.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn pairs(it: &fn((int, int))) { - let mut i: int = 0; - let mut j: int = 0; - while i < 10 { it((i, j)); i += 1; j += i; } -} - -pub fn main() { - let mut i: int = 10; - let mut j: int = 0; - do pairs() |p| { - let (_0, _1) = p; - info2!("{}", _0); - info2!("{}", _1); - assert_eq!(_0 + 10, i); - i += 1; - j = _1; - }; - assert_eq!(j, 45); -} diff --git a/gcc/testsuite/rust.test/foreach-simple-outer-slot.rs b/gcc/testsuite/rust.test/foreach-simple-outer-slot.rs deleted file mode 100644 index b5fa186..0000000 --- a/gcc/testsuite/rust.test/foreach-simple-outer-slot.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -pub fn main() { - let mut sum: int = 0; - do first_ten |i| { info2!("main"); info2!("{}", i); sum = sum + i; } - info2!("sum"); - info2!("{}", sum); - assert_eq!(sum, 45); -} - -fn first_ten(it: &fn(int)) { - let mut i: int = 0; - while i < 10 { info2!("first_ten"); it(i); i = i + 1; } -} diff --git a/gcc/testsuite/rust.test/foreign-call-no-runtime.rs b/gcc/testsuite/rust.test/foreign-call-no-runtime.rs deleted file mode 100644 index 2fa4f19..0000000 --- a/gcc/testsuite/rust.test/foreign-call-no-runtime.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::cast; -use std::libc; -use std::unstable::run_in_bare_thread; - -externfn!(fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t), - data: libc::uintptr_t) -> libc::uintptr_t) - -pub fn main() { - unsafe { - do run_in_bare_thread() { - let i = &100; - rust_dbg_call(callback, cast::transmute(i)); - } - } -} - -extern fn callback(data: libc::uintptr_t) { - unsafe { - let data: *int = cast::transmute(data); - assert_eq!(*data, 100); - } -} diff --git a/gcc/testsuite/rust.test/foreign-dupe.rs b/gcc/testsuite/rust.test/foreign-dupe.rs deleted file mode 100644 index 9f1ca43..0000000 --- a/gcc/testsuite/rust.test/foreign-dupe.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - Somehow causes check-fast to livelock?? Probably because we're -// calling pin_task and that's having wierd side-effects. - -mod rustrt1 { - use std::libc; - - #[link_name = "rustrt"] - extern { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -mod rustrt2 { - use std::libc; - - #[link_name = "rustrt"] - extern { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - rustrt1::rust_get_test_int(); - rustrt2::rust_get_test_int(); - } -} diff --git a/gcc/testsuite/rust.test/foreign-fn-linkname.rs b/gcc/testsuite/rust.test/foreign-fn-linkname.rs deleted file mode 100644 index 3c6d33c..0000000 --- a/gcc/testsuite/rust.test/foreign-fn-linkname.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -mod libc { - use std::libc::{c_char, size_t}; - - #[nolink] - extern { - #[link_name = "strlen"] - pub fn my_strlen(str: *c_char) -> size_t; - } -} - -#[fixed_stack_segment] #[inline(never)] -fn strlen(str: ~str) -> uint { - // C string is terminated with a zero - do str.with_c_str |buf| { - unsafe { - libc::my_strlen(buf) as uint - } - } -} - -pub fn main() { - let len = strlen(~"Rust"); - assert_eq!(len, 4u); -} diff --git a/gcc/testsuite/rust.test/foreign-lib-path.rs b/gcc/testsuite/rust.test/foreign-lib-path.rs deleted file mode 100644 index 7721de9..0000000 --- a/gcc/testsuite/rust.test/foreign-lib-path.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test FIXME I don't know how to test this (#2604) -// compile-flags:-L. -// The -L flag is also used for linking foreign libraries - -mod WHATGOESHERE { - // FIXME: I want to name a mod that would not link successfully - // wouthout providing a -L argument to the compiler, and that - // will also be found successfully at runtime. - extern { - pub fn IDONTKNOW() -> u32; - } -} - -pub fn main() { - assert_eq!(IDONTKNOW(), 0x_BAD_DOOD_u32); -} diff --git a/gcc/testsuite/rust.test/foreign-mod-unused-const.rs b/gcc/testsuite/rust.test/foreign-mod-unused-const.rs deleted file mode 100644 index 977488d..0000000 --- a/gcc/testsuite/rust.test/foreign-mod-unused-const.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod foo { - use std::libc::c_int; - - #[nolink] - extern { - pub static errno: c_int; - } -} - -pub fn main() { -} diff --git a/gcc/testsuite/rust.test/foreign-no-abi.rs b/gcc/testsuite/rust.test/foreign-no-abi.rs deleted file mode 100644 index 6a7ee71..0000000 --- a/gcc/testsuite/rust.test/foreign-no-abi.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ABI is cdecl by default - -mod rustrt { - use std::libc; - - extern { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -#[fixed_stack_segment] #[inline(never)] -pub fn main() { - unsafe { - rustrt::rust_get_test_int(); - } -} diff --git a/gcc/testsuite/rust.test/foreign-struct.rs b/gcc/testsuite/rust.test/foreign-struct.rs deleted file mode 100644 index a70fec9..0000000 --- a/gcc/testsuite/rust.test/foreign-struct.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Passing enums by value - -pub enum void { } - -mod bindgen { - use super::void; - - #[nolink] - extern { - pub fn printf(v: void); - } -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/foreign2.rs b/gcc/testsuite/rust.test/foreign2.rs deleted file mode 100644 index 350a3d6..0000000 --- a/gcc/testsuite/rust.test/foreign2.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod bar { - #[nolink] - extern {} -} - -mod zed { - #[nolink] - extern {} -} - -mod libc { - use std::libc::{c_int, c_void, size_t, ssize_t}; - - #[nolink] - extern { - pub fn write(fd: c_int, buf: *c_void, count: size_t) -> ssize_t; - } -} - -mod baz { - #[nolink] - extern {} -} - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/format-no-uppercase-statics.rs b/gcc/testsuite/rust.test/format-no-uppercase-statics.rs deleted file mode 100644 index 585a615..0000000 --- a/gcc/testsuite/rust.test/format-no-uppercase-statics.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deny(non_uppercase_statics)]; - -pub fn main() { - println!("I generate statics with {0, select, other{#}}", "weird names"); -} diff --git a/gcc/testsuite/rust.test/fun-call-variants.rs b/gcc/testsuite/rust.test/fun-call-variants.rs deleted file mode 100644 index 5011998..0000000 --- a/gcc/testsuite/rust.test/fun-call-variants.rs +++ /dev/null @@ -1,21 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn ho(f: &fn(int) -> int) -> int { let n: int = f(3); return n; } - -fn direct(x: int) -> int { return x + 1; } - -pub fn main() { - let a: int = direct(3); // direct - let b: int = ho(direct); // indirect unbound - - assert_eq!(a, b); -} diff --git a/gcc/testsuite/rust.test/fun-indirect-call.rs b/gcc/testsuite/rust.test/fun-indirect-call.rs deleted file mode 100644 index 7387529..0000000 --- a/gcc/testsuite/rust.test/fun-indirect-call.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -fn f() -> int { return 42; } - -pub fn main() { - let g: extern fn() -> int = f; - let i: int = g(); - assert_eq!(i, 42); -} diff --git a/gcc/testsuite/rust.test/func-arg-incomplete-pattern.rs b/gcc/testsuite/rust.test/func-arg-incomplete-pattern.rs deleted file mode 100644 index 93c9d6b..0000000 --- a/gcc/testsuite/rust.test/func-arg-incomplete-pattern.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Test that we do not leak when the arg pattern must drop part of the -// argument (in this case, the `y` field). - -struct Foo { - x: ~uint, - y: ~uint, -} - -fn foo(Foo {x, _}: Foo) -> *uint { - let addr: *uint = &*x; - addr -} - -pub fn main() { - let obj = ~1; - let objptr: *uint = &*obj; - let f = Foo {x: obj, y: ~2}; - let xptr = foo(f); - assert_eq!(objptr, xptr); -} diff --git a/gcc/testsuite/rust.test/func-arg-ref-pattern.rs b/gcc/testsuite/rust.test/func-arg-ref-pattern.rs deleted file mode 100644 index 1b7d641..0000000 --- a/gcc/testsuite/rust.test/func-arg-ref-pattern.rs +++ /dev/null @@ -1,24 +0,0 @@ -// exec-env:RUST_POISON_ON_FREE=1 - -// Test argument patterns where we create refs to the inside of `~` -// boxes. Make sure that we don't free the box as we match the -// pattern. - -fn getaddr(~ref x: ~uint) -> *uint { - let addr: *uint = &*x; - addr -} - -fn checkval(~ref x: ~uint) -> uint { - *x -} - -pub fn main() { - let obj = ~1; - let objptr: *uint = &*obj; - let xptr = getaddr(obj); - assert_eq!(objptr, xptr); - - let obj = ~22; - assert_eq!(checkval(obj), 22); -} diff --git a/gcc/testsuite/rust.test/func-arg-wild-pattern.rs b/gcc/testsuite/rust.test/func-arg-wild-pattern.rs deleted file mode 100644 index ec58198..0000000 --- a/gcc/testsuite/rust.test/func-arg-wild-pattern.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test that we can compile code that uses a `_` in function argument -// patterns. - -fn foo((x, _): (int, int)) -> int { - x -} - -pub fn main() { - assert_eq!(foo((22, 23)), 22); -} diff --git a/gcc/testsuite/rust.test/functional-struct-upd.rs b/gcc/testsuite/rust.test/functional-struct-upd.rs deleted file mode 100644 index 10efc0b..0000000 --- a/gcc/testsuite/rust.test/functional-struct-upd.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: int, - y: int -} - -pub fn main() { - let a = Foo { x: 1, y: 2 }; - let c = Foo { x: 4, .. a}; - println!("{:?}", c); -} diff --git a/gcc/testsuite/rust.test/generic-alias-box.rs b/gcc/testsuite/rust.test/generic-alias-box.rs deleted file mode 100644 index b4412db..0000000 --- a/gcc/testsuite/rust.test/generic-alias-box.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn id(t: T) -> T { return t; } - -pub fn main() { - let expected = @100; - let actual = id::<@int>(expected); - info2!("{:?}", *actual); - assert_eq!(*expected, *actual); -} diff --git a/gcc/testsuite/rust.test/generic-alias-unique.rs b/gcc/testsuite/rust.test/generic-alias-unique.rs deleted file mode 100644 index ab50b70..0000000 --- a/gcc/testsuite/rust.test/generic-alias-unique.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn id(t: T) -> T { return t; } - -pub fn main() { - let expected = ~100; - let actual = id::<~int>(expected.clone()); - info2!("{:?}", *actual); - assert_eq!(*expected, *actual); -} diff --git a/gcc/testsuite/rust.test/generic-box.rs b/gcc/testsuite/rust.test/generic-box.rs deleted file mode 100644 index ce1582b..0000000 --- a/gcc/testsuite/rust.test/generic-box.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn box(x: Box) -> @Box { return @x; } - -struct Box {x: T, y: T, z: T} - -pub fn main() { - let x: @Box = box::(Box{x: 1, y: 2, z: 3}); - assert_eq!(x.y, 2); -} diff --git a/gcc/testsuite/rust.test/generic-derived-type.rs b/gcc/testsuite/rust.test/generic-derived-type.rs deleted file mode 100644 index 7ce3dc7..0000000 --- a/gcc/testsuite/rust.test/generic-derived-type.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn g(x: X) -> X { return x; } - -#[deriving(Clone)] -struct Pair { - a: T, - b: T -} - -fn f(t: T) -> Pair { - let x: Pair = Pair {a: t.clone(), b: t}; - return g::>(x); -} - -pub fn main() { - let b = f::(10); - info2!("{:?}" ,b.a); - info2!("{:?}", b.b); - assert_eq!(b.a, 10); - assert_eq!(b.b, 10); -} diff --git a/gcc/testsuite/rust.test/generic-drop-glue.rs b/gcc/testsuite/rust.test/generic-drop-glue.rs deleted file mode 100644 index 9e0dbfb..0000000 --- a/gcc/testsuite/rust.test/generic-drop-glue.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -struct Pair { x: @int, y: @int } - -fn f(t: T) { let _t1: T = t; } - -pub fn main() { let x = Pair {x: @10, y: @12}; f(x); } diff --git a/gcc/testsuite/rust.test/generic-exterior-box.rs b/gcc/testsuite/rust.test/generic-exterior-box.rs deleted file mode 100644 index 795c730..0000000 --- a/gcc/testsuite/rust.test/generic-exterior-box.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -struct Recbox {x: @T} - -fn reclift(t: T) -> Recbox { return Recbox {x: @t}; } - -pub fn main() { - let foo: int = 17; - let rbfoo: Recbox = reclift::(foo); - assert_eq!(*rbfoo.x, foo); -} diff --git a/gcc/testsuite/rust.test/generic-exterior-unique.rs b/gcc/testsuite/rust.test/generic-exterior-unique.rs deleted file mode 100644 index 0820923..0000000 --- a/gcc/testsuite/rust.test/generic-exterior-unique.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Recbox {x: ~T} - -fn reclift(t: T) -> Recbox { return Recbox {x: ~t}; } - -pub fn main() { - let foo: int = 17; - let rbfoo: Recbox = reclift::(foo); - assert_eq!(*rbfoo.x, foo); -} diff --git a/gcc/testsuite/rust.test/generic-fn-box.rs b/gcc/testsuite/rust.test/generic-fn-box.rs deleted file mode 100644 index c5d6d23..0000000 --- a/gcc/testsuite/rust.test/generic-fn-box.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -fn f(x: @T) -> @T { return x; } - -pub fn main() { let x = f(@3); info2!("{:?}", *x); } diff --git a/gcc/testsuite/rust.test/generic-fn-infer.rs b/gcc/testsuite/rust.test/generic-fn-infer.rs deleted file mode 100644 index 092a17b..0000000 --- a/gcc/testsuite/rust.test/generic-fn-infer.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- - -// Issue #45: infer type parameters in function applications -fn id(x: T) -> T { return x; } - -pub fn main() { let x: int = 42; let y: int = id(x); assert!((x == y)); } diff --git a/gcc/testsuite/rust.test/generic-fn-twice.rs b/gcc/testsuite/rust.test/generic-fn-twice.rs deleted file mode 100644 index aace957..0000000 --- a/gcc/testsuite/rust.test/generic-fn-twice.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -mod foomod { - pub fn foo() { } -} - -pub fn main() { foomod::foo::(); foomod::foo::(); } diff --git a/gcc/testsuite/rust.test/generic-fn-unique.rs b/gcc/testsuite/rust.test/generic-fn-unique.rs deleted file mode 100644 index d4ba0dd..0000000 --- a/gcc/testsuite/rust.test/generic-fn-unique.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -fn f(x: ~T) -> ~T { return x; } - -pub fn main() { let x = f(~3); info2!("{:?}", *x); } diff --git a/gcc/testsuite/rust.test/generic-fn.rs b/gcc/testsuite/rust.test/generic-fn.rs deleted file mode 100644 index 4d8b382..0000000 --- a/gcc/testsuite/rust.test/generic-fn.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -// -*- rust -*- -fn id(x: T) -> T { return x; } - -struct Triple {x: int, y: int, z: int} - -pub fn main() { - let mut x = 62; - let mut y = 63; - let a = 'a'; - let mut b = 'b'; - let p: Triple = Triple {x: 65, y: 66, z: 67}; - let mut q: Triple = Triple {x: 68, y: 69, z: 70}; - y = id::(x); - info2!("{}", y); - assert_eq!(x, y); - b = id::(a); - info2!("{}", b); - assert_eq!(a, b); - q = id::(p); - x = p.z; - y = q.z; - info2!("{}", y); - assert_eq!(x, y); -} diff --git a/gcc/testsuite/rust.test/generic-ivec-leak.rs b/gcc/testsuite/rust.test/generic-ivec-leak.rs deleted file mode 100644 index 17de964..0000000 --- a/gcc/testsuite/rust.test/generic-ivec-leak.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum wrapper { wrapped(T), } - -pub fn main() { let _w = wrapped(~[1, 2, 3, 4, 5]); } diff --git a/gcc/testsuite/rust.test/generic-ivec.rs b/gcc/testsuite/rust.test/generic-ivec.rs deleted file mode 100644 index aac390d..0000000 --- a/gcc/testsuite/rust.test/generic-ivec.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f(_v: @T) { } -pub fn main() { f(@~[1, 2, 3, 4, 5]); } diff --git a/gcc/testsuite/rust.test/generic-newtype-struct.rs b/gcc/testsuite/rust.test/generic-newtype-struct.rs deleted file mode 100644 index 541f946..0000000 --- a/gcc/testsuite/rust.test/generic-newtype-struct.rs +++ /dev/null @@ -1,6 +0,0 @@ -struct S(T); - -pub fn main() { - let s = S(2i); - println(s.to_str()); -} diff --git a/gcc/testsuite/rust.test/generic-object.rs b/gcc/testsuite/rust.test/generic-object.rs deleted file mode 100644 index 1e532caa..0000000 --- a/gcc/testsuite/rust.test/generic-object.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Foo { - fn get(&self) -> T; -} - -struct S { - x: int -} - -impl Foo for S { - fn get(&self) -> int { - self.x - } -} - -pub fn main() { - let x = @S { x: 1 }; - let y = x as @Foo; - assert_eq!(y.get(), 1); -} diff --git a/gcc/testsuite/rust.test/generic-recursive-tag.rs b/gcc/testsuite/rust.test/generic-recursive-tag.rs deleted file mode 100644 index 6111acf..0000000 --- a/gcc/testsuite/rust.test/generic-recursive-tag.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum list { cons(@T, @list), nil, } - -pub fn main() { - let _a: list = - cons::(@10, @cons::(@12, @cons::(@13, @nil::))); -} diff --git a/gcc/testsuite/rust.test/generic-static-methods.rs b/gcc/testsuite/rust.test/generic-static-methods.rs deleted file mode 100644 index 2e28181..0000000 --- a/gcc/testsuite/rust.test/generic-static-methods.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait vec_utils { - fn map_(x: &Self, f: &fn(&T) -> U) -> ~[U]; -} - -impl vec_utils for ~[T] { - fn map_(x: &~[T], f: &fn(&T) -> U) -> ~[U] { - let mut r = ~[]; - for elt in x.iter() { - r.push(f(elt)); - } - r - } -} - -pub fn main() { - assert_eq!(vec_utils::map_(&~[1,2,3], |&x| x+1), ~[2,3,4]); -} diff --git a/gcc/testsuite/rust.test/generic-tag-corruption.rs b/gcc/testsuite/rust.test/generic-tag-corruption.rs deleted file mode 100644 index deab9c7..0000000 --- a/gcc/testsuite/rust.test/generic-tag-corruption.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// This used to cause memory corruption in stage 0. -enum thing { some(K), } - -pub fn main() { let _x = some(~"hi"); } diff --git a/gcc/testsuite/rust.test/generic-tag-local.rs b/gcc/testsuite/rust.test/generic-tag-local.rs deleted file mode 100644 index fb81407..0000000 --- a/gcc/testsuite/rust.test/generic-tag-local.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -enum clam { a(T), } - -pub fn main() { let _c = a(3); } diff --git a/gcc/testsuite/rust.test/generic-tag-match.rs b/gcc/testsuite/rust.test/generic-tag-match.rs deleted file mode 100644 index 7b3b111..0000000 --- a/gcc/testsuite/rust.test/generic-tag-match.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; - -enum foo { arm(T), } - -fn altfoo(f: foo) { - let mut hit = false; - match f { arm::(_x) => { info2!("in arm"); hit = true; } } - assert!((hit)); -} - -pub fn main() { altfoo::(arm::(10)); } diff --git a/gcc/testsuite/rust.test/generic-tag-values.rs b/gcc/testsuite/rust.test/generic-tag-values.rs deleted file mode 100644 index 739eb9f..0000000 --- a/gcc/testsuite/rust.test/generic-tag-values.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - - -// -*- rust -*- -enum noption { some(T), } - -struct Pair { x: int, y: int } - -pub fn main() { - let nop: noption = some::(5); - match nop { some::(n) => { info2!("{:?}", n); assert!((n == 5)); } } - let nop2: noption = some(Pair{x: 17, y: 42}); - match nop2 { - some(t) => { - info2!("{:?}", t.x); - info2!("{:?}", t.y); - assert_eq!(t.x, 17); - assert_eq!(t.y, 42); - } - } -} diff --git a/gcc/testsuite/rust.test/generic-tag.rs b/gcc/testsuite/rust.test/generic-tag.rs deleted file mode 100644 index 16836b0..0000000 --- a/gcc/testsuite/rust.test/generic-tag.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[allow(dead_assignment)]; -#[allow(unused_variable)]; - -enum option { some(@T), none, } - -pub fn main() { - let mut a: option = some::(@10); - a = none::; -} diff --git a/gcc/testsuite/rust.test/generic-temporary.rs b/gcc/testsuite/rust.test/generic-temporary.rs deleted file mode 100644 index 5143676..0000000 --- a/gcc/testsuite/rust.test/generic-temporary.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -fn mk() -> int { return 1; } - -fn chk(a: int) { info2!("{}", a); assert!((a == 1)); } - -fn apply(produce: extern fn() -> T, - consume: extern fn(T)) { - consume(produce()); -} - -pub fn main() { - let produce: extern fn() -> int = mk; - let consume: extern fn(v: int) = chk; - apply::(produce, consume); -} diff --git a/gcc/testsuite/rust.test/generic-tup.rs b/gcc/testsuite/rust.test/generic-tup.rs deleted file mode 100644 index f9f5da5..0000000 --- a/gcc/testsuite/rust.test/generic-tup.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn get_third(t: (T, T, T)) -> T { let (_, _, x) = t; return x; } - -pub fn main() { - info2!("{:?}", get_third((1, 2, 3))); - assert_eq!(get_third((1, 2, 3)), 3); - assert_eq!(get_third((5u8, 6u8, 7u8)), 7u8); -} diff --git a/gcc/testsuite/rust.test/generic-type-synonym.rs b/gcc/testsuite/rust.test/generic-type-synonym.rs deleted file mode 100644 index a1cf581..0000000 --- a/gcc/testsuite/rust.test/generic-type-synonym.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -struct Foo { - a: T -} - -type Bar = Foo; - -fn takebar(_b: Bar) { } - -pub fn main() { } diff --git a/gcc/testsuite/rust.test/generic-type.rs b/gcc/testsuite/rust.test/generic-type.rs deleted file mode 100644 index 0ff7ced..0000000 --- a/gcc/testsuite/rust.test/generic-type.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -struct Pair {x: T, y: T} - -pub fn main() { - let x: Pair = Pair {x: 10, y: 12}; - assert_eq!(x.x, 10); - assert_eq!(x.y, 12); -} diff --git a/gcc/testsuite/rust.test/generic-unique.rs b/gcc/testsuite/rust.test/generic-unique.rs deleted file mode 100644 index 71cc432..0000000 --- a/gcc/testsuite/rust.test/generic-unique.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Triple { x: T, y: T, z: T } - -fn box(x: Triple) -> ~Triple { return ~x; } - -pub fn main() { - let x: ~Triple = box::(Triple{x: 1, y: 2, z: 3}); - assert_eq!(x.y, 2); -} diff --git a/gcc/testsuite/rust.test/getopts_ref.rs b/gcc/testsuite/rust.test/getopts_ref.rs deleted file mode 100644 index e0ac464..0000000 --- a/gcc/testsuite/rust.test/getopts_ref.rs +++ /dev/null @@ -1,27 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern mod extra; - -use extra::getopts::{optopt, getopts}; - -pub fn main() { - let args = ~[]; - let opts = ~[optopt("b")]; - - match getopts(args, opts) { - Ok(ref m) => - assert!(!m.opt_present("b")), - Err(ref f) => fail2!("{:?}", (*f).clone().to_err_msg()) - }; - -} diff --git a/gcc/testsuite/rust.test/glob-std.rs b/gcc/testsuite/rust.test/glob-std.rs deleted file mode 100644 index acb2dde..0000000 --- a/gcc/testsuite/rust.test/glob-std.rs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast windows doesn't like 'extern mod extra' - -extern mod extra; - -use extra::glob::glob; -use extra::tempfile::TempDir; -use std::unstable::finally::Finally; -use std::{io, os, unstable}; - -pub fn main() { - fn mk_file(path: &str, directory: bool) { - if directory { - os::make_dir(&Path::new(path), 0xFFFF); - } else { - io::mk_file_writer(&Path::new(path), [io::Create]); - } - } - - fn abs_path(path: &str) -> Path { - os::getcwd().join(&Path::new(path)) - } - - fn glob_vec(pattern: &str) -> ~[Path] { - glob(pattern).collect() - } - - let root = TempDir::new("glob-tests"); - let root = root.expect("Should have created a temp directory"); - assert!(os::change_dir(root.path())); - - mk_file("aaa", true); - mk_file("aaa/apple", true); - mk_file("aaa/orange", true); - mk_file("aaa/tomato", true); - mk_file("aaa/tomato/tomato.txt", false); - mk_file("aaa/tomato/tomoto.txt", false); - mk_file("bbb", true); - mk_file("bbb/specials", true); - mk_file("bbb/specials/!", false); - - // windows does not allow `*` or `?` characters to exist in filenames - if os::consts::FAMILY != os::consts::windows::FAMILY { - mk_file("bbb/specials/*", false); - mk_file("bbb/specials/?", false); - } - - mk_file("bbb/specials/[", false); - mk_file("bbb/specials/]", false); - mk_file("ccc", true); - mk_file("xyz", true); - mk_file("xyz/x", false); - mk_file("xyz/y", false); - mk_file("xyz/z", false); - - assert_eq!(glob_vec(""), ~[]); - assert_eq!(glob_vec("."), ~[]); - assert_eq!(glob_vec(".."), ~[]); - - assert_eq!(glob_vec("aaa"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aaa/"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("a"), ~[]); - assert_eq!(glob_vec("aa"), ~[]); - assert_eq!(glob_vec("aaaa"), ~[]); - - assert_eq!(glob_vec("aaa/apple"), ~[abs_path("aaa/apple")]); - assert_eq!(glob_vec("aaa/apple/nope"), ~[]); - - // windows should support both / and \ as directory separators - if os::consts::FAMILY == os::consts::windows::FAMILY { - assert_eq!(glob_vec("aaa\\apple"), ~[abs_path("aaa/apple")]); - } - - assert_eq!(glob_vec("???/"), ~[ - abs_path("aaa"), - abs_path("bbb"), - abs_path("ccc"), - abs_path("xyz")]); - - assert_eq!(glob_vec("aaa/tomato/tom?to.txt"), ~[ - abs_path("aaa/tomato/tomato.txt"), - abs_path("aaa/tomato/tomoto.txt")]); - - assert_eq!(glob_vec("xyz/?"), ~[ - abs_path("xyz/x"), - abs_path("xyz/y"), - abs_path("xyz/z")]); - - assert_eq!(glob_vec("a*"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("*a*"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("a*a"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aaa*"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("*aaa"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("*aaa*"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("*a*a*a*"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aaa*/"), ~[abs_path("aaa")]); - - assert_eq!(glob_vec("aaa/*"), ~[ - abs_path("aaa/apple"), - abs_path("aaa/orange"), - abs_path("aaa/tomato")]); - - assert_eq!(glob_vec("aaa/*a*"), ~[ - abs_path("aaa/apple"), - abs_path("aaa/orange"), - abs_path("aaa/tomato")]); - - assert_eq!(glob_vec("*/*/*.txt"), ~[ - abs_path("aaa/tomato/tomato.txt"), - abs_path("aaa/tomato/tomoto.txt")]); - - assert_eq!(glob_vec("*/*/t[aob]m?to[.]t[!y]t"), ~[ - abs_path("aaa/tomato/tomato.txt"), - abs_path("aaa/tomato/tomoto.txt")]); - - assert_eq!(glob_vec("aa[a]"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aa[abc]"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("a[bca]a"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aa[b]"), ~[]); - assert_eq!(glob_vec("aa[xyz]"), ~[]); - assert_eq!(glob_vec("aa[]]"), ~[]); - - assert_eq!(glob_vec("aa[!b]"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aa[!bcd]"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("a[!bcd]a"), ~[abs_path("aaa")]); - assert_eq!(glob_vec("aa[!a]"), ~[]); - assert_eq!(glob_vec("aa[!abc]"), ~[]); - - assert_eq!(glob_vec("bbb/specials/[[]"), ~[abs_path("bbb/specials/[")]); - assert_eq!(glob_vec("bbb/specials/!"), ~[abs_path("bbb/specials/!")]); - assert_eq!(glob_vec("bbb/specials/[]]"), ~[abs_path("bbb/specials/]")]); - - if os::consts::FAMILY != os::consts::windows::FAMILY { - assert_eq!(glob_vec("bbb/specials/[*]"), ~[abs_path("bbb/specials/*")]); - assert_eq!(glob_vec("bbb/specials/[?]"), ~[abs_path("bbb/specials/?")]); - } - - if os::consts::FAMILY == os::consts::windows::FAMILY { - - assert_eq!(glob_vec("bbb/specials/[![]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/]")]); - - assert_eq!(glob_vec("bbb/specials/[!]]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/[")]); - - assert_eq!(glob_vec("bbb/specials/[!!]"), ~[ - abs_path("bbb/specials/["), - abs_path("bbb/specials/]")]); - - } else { - - assert_eq!(glob_vec("bbb/specials/[![]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/*"), - abs_path("bbb/specials/?"), - abs_path("bbb/specials/]")]); - - assert_eq!(glob_vec("bbb/specials/[!]]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/*"), - abs_path("bbb/specials/?"), - abs_path("bbb/specials/[")]); - - assert_eq!(glob_vec("bbb/specials/[!!]"), ~[ - abs_path("bbb/specials/*"), - abs_path("bbb/specials/?"), - abs_path("bbb/specials/["), - abs_path("bbb/specials/]")]); - - assert_eq!(glob_vec("bbb/specials/[!*]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/?"), - abs_path("bbb/specials/["), - abs_path("bbb/specials/]")]); - - assert_eq!(glob_vec("bbb/specials/[!?]"), ~[ - abs_path("bbb/specials/!"), - abs_path("bbb/specials/*"), - abs_path("bbb/specials/["), - abs_path("bbb/specials/]")]); - - } -} diff --git a/gcc/testsuite/rust.test/global-scope.rs b/gcc/testsuite/rust.test/global-scope.rs deleted file mode 100644 index 9b292a3..0000000 --- a/gcc/testsuite/rust.test/global-scope.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -pub fn f() -> int { return 1; } - -pub mod foo { - pub fn f() -> int { return 2; } - pub fn g() { assert!((f() == 2)); assert!((::f() == 1)); } -} - -pub fn main() { return foo::g(); } diff --git a/gcc/testsuite/rust.test/guards-not-exhaustive.rs b/gcc/testsuite/rust.test/guards-not-exhaustive.rs deleted file mode 100644 index 4d30fbe..0000000 --- a/gcc/testsuite/rust.test/guards-not-exhaustive.rs +++ /dev/null @@ -1,13 +0,0 @@ -enum Q { R(Option) } - -fn xyzzy(q: Q) -> uint { - match q { - R(S) if S.is_some() => { 0 } - _ => 1 - } -} - - -pub fn main() { - assert_eq!(xyzzy(R(Some(5))), 0); -} diff --git a/gcc/testsuite/rust.test/guards.rs b/gcc/testsuite/rust.test/guards.rs deleted file mode 100644 index bf29fa6..0000000 --- a/gcc/testsuite/rust.test/guards.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Pair { x: int, y: int } - -pub fn main() { - let a = - match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } }; - assert_eq!(a, 2); - - let b = - match Pair {x: 10, y: 20} { - x if x.x < 5 && x.y < 5 => { 1 } - Pair {x: x, y: y} if x == 10 && y == 20 => { 2 } - Pair {x: _x, y: _y} => { 3 } - }; - assert_eq!(b, 2); -} diff --git a/gcc/testsuite/rust.test/hashmap-memory.rs b/gcc/testsuite/rust.test/hashmap-memory.rs deleted file mode 100644 index 13a544a..0000000 --- a/gcc/testsuite/rust.test/hashmap-memory.rs +++ /dev/null @@ -1,96 +0,0 @@ -// xfail-fast - -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/** - A somewhat reduced test case to expose some Valgrind issues. - - This originally came from the word-count benchmark. -*/ - -pub fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); } - -mod map_reduce { - use std::comm::{stream, SharedChan}; - use std::hashmap::HashMap; - use std::str; - use std::task; - - pub type putter<'self> = &'self fn(~str, ~str); - - pub type mapper = extern fn(~str, putter); - - enum ctrl_proto { find_reducer(~[u8], Chan), mapper_done, } - - fn start_mappers(ctrl: SharedChan, inputs: ~[~str]) { - for i in inputs.iter() { - let ctrl = ctrl.clone(); - let i = i.clone(); - task::spawn(|| map_task(ctrl.clone(), i.clone()) ); - } - } - - fn map_task(ctrl: SharedChan, input: ~str) { - let intermediates = @mut HashMap::new(); - - fn emit(im: &mut HashMap<~str, int>, ctrl: SharedChan, key: ~str, - _val: ~str) { - if im.contains_key(&key) { - return; - } - let (pp, cc) = stream(); - error2!("sending find_reducer"); - ctrl.send(find_reducer(key.as_bytes().to_owned(), cc)); - error2!("receiving"); - let c = pp.recv(); - error2!("{:?}", c); - im.insert(key, c); - } - - let ctrl_clone = ctrl.clone(); - ::map(input, |a,b| emit(intermediates, ctrl.clone(), a, b) ); - ctrl_clone.send(mapper_done); - } - - pub fn map_reduce(inputs: ~[~str]) { - let (ctrl_port, ctrl_chan) = stream(); - let ctrl_chan = SharedChan::new(ctrl_chan); - - // This task becomes the master control task. It spawns others - // to do the rest. - - let mut reducers: HashMap<~str, int>; - - reducers = HashMap::new(); - - start_mappers(ctrl_chan, inputs.clone()); - - let mut num_mappers = inputs.len() as int; - - while num_mappers > 0 { - match ctrl_port.recv() { - mapper_done => { num_mappers -= 1; } - find_reducer(k, cc) => { - let mut c; - match reducers.find(&str::from_utf8(k)) { - Some(&_c) => { c = _c; } - None => { c = 0; } - } - cc.send(c); - } - } - } - } -} - -pub fn main() { - map_reduce::map_reduce(~[~"../src/test/run-pass/hashmap-memory.rs"]); -} diff --git a/gcc/testsuite/rust.test/hello.rs b/gcc/testsuite/rust.test/hello.rs deleted file mode 100644 index 93f6c3d..0000000 --- a/gcc/testsuite/rust.test/hello.rs +++ /dev/null @@ -1,14 +0,0 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn main() { - println("hello, world"); -} diff --git a/gcc/testsuite/rust.test/helloworld.rs b/gcc/testsuite/rust.test/helloworld.rs deleted file mode 100644 index 67adb3e..0000000 --- a/gcc/testsuite/rust.test/helloworld.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main () -{ - println ("hello, world"); -} diff --git a/gcc/testsuite/rust.test/html-literals.rs b/gcc/testsuite/rust.test/html-literals.rs deleted file mode 100644 index 9704071..0000000 --- a/gcc/testsuite/rust.test/html-literals.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A test of the macro system. Can we do HTML literals? - -#[feature(macro_rules)]; - -/* - -This is an HTML parser written as a macro. It's all CPS, and we have -to carry around a bunch of state. The arguments to macros all look like this: - -{ tag_stack* # expr* # tokens } - -The stack keeps track of where we are in the tree. The expr is a list -of children of the current node. The tokens are everything that's -left. - -*/ - -macro_rules! html ( - ( $($body:tt)* ) => ( - parse_node!( []; []; $($body)* ) - ) -) - -macro_rules! parse_node ( - ( - [:$head:ident ($(:$head_nodes:expr),*) - $(:$tags:ident ($(:$tag_nodes:expr),*))*]; - [$(:$nodes:expr),*]; - $($rest:tt)* - ) => ( - parse_node!( - [$(: $tags ($(:$tag_nodes),*))*]; - [$(:$head_nodes,)* :tag(stringify!($head).to_owned(), - ~[$($nodes),*])]; - $($rest)* - ) - ); - - ( - [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; - [$(:$nodes:expr),*]; - <$tag:ident> $($rest:tt)* - ) => ( - parse_node!( - [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*]; - []; - $($rest)* - ) - ); - - ( - [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; - [$(:$nodes:expr),*]; - . $($rest:tt)* - ) => ( - parse_node!( - [$(: $tags ($(:$tag_nodes),*))*]; - [$(:$nodes,)* :text(~".")]; - $($rest)* - ) - ); - - ( - [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; - [$(:$nodes:expr),*]; - $word:ident $($rest:tt)* - ) => ( - parse_node!( - [$(: $tags ($(:$tag_nodes),*))*]; - [$(:$nodes,)* :text(stringify!($word).to_owned())]; - $($rest)* - ) - ); - - ( []; [:$e:expr]; ) => ( $e ); -) - -pub fn main() { - let _page = html! ( - - This is the title. - -