From c37b26af145501b5a23373f65b30d36484956db4 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Wed, 17 Dec 2025 06:07:27 -0600 Subject: [PATCH] Add embeddir finally and embedstrm --- CMakeLists.txt | 1 + include/CrossLang.hpp | 65 +++++++++- src/assembler/asm.cpp | 29 +++++ src/assembler/disasm.cpp | 14 +++ src/compiler/codegen.cpp | 62 ++++++++- src/compiler/parser.cpp | 24 +++- src/crosslangcompiler.cpp | 8 +- src/crosslanginterperter.cpp | 22 ++-- src/runtime_methods/vm.cpp | 3 +- src/types/embed.cpp | 228 ++++++++++++++++++++++++++++++++++ src/types/rootenvironment.cpp | 2 +- src/vm/vm.cpp | 45 ++++++- src/vm/vm_opcode_table.h | 6 +- 13 files changed, 484 insertions(+), 25 deletions(-) create mode 100644 src/types/embed.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c1a6ef9..7864d5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,7 @@ src/runtime_methods/path.cpp src/runtime_methods/env.cpp src/runtime_methods/process.cpp src/runtime_methods/helpers.cpp +src/types/embed.cpp src/types/async.cpp src/types/associativearray.cpp src/types/any.cpp diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index e86dc3a..381000a 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -662,7 +662,9 @@ typedef enum { JMPIFCONTINUE, JMPIFDEFINED, DECLARECONSTVARIABLE, - LINEINFO + LINEINFO, + PUSHRESOURCESTREAM, + PUSHRESOUURCEDIR } Instruction; /** * @brief Base type for bytecode instruction @@ -762,6 +764,13 @@ class EmbedInstruction : public ByteCodeInstruction { size_t Size(); void Write(std::vector& data); }; +class EmbedStreamInstruction : public ByteCodeInstruction { + public: + uint32_t n; + EmbedStreamInstruction(uint32_t n); + size_t Size(); + void Write(std::vector& data); +}; class ClosureInstruction : public ByteCodeInstruction { public: @@ -867,6 +876,7 @@ class CodeGen { void GenNode(std::vector& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI); void GenPop(std::vector& instrs,SyntaxNode n); public: + std::shared_ptr embedFS; std::vector> dependencies; std::vector> tools; TVMVersion version; @@ -874,7 +884,7 @@ class CodeGen { std::string info; std::string icon; void GenRoot(SyntaxNode n); - void Save(std::shared_ptr embedFS,std::shared_ptr output); + void Save(std::shared_ptr output); ~CodeGen(); }; /** @@ -883,10 +893,20 @@ class CodeGen { */ constexpr std::string_view HtmlRootExpression = "htmlRootExpression"; /** - * @brief an intrinsic function that embeads a resource from the filename based on the constant string argument + * @brief an intrinsic function that embeds a resource from the filename based on the constant string argument * */ constexpr std::string_view EmbedExpression = "embedExpression"; +/** + * @brief an intrinsic function that embeds a resource as a stream from the filename based on the constant string argument + * + */ +constexpr std::string_view EmbedStreamExpression = "embedStreamExpression"; +/** + * @brief an intrinsic function that embeds a resource directory from the directory name based on the constant string argument + * + */ +constexpr std::string_view EmbedDirectoryExpression = "embedDirectoryExpression"; /** * @brief Negative operator -EXPR * @@ -2061,6 +2081,8 @@ class GC { ~TObjectStream(); }; + + class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer { public: @@ -2279,6 +2301,8 @@ class GC { bool JumpIfBreak(GC* gc); bool JumpIfContinue(GC* gc); bool LineInfo(GC* gc); + bool PushResourceStream(GC* gc); + bool PushResourceDirectory(GC* gc); public: static InterperterThread* Create(GCList* ls); static InterperterThread* Create(GCList& ls); @@ -2543,4 +2567,39 @@ class GC { std::shared_ptr ToHttpServer(GC* gc,TObject obj); + + class EmbedStream : public Tesses::Framework::Streams::Stream + { + size_t offset; + MarkedTObject file; + uint32_t resource; + + public: + EmbedStream(GC* gc, TFile* file, uint32_t resource); + bool CanRead(); + bool CanSeek(); + bool EndOfStream(); + size_t Read(uint8_t* buff, size_t len); + int64_t GetPosition(); + int64_t GetLength(); + void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence); + }; + + class EmbedDirectory : public Tesses::Framework::Filesystem::VFS + { + MarkedTObject dir; + TObject getEntry(Tesses::Framework::Filesystem::VFSPath path); + public: + EmbedDirectory(GC* gc, TDictionary* dict); + std::shared_ptr OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode); + void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path); + void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path); + bool RegularFileExists(Tesses::Framework::Filesystem::VFSPath path); + bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path); + void DeleteFile(Tesses::Framework::Filesystem::VFSPath path); + Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path); + void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest); + std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path); + Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path); + }; }; diff --git a/src/assembler/asm.cpp b/src/assembler/asm.cpp index 59e7f24..9ed5994 100644 --- a/src/assembler/asm.cpp +++ b/src/assembler/asm.cpp @@ -83,6 +83,18 @@ namespace Tesses::CrossLang { } }; + + class PushResourceStreamChunkInstruction : public ChunkInstruction { + public: + PushResourceStreamChunkInstruction(std::string v) : value(v) + {} + std::string value; + size_t Size() + { + return 5; + } + }; + class LabelChunkInstruction : public ChunkInstruction { public: LabelChunkInstruction(std::string lbl) : lbl(lbl) @@ -285,6 +297,10 @@ namespace Tesses::CrossLang { { instrs.push_back(std::make_shared(LINEINFO)); } + else if(name == "embeddir") + { + instrs.push_back(std::make_shared(PUSHRESOUURCEDIR)); + } else if(name == "pushclosure") { auto closure = std::make_shared(true); @@ -325,6 +341,14 @@ namespace Tesses::CrossLang { instrs.push_back(std::make_shared(str)); } } + else if(name == "embedstrm") + { + if(i < tokens.size() && tokens[i].type == LexTokenType::String) + { + std::string str = tokens[i++].text; + instrs.push_back(std::make_shared(str)); + } + } else if(name == "push") { if(IsSym(".")) @@ -1031,6 +1055,7 @@ namespace Tesses::CrossLang { auto chr = std::dynamic_pointer_cast(item); auto chk = std::dynamic_pointer_cast(item); auto reso = std::dynamic_pointer_cast(item); + auto resos = std::dynamic_pointer_cast(item); auto jmp = std::dynamic_pointer_cast(item); auto scopeend = std::dynamic_pointer_cast(item); if(lbl) @@ -1066,6 +1091,10 @@ namespace Tesses::CrossLang { { chunks[chunkId].second.push_back(std::make_shared(GetResource(reso->value))); } + if(resos) + { + chunks[chunkId].second.push_back(std::make_shared(GetResource(reso->value))); + } if(jmp) { chunks[chunkId].second.push_back(std::make_shared(jmp->instr,jmp->lbl)); diff --git a/src/assembler/disasm.cpp b/src/assembler/disasm.cpp index 758f1da..ff6d249 100644 --- a/src/assembler/disasm.cpp +++ b/src/assembler/disasm.cpp @@ -223,6 +223,7 @@ namespace Tesses::CrossLang { { switch(code[i++]) { + case PUSHRESOURCESTREAM: case PUSHRESOURCE: case PUSHSTRING: case SCOPEENDTIMES: @@ -381,6 +382,9 @@ namespace Tesses::CrossLang { case APPENDDICT: buffer.append("appenddict"); break; + case PUSHRESOUURCEDIR: + buffer.append("embeddir"); + break; case PUSHRESOURCE: { uint32_t clId = (uint32_t)code[i++] << 24; @@ -391,6 +395,16 @@ namespace Tesses::CrossLang { buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true)); } break; + case PUSHRESOURCESTREAM: + { + uint32_t clId = (uint32_t)code[i++] << 24; + clId |= (uint32_t)code[i++] << 16; + clId |= (uint32_t)code[i++] << 8; + clId |= (uint32_t)code[i++]; + buffer.append("embedstrm "); + buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true)); + } + break; case PUSHLONG: { uint64_t number = (uint64_t)code[i++] << 56; diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index 9e2207a..567af5b 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -34,7 +34,7 @@ namespace Tesses::CrossLang } - void CodeGen::Save(std::shared_ptr vfs, std::shared_ptr stream) + void CodeGen::Save(std::shared_ptr stream) { TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); uint8_t buffer[18]; @@ -235,7 +235,7 @@ namespace Tesses::CrossLang { memcpy(buffer,"RESO",4); Write(stream,buffer,4); - WriteInt(stream,reso->GetLength(vfs)); + WriteInt(stream,reso->GetLength(embedFS)); reso->Write(stream); } if(!this->icon.empty()) @@ -354,6 +354,21 @@ namespace Tesses::CrossLang BitConverter::FromUint32BE(buff[0],this->n); instr.insert(instr.end(),buff.begin(),buff.end()); } + EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s) + { + this->n = s; + } + size_t EmbedStreamInstruction::Size() + { + return 5; + } + void EmbedStreamInstruction::Write(std::vector& instr) + { + instr.push_back(PUSHRESOURCESTREAM); + std::array buff; + BitConverter::FromUint32BE(buff[0],this->n); + instr.insert(instr.end(),buff.begin(),buff.end()); + } ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope) { this->n = s; @@ -1365,6 +1380,49 @@ namespace Tesses::CrossLang instructions.push_back(new EmbedInstruction(GetResource(std::make_shared(filename)))); } + else if(adv.nodeName == EmbedStreamExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) + { + std::string filename = std::get(adv.nodes[0]); + instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared(filename)))); + + } + else if(adv.nodeName == EmbedDirectoryExpression && adv.nodes.size() == 1 && std::holds_alternative(adv.nodes[0])) + { + std::string filename = std::get(adv.nodes[0]); + std::function embedDir; + embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void { + instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); + + if(embedFS != nullptr && embedFS->DirectoryExists(path)) + for(auto& item : embedFS->EnumeratePaths(path)) + { + 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)); + } + }; + embedDir(filename); + // + //instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared(filename)))); + instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR)); + } else if(adv.nodeName == HtmlRootExpression) { scope++; diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index 349fa74..057b9d0 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -922,7 +922,7 @@ namespace Tesses::CrossLang auto ms = std::make_shared(true); - gen.Save(nullptr,ms); + gen.Save(ms); ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin); @@ -962,7 +962,27 @@ namespace Tesses::CrossLang if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); EnsureSymbol(")"); node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text}); - } + } + else if(IsIdentifier("embedstrm")) + { + EnsureSymbol("("); + if(i >= tokens.size()) throw std::out_of_range("End of file"); + auto embed = tokens[i]; + i++; + if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); + EnsureSymbol(")"); + node = AdvancedSyntaxNode::Create(EmbedStreamExpression, true,{embed.text}); + } + else if(IsIdentifier("embeddir")) + { + EnsureSymbol("("); + if(i >= tokens.size()) throw std::out_of_range("End of file"); + auto embed = tokens[i]; + i++; + if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\""); + EnsureSymbol(")"); + node = AdvancedSyntaxNode::Create(EmbedDirectoryExpression, true,{embed.text}); + } else if(tokens[i].type == LexTokenType::Identifier) { auto token=tokens[i]; diff --git a/src/crosslangcompiler.cpp b/src/crosslangcompiler.cpp index 2e8fa46..fbd92f4 100644 --- a/src/crosslangcompiler.cpp +++ b/src/crosslangcompiler.cpp @@ -256,6 +256,10 @@ int main(int argc, char** argv) Parser parser(tokens,gc,env); parser.debug = debug; CodeGen gen; + + auto sfs = std::make_shared(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string())); + gen.embedFS = sfs; + gen.GenRoot(parser.ParseRoot()); gen.name = name; gen.version = version; @@ -275,9 +279,7 @@ int main(int argc, char** argv) { auto strm = std::make_shared(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb"); - auto sfs = std::make_shared(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string())); - - gen.Save(sfs,strm); + gen.Save(strm); } if(gc != nullptr) { diff --git a/src/crosslanginterperter.cpp b/src/crosslanginterperter.cpp index bea43c2..a8aeb7d 100644 --- a/src/crosslanginterperter.cpp +++ b/src/crosslanginterperter.cpp @@ -24,13 +24,14 @@ int main(int argc, char** argv) Parser parser(tokens); CodeGen gen; + + auto sfs = std::make_shared(LocalFS,VFSPath(".")); + gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); std::vector data; { - auto sfs = std::make_shared(LocalFS,VFSPath(".")); - auto strm2 = std::make_shared(true); - gen.Save(sfs,strm2); + gen.Save(strm2); { @@ -78,11 +79,12 @@ int main(int argc, char** argv) Parser parser(tokens); CodeGen gen; + + auto sfs = std::make_shared(LocalFS,VFSPath(".")); + gen.embedFS = sfs; gen.GenRoot(parser.ParseRoot()); - auto sfs = std::make_shared(LocalFS,VFSPath(".")); - - gen.Save(sfs, strm2); + gen.Save(strm2); } else if(source == "exit") @@ -98,11 +100,13 @@ int main(int argc, char** argv) Parser parser(tokens); CodeGen gen; + + auto sfs = std::make_shared(LocalFS,VFSPath(".")); + gen.embedFS = sfs; + gen.GenRoot(parser.ParseRoot()); - auto sfs = std::make_shared(LocalFS,VFSPath(".")); - - gen.Save(sfs,strm2); + gen.Save(strm2); } { diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index 9789ec9..269f904 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -264,6 +264,7 @@ namespace Tesses::CrossLang parser.debug = debug; SyntaxNode n = parser.ParseRoot(); CodeGen gen; + gen.embedFS = vfs; gen.GenRoot(n); gen.dependencies = dependencies; gen.tools = tools; @@ -275,7 +276,7 @@ namespace Tesses::CrossLang std::shared_ptr stream; if(GetObject(_out, stream)) { - gen.Save(vfs, stream); + gen.Save(stream); } diff --git a/src/types/embed.cpp b/src/types/embed.cpp new file mode 100644 index 0000000..2776a4f --- /dev/null +++ b/src/types/embed.cpp @@ -0,0 +1,228 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { + + EmbedStream::EmbedStream(GC* gc, TFile* file, uint32_t resource) + { + this->offset = 0; + this->resource = resource; + this->file = CreateMarkedTObject(gc,file); + } + bool EmbedStream::CanRead() + { + TFile* file; + if(GetObjectHeap(this->file->GetObject(),file)) + { + if(this->resource >= file->resources.size()) return false; + if(this->offset >= file->resources[this->resource].size()) return false; + return true; + } + return false; + } + bool EmbedStream::CanSeek() + { + return true; + } + bool EmbedStream::EndOfStream() + { + return !CanRead(); + } + size_t EmbedStream::Read(uint8_t* buff, size_t len) + { + TFile* file; + + if(GetObjectHeap(this->file->GetObject(),file)) + { + if(this->resource >= file->resources.size()) return 0; + auto flen = file->resources[this->resource].size(); + if(this->offset >= flen) return 0; + + len = std::min(len, std::min( + flen, + flen - this->offset + )); + + memcpy(buff,file->resources[this->resource].data() + this->offset,len); + this->offset += len; + return len; + } + return 0; + } + int64_t EmbedStream::GetPosition() + { + return (int64_t)this->offset; + } + int64_t EmbedStream::GetLength() + { + TFile* file; + + if(GetObjectHeap(this->file->GetObject(),file)) + { + if(this->resource >= file->resources.size()) return 0; + return (int64_t)file->resources[this->resource].size(); + } + return 0; + } + void EmbedStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence) + { + switch(whence) + { + case Tesses::Framework::Streams::SeekOrigin::Begin: + this->offset = (uint32_t)pos; + break; + case Tesses::Framework::Streams::SeekOrigin::Current: + { + int64_t cur = this->offset; + cur += pos; + this->offset = (uint32_t)cur; + } + break; + case Tesses::Framework::Streams::SeekOrigin::End: + { + TFile* file; + + if(GetObjectHeap(this->file->GetObject(),file)) + { + if(this->resource >= file->resources.size()) return; + int64_t cur = (int64_t)file->resources[this->resource].size(); + cur += pos; + this->offset = (uint32_t)cur; + } + break; + } + } + } + TObject EmbedDirectory::getEntry(Tesses::Framework::Filesystem::VFSPath path) + { + path = path.CollapseRelativeParents(); + auto curEntry = this->dir->GetObject(); + for(auto item : path.path) + { + TDictionary* dict; + if(GetObjectHeap(curEntry,dict) && dict->HasValue(item)) + { + curEntry = dict->GetValue(item); + continue; //don't want to return undefined now do we + } + return Undefined(); + } + return curEntry; + } + + std::shared_ptr EmbedDirectory::OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode) + { + if(mode != "r" && mode != "rb") return nullptr; + + auto ent = getEntry(path); + TCallable* call; + if(GetObjectHeap(ent,call)) + { + GCList ls(this->dir->GetGC()); + auto fileO = call->Call(ls,{}); + std::shared_ptr strm; + if(GetObject(fileO,strm)) return strm; + } + return nullptr; + } + bool EmbedDirectory::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path) + { + auto ent = getEntry(path); + TCallable* call; + return GetObjectHeap(ent,call); + } + bool EmbedDirectory::DirectoryExists(Tesses::Framework::Filesystem::VFSPath path) + { + auto ent = getEntry(path); + TDictionary* dict; + return GetObjectHeap(ent,dict); + } + + class DICT_DIRENUM + { + GCList ls; + TDictionary* dict; + std::map::iterator current; + bool hasStarted = false; + public: + std::string GetCurrent() + { + return this->current->first; + } + DICT_DIRENUM(GC* gc, TDictionary* dict) : ls(gc), dict(dict) + { + ls.Add(dict); + } + bool MoveNext() + { + if(!this->hasStarted) + { + this->hasStarted=true; + this->current = this->dict->items.begin(); + return !this->dict->items.empty(); + } + else + { + this->current++; + return this->current != this->dict->items.end(); + } + } + + }; + + + Tesses::Framework::Filesystem::VFSPathEnumerator EmbedDirectory::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path) + { + auto ent = getEntry(path); + TDictionary* dict; + if(GetObjectHeap(ent,dict)) + { + DICT_DIRENUM* dir2 = new DICT_DIRENUM(this->dir->GetGC(), dict); + + Tesses::Framework::Filesystem::VFSPathEnumerator er( + [dir2,path](Tesses::Framework::Filesystem::VFSPath& path2)->bool { + if(dir2->MoveNext()) + { + path2 = path / dir2->GetCurrent(); + return true; + } + return false; + }, + [dir2]()->void { + delete dir2; + } + ); + + return er; + } + return Tesses::Framework::Filesystem::VFSPathEnumerator(); + } + + EmbedDirectory::EmbedDirectory(GC* gc, TDictionary* dict) + { + this->dir = CreateMarkedTObject(gc, dict); + } + void EmbedDirectory::CreateDirectory(Tesses::Framework::Filesystem::VFSPath path) + { + //DO NOTHING + } + void EmbedDirectory::DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path) + { + + } + void EmbedDirectory::DeleteFile(Tesses::Framework::Filesystem::VFSPath path) + { + + } + void EmbedDirectory::MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest) + { + + } + std::string EmbedDirectory::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path) + { + return path.ToString(); + } + Tesses::Framework::Filesystem::VFSPath EmbedDirectory::SystemToVFSPath(std::string path) + { + return path; + } +} \ No newline at end of file diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index e84d44c..3d5a669 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -123,7 +123,7 @@ namespace Tesses::CrossLang { CodeGen gen; gen.GenRoot(n); auto ms = std::make_shared(true); - gen.Save(nullptr, ms); + gen.Save(ms); ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin); TFile* f = TFile::Create(ls); f->Load(ls.GetGC(),ms); diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 6366f65..a7e19d3 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -6971,7 +6971,35 @@ namespace Tesses::CrossLang { } return false; } - + bool InterperterThread::PushResourceStream(GC* gc) + { + std::vector& cse=this->call_stack_entries; + if(!cse.empty()) + { + auto stk = cse.back(); + std::vector& code = stk->callable->closure->code; + if(stk->ip + 4 <= code.size()) + { + uint32_t n=BitConverter::ToUint32BE(code[stk->ip]); + if(n >= stk->callable->file->resources.size()) + throw VMException("Can't read resource."); + stk->ip = stk->ip + 4; + + gc->BarrierBegin(); + GCList ls(gc); + // TByteArray* arr = TByteArray::Create(ls); +// arr->data = stk->callable->file->resources[n]; + stk->Push(gc, std::make_shared(gc,stk->callable->file,n)); + + gc->BarrierEnd(); + } + else + { + throw VMException("Can't read chunk."); + } + } + return false; + } bool InterperterThread::PushResource(GC* gc) { @@ -7016,6 +7044,21 @@ namespace Tesses::CrossLang { } return false; } + bool InterperterThread::PushResourceDirectory(GC* gc) + { + std::vector& cse=this->call_stack_entries; + GCList ls(gc); + auto _res2 = cse.back()->Pop(ls); + TDictionary* dict; + if(GetObjectHeap(_res2, dict)) + { + cse.back()->Push(gc, std::make_shared(gc,dict)); + } + else { + cse.back()->Push(gc, Undefined()); + } + return false; + } bool InterperterThread::JumpIfDefined(GC* gc) { diff --git a/src/vm/vm_opcode_table.h b/src/vm/vm_opcode_table.h index f21914e..2bc176d 100644 --- a/src/vm/vm_opcode_table.h +++ b/src/vm/vm_opcode_table.h @@ -64,9 +64,9 @@ static opcode opcodes[256]={ &InterperterThread::JumpIfContinue, &InterperterThread::JumpIfDefined, &InterperterThread::DeclareConstVariable, - &InterperterThread::LineInfo, - &InterperterThread::Illegal, - &InterperterThread::Illegal, + &InterperterThread::LineInfo, + &InterperterThread::PushResourceStream, + &InterperterThread::PushResourceDirectory, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal,