mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2025-04-15 00:50:33 +00:00

Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/I5G96F Test: Test262 suit, ark unittest, rk3568 XTS, ark previewer demo Signed-off-by: huangyu <huangyu76@huawei.com> Change-Id: I3f63d129a07deaa27a390f556dcaa5651c098185
4299 lines
162 KiB
C++
4299 lines
162 KiB
C++
/**
|
|
* 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 <gtest/gtest.h>
|
|
#include <string>
|
|
|
|
using namespace panda::pandasm;
|
|
|
|
TEST(parsertests, test1)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::string> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::string> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::string> 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<std::vector<panda::pandasm::Token>> 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<std::string> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<uint16_t> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> v;
|
|
Lexer l;
|
|
Parser p;
|
|
v.push_back(l.TokenizeString(".record panda.String <external>").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<std::vector<panda::pandasm::Token>> 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 <external>
|
|
|
|
.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 <external>
|
|
|
|
.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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<Function::Parameter> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::string> 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<std::vector<panda::pandasm::Token>> 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 <exception_record>, "
|
|
"<try_begin_label>, <try_end_label>, <catch_begin_label>[, <catch_end_label>]");
|
|
}
|
|
}
|
|
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<std::string> labels {"try_begin", "try_end", "catch_begin"};
|
|
std::vector<std::string> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::string> directives {".catchall", ".catchall t1", ".catchall t1,",
|
|
".catchall t1, t2", ".catchall t1, t2,", ".catchall t1, t2, c,"};
|
|
|
|
for (auto s : directives) {
|
|
std::vector<std::vector<panda::pandasm::Token>> 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 <try_begin_label>, "
|
|
"<try_end_label>, <catch_begin_label>[, <catch_end_label>]");
|
|
}
|
|
}
|
|
|
|
{
|
|
std::vector<std::string> labels {"try_begin", "try_end", "catch_begin"};
|
|
std::vector<std::string> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> v;
|
|
Lexer l;
|
|
Parser p;
|
|
|
|
std::string s = "i32 f <value=A>";
|
|
|
|
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<std::vector<panda::pandasm::Token>> v;
|
|
Lexer l;
|
|
Parser p;
|
|
|
|
std::string s = "i32 f <value=10>";
|
|
|
|
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<int32_t>(), 10);
|
|
}
|
|
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> v;
|
|
Lexer l;
|
|
Parser p;
|
|
|
|
std::string s = "panda.String f <value=\"10\">";
|
|
|
|
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<std::string>(), "10");
|
|
}
|
|
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<std::vector<panda::pandasm::Token>> 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<bool>(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<uint8_t>(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<int8_t>(std::get<uint8_t>(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<uint16_t>(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<int16_t>(std::get<uint16_t>(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<uint32_t>(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<int32_t>(std::get<uint32_t>(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<uint64_t>(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<int64_t>(std::get<uint64_t>(item.Value().literalarray_table.at("array").literals_[8].value_)),
|
|
-90000000);
|
|
}
|
|
|
|
TEST(parsertests, test_array_float_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<float>(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<double>(item.Value().literalarray_table.at("array").literals_[1].value_), -1234.5, 0.01f);
|
|
}
|
|
|
|
TEST(parsertests, test_array_string_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<std::string>(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<std::string>(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<std::string>(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<uint8_t>(item.Value().literalarray_table.at("array_static").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<std::string>(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<std::string>(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<std::string>(item.Value().literalarray_table.at("array_static").literals_[4].value_), "abc");
|
|
}
|
|
|
|
TEST(parsertests, test_array_static_bool_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<uint8_t>(item.Value().literalarray_table.at("array").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<bool>(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<bool>(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<bool>(item.Value().literalarray_table.at("array").literals_[4].value_), true);
|
|
}
|
|
|
|
TEST(parsertests, test_array_static_integer_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<uint8_t>(item.Value().literalarray_table.at("array_unsigned_byte").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(item.Value().literalarray_table.at("array_byte").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<int8_t>(std::get<uint8_t>(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<int8_t>(std::get<uint8_t>(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<int8_t>(std::get<uint8_t>(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<uint8_t>(item.Value().literalarray_table.at("array_unsigned_short").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint8_t>(item.Value().literalarray_table.at("array_short").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<int16_t>(std::get<uint16_t>(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<int16_t>(std::get<uint16_t>(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<int16_t>(std::get<uint16_t>(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<uint8_t>(item.Value().literalarray_table.at("array_unsigned_int").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint8_t>(item.Value().literalarray_table.at("array_int").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<int32_t>(std::get<uint32_t>(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<int32_t>(std::get<uint32_t>(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<int32_t>(std::get<uint32_t>(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<uint8_t>(item.Value().literalarray_table.at("array_unsigned_long").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<uint64_t>(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<uint64_t>(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<uint64_t>(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<uint8_t>(item.Value().literalarray_table.at("array_long").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<int64_t>(std::get<uint64_t>(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<int64_t>(std::get<uint64_t>(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<int64_t>(std::get<uint64_t>(item.Value().literalarray_table.at("array_long").literals_[4].value_)),
|
|
30000);
|
|
}
|
|
|
|
TEST(parsertests, test_array_static_float_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<uint8_t>(item.Value().literalarray_table.at("array_float").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<float>(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<float>(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<float>(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<uint8_t>(item.Value().literalarray_table.at("array_double").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<double>(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<double>(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<double>(item.Value().literalarray_table.at("array_double").literals_[4].value_), -120.345,
|
|
0.0001f);
|
|
}
|
|
|
|
TEST(parsertests, test_array_static_string_def)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<uint8_t>(item.Value().literalarray_table.at("array").literals_[0].value_),
|
|
static_cast<uint8_t>(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<uint32_t>(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<std::string>(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<std::string>(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<std::string>(item.Value().literalarray_table.at("array").literals_[4].value_), "abc");
|
|
}
|
|
|
|
TEST(parsertests, test_array_string_use)
|
|
{
|
|
std::vector<std::vector<panda::pandasm::Token>> 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<Function::Parameter> 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<Function::Parameter> 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<Function::Parameter> params_main;
|
|
params_main.emplace_back(Type {"u1", 0}, language);
|
|
std::vector<Function::Parameter> 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<Function::Parameter> params_main;
|
|
params_main.emplace_back(Type {"u1", 0}, language);
|
|
std::vector<Function::Parameter> params_fi8;
|
|
params_fi8.emplace_back(Type {"i8", 0}, language);
|
|
std::vector<Function::Parameter> params_fu8;
|
|
params_fu8.emplace_back(Type {"u8", 0}, language);
|
|
std::vector<Function::Parameter> 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);
|
|
}
|