Tasmota/lib/libesp32/Berry/tools/coc/block_builder.cpp

205 lines
6.0 KiB
C++
Executable File

/********************************************************************
** Copyright (c) 2018-2020 Guan Wenliang
** This file is part of the Berry default interpreter.
** skiars@qq.com, https://github.com/Skiars/berry
** See Copyright Notice in the LICENSE file or at
** https://github.com/Skiars/berry/blob/master/LICENSE
********************************************************************/
#include "block_builder.h"
#include "hash_map.h"
#include "macro_table.h"
#include "object_block.h"
#include <sstream>
#include <fstream>
static bool depend(const object_block *object, const macro_table *macro)
{
auto it = object->attr.find("depend");
if (it != object->attr.end()) {
return macro->query(it->second);
}
return true;
}
block_builder::block_builder(const object_block *object, const macro_table *macro)
{
m_block.name = object->name;
if (depend(object, macro)) {
m_block.type = object->type;
m_block.attr = object->attr;
auto it = object->attr.find("name");
if (it != object->attr.end()) {
m_strtab.push_back(it->second);
}
for (auto key : object->data_ordered) {
auto second = object->data.at(key);
if (second.depend.empty() || macro->query(second.depend)) {
m_block.data[key] = second.value;
m_strtab.push_back(key);
m_block.data_ordered.push_back(key); /* record insertion order */
}
}
}
}
std::string block_builder::block_tostring(const block &block)
{
std::ostringstream ostr;
if (block.type == "map") {
ostr << map_tostring(block, block.name);
} else if (block.type == "class") {
ostr << class_tostring(block);
} else if (block.type == "vartab") {
ostr << vartab_tostring(block);
} else if (block.type == "module") {
ostr << module_tostring(block);
}
return ostr.str();
}
std::string block_builder::class_tostring(const block &block)
{
bool empty_map = block.data.empty();
std::ostringstream ostr;
hash_map map(block.data);
std::string map_name(block.name + "_map");
if (!empty_map) {
ostr << map_tostring(block, map_name, true) << std::endl;
}
ostr << scope(block) << " be_define_const_class(\n "
<< block.name << ",\n "
<< map.var_count() << ",\n "
<< super(block) << ",\n "
<< name(block) << "\n"
");" << std::endl;
return ostr.str();
}
std::string block_builder::map_tostring(const block &block, const std::string &name, bool local)
{
std::ostringstream ostr;
hash_map map(block.data);
hash_map::entry_table list = map.entry_list();
ostr << "static be_define_const_map_slots(" << name << ") {\n";
for (auto it : list) {
ostr << " { be_const_key(" << it.key << ", "
<< it.next << "), " << it.value << " }," << std::endl;
}
ostr << "};\n\n";
ostr << (local ? "static" : scope(block))
<< " be_define_const_map(\n "
<< name << ",\n "
<< list.size() << "\n"
");" << std::endl;
return ostr.str();
}
std::string block_builder::vartab_tostring(const block &block)
{
std::ostringstream ostr;
struct block idxblk;
std::vector<std::string> varvec;
int index = 0;
idxblk = block;
idxblk.data.clear();
for (auto key : block.data_ordered) {
varvec.push_back(block.data.at(key));
idxblk.data[key] = "int(" + std::to_string(index++) + ")";
}
ostr << map_tostring(idxblk, block.name + "_map", true) << std::endl;
ostr << "static const bvalue __vlist_array[] = {\n";
for (auto it : varvec) {
ostr << " be_const_" << it << "," << std::endl;
}
ostr << "};\n\n";
ostr << "static be_define_const_vector(\n "
<< block.name << "_vector,\n "
"__vlist_array,\n "
<< varvec.size() << "\n"
");" << std::endl;
return ostr.str();
}
std::string block_builder::module_tostring(const block &block)
{
std::ostringstream ostr;
std::string name("m_lib" + block.name);
std::string map_name(name + "_map");
ostr << map_tostring(block, map_name, true) << std::endl
<< "static be_define_const_module(\n "
<< name << ",\n "
"\"" << block.name << "\"\n"
");" << std::endl;
std::string scp = scope(block);
if (scp != "static") { /* extern */
ostr << "\n" << scp
<< " be_define_const_native_module("
<< block.name << ", "
<< init(block) << ");" << std::endl;
}
return ostr.str();
}
std::string block_builder::scope(const block &block)
{
auto it = block.attr.find("scope");
return it != block.attr.end() && it->second == "local" ?
"static" : "BE_EXPORT_VARIABLE";
}
std::string block_builder::super(const block &block)
{
auto it = block.attr.find("super");
return it == block.attr.end() ? "NULL" : "(bclass *)&" + it->second;
}
std::string block_builder::name(const block &block)
{
auto it = block.attr.find("name");
return it == block.attr.end() ? block.name : it->second;
}
std::string block_builder::init(const block &block)
{
auto it = block.attr.find("init");
return it == block.attr.end() ? "NULL" : it->second;
}
void block_builder::writefile(const std::string &filename, const std::string &text)
{
std::string pathname(filename);
std::string otext("#include \"be_constobj.h\"\n\n" + text);
std::ostringstream buf;
std::ifstream fin(pathname);
buf << fin.rdbuf();
if (buf.str() != otext) {
std::ofstream fout;
fout.open(pathname, std::ios::out);
fout << otext;
fout.close();
}
}
void block_builder::dumpfile(const std::string &path)
{
std::string s = block_tostring(m_block);
auto it = m_block.attr.find("file");
std::string &name = it != m_block.attr.end() ? it->second : m_block.name;
writefile(path + "/be_fixed_" + name + ".h", s);
}
const std::vector<std::string>& block_builder::strtab() const
{
return m_strtab;
}