mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-17 09:37:03 +00:00
Implement meta tag
This commit is contained in:
@@ -871,8 +871,10 @@ class CodeGen {
|
||||
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
||||
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
||||
std::vector<CodeGenClass> classes;
|
||||
|
||||
|
||||
std::vector<std::vector<uint8_t>> meta;
|
||||
SyntaxNode OptimizeNode(SyntaxNode n);
|
||||
void WriteMetadataObject(std::vector<uint8_t>& bytes, SyntaxNode n);
|
||||
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
||||
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
||||
public:
|
||||
@@ -1264,6 +1266,11 @@ constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression"
|
||||
* @brief For debugging (store line info and filename)
|
||||
*/
|
||||
constexpr std::string_view LineNode="lineNode";
|
||||
/**
|
||||
* @brief For storing generic metadata
|
||||
*/
|
||||
constexpr std::string_view MetadataStatement = "MetadataStatement";
|
||||
|
||||
/**
|
||||
* @brief Advanced AST node
|
||||
*
|
||||
@@ -1532,7 +1539,7 @@ class GC {
|
||||
TObject value;
|
||||
|
||||
};
|
||||
|
||||
class TDictionary;
|
||||
class TFile : public THeapObject
|
||||
{
|
||||
public:
|
||||
@@ -1547,6 +1554,7 @@ class GC {
|
||||
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
||||
std::vector<std::pair<std::string,TVMVersion>> tools;
|
||||
std::vector<std::pair<std::string,std::vector<uint8_t>>> sections;
|
||||
std::vector<std::pair<std::string,std::vector<uint8_t>>> metadata;
|
||||
std::vector<std::vector<uint8_t>> resources;
|
||||
std::vector<TClass> classes;
|
||||
std::string name;
|
||||
@@ -1564,6 +1572,8 @@ class GC {
|
||||
void Mark();
|
||||
|
||||
void EnsureCanRunInCrossLang();
|
||||
|
||||
TDictionary* DecodeMetadata(GCList& ls, size_t index);
|
||||
};
|
||||
class TAssociativeArray : public THeapObject
|
||||
{
|
||||
|
||||
@@ -33,6 +33,350 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
}
|
||||
|
||||
SyntaxNode CodeGen::OptimizeNode(SyntaxNode n)
|
||||
{
|
||||
if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||
{
|
||||
auto& asn = std::get<AdvancedSyntaxNode>(n);
|
||||
if(asn.nodeName == AddExpression && asn.nodes.size() == 2)
|
||||
{
|
||||
auto leftNode = OptimizeNode(asn.nodes[0]);
|
||||
auto rightNode = OptimizeNode(asn.nodes[1]);
|
||||
|
||||
|
||||
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||
{
|
||||
return std::get<int64_t>(leftNode) + std::get<int64_t>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||
{
|
||||
return std::get<double>(leftNode) + std::get<double>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||
{
|
||||
return (double)std::get<int64_t>(leftNode) + std::get<double>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||
{
|
||||
return std::get<double>(leftNode) + (double)std::get<int64_t>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<std::string>(leftNode) && std::holds_alternative<std::string>(rightNode))
|
||||
{
|
||||
return std::get<std::string>(leftNode) + std::get<std::string>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<std::string>(leftNode) && std::holds_alternative<char>(rightNode))
|
||||
{
|
||||
return std::get<std::string>(leftNode) + std::get<char>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<char>(leftNode) && std::holds_alternative<std::string>(rightNode))
|
||||
{
|
||||
return std::get<char>(leftNode) + std::get<std::string>(rightNode);
|
||||
}
|
||||
}
|
||||
if(asn.nodeName == SubExpression && asn.nodes.size() == 2)
|
||||
{
|
||||
auto leftNode = OptimizeNode(asn.nodes[0]);
|
||||
auto rightNode = OptimizeNode(asn.nodes[1]);
|
||||
|
||||
|
||||
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||
{
|
||||
return std::get<int64_t>(leftNode) - std::get<int64_t>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||
{
|
||||
return std::get<double>(leftNode) - std::get<double>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<int64_t>(leftNode) && std::holds_alternative<double>(rightNode))
|
||||
{
|
||||
return (double)std::get<int64_t>(leftNode) - std::get<double>(rightNode);
|
||||
}
|
||||
if(std::holds_alternative<double>(leftNode) && std::holds_alternative<int64_t>(rightNode))
|
||||
{
|
||||
return std::get<double>(leftNode) - (double)std::get<int64_t>(rightNode);
|
||||
}
|
||||
}
|
||||
if(asn.nodeName == CommaExpression && asn.nodes.size() == 2)
|
||||
{
|
||||
return AdvancedSyntaxNode::Create(CommaExpression,true, {
|
||||
OptimizeNode(asn.nodes[0]),
|
||||
OptimizeNode(asn.nodes[1])
|
||||
});
|
||||
}
|
||||
if(asn.nodeName == ScopeNode)
|
||||
{
|
||||
if(asn.nodes.empty())
|
||||
{
|
||||
asn.nodeName = NodeList;
|
||||
return asn;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto& item : asn.nodes)
|
||||
{
|
||||
item = OptimizeNode(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
0: false,
|
||||
1: true,
|
||||
2: null,
|
||||
3: Long,
|
||||
4: Double,
|
||||
5: Char
|
||||
6: String,
|
||||
7: List,
|
||||
8: Dictionary,
|
||||
9: ByteArray (embed),
|
||||
10: Stream (embedstrm),
|
||||
11: VFS (embeddir),
|
||||
12: ClosureOfEmbedStream (used by embeddir)
|
||||
*/
|
||||
|
||||
void CodeGen::WriteMetadataObject(std::vector<uint8_t>& bytes, SyntaxNode n)
|
||||
{
|
||||
if(std::holds_alternative<bool>(n))
|
||||
{
|
||||
bytes.push_back(std::get<bool>(n) ? 1 : 0);
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<nullptr_t>(n))
|
||||
{
|
||||
bytes.push_back(2);
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<int64_t>(n))
|
||||
{
|
||||
auto num = std::get<int64_t>(n);
|
||||
bytes.push_back(3);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+8);
|
||||
BitConverter::FromUint64BE(bytes[offset],num);
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<double>(n))
|
||||
{
|
||||
auto num = std::get<double>(n);
|
||||
bytes.push_back(4);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+8);
|
||||
BitConverter::FromDoubleBE(bytes[offset],num);
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<char>(n))
|
||||
{
|
||||
auto chr = std::get<char>(n);
|
||||
bytes.push_back(5);
|
||||
bytes.push_back((uint8_t)chr);
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<std::string>(n))
|
||||
{
|
||||
auto& str = std::get<std::string>(n);
|
||||
bytes.push_back(6);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], GetString(str));
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||
{
|
||||
auto& asn = std::get<AdvancedSyntaxNode>(n);
|
||||
if(asn.nodeName == ArrayExpression)
|
||||
{
|
||||
std::vector<SyntaxNode> itms;
|
||||
if(asn.nodes.size() > 0)
|
||||
|
||||
GetFunctionArgs(itms,asn.nodes[0]);
|
||||
bytes.push_back(7);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
||||
for(auto& item : itms)
|
||||
{
|
||||
WriteMetadataObject(bytes,item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(asn.nodeName == DictionaryExpression)
|
||||
{
|
||||
std::vector<SyntaxNode> itms;
|
||||
if(asn.nodes.size() > 0)
|
||||
|
||||
GetFunctionArgs(itms,asn.nodes[0]);
|
||||
bytes.push_back(8);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
||||
for(auto& item : itms)
|
||||
{
|
||||
if(std::holds_alternative<AdvancedSyntaxNode>(item))
|
||||
{
|
||||
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
||||
if(tkn.nodeName == GetVariableExpression && !tkn.nodes.empty())
|
||||
{
|
||||
if(std::holds_alternative<std::string>(tkn.nodes[0]))
|
||||
{
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString(std::get<std::string>(tkn.nodes[0])));
|
||||
bytes.push_back(2);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||
bytes.push_back(2);
|
||||
|
||||
}
|
||||
}
|
||||
else if(tkn.nodeName == AssignExpression && tkn.nodes.size()==2 && std::holds_alternative<AdvancedSyntaxNode>(tkn.nodes[0]))
|
||||
{
|
||||
auto myTn = std::get<AdvancedSyntaxNode>(tkn.nodes[0]);
|
||||
if(myTn.nodeName == GetVariableExpression && !myTn.nodes.empty())
|
||||
{
|
||||
if(std::holds_alternative<std::string>(myTn.nodes[0]))
|
||||
{
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString(std::get<std::string>(myTn.nodes[0])));
|
||||
WriteMetadataObject(bytes,tkn.nodes[1]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||
bytes.push_back(2);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||
bytes.push_back(2);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
size_t offset2 = bytes.size();
|
||||
bytes.resize(offset2+4);
|
||||
BitConverter::FromUint32BE(bytes[offset2], GetString("__unknown"));
|
||||
bytes.push_back(2);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(asn.nodeName == EmbedExpression)
|
||||
{
|
||||
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||
{
|
||||
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||
bytes.push_back(9);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared<ResourceFile>(filename)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(asn.nodeName == EmbedStreamExpression)
|
||||
{
|
||||
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||
{
|
||||
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||
bytes.push_back(10);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], GetResource(std::make_shared<ResourceFile>(filename)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(asn.nodeName == EmbedDirectoryExpression)
|
||||
{
|
||||
if(!asn.nodes.empty() && std::holds_alternative<std::string>(asn.nodes[0]))
|
||||
{
|
||||
auto& filename = std::get<std::string>(asn.nodes[0]);
|
||||
bytes.push_back(11);
|
||||
|
||||
|
||||
std::function<void(Tesses::Framework::Filesystem::VFSPath path)> embedDir;
|
||||
embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void {
|
||||
bytes.push_back(8);
|
||||
std::vector<std::pair<Tesses::Framework::Filesystem::VFSPath, bool>> entries;
|
||||
if(embedFS != nullptr && embedFS->DirectoryExists(path))
|
||||
for(auto& item : embedFS->EnumeratePaths(path))
|
||||
{
|
||||
if(embedFS->DirectoryExists(item))
|
||||
entries.emplace_back(item,true);
|
||||
else if(embedFS->FileExists(item))
|
||||
entries.emplace_back(item,false);
|
||||
|
||||
|
||||
/*GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI);
|
||||
if(embedFS->DirectoryExists(item))
|
||||
{
|
||||
embedDir(item);
|
||||
}
|
||||
else if(embedFS->RegularFileExists(item))
|
||||
{
|
||||
auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),
|
||||
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||
AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()})
|
||||
})
|
||||
});
|
||||
GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI);
|
||||
}
|
||||
else {
|
||||
instructions.push_back(new SimpleInstruction(PUSHUNDEFINED));
|
||||
}
|
||||
|
||||
instructions.push_back(new SimpleInstruction(APPENDDICT));*/
|
||||
}
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset], (uint32_t)entries.size());
|
||||
for(auto& item : entries)
|
||||
{
|
||||
offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset],GetString(item.first.GetFileName()));
|
||||
if(item.second)
|
||||
embedDir(item.first);
|
||||
else {
|
||||
bytes.push_back(12);
|
||||
offset = bytes.size();
|
||||
bytes.resize(offset+4);
|
||||
bytes.resize(offset+4);
|
||||
BitConverter::FromUint32BE(bytes[offset],GetResource(std::make_shared<ResourceFile>(item.first.ToString())));
|
||||
}
|
||||
}
|
||||
};
|
||||
embedDir(filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bytes.push_back(2);
|
||||
}
|
||||
|
||||
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
@@ -56,6 +400,10 @@ namespace Tesses::CrossLang
|
||||
GetString(tool.first);
|
||||
sections++;
|
||||
}
|
||||
for(auto& meta : this->meta)
|
||||
{
|
||||
sections++;
|
||||
}
|
||||
if(!this->icon.empty())
|
||||
{
|
||||
this->GetResource(std::make_shared<ResourceFile>(this->icon));
|
||||
@@ -246,6 +594,13 @@ namespace Tesses::CrossLang
|
||||
WriteInt(stream,this->GetResource(std::make_shared<ResourceFile>(this->icon)));
|
||||
|
||||
}
|
||||
for(auto& meta : this->meta)
|
||||
{
|
||||
memcpy(buffer,"META", 4);
|
||||
Write(stream,buffer,4);
|
||||
WriteInt(stream,(uint32_t)meta.size());
|
||||
Write(stream,meta.data(),meta.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1380,6 +1735,17 @@ namespace Tesses::CrossLang
|
||||
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||
|
||||
}
|
||||
else if(adv.nodeName == MetadataStatement && adv.nodes.size() == 2 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||
{
|
||||
auto& name = std::get<std::string>(adv.nodes[0]);
|
||||
|
||||
|
||||
auto& metabytes= this->meta.emplace_back();
|
||||
metabytes.resize(4);
|
||||
BitConverter::FromUint32BE(metabytes[0],GetString(name));
|
||||
|
||||
WriteMetadataObject(metabytes, adv.nodes[1]);
|
||||
}
|
||||
else if(adv.nodeName == EmbedStreamExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||
{
|
||||
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||
@@ -1446,6 +1812,7 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
else if(adv.nodeName == ScopeNode)
|
||||
{
|
||||
|
||||
scope++;
|
||||
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
||||
for(size_t i = 0; i < adv.nodes.size(); i++)
|
||||
|
||||
@@ -1456,7 +1456,7 @@ namespace Tesses::CrossLang
|
||||
EnsureSymbol("(");
|
||||
SyntaxNode list = ParseExpression();
|
||||
SyntaxNode body = nullptr;
|
||||
if(IsSymbol(":"))
|
||||
if(IsSymbol(":") || IsIdentifier("in"))
|
||||
{
|
||||
item = list;
|
||||
list = ParseExpression();
|
||||
@@ -1467,6 +1467,11 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
body = ParseNode();
|
||||
}
|
||||
if(std::holds_alternative<nullptr_t>(item))
|
||||
item = AdvancedSyntaxNode::Create(DeclareExpression,true, {
|
||||
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"item"})
|
||||
});
|
||||
|
||||
return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body});
|
||||
}
|
||||
if(IsIdentifier("class"))
|
||||
@@ -1681,6 +1686,25 @@ namespace Tesses::CrossLang
|
||||
});
|
||||
}
|
||||
}
|
||||
if(IsIdentifier("meta"))
|
||||
{
|
||||
if(i >= tokens.size() || tokens[i].type != LexTokenType::String)
|
||||
{
|
||||
std::cout << "WARN: meta is a conditional keyword,\nif you suffix it with a string, it will be assumed to be a metadata tag" << std::endl;
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
std::string name = tokens[i++].text;
|
||||
EnsureSymbol("{");
|
||||
auto expr = ParseExpression();
|
||||
|
||||
|
||||
EnsureSymbol("}");
|
||||
|
||||
return AdvancedSyntaxNode::Create(MetadataStatement,false,{name, AdvancedSyntaxNode::Create(DictionaryExpression,true,{expr})});
|
||||
}
|
||||
|
||||
}
|
||||
if(IsIdentifier("func"))
|
||||
{
|
||||
|
||||
|
||||
@@ -118,6 +118,167 @@ namespace Tesses::CrossLang
|
||||
throw VMException(errorMessage);
|
||||
}
|
||||
|
||||
TDictionary* TFile::DecodeMetadata(GCList& ls, size_t midx)
|
||||
{
|
||||
if(midx >= this->metadata.size()) return nullptr;
|
||||
if(this->metadata[midx].second.empty()) return nullptr;
|
||||
if(this->metadata[midx].second[0] != 8) return nullptr;
|
||||
size_t index = 0;
|
||||
auto& bytes = this->metadata[midx].second;
|
||||
|
||||
std::function<TObject()> parseEnt;
|
||||
parseEnt = [&]()->TObject {
|
||||
if(index >= bytes.size()) throw std::out_of_range("Abrupt end of metadata");
|
||||
switch(bytes[index++])
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
return true;
|
||||
case 2:
|
||||
return nullptr;
|
||||
case 3:
|
||||
{
|
||||
if(index + 8 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint64BE(bytes[index]);
|
||||
index+=8;
|
||||
int64_t val2;
|
||||
memcpy(&val2,&val,sizeof(val));
|
||||
return val2;
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
if(index + 8 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToDoubleBE(bytes[index]);
|
||||
index+=8;
|
||||
return val;
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
|
||||
if(index + 1 <= bytes.size())
|
||||
{
|
||||
return (char)bytes[index++];
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
return this->strings.at((size_t)val);
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::vector<TObject> items;
|
||||
for(uint32_t i = 0; i < val; i++)
|
||||
{
|
||||
items.push_back(parseEnt());
|
||||
}
|
||||
|
||||
return TList::Create(ls,items.begin(),items.end());
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::vector<TDItem> items;
|
||||
|
||||
for(uint32_t i = 0; i < val; i++)
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val2= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::string& text=this->strings.at((size_t)val2);
|
||||
items.emplace_back(text,parseEnt());
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
|
||||
}
|
||||
|
||||
return TDictionary::Create(ls, items.begin(),items.end());
|
||||
}else throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 9:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
auto ba = TByteArray::Create(ls);
|
||||
ba->data = this->resources.at((size_t)val);
|
||||
return ba;
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
auto data = parseEnt();
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(data,dict))
|
||||
{
|
||||
return std::make_shared<EmbedDirectory>(ls.GetGC(),dict);
|
||||
}
|
||||
else return Undefined();
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
ls.GetGC()->BarrierBegin();
|
||||
auto em = TExternalMethod::Create(ls,"",{},[val,this](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||
});
|
||||
em->watch.push_back(this);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return em;
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid metadata opcode");
|
||||
}
|
||||
};
|
||||
|
||||
TDictionary* dict_res;
|
||||
TObject ent = parseEnt();
|
||||
if(GetObjectHeap(ent, dict_res)) return dict_res;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TFile::Load(GC* gc, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
|
||||
@@ -166,10 +327,8 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed)
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
data.resize(tableLen);
|
||||
Ensure(stream,data.data(), tableLen);
|
||||
this->resources.push_back(data);
|
||||
auto& data = this->resources.emplace_back(tableLen);
|
||||
Ensure(stream,data.data(), data.size());
|
||||
}
|
||||
else if(strncmp(table_name,"CHKS",4) == 0 && gc != nullptr) //chunks
|
||||
{
|
||||
@@ -268,13 +427,22 @@ namespace Tesses::CrossLang
|
||||
this->classes.push_back(cls);
|
||||
}
|
||||
}
|
||||
else if(strncmp(table_name,"META",4) == 0) //structured metadata
|
||||
{
|
||||
if(tableLen > 4)
|
||||
{
|
||||
auto name = this->GetString(stream);
|
||||
auto& data = this->metadata.emplace_back(name, std::vector<uint8_t>(tableLen-4));
|
||||
Ensure(stream,data.second.data(), tableLen-4);
|
||||
}
|
||||
else throw VMException("meta tag is not valid");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
data.resize(tableLen);
|
||||
Ensure(stream,data.data(), tableLen);
|
||||
std::string key(std::string(table_name), 4);
|
||||
this->sections.push_back(std::pair<std::string,std::vector<uint8_t>>(key,data));
|
||||
auto& data = this->sections.emplace_back(std::string(table_name, 4), std::vector<uint8_t>(tableLen));
|
||||
Ensure(stream,data.second.data(), tableLen);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4328,7 +4328,31 @@ namespace Tesses::CrossLang {
|
||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
|
||||
auto ttask = dynamic_cast<TTask*>(obj);
|
||||
auto file = dynamic_cast<TFile*>(obj);
|
||||
|
||||
if(file != nullptr)
|
||||
{
|
||||
if(key == "MetadataDecode")
|
||||
{
|
||||
int64_t index;
|
||||
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
|
||||
{
|
||||
cse.back()->Push(gc,file->DecodeMetadata(ls,(size_t)index));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(key == "MetadataName")
|
||||
{
|
||||
int64_t index;
|
||||
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
|
||||
{
|
||||
cse.back()->Push(gc,file->metadata.at((size_t)index).first);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cse.back()->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
if(ttask != nullptr)
|
||||
{
|
||||
if(key == "ContinueWith")
|
||||
@@ -6017,6 +6041,32 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc, list);
|
||||
return false;
|
||||
}
|
||||
else if(key == "MetadataCount")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc, (int64_t)file->metadata.size());
|
||||
return false;
|
||||
}
|
||||
else if(key == "Metadata")
|
||||
{
|
||||
TList* meta = TList::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
for(size_t i = 0; i < file->metadata.size(); i++)
|
||||
{
|
||||
meta->Add(
|
||||
TDictionary::Create(ls,
|
||||
{
|
||||
TDItem("Name", file->metadata[i].first),
|
||||
TDItem("Index",(int64_t)i)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
gc->BarrierEnd();
|
||||
|
||||
cse.back()->Push(gc, meta);
|
||||
return false;
|
||||
}
|
||||
else if(key == "Sections")
|
||||
{
|
||||
TList* sections = TList::Create(ls);
|
||||
|
||||
Reference in New Issue
Block a user