/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "operand_types_print.h" #include "mangling.h" #include #include using namespace panda::pandasm; TEST(parsertests, test1) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("mov v1, v2}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[0], 1) << "1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[1], 2) << "2 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test2) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("label:}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].label, "label") << "label expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].set_label, true) << "true expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::INVALID) << "NONE expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test3) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("jlt v10, lab123}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_LABEL_EXT) << "ERR_BAD_LABEL_EXT expected"; } TEST(parsertests, test4) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("11111111}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERATION_NAME) << "ERR_BAD_OPERATION_NAME expected"; } TEST(parsertests, test5) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("addi 1}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::ADDI) << "IMM expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(1))) << "1 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test6) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("addi 12345}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::ADDI) << "IMM expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(12345))) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test7) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("addi 11.3}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_INTEGER_NAME) << "ERR_NONE expected"; } TEST(parsertests, test8) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("ashdjbf iashudbfiun as}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERATION_NAME) << "ERR_BAD_OPERATION expected"; } TEST(parsertests, test9) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("lda v1").first); v.push_back(l.TokenizeString("movi v10, 1001}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::LDA) << "V expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[0], 1) << "1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].opcode, Opcode::MOVI) << "V_IMM expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].regs[0], 10) << "10 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].imms[0], Ins::IType(int64_t(1001))) << "1001 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test10) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 main(){").first); v.push_back(l.TokenizeString("call.short nain, v1, v2}").first); v.push_back(l.TokenizeString(".function u1 nain(){}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); const auto sig_nain = GetFunctionSignatureFromName("nain", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::CALL_SHORT) << "V_V_ID expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].ids[0], sig_nain) << "nain expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[0], 1) << "1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[1], 2) << "2 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test11) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("i64tof64}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::I64TOF64) << "NONE expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test12) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("jmp l123}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_LABEL_EXT) << "ERR_BAD_LABEL_EXT expected"; } TEST(parsertests, test13) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("l123: jmp l123}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::JMP) << "ID expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].ids[0], "l123") << "l123 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE"; } TEST(parsertests, test14) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("jmp 123}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_ID) << "ERR_BAD_NAME_ID expected"; } TEST(parsertests, test15) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("shli 12 asd}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS) << "ERR_BAD_NUMBER_OPERANDS expected"; } TEST(parsertests, test17) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("ldarr.8 v120}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::LDARR_8) << "V expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[0], 120) << "120 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test18) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("return}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::RETURN) << "NONE expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test19) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("return1}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERATION_NAME) << "ERR_BAD_OPERATION expected"; } TEST(parsertests, test20) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("return 1}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS) << "ERR_BAD_NUMBER_OPERANDS expected"; } TEST(parsertests, test21) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("ashr2.64 1234}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG) << "ERR_BAD_NAME_REG expected"; } TEST(parsertests, test22) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("ashr2.64 v12}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::ASHR2_64) << "V expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].regs[0], 12) << "12 expected"; } TEST(parsertests, test23) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("label1:").first); v.push_back(l.TokenizeString("jle v0, label2").first); v.push_back(l.TokenizeString("movi v15, 26").first); v.push_back(l.TokenizeString("label2: mov v0, v1").first); v.push_back(l.TokenizeString("call m123, v2, v6, v3, v4").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function f64 m123(u1 a0, f32 a1){").first); v.push_back(l.TokenizeString("lda v10").first); v.push_back(l.TokenizeString("sta a0").first); v.push_back(l.TokenizeString("la1:").first); v.push_back(l.TokenizeString("jle a1, la1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); params.emplace_back(Type {"f32", 0}, language); const auto sig_m123 = GetFunctionSignatureFromName("m123", params); ASSERT_EQ(item.Value().function_table.at(sig_main).name, sig_main); ASSERT_EQ(item.Value().function_table.at(sig_m123).name, sig_m123); ASSERT_EQ(item.Value().function_table.at(sig_main).GetParamsNum(), 0U); ASSERT_EQ(item.Value().function_table.at(sig_m123).GetParamsNum(), 2U); ASSERT_EQ(item.Value().function_table.at(sig_m123).params[0].type.GetId(), panda::panda_file::Type::TypeId::U1); ASSERT_EQ(item.Value().function_table.at(sig_m123).params[1].type.GetId(), panda::panda_file::Type::TypeId::F32); ASSERT_EQ(item.Value().function_table.at(sig_main).return_type.GetId(), panda::panda_file::Type::TypeId::U8); ASSERT_EQ(item.Value().function_table.at(sig_m123).return_type.GetId(), panda::panda_file::Type::TypeId::F64); ASSERT_EQ(item.Value().function_table.at(sig_main).label_table.at("label1").file_location->line_number, 2U); ASSERT_EQ(item.Value().function_table.at(sig_main).label_table.at("label1").file_location->is_defined, true); ASSERT_EQ(item.Value().function_table.at(sig_main).label_table.at("label2").file_location->line_number, 3U); ASSERT_EQ(item.Value().function_table.at(sig_main).label_table.at("label2").file_location->is_defined, true); ASSERT_EQ(item.Value().function_table.at(sig_m123).label_table.at("la1").file_location->line_number, 11U); ASSERT_EQ(item.Value().function_table.at(sig_m123).label_table.at("la1").file_location->is_defined, true); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].opcode, Opcode::INVALID); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].label, "label1"); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].opcode, Opcode::JLE); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].regs[0], 0); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].ids[0], "label2"); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[2].opcode, Opcode::MOVI); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[2].regs[0], 15); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[2].imms[0], Ins::IType(int64_t(26))); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[2].set_label, false); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].regs[0], 0); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].regs[1], 1); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].label, "label2"); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].set_label, true); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].opcode, Opcode::CALL); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].regs[0], 2); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].regs[1], 6); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].regs[2], 3); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].regs[3], 4); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].ids[0], sig_m123); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[0].opcode, Opcode::LDA); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[0].regs[0], 10); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[1].opcode, Opcode::STA); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[1].regs[0], 11); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[2].opcode, Opcode::INVALID); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[2].label, "la1"); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[2].set_label, true); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[3].opcode, Opcode::JLE); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[3].regs[0], 12); ASSERT_EQ(item.Value().function_table.at(sig_m123).ins[3].ids[0], "la1"); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } TEST(parsertests, test24_functions) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main()").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("movi v0, 0x100").first); v.push_back(l.TokenizeString("movi v15, 0xffffffff").first); v.push_back(l.TokenizeString("movi v15, 0xf").first); v.push_back(l.TokenizeString("fmovi.64 v15, 1e3").first); v.push_back(l.TokenizeString("movi v15, 0xE994").first); v.push_back(l.TokenizeString("fmovi.64 v15, 1.1").first); v.push_back(l.TokenizeString("fmovi.64 v15, 1.").first); v.push_back(l.TokenizeString("fmovi.64 v15, .1").first); v.push_back(l.TokenizeString("movi v15, 0").first); v.push_back(l.TokenizeString("fmovi.64 v15, 0.1").first); v.push_back(l.TokenizeString("fmovi.64 v15, 00.1").first); v.push_back(l.TokenizeString("fmovi.64 v15, 00.").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_main = GetFunctionSignatureFromName("main", {}); const auto sig_niam = GetFunctionSignatureFromName("niam", {}); ASSERT_EQ(item.Value().function_table.at(sig_main).return_type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(256))) << "256 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[1].imms[0], Ins::IType(int64_t(4294967295))) << "4294967295 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[2].imms[0], Ins::IType(int64_t(15))) << "15 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[3].imms[0], Ins::IType(1000.0)) << "1000.0 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[4].imms[0], Ins::IType(int64_t(59796))) << "59796 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[5].imms[0], Ins::IType(1.1)) << "1.1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[7].imms[0], Ins::IType(.1)) << ".1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[8].imms[0], Ins::IType(int64_t(0))) << "0 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[9].imms[0], Ins::IType(0.1)) << "0.1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[10].imms[0], Ins::IType(00.1)) << "00.1 expected"; ASSERT_EQ(item.Value().function_table.at(sig_main).ins[11].imms[0], Ins::IType(00.)) << "00. expected"; ASSERT_EQ(item.Value().function_table.at(sig_niam).ins[0].imms[0], Ins::IType(int64_t(-1))) << "-1 expected"; } TEST(parsertests, test25_record_alone) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().record_table.at("Asm").name, "Asm"); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); } TEST(parsertests, test26_records) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm2 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3 }").first); v.push_back(l.TokenizeString(".record Asm3").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm4 { i32 asm1 }").first); v.push_back(l.TokenizeString(".record Asm5 { i32 asm1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().record_table.at("Asm1").name, "Asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().record_table.at("Asm2").name, "Asm2"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().record_table.at("Asm3").name, "Asm3"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().record_table.at("Asm4").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm4").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().record_table.at("Asm5").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm5").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I32); } TEST(parsertests, test27_record_and_function) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_niam = GetFunctionSignatureFromName("niam", {}); ASSERT_EQ(item.Value().record_table.at("Asm1").name, "Asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().function_table.at(sig_niam).ins[0].imms[0], Ins::IType(int64_t(-1))) << "-1 expected"; } TEST(parsertests, test28_records_and_functions) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam1(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm2 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam2(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm3 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam3(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_niam1 = GetFunctionSignatureFromName("niam1", {}); const auto sig_niam2 = GetFunctionSignatureFromName("niam2", {}); const auto sig_niam3 = GetFunctionSignatureFromName("niam3", {}); ASSERT_EQ(item.Value().record_table.at("Asm1").name, "Asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().function_table.at(sig_niam1).ins[0].imms[0], Ins::IType(int64_t(-1))) << "-1 expected"; ASSERT_EQ(item.Value().record_table.at("Asm2").name, "Asm2"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().function_table.at(sig_niam2).ins[0].imms[0], Ins::IType(int64_t(-1))) << "-1 expected"; ASSERT_EQ(item.Value().record_table.at("Asm3").name, "Asm3"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].name, "asm1"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[1].name, "asm2"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[2].name, "asm3"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().function_table.at(sig_niam3).ins[0].imms[0], Ins::IType(int64_t(-1))) << "-1 expected"; } TEST(parsertests, test29_instructions_def_lines) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 niam1(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam2(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam3()").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam4(){ldai -1}").first); v.push_back(l.TokenizeString(".function u8 niam5(){ldai -1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_niam1 = GetFunctionSignatureFromName("niam1", {}); const auto sig_niam2 = GetFunctionSignatureFromName("niam2", {}); const auto sig_niam3 = GetFunctionSignatureFromName("niam3", {}); const auto sig_niam4 = GetFunctionSignatureFromName("niam4", {}); const auto sig_niam5 = GetFunctionSignatureFromName("niam5", {}); ASSERT_EQ(item.Value().function_table.at(sig_niam1).ins[0].ins_debug.line_number, 2U) << "2 expected"; ASSERT_EQ(item.Value().function_table.at(sig_niam2).ins[0].ins_debug.line_number, 5U) << "5 expected"; ASSERT_EQ(item.Value().function_table.at(sig_niam3).ins[0].ins_debug.line_number, 9U) << "9 expected"; ASSERT_EQ(item.Value().function_table.at(sig_niam4).ins[0].ins_debug.line_number, 11U) << "11 expected"; ASSERT_EQ(item.Value().function_table.at(sig_niam5).ins[0].ins_debug.line_number, 12U) << "12 expected"; } TEST(parsertests, test30_fields_def_lines) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm2 {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3 }").first); v.push_back(l.TokenizeString(".record Asm3").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm4 { i32 asm1 }").first); v.push_back(l.TokenizeString(".record Asm5 { i32 asm1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].line_of_def, 2U); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].line_of_def, 3U); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].line_of_def, 4U); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].line_of_def, 7U); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[1].line_of_def, 8U); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[2].line_of_def, 9U); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].line_of_def, 12U); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[1].line_of_def, 13U); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[2].line_of_def, 14U); ASSERT_EQ(item.Value().record_table.at("Asm4").field_list[0].line_of_def, 16U); ASSERT_EQ(item.Value().record_table.at("Asm5").field_list[0].line_of_def, 17U); } TEST(parsertests, test31_own_types) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm {").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("Asm asm1").first); v.push_back(l.TokenizeString("void asm2").first); v.push_back(l.TokenizeString("i32 asm3 }").first); v.push_back(l.TokenizeString(".record Asm2 { Asm1 asm1 }").first); v.push_back(l.TokenizeString(".record Asm3 { Asm2 asm1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetName(), "Asm"); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID); ASSERT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32); ASSERT_EQ(item.Value().record_table.at("Asm2").field_list[0].type.GetName(), "Asm1"); ASSERT_EQ(item.Value().record_table.at("Asm3").field_list[0].type.GetName(), "Asm2"); } TEST(parsertests, test32_names) { ASSERT_EQ(GetOwnerName("Asm.main"), "Asm"); ASSERT_EQ(GetOwnerName("main"), ""); ASSERT_EQ(GetItemName("Asm.main"), "main"); ASSERT_EQ(GetItemName("main"), "main"); } TEST(parsertests, test33_params_number) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 niam1(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam2(u1 a0, i64 a1, i32 a2){").first); v.push_back(l.TokenizeString("mov v0, v3").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_niam1 = GetFunctionSignatureFromName("niam1", {}); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); params.emplace_back(Type {"i64", 0}, language); params.emplace_back(Type {"i32", 0}, language); const auto sig_niam2 = GetFunctionSignatureFromName("niam2", params); ASSERT_EQ(item.Value().function_table.at(sig_niam1).GetParamsNum(), 0U); ASSERT_EQ(item.Value().function_table.at(sig_niam1).value_of_first_param + 1, 0); ASSERT_EQ(item.Value().function_table.at(sig_niam2).GetParamsNum(), 3U); ASSERT_EQ(item.Value().function_table.at(sig_niam2).value_of_first_param + 1, 4); } TEST(parsertests, test34_vregs_number) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 niam1(){").first); v.push_back(l.TokenizeString("ldai -1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 niam2(u1 a0, i64 a1, i32 a2){").first); v.push_back(l.TokenizeString("mov v0, v5").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_niam1 = GetFunctionSignatureFromName("niam1", {}); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); params.emplace_back(Type {"i64", 0}, language); params.emplace_back(Type {"i32", 0}, language); const auto sig_niam2 = GetFunctionSignatureFromName("niam2", params); ASSERT_EQ(item.Value().function_table.at(sig_niam1).regs_num, 0U); ASSERT_EQ(item.Value().function_table.at(sig_niam2).regs_num, 6U); } TEST(parsertests, test35_functions_bracket) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain1(i64 a0) <> {").first); v.push_back(l.TokenizeString("mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain2(i64 a0) <> { mov v0, a0}").first); v.push_back(l.TokenizeString(".function u1 nain3(i64 a0) <> { mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain4(i64 a0) ").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain5(i64 a0) <>{").first); v.push_back(l.TokenizeString("mov v0, a0}").first); v.push_back(l.TokenizeString(".function u1 nain6(i64 a0) <>").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("mov v0, a0}").first); v.push_back(l.TokenizeString(".function u1 nain7(i64 a0) <> {").first); v.push_back(l.TokenizeString("mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain8(i64 a0) { mov v0, a0}").first); v.push_back(l.TokenizeString(".function u1 nain9(i64 a0) { mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain10(i64 a0) <>").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain11(i64 a0) {").first); v.push_back(l.TokenizeString("mov v0, a0}").first); v.push_back(l.TokenizeString(".function u1 nain12(i64 a0)").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("mov v0, a0}").first); auto item = p.Parse(v); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"i64", 0}, language); const auto sig_nain1 = GetFunctionSignatureFromName("nain1", params); const auto sig_nain2 = GetFunctionSignatureFromName("nain2", params); const auto sig_nain3 = GetFunctionSignatureFromName("nain3", params); const auto sig_nain4 = GetFunctionSignatureFromName("nain4", params); const auto sig_nain5 = GetFunctionSignatureFromName("nain5", params); const auto sig_nain6 = GetFunctionSignatureFromName("nain6", params); const auto sig_nain7 = GetFunctionSignatureFromName("nain7", params); const auto sig_nain8 = GetFunctionSignatureFromName("nain8", params); const auto sig_nain9 = GetFunctionSignatureFromName("nain9", params); const auto sig_nain10 = GetFunctionSignatureFromName("nain10", params); const auto sig_nain11 = GetFunctionSignatureFromName("nain11", params); const auto sig_nain12 = GetFunctionSignatureFromName("nain12", params); ASSERT_EQ(item.Value().function_table.at(sig_nain1).name, sig_nain1); ASSERT_EQ(item.Value().function_table.at(sig_nain12).name, sig_nain12); ASSERT_EQ(item.Value().function_table.at(sig_nain3).name, sig_nain3); ASSERT_EQ(item.Value().function_table.at(sig_nain2).name, sig_nain2); ASSERT_EQ(item.Value().function_table.at(sig_nain4).name, sig_nain4); ASSERT_EQ(item.Value().function_table.at(sig_nain5).name, sig_nain5); ASSERT_EQ(item.Value().function_table.at(sig_nain6).name, sig_nain6); ASSERT_EQ(item.Value().function_table.at(sig_nain7).name, sig_nain7); ASSERT_EQ(item.Value().function_table.at(sig_nain8).name, sig_nain8); ASSERT_EQ(item.Value().function_table.at(sig_nain9).name, sig_nain9); ASSERT_EQ(item.Value().function_table.at(sig_nain10).name, sig_nain10); ASSERT_EQ(item.Value().function_table.at(sig_nain11).name, sig_nain11); ASSERT_EQ(item.Value().function_table.at(sig_nain1).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain2).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain3).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain4).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain5).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain6).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain7).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain8).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain9).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain10).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain11).ins[0].opcode, Opcode::MOV); ASSERT_EQ(item.Value().function_table.at(sig_nain12).ins[0].opcode, Opcode::MOV); } TEST(parsertests, test36_records_bracket) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record rec1 <> {").first); v.push_back(l.TokenizeString("i64 asm1 <>").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record rec2 <> { i64 asm1}").first); v.push_back(l.TokenizeString(".record rec3 <> { i64 asm1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record rec4").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".record rec5{").first); v.push_back(l.TokenizeString("i64 asm1}").first); v.push_back(l.TokenizeString(".record rec6").first); v.push_back(l.TokenizeString("{").first); v.push_back(l.TokenizeString("i64 asm1}").first); v.push_back(l.TokenizeString(".record rec7{").first); v.push_back(l.TokenizeString("i64 asm1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().record_table.at("rec1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec2").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec3").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec4").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec5").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec6").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); ASSERT_EQ(item.Value().record_table.at("rec7").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64); } TEST(parsertests, test37_operand_type_print) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain1(i64 a0) <> {").first); v.push_back(l.TokenizeString("L: mov v0, a0").first); v.push_back(l.TokenizeString("movi v0, 0").first); v.push_back(l.TokenizeString("jmp L").first); v.push_back(l.TokenizeString("sta a0").first); v.push_back(l.TokenizeString("neg").first); v.push_back(l.TokenizeString("call.short nain1, v0, v1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"i64", 0}, language); const auto sig_nain1 = GetFunctionSignatureFromName("nain1", params); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[0].opcode), "reg_reg"); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[1].opcode), "reg_imm"); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[2].opcode), "label"); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[3].opcode), "reg"); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[4].opcode), "none"); ASSERT_EQ(OperandTypePrint(item.Value().function_table.at(sig_nain1).ins[5].opcode), "call_reg_reg"); } TEST(parsertests, test38_record_invalid_field) { { std::vector> v; Lexer l; Parser p; std::string f = "T"; v.push_back(l.TokenizeString(".record Rec {").first); v.push_back(l.TokenizeString(f).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_FIELD_MISSING_NAME); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, f.length()); ASSERT_EQ(e.message, "Expected field name."); } { std::vector> v; Lexer l; Parser p; std::string f = "T f <"; v.push_back(l.TokenizeString(".record Rec {").first); v.push_back(l.TokenizeString(f).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_METADATA_BOUND); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, f.length()); ASSERT_EQ(e.message, "Expected '>'."); } } TEST(parsertests, test39_parse_operand_string) { { std::vector> v; Lexer l; Parser p; std::string op = "lda.str 123"; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_OPERAND); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find(' ') + 1); ASSERT_EQ(e.message, "Expected string literal"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str a\"bcd"; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_OPERAND); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find(' ') + 1); ASSERT_EQ(e.message, "Expected string literal"); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("lda.str \" abc123 \"").first); v.push_back(l.TokenizeString("lda.str \"zxcvb\"").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); std::unordered_set strings = {" abc123 ", "zxcvb"}; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); ASSERT_EQ(item.Value().strings, strings); } } TEST(parsertests, test40_parse_operand_string_escape_seq) { { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\z\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_STRING_UNKNOWN_ESCAPE_SEQUENCE); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find('\\')); ASSERT_EQ(e.message, "Unknown escape sequence"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \" \\\" \\' \\\\ \\a \\b \\f \\n \\r \\t \\v \""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); Error e = p.ShowError(); auto item = p.Parse(v); std::unordered_set strings = {" \" ' \\ \a \b \f \n \r \t \v "}; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); ASSERT_EQ(item.Value().strings, strings); } } TEST(parsertests, test41_parse_operand_string_hex_escape_seq) { { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\x\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find('\\')); ASSERT_EQ(e.message, "Invalid \\x escape sequence"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\xZZ\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find('\\')); ASSERT_EQ(e.message, "Invalid \\x escape sequence"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\xAZ\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find('\\')); ASSERT_EQ(e.message, "Invalid \\x escape sequence"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\xZA\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE); ASSERT_EQ(e.line_number, 2U); ASSERT_EQ(e.pos, op.find('\\')); ASSERT_EQ(e.message, "Invalid \\x escape sequence"); } { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\xaa\\x65\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); std::unordered_set strings = {"123\xaa\x65"}; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); ASSERT_EQ(item.Value().strings, strings); } } TEST(parsertests, test42_parse_operand_string_octal_escape_seq) { std::vector> v; Lexer l; Parser p; std::string op = "lda.str \"123\\1\\02\\00123\""; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString(op).first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); std::unordered_set strings = {"123\1\02\00123"}; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); ASSERT_EQ(item.Value().strings, strings); } TEST(parsertests, test43_call_short) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.short f").first); v.push_back(l.TokenizeString("call.virt.short f").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.short f, v0").first); v.push_back(l.TokenizeString("call.virt.short f, v0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.short f, v0, v1").first); v.push_back(l.TokenizeString("call.virt.short f, v0, v1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0, 1}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.short f, v0, v1, v2").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.virt.short f, v0, v1, v2").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS); } } TEST(parsertests, test44_call) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call f").first); v.push_back(l.TokenizeString("call.virt f").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call f, v0").first); v.push_back(l.TokenizeString("call.virt f, v0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call f, v0, v1").first); v.push_back(l.TokenizeString("call.virt f, v0, v1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0, 1}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call f, v0, v1, v2").first); v.push_back(l.TokenizeString("call.virt f, v0, v1, v2").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0, 1, 2}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call f, v0, v1, v2, v3").first); v.push_back(l.TokenizeString("call.virt f, v0, v1, v2, v3").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_TRUE(item.HasValue()); std::vector regs {0, 1, 2, 3}; ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].regs, regs); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].regs, regs); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.short f, v0, v1, v2, v3, v4").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.virt.short f, v0, v1, v2, v3, v4").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS); } } TEST(parsertests, function_argument_mismatch) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("call.short nain, v0, v1").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 nain(i32 a0, i32 a1){").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("call.range nain, v0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 nain(i32 a0, i32 a1){").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("call nain, v0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 nain(i32 a0, i32 a1){").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_FUNCTION_ARGUMENT_MISMATCH); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("call nain, v0, v1, v2, v3").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u8 nain(i32 a0, i32 a1){").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, test45_argument_width_mov) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("mov v67000, v0").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERAND); } TEST(parsertests, test45_argument_width_call) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("call.range f, v256").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERAND); } TEST(parsertests, test_argument_width_call_param) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void g(u1 a0, u1 a1) {").first); v.push_back(l.TokenizeString("call.range f, v256").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("movi v5, 0").first); v.push_back(l.TokenizeString("call g, a1, v15").first); v.push_back(l.TokenizeString("return").first); v.push_back(l.TokenizeString("}").first); p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_OPERAND); } TEST(parsertests, Naming_function_function) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("L: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("L: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ID_FUNCTION); } TEST(parsertests, Naming_label_label) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("SAME: mov v0, a0").first); v.push_back(l.TokenizeString("SAME: sta v0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_LABEL_EXT); } TEST(parsertests, Naming_function_label) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("nain: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, Naming_function_operation) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 mov(i64 a0) <> {").first); v.push_back(l.TokenizeString("L: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, Naming_label_operation) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("mov: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, Naming_function_label_operation) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 mov(i64 a0) <> {").first); v.push_back(l.TokenizeString("mov: mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, Naming_jump_label) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 mov(i64 a0) <> {").first); v.push_back(l.TokenizeString("jmp mov").first); v.push_back(l.TokenizeString("mov:").first); v.push_back(l.TokenizeString("return").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, Naming_call_function) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 mov(i64 a0) <> {").first); v.push_back(l.TokenizeString("call.short mov, v0, v1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, register_naming_incorr) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta 123").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f(i32 a0) {").first); v.push_back(l.TokenizeString("sta a01").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta 123").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta q0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta vy1").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta v01").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } } TEST(parsertests, register_naming_corr) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta v123").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("sta v0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f(i32 a0) {").first); v.push_back(l.TokenizeString("sta a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f(i32 a0) {").first); v.push_back(l.TokenizeString("mov v0, a0").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, array_type) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record R {").first); v.push_back(l.TokenizeString("R[][] f").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".function R[] f(i8[ ] a0) {").first); v.push_back(l.TokenizeString("newarr v0, v0, i32[ ][]").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"i8", 1}, language); const auto sig_f = GetFunctionSignatureFromName("f", params); ASSERT_TRUE(item.HasValue()); ASSERT_EQ(item.Value().record_table.at("R").field_list.size(), 1U); ASSERT_TRUE(item.Value().record_table.at("R").field_list[0].type.IsArray()); ASSERT_TRUE(item.Value().record_table.at("R").field_list[0].type.IsObject()); ASSERT_EQ(item.Value().record_table.at("R").field_list[0].type.GetName(), "R[][]"); ASSERT_EQ(item.Value().record_table.at("R").field_list[0].type.GetComponentName(), "R"); ASSERT_EQ(item.Value().record_table.at("R").field_list[0].type.GetDescriptor(), "[[LR;"); ASSERT_TRUE(item.Value().function_table.at(sig_f).return_type.IsArray()); ASSERT_TRUE(item.Value().function_table.at(sig_f).return_type.IsObject()); ASSERT_EQ(item.Value().function_table.at(sig_f).return_type.GetName(), "R[]"); ASSERT_EQ(item.Value().function_table.at(sig_f).return_type.GetComponentName(), "R"); ASSERT_EQ(item.Value().function_table.at(sig_f).return_type.GetDescriptor(), "[LR;"); ASSERT_EQ(item.Value().function_table.at(sig_f).params.size(), 1U); ASSERT_TRUE(item.Value().function_table.at(sig_f).params[0].type.IsArray()); ASSERT_TRUE(item.Value().function_table.at(sig_f).params[0].type.IsObject()); ASSERT_EQ(item.Value().function_table.at(sig_f).params[0].type.GetName(), "i8[]"); ASSERT_EQ(item.Value().function_table.at(sig_f).params[0].type.GetComponentName(), "i8"); ASSERT_EQ(item.Value().function_table.at(sig_f).params[0].type.GetDescriptor(), "[B"); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].ids.size(), 1U); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].ids[0], "i32[][]"); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f(i32 a0) {").first); v.push_back(l.TokenizeString("newarr v0, v0, i32[][").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function f64[ f(i32 a0) {").first); v.push_back(l.TokenizeString("newarr v0, v0, i32[]").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void f(i32[][][ a0) {").first); v.push_back(l.TokenizeString("newarr v0, v0, i32[]").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record R {").first); v.push_back(l.TokenizeString("R[][ f").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND); } } TEST(parsertests, undefined_type) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main() <> {").first); v.push_back(l.TokenizeString("movi v0, 5").first); v.push_back(l.TokenizeString("newarr v0, v0, panda.String[]").first); v.push_back(l.TokenizeString("return.void").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ID_RECORD); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record panda.String ").first); v.push_back(l.TokenizeString(".function void main() <> {").first); v.push_back(l.TokenizeString("movi v0, 5").first); v.push_back(l.TokenizeString("newarr v0, v0, panda.String[]").first); v.push_back(l.TokenizeString("return.void").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main() <> {").first); v.push_back(l.TokenizeString("movi v0, 5").first); v.push_back(l.TokenizeString("newarr v0, v0, i32[]").first); v.push_back(l.TokenizeString("return.void").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, parse_undefined_record_field) { { Parser p; std::string source = R"( .function u1 main() { newobj v0, ObjWrongType lda.obj v0 return } .record ObjType {} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, 27); ASSERT_EQ(e.message, "This record does not exist."); } { Parser p; std::string source = R"( .function u1 main() { newobj v0, ObjType lda.obj v0 return } .record ObjType {} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .function u1 main() { ldobj v0, ObjWrongType.fld return } .record ObjType { i32 fld } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, 26); ASSERT_EQ(e.message, "This record does not exist."); } { Parser p; std::string source = R"( .function u1 main() { ldobj v0, ObjType.fldwrong return } .record ObjType { i32 fld } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_FIELD); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, 34); ASSERT_EQ(e.message, "This field does not exist."); } { Parser p; std::string source = R"( .function u1 main() { ldobj v0, ObjType.fld return } .record ObjType { i32 fld } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .function u1 main() { lda.type i64[] return } .record ObjType { i32 fld } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .record panda.String .function panda.String panda.NullPointerException.getMessage(panda.NullPointerException a0) { ldobj.obj a0, panda.NullPointerException.messagewrong return.obj } .record panda.NullPointerException { panda.String message } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_FIELD); ASSERT_EQ(e.line_number, 5); ASSERT_EQ(e.pos, 57); ASSERT_EQ(e.message, "This field does not exist."); } { Parser p; std::string source = R"( .record panda.String .function panda.String panda.NullPointerException.getMessage(panda.NullPointerException a0) { ldobj.obj a0, panda.NullPointerException.message return.obj } .record panda.NullPointerException { panda.String message } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .function u1 main(u1 a0) { newarr a0, a0, ObjWrongType[] return } .record ObjType {} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, 44); ASSERT_EQ(e.message, "This record does not exist."); } { Parser p; std::string source = R"( .function u1 main(u1 a0) { newarr a0, a0, ObjType[] return } .record ObjType {} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, Vreg_width) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("mov v999, a0").first); v.push_back(l.TokenizeString("movi a0, 0").first); v.push_back(l.TokenizeString("lda a0").first); v.push_back(l.TokenizeString("return").first); v.push_back(l.TokenizeString("mov a0, v999").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u1 nain(i64 a0) <> {").first); v.push_back(l.TokenizeString("movi.64 v15, 222").first); v.push_back(l.TokenizeString("call bar, a0, v0").first); v.push_back(l.TokenizeString("return").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_NAME_REG); } } TEST(parsertests, Num_vregs) { { Parser p; std::string source = R"( .record KKK{} .function u1 main(u1 a0) { movi v1, 1 mov v0, a0 return } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); auto &program = res.Value(); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); const auto sig_main = GetFunctionSignatureFromName("main", params); auto it_func = program.function_table.find(sig_main); ASSERT_TRUE(it_func != program.function_table.end()); ASSERT_EQ(it_func->second.regs_num, 2); } { Parser p; std::string source = R"( .function u1 main(u1 a0) { movi v1, 1 mov v0, a0 return } .record KKK{} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); const auto sig_main = GetFunctionSignatureFromName("main", params); auto &program = res.Value(); auto it_func = program.function_table.find(sig_main); ASSERT_TRUE(it_func != program.function_table.end()); ASSERT_EQ(it_func->second.regs_num, 2); } { Parser p; std::string source = R"( .function u1 main() { movi v0, 1 return } .record KKK{} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); const auto sig_main = GetFunctionSignatureFromName("main", {}); auto &program = res.Value(); auto it_func = program.function_table.find(sig_main); ASSERT_TRUE(it_func != program.function_table.end()); ASSERT_EQ(it_func->second.regs_num, 1); } { Parser p; std::string source = R"( .function u1 main() { movi v1, 1 movi v0, 0 movi v2, 2 movi v3, 3 movi v4, 4 return } .record KKK{} )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); const auto sig_main = GetFunctionSignatureFromName("main", {}); auto &program = res.Value(); auto it_func = program.function_table.find(sig_main); ASSERT_TRUE(it_func != program.function_table.end()); ASSERT_EQ(it_func->second.regs_num, 5); } } TEST(parsertests, Bad_imm_value) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u n(){movi v0,.").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_INTEGER_NAME); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u n(){movi v0,%").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_INTEGER_NAME); } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u n(){movi v0,;").first); auto item = p.Parse(v); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_INTEGER_NAME); } } TEST(parsertests, parse_catch_directive) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".catch Exception, try_begin, try_end, catch_begin").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION); ASSERT_EQ(e.line_number, 2); ASSERT_EQ(e.message, ".catch directive is located outside of a function body."); } { std::vector directives { ".catch", ".catch R", ".catch R,", ".catch R, t1", ".catch R, t1,", ".catch R, t1, t2", ".catch R, t1, t2,", ".catch R, t1, t2, c,"}; for (auto s : directives) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, 0); ASSERT_EQ(e.message, "Incorrect catch block declaration. Must be in the format: .catch , " ", , [, ]"); } } { std::vector> v; Lexer l; Parser p; std::string s = ".catch $Exception, try_begin, try_end, catch_begin"; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_RECORD_NAME); ASSERT_EQ(e.line_number, 3); ASSERT_EQ(e.pos, s.find("$")); ASSERT_EQ(e.message, "Invalid name of the exception record."); } { std::vector labels {"try_begin", "try_end", "catch_begin"}; std::vector label_names {"try block begin", "try block end", "catch block begin"}; for (size_t i = 0; i < labels.size(); i++) { std::string s = ".catch Exception"; { std::string directive = s; for (size_t j = 0; j < labels.size(); j++) { directive += i == j ? " $ " : " , "; directive += labels[j]; } std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(directive).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION) << "Test " << directive; ASSERT_EQ(e.line_number, 3) << "Test " << directive; ASSERT_EQ(e.pos, directive.find("$")) << "Test " << directive; ASSERT_EQ(e.message, "Expected comma.") << "Test " << directive; } { std::string directive = s; for (size_t j = 0; j < labels.size(); j++) { directive += " , "; directive += i == j ? "$" : labels[j]; } std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(directive).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_LABEL) << "Test " << directive; ASSERT_EQ(e.line_number, 3) << "Test " << directive; ASSERT_EQ(e.pos, directive.find("$")) << "Test " << directive; ASSERT_EQ(e.message, std::string("Invalid name of the ") + label_names[i] + " label.") << "Test " << directive; } { std::stringstream ss; ss << "Test " << labels[i] << " does not exists"; std::vector> v; Lexer l; Parser p; std::string catch_table = ".catch Exception, try_begin, try_end, catch_begin"; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); for (size_t j = 0; j < labels.size(); j++) { if (i != j) { v.push_back(l.TokenizeString(labels[j] + ":").first); } } v.push_back(l.TokenizeString(catch_table).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_LABEL_EXT) << ss.str(); ASSERT_EQ(e.pos, catch_table.find(labels[i])) << ss.str(); ASSERT_EQ(e.message, "This label does not exist.") << ss.str(); } } } { std::vector> v; Lexer l; Parser p; std::string s = ".catch Exception, try_begin, try_end, catch_begin"; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString("try_begin:").first); v.push_back(l.TokenizeString("try_end:").first); v.push_back(l.TokenizeString("catch_begin:").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); auto &program = res.Value(); auto &function = program.function_table.find(sig_main)->second; ASSERT_EQ(function.catch_blocks.size(), 1); ASSERT_EQ(function.catch_blocks[0].exception_record, "Exception"); ASSERT_EQ(function.catch_blocks[0].try_begin_label, "try_begin"); ASSERT_EQ(function.catch_blocks[0].try_end_label, "try_end"); ASSERT_EQ(function.catch_blocks[0].catch_begin_label, "catch_begin"); ASSERT_EQ(function.catch_blocks[0].catch_end_label, "catch_begin"); } { std::vector> v; Lexer l; Parser p; std::string s = ".catch Exception, try_begin, try_end, catch_begin, catch_end"; v.push_back(l.TokenizeString(".record Exception {}").first); v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString("try_begin:").first); v.push_back(l.TokenizeString("try_end:").first); v.push_back(l.TokenizeString("catch_begin:").first); v.push_back(l.TokenizeString("catch_end:").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); auto &program = res.Value(); auto &function = program.function_table.find(sig_main)->second; ASSERT_EQ(function.catch_blocks.size(), 1); ASSERT_EQ(function.catch_blocks[0].exception_record, "Exception"); ASSERT_EQ(function.catch_blocks[0].try_begin_label, "try_begin"); ASSERT_EQ(function.catch_blocks[0].try_end_label, "try_end"); ASSERT_EQ(function.catch_blocks[0].catch_begin_label, "catch_begin"); ASSERT_EQ(function.catch_blocks[0].catch_end_label, "catch_end"); } } TEST(parsertests, parse_catchall_directive) { { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".catchall try_begin, try_end, catch_begin").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION); ASSERT_EQ(e.line_number, 1); ASSERT_EQ(e.message, ".catchall directive is located outside of a function body."); } { std::vector directives {".catchall", ".catchall t1", ".catchall t1,", ".catchall t1, t2", ".catchall t1, t2,", ".catchall t1, t2, c,"}; for (auto s : directives) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION); ASSERT_EQ(e.line_number, 2); ASSERT_EQ(e.pos, 0); ASSERT_EQ(e.message, "Incorrect catch block declaration. Must be in the format: .catchall , " ", [, ]"); } } { std::vector labels {"try_begin", "try_end", "catch_begin"}; std::vector label_names {"try block begin", "try block end", "catch block begin"}; for (size_t i = 0; i < labels.size(); i++) { std::string s = ".catchall "; if (i != 0) { std::string directive = s; for (size_t j = 0; j < labels.size(); j++) { if (j != 0) { directive += i == j ? " $ " : " , "; } directive += labels[j]; } std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(directive).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION) << "Test " << directive; ASSERT_EQ(e.line_number, 2) << "Test " << directive; ASSERT_EQ(e.pos, directive.find("$")) << "Test " << directive; ASSERT_EQ(e.message, "Expected comma.") << "Test " << directive; } { std::string directive = s; for (size_t j = 0; j < labels.size(); j++) { if (j != 0) { directive += " , "; } directive += i == j ? "$" : labels[j]; } std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString(directive).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_LABEL) << "Test " << directive; ASSERT_EQ(e.line_number, 2) << "Test " << directive; ASSERT_EQ(e.pos, directive.find("$")) << "Test " << directive; ASSERT_EQ(e.message, std::string("Invalid name of the ") + label_names[i] + " label.") << "Test " << directive; } { std::stringstream ss; ss << "Test " << labels[i] << " does not exists"; std::vector> v; Lexer l; Parser p; std::string catch_table = ".catchall try_begin, try_end, catch_begin"; v.push_back(l.TokenizeString(".function void main() {").first); for (size_t j = 0; j < labels.size(); j++) { if (i != j) { v.push_back(l.TokenizeString(labels[j] + ":").first); } } v.push_back(l.TokenizeString(catch_table).first); v.push_back(l.TokenizeString("}").first); p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_LABEL_EXT) << ss.str(); ASSERT_EQ(e.pos, catch_table.find(labels[i])) << ss.str(); ASSERT_EQ(e.message, "This label does not exist.") << ss.str(); } } } { std::vector> v; Lexer l; Parser p; std::string s = ".catchall try_begin, try_end, catch_begin"; v.push_back(l.TokenizeString(".function void main() {").first); v.push_back(l.TokenizeString("try_begin:").first); v.push_back(l.TokenizeString("try_end:").first); v.push_back(l.TokenizeString("catch_begin:").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); const auto sig_main = GetFunctionSignatureFromName("main", {}); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); auto &program = res.Value(); auto &function = program.function_table.find(sig_main)->second; ASSERT_EQ(function.catch_blocks.size(), 1); ASSERT_EQ(function.catch_blocks[0].exception_record, ""); ASSERT_EQ(function.catch_blocks[0].try_begin_label, "try_begin"); ASSERT_EQ(function.catch_blocks[0].try_end_label, "try_end"); ASSERT_EQ(function.catch_blocks[0].catch_begin_label, "catch_begin"); } } TEST(parsertests, parse_numbers) { const auto sig_main = GetFunctionSignatureFromName("main", {}); { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, 12345}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(12345))) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, 0xFEFfe}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(0xFEFfe))) << "0xFEFfe expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, 01237}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(01237))) << "01237 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, 0b10101}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(0b10101))) << "0b10101 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, -12345}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(-12345))) << "-12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, -0xFEFfe}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(-0xFEFfe))) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, -01237}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(-01237))) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("movi v0, -0b10101}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(int64_t(-0b10101))) << "-0b10101 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.0}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.0)) << "1.0 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.)) << "1. expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, .1}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(.1)) << ".0 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1e10)) << "1e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1e+10)) << "1e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1e-10)) << "1e-10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.0e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.0e10)) << "1.0e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.0e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.0e+10)) << "1.0e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.0e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.0e-10)) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.e10)) << "1.e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.e+10)) << "1.e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, 1.e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(1.e-10)) << "12345 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.0}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.0)) << "-1.0 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.)) << "-1. expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -.1}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-.1)) << "-.0 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1e10)) << "-1e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1e+10)) << "-1e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1e-10)) << "-1e-10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.0e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.0e10)) << "-1.0e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.0e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.0e+10)) << "-1.0e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.0e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.0e-10)) << "-1.0e-10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.e10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.e10)) << "-1.e10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.e+10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.e+10)) << "-1.e+10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".function u8 main(){").first); v.push_back(l.TokenizeString("fmovi.64 v0, -1.e-10}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().function_table.at(sig_main).ins[0].imms[0], Ins::IType(-1.e-10)) << "-1.e-10 expected"; ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; } } TEST(parsertests, field_value) { { std::vector> v; Lexer l; Parser p; std::string s = "i32 f "; v.push_back(l.TokenizeString(".record A {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_METADATA_INVALID_VALUE); ASSERT_EQ(e.line_number, 2); ASSERT_EQ(e.pos, s.find("A")); ASSERT_EQ(e.message, "Excepted integer literal"); } { std::vector> v; Lexer l; Parser p; std::string s = "i32 f "; v.push_back(l.TokenizeString(".record A {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE) << e.message; auto &program = res.Value(); auto &record = program.record_table.find("A")->second; auto &field = record.field_list[0]; ASSERT_EQ(field.metadata->GetFieldType().GetName(), "i32"); ASSERT_TRUE(field.metadata->GetValue()); ASSERT_EQ(field.metadata->GetValue()->GetType(), Value::Type::I32); ASSERT_EQ(field.metadata->GetValue()->GetValue(), 10); } { std::vector> v; Lexer l; Parser p; std::string s = "panda.String f "; v.push_back(l.TokenizeString(".record A {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE) << e.message; auto &program = res.Value(); auto &record = program.record_table.find("A")->second; auto &field = record.field_list[0]; ASSERT_EQ(field.metadata->GetFieldType().GetName(), "panda.String"); ASSERT_TRUE(field.metadata->GetValue()); ASSERT_EQ(field.metadata->GetValue()->GetType(), Value::Type::STRING); ASSERT_EQ(field.metadata->GetValue()->GetValue(), "10"); } { std::vector> v; Lexer l; Parser p; std::string s = "panda.String f"; v.push_back(l.TokenizeString(".record A {").first); v.push_back(l.TokenizeString(s).first); v.push_back(l.TokenizeString("}").first); auto res = p.Parse(v); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE) << e.message; auto &program = res.Value(); auto &record = program.record_table.find("A")->second; auto &field = record.field_list[0]; ASSERT_EQ(field.metadata->GetFieldType().GetName(), "panda.String"); ASSERT_FALSE(field.metadata->GetValue()); } } TEST(parsertests, call_short_0args) { { Parser p; std::string source = R"( .function void f() { call.short } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_NUMBER_OPERANDS); } } TEST(parsertests, type_id_tests_lda) { { Parser p; std::string source = R"( .function void f() { lda.type a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .function void f() { lda.type a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .record a {} .function void f() { lda.type a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, type_id_tests_newarr) { { Parser p; std::string source = R"( .function void f() { newarr v0, v0, a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .function void f() { newarr v0, v0, a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .record a {} .function void f() { newarr v0, v0, a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .record a {} .function void f() { newarr v0, v0, a } )"; auto res = p.Parse(source); Error e = p.ShowError(); Error w = p.ShowWarnings()[0]; ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); ASSERT_EQ(w.err, Error::ErrorType::WAR_UNEXPECTED_TYPE_ID); } } TEST(parsertests, type_id_tests_newobj) { { Parser p; std::string source = R"( .function void f() { newobj v0, a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .function void f() { newobj v0, a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .record a {} .function void f() { newobj v0, a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } { Parser p; std::string source = R"( .record a {} .function void f() { newobj v0, a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); Error w = p.ShowWarnings()[0]; ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); ASSERT_EQ(w.err, Error::ErrorType::WAR_UNEXPECTED_TYPE_ID); } } TEST(parsertests, type_id_tests_checkcast) { { Parser p; std::string source = R"( .function void f() { checkcast a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .function void f() { checkcast a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .record a {} .function void f() { checkcast a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, type_id_tests_isinstance) { { Parser p; std::string source = R"( .function void f() { isinstance a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .function void f() { isinstance a[] } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_ID_RECORD); } { Parser p; std::string source = R"( .record a {} .function void f() { isinstance a } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, test_fields_same_name) { { Parser p; std::string source = R"( .record A { i16 aaa u8 aaa i32 aaa } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_REPEATING_FIELD_NAME); } { Parser p; std::string source = R"( .function i32 main() { ldobj.64 v0, A.aaa ldai 0 return } .record A { i16 aaa } )"; auto res = p.Parse(source); Error e = p.ShowError(); ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE); } } TEST(parsertests, test_array_integer_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array {").first); v.push_back(l.TokenizeString("u1 1").first); v.push_back(l.TokenizeString("u8 2").first); v.push_back(l.TokenizeString("i8 -30").first); v.push_back(l.TokenizeString("u16 400").first); v.push_back(l.TokenizeString("i16 -5000").first); v.push_back(l.TokenizeString("u32 60000").first); v.push_back(l.TokenizeString("i32 -700000").first); v.push_back(l.TokenizeString("u64 8000000").first); v.push_back(l.TokenizeString("i64 -90000000").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[0].tag_, panda::panda_file::LiteralTag::ARRAY_U1); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[0].value_), true); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[1].tag_, panda::panda_file::LiteralTag::ARRAY_U8); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[1].value_), 2); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_I8); ASSERT_EQ(static_cast(std::get(item.Value().literalarray_table.at("array").literals_[2].value_)), -30); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U16); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[3].value_), 400); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_I16); ASSERT_EQ(static_cast(std::get(item.Value().literalarray_table.at("array").literals_[4].value_)), -5000); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[5].tag_, panda::panda_file::LiteralTag::ARRAY_U32); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[5].value_), 60000); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[6].tag_, panda::panda_file::LiteralTag::ARRAY_I32); ASSERT_EQ(static_cast(std::get(item.Value().literalarray_table.at("array").literals_[6].value_)), -700000); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[7].tag_, panda::panda_file::LiteralTag::ARRAY_U64); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[7].value_), 8000000); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[8].tag_, panda::panda_file::LiteralTag::ARRAY_I64); ASSERT_EQ(static_cast(std::get(item.Value().literalarray_table.at("array").literals_[8].value_)), -90000000); } TEST(parsertests, test_array_float_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array {").first); v.push_back(l.TokenizeString("f32 -123.4").first); v.push_back(l.TokenizeString("f64 -1234.5").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[0].tag_, panda::panda_file::LiteralTag::ARRAY_F32); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array").literals_[0].value_), -123.4, 0.01f); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[1].tag_, panda::panda_file::LiteralTag::ARRAY_F64); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array").literals_[1].value_), -1234.5, 0.01f); } TEST(parsertests, test_array_string_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array {").first); v.push_back(l.TokenizeString("panda.String \"a\"").first); v.push_back(l.TokenizeString("panda.String \"ab\"").first); v.push_back(l.TokenizeString("panda.String \"abc\"").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".array array_static panda.String 3 { \"a\" \"ab\" \"abc\" }").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[0].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[0].value_), "a"); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[1].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[1].value_), "ab"); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[2].value_), "abc"); // string intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_static").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_static").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_STRING)); ASSERT_EQ(item.Value().literalarray_table.at("array_static").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_static").literals_[1].value_), 3); // string array elements ASSERT_EQ(item.Value().literalarray_table.at("array_static").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_static").literals_[2].value_), "a"); ASSERT_EQ(item.Value().literalarray_table.at("array_static").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_static").literals_[3].value_), "ab"); ASSERT_EQ(item.Value().literalarray_table.at("array_static").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_static").literals_[4].value_), "abc"); } TEST(parsertests, test_array_static_bool_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array u1 3 { 1 0 1 }").first); auto item = p.Parse(v); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_U1)); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[1].value_), 3); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_U1); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[2].value_), true); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U1); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[3].value_), false); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_U1); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[4].value_), true); } TEST(parsertests, test_array_static_integer_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array_unsigned_byte u8 3 { 1 2 3 }").first); v.push_back(l.TokenizeString(".array array_byte i8 3 { -1 2 -3 }").first); v.push_back(l.TokenizeString(".array array_unsigned_short u16 3 { 100 200 300 }").first); v.push_back(l.TokenizeString(".array array_short i16 3 { 100 -200 300 }").first); v.push_back(l.TokenizeString(".array array_unsigned_int u32 3 { 1000 2000 3000 }").first); v.push_back(l.TokenizeString(".array array_int i32 3 { -1000 2000 -3000 }").first); v.push_back(l.TokenizeString(".array array_unsigned_long u64 3 { 10000 20000 30000 }").first); v.push_back(l.TokenizeString(".array array_long i64 3 { 10000 -20000 30000 }").first); auto item = p.Parse(v); // unsigned byte intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_byte").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_byte").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_U8)); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_byte").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_byte").literals_[1].value_), 3); // unsigned byte array elements ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_byte").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_U8); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_byte").literals_[2].value_), 1); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_byte").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U8); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_byte").literals_[3].value_), 2); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_byte").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_U8); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_byte").literals_[4].value_), 3); // byte intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_byte").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_byte").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_I8)); ASSERT_EQ(item.Value().literalarray_table.at("array_byte").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_byte").literals_[1].value_), 3); // byte array elements ASSERT_EQ(item.Value().literalarray_table.at("array_byte").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_I8); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_byte").literals_[2].value_)), -1); ASSERT_EQ(item.Value().literalarray_table.at("array_byte").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_I8); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_byte").literals_[3].value_)), 2); ASSERT_EQ(item.Value().literalarray_table.at("array_byte").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_I8); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_byte").literals_[4].value_)), -3); // unsigned short intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_short").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_short").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_U16)); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_short").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_short").literals_[1].value_), 3); // unsigned short array elements ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_short").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_U16); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_short").literals_[2].value_), 100); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_short").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U16); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_short").literals_[3].value_), 200); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_short").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_U16); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_short").literals_[4].value_), 300); // short intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_short").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_short").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_I16)); ASSERT_EQ(item.Value().literalarray_table.at("array_short").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_short").literals_[1].value_), 3); // short array elements ASSERT_EQ(item.Value().literalarray_table.at("array_short").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_I16); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_short").literals_[2].value_)), 100); ASSERT_EQ(item.Value().literalarray_table.at("array_short").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_I16); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_short").literals_[3].value_)), -200); ASSERT_EQ(item.Value().literalarray_table.at("array_short").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_I16); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_short").literals_[4].value_)), 300); // unsigned int intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_int").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_int").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_U32)); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_int").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_int").literals_[1].value_), 3); // unsigned int array elements ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_int").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_U32); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_int").literals_[2].value_), 1000); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_int").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U32); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_int").literals_[3].value_), 2000); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_int").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_U32); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_int").literals_[4].value_), 3000); // int intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_int").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_int").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_I32)); ASSERT_EQ(item.Value().literalarray_table.at("array_int").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_int").literals_[1].value_), 3); // int array elements ASSERT_EQ(item.Value().literalarray_table.at("array_int").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_I32); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_int").literals_[2].value_)), -1000); ASSERT_EQ(item.Value().literalarray_table.at("array_int").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_I32); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_int").literals_[3].value_)), 2000); ASSERT_EQ(item.Value().literalarray_table.at("array_int").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_I32); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_int").literals_[4].value_)), -3000); // unsigned long intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_long").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_long").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_U64)); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_long").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_long").literals_[1].value_), 3); // unsigned long array elements ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_long").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_U64); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_long").literals_[2].value_), 10000); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_long").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_U64); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_long").literals_[3].value_), 20000); ASSERT_EQ(item.Value().literalarray_table.at("array_unsigned_long").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_U64); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_unsigned_long").literals_[4].value_), 30000); // long intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_long").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_long").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_I64)); ASSERT_EQ(item.Value().literalarray_table.at("array_long").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_long").literals_[1].value_), 3); // long array elements ASSERT_EQ(item.Value().literalarray_table.at("array_long").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_I64); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_long").literals_[2].value_)), 10000); ASSERT_EQ(item.Value().literalarray_table.at("array_long").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_I64); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_long").literals_[3].value_)), -20000); ASSERT_EQ(item.Value().literalarray_table.at("array_long").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_I64); ASSERT_EQ( static_cast(std::get(item.Value().literalarray_table.at("array_long").literals_[4].value_)), 30000); } TEST(parsertests, test_array_static_float_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array_float f32 3 { 12.3 -12.34 12.345 }").first); v.push_back(l.TokenizeString(".array array_double f64 3 { -120.3 120.34 -120.345 }").first); auto item = p.Parse(v); // float intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_float").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_float").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_F32)); ASSERT_EQ(item.Value().literalarray_table.at("array_float").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_float").literals_[1].value_), 3); // float array elements ASSERT_EQ(item.Value().literalarray_table.at("array_float").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_F32); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_float").literals_[2].value_), 12.3, 0.01f); ASSERT_EQ(item.Value().literalarray_table.at("array_float").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_F32); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_float").literals_[3].value_), -12.34, 0.001f); ASSERT_EQ(item.Value().literalarray_table.at("array_float").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_F32); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_float").literals_[4].value_), 12.345, 0.0001f); // double intro literals ASSERT_EQ(item.Value().literalarray_table.at("array_double").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_double").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_F64)); ASSERT_EQ(item.Value().literalarray_table.at("array_double").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array_double").literals_[1].value_), 3); // double array elements ASSERT_EQ(item.Value().literalarray_table.at("array_double").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_F64); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_double").literals_[2].value_), -120.3, 0.01f); ASSERT_EQ(item.Value().literalarray_table.at("array_double").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_F64); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_double").literals_[3].value_), 120.34, 0.001f); ASSERT_EQ(item.Value().literalarray_table.at("array_double").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_F64); ASSERT_NEAR(std::get(item.Value().literalarray_table.at("array_double").literals_[4].value_), -120.345, 0.0001f); } TEST(parsertests, test_array_static_string_def) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".array array panda.String 3 { \"a\" \"ab\" \"abc\" }").first); auto item = p.Parse(v); // string intro literals ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[0].tag_, panda::panda_file::LiteralTag::TAGVALUE); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[0].value_), static_cast(panda::panda_file::LiteralTag::ARRAY_STRING)); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[1].tag_, panda::panda_file::LiteralTag::INTEGER); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[1].value_), 3); // string array elements ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[2].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[2].value_), "a"); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[3].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[3].value_), "ab"); ASSERT_EQ(item.Value().literalarray_table.at("array").literals_[4].tag_, panda::panda_file::LiteralTag::ARRAY_STRING); ASSERT_EQ(std::get(item.Value().literalarray_table.at("array").literals_[4].value_), "abc"); } TEST(parsertests, test_array_string_use) { std::vector> v; Lexer l; Parser p; v.push_back(l.TokenizeString(".record Asm1 {").first); v.push_back(l.TokenizeString("void f").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".array array {").first); v.push_back(l.TokenizeString("panda.String \"a\"").first); v.push_back(l.TokenizeString("panda.String \"ab\"").first); v.push_back(l.TokenizeString("panda.String \"abc\"").first); v.push_back(l.TokenizeString("}").first); v.push_back(l.TokenizeString(".array array_static panda.String 3 { \"a\" \"ab\" \"abc\" }").first); v.push_back(l.TokenizeString(".function void f() {").first); v.push_back(l.TokenizeString("lda.const v0, array").first); v.push_back(l.TokenizeString("lda.const v1, array_static").first); v.push_back(l.TokenizeString("}").first); auto item = p.Parse(v); const auto sig_f = GetFunctionSignatureFromName("f", {}); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].opcode, Opcode::LDA_CONST); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[0].ids[0], "array"); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].opcode, Opcode::LDA_CONST); ASSERT_EQ(item.Value().function_table.at(sig_f).ins[1].ids[0], "array_static"); } TEST(parsertests, test_function_overloading_1) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; auto &program = res.Value(); std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"i8", 0}, language); const auto sig_f = GetFunctionSignatureFromName("f", {}); const auto sig_fi8 = GetFunctionSignatureFromName("f", params); ASSERT_TRUE(program.function_table.find(sig_f) != program.function_table.end()); ASSERT_TRUE(program.function_table.find(sig_fi8) != program.function_table.end()); } TEST(parsertests, test_function_overloading_2) { Parser p; std::string source = R"( .function u1 f(i8 a0) {} .function i8 f(i8 a0) {} )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ID_FUNCTION); } TEST(parsertests, test_function_overloading_3) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES); } TEST(parsertests, test_function_overloading_4) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f:(), a0 call f:(i8), a0 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); } TEST(parsertests, test_function_overloading_5) { Parser p; std::string source = R"( .function u1 f() {} .function void main(u1 a0) { call f:() call f } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; std::vector params; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; params.emplace_back(Type {"u1", 0}, language); const auto sig_f = GetFunctionSignatureFromName("f", {}); const auto sig_main = GetFunctionSignatureFromName("main", params); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[1].ids[0], sig_f); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[0].ids[0], sig_f); } TEST(parsertests, test_function_overloading_6) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f:(u1) } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ID_FUNCTION); } TEST(parsertests, test_function_overloading_7) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f:(u1,) } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_SIGNATURE_PARAMETERS); } TEST(parsertests, test_function_overloading_8) { Parser p; std::string source = R"( .function u1 f(u1 a0) {} .function u1 f(i8 a0, u8 a1) {} .function void main(u1 a0) { call f:(i8, u8), a0 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_FUNCTION_ARGUMENT_MISMATCH); } TEST(parsertests, test_function_overloading_9) { Parser p; std::string source = R"( .function u1 f(i8 a0) {} .function void main(u1 a0) { call f:(i8), a0 call f, v1 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; std::vector params_main; params_main.emplace_back(Type {"u1", 0}, language); std::vector params_f; params_f.emplace_back(Type {"i8", 0}, language); const auto sig_f = GetFunctionSignatureFromName("f", params_f); const auto sig_main = GetFunctionSignatureFromName("main", params_main); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[1].ids[0], sig_f); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[1].regs[0], 1); // v0, [v1], a0 ASSERT_EQ(res.Value().function_table.at(sig_main).ins[0].ids[0], sig_f); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[0].regs[0], 2); // v0, v1, [a0] } TEST(parsertests, test_function_overloading_10) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f:(i8, u1 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_SIGNATURE); } TEST(parsertests, test_function_overloading_11) { Parser p; std::string source = R"( .function u1 f() {} .function u1 f(i8 a0) {} .function void main(u1 a0) { call f: } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_SIGNATURE); } TEST(parsertests, test_function_overloading_12) { Parser p; std::string source = R"( .function u1 f(i8 a0) {} .function u1 f() {} .function u1 f(u8 a0) {} .function u1 f(i8 a0, u8 a1) {} .function void main(u1 a0) { call f:(i8), a0 call f, a0 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES); } TEST(parsertests, test_function_overloading_13) { Parser p; std::string source = R"( .function u1 f(i8 a0) {} .function u1 f() {} .function u1 f(u8 a0) {} .function u1 f(i8 a0, u8 a1) {} .function void main(u1 a0) { call f:(i8), a0 call f:(), v1 call f:(u8), v2 call f:(i8, u8), v3, v4 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE); auto &program = res.Value(); panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; std::vector params_main; params_main.emplace_back(Type {"u1", 0}, language); std::vector params_fi8; params_fi8.emplace_back(Type {"i8", 0}, language); std::vector params_fu8; params_fu8.emplace_back(Type {"u8", 0}, language); std::vector params_fi8u8; params_fi8u8.emplace_back(Type {"i8", 0}, language); params_fi8u8.emplace_back(Type {"u8", 0}, language); const auto sig_f = GetFunctionSignatureFromName("f", {}); const auto sig_fi8 = GetFunctionSignatureFromName("f", params_fi8); const auto sig_fu8 = GetFunctionSignatureFromName("f", params_fu8); const auto sig_fi8u8 = GetFunctionSignatureFromName("f", params_fi8u8); const auto sig_main = GetFunctionSignatureFromName("main", params_main); ASSERT_TRUE(program.function_table.find(sig_main) != program.function_table.end()); ASSERT_TRUE(program.function_table.find(sig_f) != program.function_table.end()); ASSERT_TRUE(program.function_table.find(sig_fi8) != program.function_table.end()); ASSERT_TRUE(program.function_table.find(sig_fu8) != program.function_table.end()); ASSERT_TRUE(program.function_table.find(sig_fi8u8) != program.function_table.end()); // f:(i8) ASSERT_EQ(res.Value().function_table.at(sig_main).ins[0].ids[0], sig_fi8); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[0].regs[0], 5); // f:() ASSERT_EQ(res.Value().function_table.at(sig_main).ins[1].ids[0], sig_f); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[1].regs[0], 1); // f:(u8) ASSERT_EQ(res.Value().function_table.at(sig_main).ins[2].ids[0], sig_fu8); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[2].regs[0], 2); // f:(i8u8) ASSERT_EQ(res.Value().function_table.at(sig_main).ins[3].ids[0], sig_fi8u8); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[3].regs[0], 3); ASSERT_EQ(res.Value().function_table.at(sig_main).ins[3].regs[1], 4); } TEST(parsertests, test_function_doesnt_exist) { Parser p; std::string source = R"( .function void gg(u1 a0) {} .function void f() { call g, v0 } )"; auto res = p.Parse(source); ASSERT_EQ(p.ShowError().err, Error::ErrorType::ERR_BAD_ID_FUNCTION); }