mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-18 14:17:03 +00:00
Compare commits
2 Commits
bbf122a7eb
...
c37b26af14
| Author | SHA1 | Date | |
|---|---|---|---|
| c37b26af14 | |||
| deb492b8c4 |
@@ -154,6 +154,7 @@ src/runtime_methods/path.cpp
|
|||||||
src/runtime_methods/env.cpp
|
src/runtime_methods/env.cpp
|
||||||
src/runtime_methods/process.cpp
|
src/runtime_methods/process.cpp
|
||||||
src/runtime_methods/helpers.cpp
|
src/runtime_methods/helpers.cpp
|
||||||
|
src/types/embed.cpp
|
||||||
src/types/async.cpp
|
src/types/async.cpp
|
||||||
src/types/associativearray.cpp
|
src/types/associativearray.cpp
|
||||||
src/types/any.cpp
|
src/types/any.cpp
|
||||||
@@ -173,6 +174,7 @@ src/vm/filereader.cpp
|
|||||||
src/vm/gc.cpp
|
src/vm/gc.cpp
|
||||||
src/vm/gclist.cpp
|
src/vm/gclist.cpp
|
||||||
src/vm/vm.cpp
|
src/vm/vm.cpp
|
||||||
|
src/vm/exception.cpp
|
||||||
src/archive.cpp
|
src/archive.cpp
|
||||||
src/markedtobject.cpp
|
src/markedtobject.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -661,7 +661,10 @@ typedef enum {
|
|||||||
JMPIFBREAK,
|
JMPIFBREAK,
|
||||||
JMPIFCONTINUE,
|
JMPIFCONTINUE,
|
||||||
JMPIFDEFINED,
|
JMPIFDEFINED,
|
||||||
DECLARECONSTVARIABLE
|
DECLARECONSTVARIABLE,
|
||||||
|
LINEINFO,
|
||||||
|
PUSHRESOURCESTREAM,
|
||||||
|
PUSHRESOUURCEDIR
|
||||||
} Instruction;
|
} Instruction;
|
||||||
/**
|
/**
|
||||||
* @brief Base type for bytecode instruction
|
* @brief Base type for bytecode instruction
|
||||||
@@ -761,6 +764,13 @@ class EmbedInstruction : public ByteCodeInstruction {
|
|||||||
size_t Size();
|
size_t Size();
|
||||||
void Write(std::vector<uint8_t>& data);
|
void Write(std::vector<uint8_t>& data);
|
||||||
};
|
};
|
||||||
|
class EmbedStreamInstruction : public ByteCodeInstruction {
|
||||||
|
public:
|
||||||
|
uint32_t n;
|
||||||
|
EmbedStreamInstruction(uint32_t n);
|
||||||
|
size_t Size();
|
||||||
|
void Write(std::vector<uint8_t>& data);
|
||||||
|
};
|
||||||
|
|
||||||
class ClosureInstruction : public ByteCodeInstruction {
|
class ClosureInstruction : public ByteCodeInstruction {
|
||||||
public:
|
public:
|
||||||
@@ -866,6 +876,7 @@ class CodeGen {
|
|||||||
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
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);
|
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
||||||
public:
|
public:
|
||||||
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS;
|
||||||
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
||||||
std::vector<std::pair<std::string, TVMVersion>> tools;
|
std::vector<std::pair<std::string, TVMVersion>> tools;
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
@@ -873,7 +884,7 @@ class CodeGen {
|
|||||||
std::string info;
|
std::string info;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
void GenRoot(SyntaxNode n);
|
void GenRoot(SyntaxNode n);
|
||||||
void Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS,std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
void Save(std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
||||||
~CodeGen();
|
~CodeGen();
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -882,10 +893,20 @@ class CodeGen {
|
|||||||
*/
|
*/
|
||||||
constexpr std::string_view HtmlRootExpression = "htmlRootExpression";
|
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";
|
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
|
* @brief Negative operator -EXPR
|
||||||
*
|
*
|
||||||
@@ -1239,6 +1260,10 @@ constexpr std::string_view AwaitExpression = "awaitExpression";
|
|||||||
* @brief ?? operator
|
* @brief ?? operator
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression";
|
constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression";
|
||||||
|
/**
|
||||||
|
* @brief For debugging (store line info and filename)
|
||||||
|
*/
|
||||||
|
constexpr std::string_view LineNode="lineNode";
|
||||||
/**
|
/**
|
||||||
* @brief Advanced AST node
|
* @brief Advanced AST node
|
||||||
*
|
*
|
||||||
@@ -1315,8 +1340,11 @@ class Parser {
|
|||||||
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
||||||
GC* gc;
|
GC* gc;
|
||||||
TRootEnvironment* env;
|
TRootEnvironment* env;
|
||||||
|
int lastLine=-1;
|
||||||
|
std::string lastFile="";
|
||||||
|
bool CanEmit(LexTokenLineInfo& token);
|
||||||
public:
|
public:
|
||||||
|
bool debug=true;
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Parser object
|
* @brief Construct a new Parser object
|
||||||
*
|
*
|
||||||
@@ -1455,6 +1483,7 @@ class GC {
|
|||||||
TFile* file;
|
TFile* file;
|
||||||
std::vector<uint8_t> code;
|
std::vector<uint8_t> code;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::optional<std::string> name;
|
||||||
void Mark();
|
void Mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1642,6 +1671,7 @@ class GC {
|
|||||||
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args);
|
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
|
TObject CallMethodWithFatalError(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1655,9 +1685,12 @@ class GC {
|
|||||||
TObject tag;
|
TObject tag;
|
||||||
std::string documentation;
|
std::string documentation;
|
||||||
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
|
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
|
||||||
|
TObject CallWithFatalError(GCList& ls, std::vector<TObject> args);
|
||||||
virtual void Mark();
|
virtual void Mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ThrowFatalError(std::exception& ex);
|
||||||
|
|
||||||
void ThrowConstError(std::string key);
|
void ThrowConstError(std::string key);
|
||||||
|
|
||||||
class TEnvironment : public THeapObject {
|
class TEnvironment : public THeapObject {
|
||||||
@@ -1694,7 +1727,7 @@ class GC {
|
|||||||
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
||||||
TObject CallFunction(GCList& ls, std::string key, std::vector<TObject> args);
|
TObject CallFunction(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
|
TObject CallFunctionWithFatalError(GCList& ls, std::string key, std::vector<TObject> args);
|
||||||
};
|
};
|
||||||
class TClassEnvironment;
|
class TClassEnvironment;
|
||||||
class TClassObject : public THeapObject
|
class TClassObject : public THeapObject
|
||||||
@@ -2048,6 +2081,8 @@ class GC {
|
|||||||
~TObjectStream();
|
~TObjectStream();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -2134,18 +2169,21 @@ class GC {
|
|||||||
|
|
||||||
~TDynamicDictionary();
|
~TDynamicDictionary();
|
||||||
};
|
};
|
||||||
|
class InterperterThread;
|
||||||
|
|
||||||
class CallStackEntry : public THeapObject
|
class CallStackEntry : public THeapObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static CallStackEntry* Create(GCList* ls);
|
static CallStackEntry* Create(GCList* ls);
|
||||||
static CallStackEntry* Create(GCList& ls);
|
static CallStackEntry* Create(GCList& ls);
|
||||||
|
InterperterThread* thread;
|
||||||
std::vector<TObject> stack;
|
std::vector<TObject> stack;
|
||||||
TEnvironment* env;
|
TEnvironment* env;
|
||||||
TClosure* callable;
|
TClosure* callable;
|
||||||
uint32_t ip;
|
uint32_t ip;
|
||||||
uint32_t scopes;
|
uint32_t scopes;
|
||||||
|
int64_t srcline;
|
||||||
|
std::string srcfile;
|
||||||
bool mustReturn;
|
bool mustReturn;
|
||||||
|
|
||||||
void Mark();
|
void Mark();
|
||||||
@@ -2262,6 +2300,9 @@ class GC {
|
|||||||
bool PushContinue(GC* gc);
|
bool PushContinue(GC* gc);
|
||||||
bool JumpIfBreak(GC* gc);
|
bool JumpIfBreak(GC* gc);
|
||||||
bool JumpIfContinue(GC* gc);
|
bool JumpIfContinue(GC* gc);
|
||||||
|
bool LineInfo(GC* gc);
|
||||||
|
bool PushResourceStream(GC* gc);
|
||||||
|
bool PushResourceDirectory(GC* gc);
|
||||||
public:
|
public:
|
||||||
static InterperterThread* Create(GCList* ls);
|
static InterperterThread* Create(GCList* ls);
|
||||||
static InterperterThread* Create(GCList& ls);
|
static InterperterThread* Create(GCList& ls);
|
||||||
@@ -2387,22 +2428,30 @@ class GC {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
TObject exception;
|
TObject exception;
|
||||||
|
std::vector<CallStackEntry*> stack_trace;
|
||||||
|
|
||||||
|
|
||||||
VMByteCodeException()
|
VMByteCodeException()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VMByteCodeException(GC* gc,TObject obj)
|
VMByteCodeException(GC* gc,TObject obj, CallStackEntry* ent)
|
||||||
{
|
{
|
||||||
gcList = std::make_shared<GCList>(gc);
|
gcList = std::make_shared<GCList>(gc);
|
||||||
gcList.get()->Add(obj);
|
gcList->Add(obj);
|
||||||
|
if(ent != nullptr && ent->thread != nullptr)
|
||||||
|
{
|
||||||
|
this->stack_trace = ent->thread->call_stack_entries;
|
||||||
|
for(auto item : this->stack_trace)
|
||||||
|
gcList->Add(item);
|
||||||
|
}
|
||||||
this->exception = obj;
|
this->exception = obj;
|
||||||
UpdateError();
|
UpdateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateError()
|
void UpdateError()
|
||||||
{
|
{
|
||||||
lastErrorText = ToString(gcList.get()->GetGC(),exception);
|
lastErrorText = ToString(gcList->GetGC(),exception);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2410,14 +2459,19 @@ class GC {
|
|||||||
{
|
{
|
||||||
return lastErrorText.c_str();
|
return lastErrorText.c_str();
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<GCList> GetGCList() {
|
||||||
|
return this->gcList;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyntaxException : public std::exception
|
class SyntaxException : public std::exception
|
||||||
{
|
{
|
||||||
std::string msg={};
|
std::string msg={};
|
||||||
|
LexTokenLineInfo line;
|
||||||
|
std::string message;
|
||||||
public:
|
public:
|
||||||
SyntaxException(LexTokenLineInfo lineInfo, std::string message)
|
SyntaxException(LexTokenLineInfo lineInfo, std::string message) : line(lineInfo), message(message)
|
||||||
{
|
{
|
||||||
msg.append("in file: ");
|
msg.append("in file: ");
|
||||||
msg.append(lineInfo.filename);
|
msg.append(lineInfo.filename);
|
||||||
@@ -2434,6 +2488,9 @@ class GC {
|
|||||||
{
|
{
|
||||||
return msg.c_str();
|
return msg.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Message() { return message;}
|
||||||
|
LexTokenLineInfo LineInfo() { return line;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2510,4 +2567,39 @@ class GC {
|
|||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Tesses::Framework::Http::IHttpServer> ToHttpServer(GC* gc,TObject obj);
|
std::shared_ptr<Tesses::Framework::Http::IHttpServer> 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<Tesses::Framework::Streams::Stream> 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);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 {
|
class LabelChunkInstruction : public ChunkInstruction {
|
||||||
public:
|
public:
|
||||||
LabelChunkInstruction(std::string lbl) : lbl(lbl)
|
LabelChunkInstruction(std::string lbl) : lbl(lbl)
|
||||||
@@ -281,6 +293,14 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(NOP));
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(NOP));
|
||||||
}
|
}
|
||||||
|
else if(name == "lineinfo")
|
||||||
|
{
|
||||||
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(LINEINFO));
|
||||||
|
}
|
||||||
|
else if(name == "embeddir")
|
||||||
|
{
|
||||||
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(PUSHRESOUURCEDIR));
|
||||||
|
}
|
||||||
else if(name == "pushclosure")
|
else if(name == "pushclosure")
|
||||||
{
|
{
|
||||||
auto closure = std::make_shared<ClosureChunkInstruction>(true);
|
auto closure = std::make_shared<ClosureChunkInstruction>(true);
|
||||||
@@ -321,6 +341,14 @@ namespace Tesses::CrossLang {
|
|||||||
instrs.push_back(std::make_shared<PushResourceChunkInstruction>(str));
|
instrs.push_back(std::make_shared<PushResourceChunkInstruction>(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<PushResourceStreamChunkInstruction>(str));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(name == "push")
|
else if(name == "push")
|
||||||
{
|
{
|
||||||
if(IsSym("."))
|
if(IsSym("."))
|
||||||
@@ -1027,6 +1055,7 @@ namespace Tesses::CrossLang {
|
|||||||
auto chr = std::dynamic_pointer_cast<PushCharChunkInstruction>(item);
|
auto chr = std::dynamic_pointer_cast<PushCharChunkInstruction>(item);
|
||||||
auto chk = std::dynamic_pointer_cast<ClosureChunkInstruction>(item);
|
auto chk = std::dynamic_pointer_cast<ClosureChunkInstruction>(item);
|
||||||
auto reso = std::dynamic_pointer_cast<PushResourceChunkInstruction>(item);
|
auto reso = std::dynamic_pointer_cast<PushResourceChunkInstruction>(item);
|
||||||
|
auto resos = std::dynamic_pointer_cast<PushResourceStreamChunkInstruction>(item);
|
||||||
auto jmp = std::dynamic_pointer_cast<JumpStyleChunkInstruction>(item);
|
auto jmp = std::dynamic_pointer_cast<JumpStyleChunkInstruction>(item);
|
||||||
auto scopeend = std::dynamic_pointer_cast<ScopeEndTimesChunkInstruction>(item);
|
auto scopeend = std::dynamic_pointer_cast<ScopeEndTimesChunkInstruction>(item);
|
||||||
if(lbl)
|
if(lbl)
|
||||||
@@ -1062,6 +1091,10 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
chunks[chunkId].second.push_back(std::make_shared<EmbedInstruction>(GetResource(reso->value)));
|
chunks[chunkId].second.push_back(std::make_shared<EmbedInstruction>(GetResource(reso->value)));
|
||||||
}
|
}
|
||||||
|
if(resos)
|
||||||
|
{
|
||||||
|
chunks[chunkId].second.push_back(std::make_shared<EmbedStreamInstruction>(GetResource(reso->value)));
|
||||||
|
}
|
||||||
if(jmp)
|
if(jmp)
|
||||||
{
|
{
|
||||||
chunks[chunkId].second.push_back(std::make_shared<JumpStyleInstruction>(jmp->instr,jmp->lbl));
|
chunks[chunkId].second.push_back(std::make_shared<JumpStyleInstruction>(jmp->instr,jmp->lbl));
|
||||||
|
|||||||
@@ -223,6 +223,7 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
switch(code[i++])
|
switch(code[i++])
|
||||||
{
|
{
|
||||||
|
case PUSHRESOURCESTREAM:
|
||||||
case PUSHRESOURCE:
|
case PUSHRESOURCE:
|
||||||
case PUSHSTRING:
|
case PUSHSTRING:
|
||||||
case SCOPEENDTIMES:
|
case SCOPEENDTIMES:
|
||||||
@@ -381,6 +382,9 @@ namespace Tesses::CrossLang {
|
|||||||
case APPENDDICT:
|
case APPENDDICT:
|
||||||
buffer.append("appenddict");
|
buffer.append("appenddict");
|
||||||
break;
|
break;
|
||||||
|
case PUSHRESOUURCEDIR:
|
||||||
|
buffer.append("embeddir");
|
||||||
|
break;
|
||||||
case PUSHRESOURCE:
|
case PUSHRESOURCE:
|
||||||
{
|
{
|
||||||
uint32_t clId = (uint32_t)code[i++] << 24;
|
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));
|
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case PUSHLONG:
|
||||||
{
|
{
|
||||||
uint64_t number = (uint64_t)code[i++] << 56;
|
uint64_t number = (uint64_t)code[i++] << 56;
|
||||||
@@ -571,6 +585,9 @@ namespace Tesses::CrossLang {
|
|||||||
case BREAKPOINT:
|
case BREAKPOINT:
|
||||||
buffer.append("breakpoint");
|
buffer.append("breakpoint");
|
||||||
break;
|
break;
|
||||||
|
case LINEINFO:
|
||||||
|
buffer.append("lineinfo");
|
||||||
|
break;
|
||||||
case PUSHBREAK:
|
case PUSHBREAK:
|
||||||
buffer.append("push break");
|
buffer.append("push break");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||||
{
|
{
|
||||||
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||||
uint8_t buffer[18];
|
uint8_t buffer[18];
|
||||||
@@ -235,7 +235,7 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
memcpy(buffer,"RESO",4);
|
memcpy(buffer,"RESO",4);
|
||||||
Write(stream,buffer,4);
|
Write(stream,buffer,4);
|
||||||
WriteInt(stream,reso->GetLength(vfs));
|
WriteInt(stream,reso->GetLength(embedFS));
|
||||||
reso->Write(stream);
|
reso->Write(stream);
|
||||||
}
|
}
|
||||||
if(!this->icon.empty())
|
if(!this->icon.empty())
|
||||||
@@ -354,6 +354,21 @@ namespace Tesses::CrossLang
|
|||||||
BitConverter::FromUint32BE(buff[0],this->n);
|
BitConverter::FromUint32BE(buff[0],this->n);
|
||||||
instr.insert(instr.end(),buff.begin(),buff.end());
|
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<uint8_t>& instr)
|
||||||
|
{
|
||||||
|
instr.push_back(PUSHRESOURCESTREAM);
|
||||||
|
std::array<uint8_t,4> buff;
|
||||||
|
BitConverter::FromUint32BE(buff[0],this->n);
|
||||||
|
instr.insert(instr.end(),buff.begin(),buff.end());
|
||||||
|
}
|
||||||
ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope)
|
ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope)
|
||||||
{
|
{
|
||||||
this->n = s;
|
this->n = s;
|
||||||
@@ -522,7 +537,14 @@ namespace Tesses::CrossLang
|
|||||||
TWO_EXPR(NotEqualsExpression, NEQ)
|
TWO_EXPR(NotEqualsExpression, NEQ)
|
||||||
TWO_EXPR(EqualsExpression, EQ)
|
TWO_EXPR(EqualsExpression, EQ)
|
||||||
TWO_EXPR(XOrExpression, XOR)
|
TWO_EXPR(XOrExpression, XOR)
|
||||||
if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2)
|
if(adv.nodeName == LineNode && adv.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||||
|
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||||
|
instructions.push_back(new SimpleInstruction(LINEINFO));
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2)
|
||||||
{
|
{
|
||||||
uint32_t ifId = NewId();
|
uint32_t ifId = NewId();
|
||||||
std::string ifIdTrue = "__compGenTrue";
|
std::string ifIdTrue = "__compGenTrue";
|
||||||
@@ -1358,6 +1380,49 @@ namespace Tesses::CrossLang
|
|||||||
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
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]);
|
||||||
|
instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == EmbedDirectoryExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
|
{
|
||||||
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||||
|
std::function<void(Tesses::Framework::Filesystem::VFSPath path)> 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<ResourceFile>(filename))));
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR));
|
||||||
|
}
|
||||||
else if(adv.nodeName == HtmlRootExpression)
|
else if(adv.nodeName == HtmlRootExpression)
|
||||||
{
|
{
|
||||||
scope++;
|
scope++;
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
|
|
||||||
gen.Save(nullptr,ms);
|
gen.Save(ms);
|
||||||
|
|
||||||
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
|
|
||||||
@@ -963,6 +963,26 @@ namespace Tesses::CrossLang
|
|||||||
EnsureSymbol(")");
|
EnsureSymbol(")");
|
||||||
node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text});
|
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)
|
else if(tokens[i].type == LexTokenType::Identifier)
|
||||||
{
|
{
|
||||||
auto token=tokens[i];
|
auto token=tokens[i];
|
||||||
@@ -1304,6 +1324,15 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
bool Parser::CanEmit(LexTokenLineInfo& ifo)
|
||||||
|
{
|
||||||
|
if(!this->debug) return false;
|
||||||
|
bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile;
|
||||||
|
this->lastFile = ifo.filename;
|
||||||
|
this->lastLine = ifo.line;
|
||||||
|
|
||||||
|
return !same;
|
||||||
|
}
|
||||||
SyntaxNode Parser::ParseNode(bool isRoot)
|
SyntaxNode Parser::ParseNode(bool isRoot)
|
||||||
{
|
{
|
||||||
std::string documentation="";
|
std::string documentation="";
|
||||||
@@ -1324,6 +1353,8 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
while(i < tokens.size() && (isRoot || !IsSymbol("}",false)))
|
while(i < tokens.size() && (isRoot || !IsSymbol("}",false)))
|
||||||
{
|
{
|
||||||
|
auto token = tokens[i];
|
||||||
|
if(CanEmit(token.lineInfo)) aSN.nodes.push_back(AdvancedSyntaxNode::Create(LineNode,false, {(int64_t)tokens[i].lineInfo.line,tokens[i].lineInfo.filename}));
|
||||||
aSN.nodes.push_back(ParseNode());
|
aSN.nodes.push_back(ParseNode());
|
||||||
IsSymbol(";");
|
IsSymbol(";");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ void Help(const char* filename)
|
|||||||
printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n");
|
printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n");
|
||||||
printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n");
|
printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n");
|
||||||
printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n");
|
printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n");
|
||||||
|
printf(" -D: enable debug)\n");
|
||||||
printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n");
|
printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n");
|
||||||
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
||||||
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
||||||
@@ -46,7 +47,7 @@ int main(int argc, char** argv)
|
|||||||
std::string icon="";
|
std::string icon="";
|
||||||
std::string comptime="none";
|
std::string comptime="none";
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
|
bool debug=false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
Help(argv[0]);
|
Help(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(strcmp(argv[i], "-o") == 0)
|
else if(strcmp(argv[i], "-o") == 0)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
@@ -187,6 +189,10 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[i],"-D") == 0)
|
||||||
|
{
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
source.push_back(argv[i]);
|
source.push_back(argv[i]);
|
||||||
}
|
}
|
||||||
@@ -202,7 +208,7 @@ int main(int argc, char** argv)
|
|||||||
for(auto src : source)
|
for(auto src : source)
|
||||||
{
|
{
|
||||||
std::ifstream strm(src,std::ios_base::in|std::ios_base::binary);
|
std::ifstream strm(src,std::ios_base::in|std::ios_base::binary);
|
||||||
int res = Lex(argv[1],strm,tokens);
|
int res = Lex(std::filesystem::absolute(src).string(),strm,tokens);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +254,12 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Parser parser(tokens,gc,env);
|
Parser parser(tokens,gc,env);
|
||||||
|
parser.debug = debug;
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
||||||
|
gen.embedFS = sfs;
|
||||||
|
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
gen.name = name;
|
gen.name = name;
|
||||||
gen.version = version;
|
gen.version = version;
|
||||||
@@ -269,9 +279,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
auto strm = std::make_shared<Tesses::Framework::Streams::FileStream>(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb");
|
auto strm = std::make_shared<Tesses::Framework::Streams::FileStream>(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb");
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
gen.Save(strm);
|
||||||
|
|
||||||
gen.Save(sfs,strm);
|
|
||||||
}
|
}
|
||||||
if(gc != nullptr)
|
if(gc != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
|
||||||
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
{
|
{
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
|
||||||
|
|
||||||
auto strm2 = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto strm2 = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
gen.Save(sfs,strm2);
|
gen.Save(strm2);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -49,7 +50,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
@@ -78,11 +79,12 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
|
gen.GenRoot(parser.ParseRoot());
|
||||||
|
|
||||||
gen.Save(sfs, strm2);
|
gen.Save(strm2);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(source == "exit")
|
else if(source == "exit")
|
||||||
@@ -98,11 +100,13 @@ int main(int argc, char** argv)
|
|||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
|
||||||
|
|
||||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||||
|
gen.embedFS = sfs;
|
||||||
|
|
||||||
gen.Save(sfs,strm2);
|
gen.GenRoot(parser.ParseRoot());
|
||||||
|
|
||||||
|
gen.Save(strm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ int main(int argc, char** argv)
|
|||||||
args2->Add(item);
|
args2->Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = env->CallFunction(ls, "WebAppMain", {args2});
|
auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2});
|
||||||
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,res);
|
auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,res);
|
||||||
if(svr2 == nullptr) return 1;
|
if(svr2 == nullptr) return 1;
|
||||||
Tesses::Framework::Http::HttpServer svr(port,svr2);
|
Tesses::Framework::Http::HttpServer svr(port,svr2);
|
||||||
@@ -58,7 +58,7 @@ int main(int argc, char** argv)
|
|||||||
for(int arg=1;arg<argc;arg++)
|
for(int arg=1;arg<argc;arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
auto res = env->CallFunction(ls,"main",{args});
|
auto res = env->CallFunctionWithFatalError(ls,"main",{args});
|
||||||
int64_t iresult;
|
int64_t iresult;
|
||||||
if(GetObject(res,iresult))
|
if(GetObject(res,iresult))
|
||||||
return (int)iresult;
|
return (int)iresult;
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ namespace Tesses::CrossLang
|
|||||||
std::vector<std::pair<std::string,TVMVersion>> tools;
|
std::vector<std::pair<std::string,TVMVersion>> tools;
|
||||||
std::string info;
|
std::string info;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
|
bool debug=false;
|
||||||
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
|
||||||
|
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
@@ -152,6 +153,7 @@ namespace Tesses::CrossLang
|
|||||||
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
||||||
|
|
||||||
TObject _out = dict->GetValue("Output");
|
TObject _out = dict->GetValue("Output");
|
||||||
|
TObject _dbg = dict->GetValue("Debug");
|
||||||
TList* _toolList;
|
TList* _toolList;
|
||||||
TList* _depList; TList* srcLst;
|
TList* _depList; TList* srcLst;
|
||||||
TRootEnvironment* comptimeEnv=nullptr;
|
TRootEnvironment* comptimeEnv=nullptr;
|
||||||
@@ -160,6 +162,7 @@ namespace Tesses::CrossLang
|
|||||||
GetObject<std::string>(_icon,icon);
|
GetObject<std::string>(_icon,icon);
|
||||||
GetObject(_resourceFileSystem, vfs);
|
GetObject(_resourceFileSystem, vfs);
|
||||||
GetObjectHeap(_comptime,comptimeEnv);
|
GetObjectHeap(_comptime,comptimeEnv);
|
||||||
|
GetObject(_dbg,debug);
|
||||||
std::string v2;
|
std::string v2;
|
||||||
if(GetObject<std::string>(_version,v2))
|
if(GetObject<std::string>(_version,v2))
|
||||||
TVMVersion::TryParse(v2, version);
|
TVMVersion::TryParse(v2, version);
|
||||||
@@ -258,8 +261,10 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Parser parser(tokens,ls.GetGC(),comptimeEnv);
|
Parser parser(tokens,ls.GetGC(),comptimeEnv);
|
||||||
|
parser.debug = debug;
|
||||||
SyntaxNode n = parser.ParseRoot();
|
SyntaxNode n = parser.ParseRoot();
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
|
gen.embedFS = vfs;
|
||||||
gen.GenRoot(n);
|
gen.GenRoot(n);
|
||||||
gen.dependencies = dependencies;
|
gen.dependencies = dependencies;
|
||||||
gen.tools = tools;
|
gen.tools = tools;
|
||||||
@@ -271,7 +276,7 @@ namespace Tesses::CrossLang
|
|||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream;
|
std::shared_ptr<Tesses::Framework::Streams::Stream> stream;
|
||||||
if(GetObject(_out, stream))
|
if(GetObject(_out, stream))
|
||||||
{
|
{
|
||||||
gen.Save(vfs, stream);
|
gen.Save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -282,11 +287,43 @@ namespace Tesses::CrossLang
|
|||||||
return Failure(ls, ex.what());
|
return Failure(ls, ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static TObject VM_GetStacktrace(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(current_function != nullptr)
|
||||||
|
{
|
||||||
|
if(current_function->thread != nullptr)
|
||||||
|
{
|
||||||
|
TList* list = TList::Create(ls);
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
for(auto item : current_function->thread->call_stack_entries)
|
||||||
|
{
|
||||||
|
auto dict = TDictionary::Create(ls);
|
||||||
|
if(item->callable->closure->name)
|
||||||
|
dict->SetValue("Name", *item->callable->closure->name);
|
||||||
|
|
||||||
|
dict->SetValue("Closure", item->callable->closure);
|
||||||
|
dict->SetValue("FileName", item->callable->file->name + "-" + item->callable->file->version.ToString() + ".crvm");
|
||||||
|
dict->SetValue("IP",(int64_t)item->ip);
|
||||||
|
if(item->srcline >= 1)
|
||||||
|
{
|
||||||
|
dict->SetValue("SourceFile", item->srcfile);
|
||||||
|
dict->SetValue("SourceLine",item->srcline);
|
||||||
|
}
|
||||||
|
list->Add(dict);
|
||||||
|
}
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
void TStd::RegisterVM(GC* gc,TRootEnvironment* env)
|
void TStd::RegisterVM(GC* gc,TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
env->permissions.canRegisterVM=true;
|
env->permissions.canRegisterVM=true;
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
|
|
||||||
TDictionary* dict = TDictionary::Create(ls);
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
|
dict->DeclareFunction(gc, "GetStacktrace","Get the current stack trace", {}, VM_GetStacktrace);
|
||||||
dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector<TObject> args)-> TObject{
|
dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector<TObject> args)-> TObject{
|
||||||
return env->GetDictionary();
|
return env->GetDictionary();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ namespace Tesses::CrossLang
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||||
|
clos->closure->name = obj->name + "::" + ent.name;
|
||||||
clos->className = ownerNow;
|
clos->className = ownerNow;
|
||||||
clos->documentation = entry.documentation;
|
clos->documentation = entry.documentation;
|
||||||
ent.value = clos;
|
ent.value = clos;
|
||||||
@@ -163,6 +164,7 @@ namespace Tesses::CrossLang
|
|||||||
if(entry.isAbstract) ent.value = Undefined();
|
if(entry.isAbstract) ent.value = Undefined();
|
||||||
else {
|
else {
|
||||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||||
|
clos->closure->name = obj->name + "::" + ent.name;
|
||||||
clos->className = ownerNow;
|
clos->className = ownerNow;
|
||||||
ent.value = clos->Call(*ls,{});
|
ent.value = clos->Call(*ls,{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,33 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
TObject TDictionary::CallMethodWithFatalError(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto res = this->GetValue(key);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
TCallable* callable;
|
||||||
|
|
||||||
|
if(GetObjectHeap(res,callable))
|
||||||
|
{
|
||||||
|
auto closure = dynamic_cast<TClosure*>(callable);
|
||||||
|
if(closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this")
|
||||||
|
{
|
||||||
|
std::vector<TObject> args2;
|
||||||
|
args2.push_back(this);
|
||||||
|
args2.insert(args2.end(), args.begin(),args.end());
|
||||||
|
return closure->CallWithFatalError(ls,args2);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return callable->CallWithFatalError(ls,args);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
void TDictionary::DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb)
|
void TDictionary::DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb)
|
||||||
{
|
{
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
@@ -204,4 +231,5 @@ namespace Tesses::CrossLang {
|
|||||||
_gc->Watch(dict);
|
_gc->Watch(dict);
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
228
src/types/embed.cpp
Normal file
228
src/types/embed.cpp
Normal file
@@ -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<Tesses::Framework::Streams::Stream> 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<Tesses::Framework::Streams::Stream> 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<std::string, Tesses::CrossLang::TObject>::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,11 +118,12 @@ namespace Tesses::CrossLang {
|
|||||||
throw VMException("Lex error at line: " + std::to_string(res));
|
throw VMException("Lex error at line: " + std::to_string(res));
|
||||||
}
|
}
|
||||||
Parser parser(tokens);
|
Parser parser(tokens);
|
||||||
|
|
||||||
SyntaxNode n = parser.ParseRoot();
|
SyntaxNode n = parser.ParseRoot();
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(n);
|
gen.GenRoot(n);
|
||||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||||
gen.Save(nullptr, ms);
|
gen.Save(ms);
|
||||||
ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
TFile* f = TFile::Create(ls);
|
TFile* f = TFile::Create(ls);
|
||||||
f->Load(ls.GetGC(),ms);
|
f->Load(ls.GetGC(),ms);
|
||||||
@@ -230,6 +231,9 @@ namespace Tesses::CrossLang {
|
|||||||
std::vector<std::string> method=file->classes[i].name;
|
std::vector<std::string> method=file->classes[i].name;
|
||||||
method.push_back(meth.name);
|
method.push_back(meth.name);
|
||||||
auto clo = TClosure::Create(ls,this,file,meth.chunkId);
|
auto clo = TClosure::Create(ls,this,file,meth.chunkId);
|
||||||
|
clo->closure->name = JoinPeriod(method);
|
||||||
|
|
||||||
|
|
||||||
clo->documentation = meth.documentation;
|
clo->documentation = meth.documentation;
|
||||||
this->DeclareVariable(gc, method, clo);
|
this->DeclareVariable(gc, method, clo);
|
||||||
}
|
}
|
||||||
@@ -239,7 +243,6 @@ namespace Tesses::CrossLang {
|
|||||||
for(auto fn : file->functions)
|
for(auto fn : file->functions)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
|
|
||||||
if(fn.first.size() < 2) throw VMException("No function name.");
|
if(fn.first.size() < 2) throw VMException("No function name.");
|
||||||
@@ -248,6 +251,7 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds.");
|
if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds.");
|
||||||
TFileChunk* chunk = file->chunks[fn.second];
|
TFileChunk* chunk = file->chunks[fn.second];
|
||||||
|
chunk->name = JoinPeriod(items);
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
||||||
closure->documentation = fn.first[0];
|
closure->documentation = fn.first[0];
|
||||||
|
|||||||
@@ -163,6 +163,19 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
TObject TEnvironment::CallFunctionWithFatalError(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto res = this->GetVariable(key);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
TCallable* callable;
|
||||||
|
|
||||||
|
if(GetObjectHeap(res,callable))
|
||||||
|
{
|
||||||
|
return callable->CallWithFatalError(ls,args);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc)
|
TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc)
|
||||||
{
|
{
|
||||||
auto dict=TDictionary::Create(gc);
|
auto dict=TDictionary::Create(gc);
|
||||||
|
|||||||
107
src/vm/exception.cpp
Normal file
107
src/vm/exception.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TObject TCallable::CallWithFatalError(GCList& ls, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Call(ls,args);
|
||||||
|
}
|
||||||
|
catch(VMByteCodeException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(VMException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(SyntaxException& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(std::runtime_error& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
catch(std::exception& ex)
|
||||||
|
{
|
||||||
|
ThrowFatalError(ex);
|
||||||
|
}
|
||||||
|
return (int64_t)1;
|
||||||
|
}
|
||||||
|
void ThrowFatalError(std::exception& ex)
|
||||||
|
{
|
||||||
|
using namespace Tesses::Framework::TextStreams;
|
||||||
|
std::exception* ex2 = &ex;
|
||||||
|
auto clexcept = dynamic_cast<VMByteCodeException*>(ex2);
|
||||||
|
auto clrtexcept = dynamic_cast<VMException*>(ex2);
|
||||||
|
auto compiler = dynamic_cast<SyntaxException*>(ex2);
|
||||||
|
Tesses::Framework::TextStreams::ConsoleWriter error(true);
|
||||||
|
|
||||||
|
if(clexcept != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal exception");
|
||||||
|
error.WriteLine();
|
||||||
|
|
||||||
|
error.WriteLine(ToString(clexcept->GetGCList()->GetGC(),clexcept->exception));
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine("STACKTRACE:");
|
||||||
|
|
||||||
|
for(auto ittr = clexcept->stack_trace.crbegin(); ittr != clexcept->stack_trace.crend(); ittr++)
|
||||||
|
{
|
||||||
|
auto item = *ittr;
|
||||||
|
std::string text = "\t";
|
||||||
|
text += item->callable->closure->name.value_or((std::string)"<Closure>");
|
||||||
|
text += "(";
|
||||||
|
bool first=true;
|
||||||
|
for(auto& arg : item->callable->closure->args)
|
||||||
|
{
|
||||||
|
if(!first) text += ", ";
|
||||||
|
text += arg;
|
||||||
|
first=false;
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
if(item->srcline >= 1)
|
||||||
|
{
|
||||||
|
text += " at ";
|
||||||
|
text += item->srcfile;
|
||||||
|
text += ":";
|
||||||
|
text += std::to_string(item->srcline);
|
||||||
|
}
|
||||||
|
error.WriteLine(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(clrtexcept != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine(clrtexcept->what());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(compiler != nullptr)
|
||||||
|
{
|
||||||
|
error.WriteLine("CrossLang has encountered a compiler error");
|
||||||
|
error.WriteLine();
|
||||||
|
error.WriteLine(compiler->Message());
|
||||||
|
error.WriteLine();
|
||||||
|
auto li = compiler->LineInfo();
|
||||||
|
error.Write("in file: ");
|
||||||
|
error.Write(li.filename);
|
||||||
|
error.Write(":");
|
||||||
|
error.Write((int64_t)li.line);
|
||||||
|
error.Write(":");
|
||||||
|
error.Write((int64_t)li.column);
|
||||||
|
error.Write(":");
|
||||||
|
error.WriteLine((int64_t)li.offset);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||||
|
error.WriteLine();
|
||||||
|
error.Write("what(): ");
|
||||||
|
error.WriteLine(ex2->what());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4237,7 +4237,7 @@ namespace Tesses::CrossLang {
|
|||||||
if(args.size() > 0)
|
if(args.size() > 0)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
throw VMByteCodeException(gc,args[0]);
|
throw VMByteCodeException(gc,args[0],cse.back());
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
ttask->SetFailed(std::current_exception());
|
ttask->SetFailed(std::current_exception());
|
||||||
}
|
}
|
||||||
@@ -6971,7 +6971,35 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool InterperterThread::PushResourceStream(GC* gc)
|
||||||
|
{
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
if(!cse.empty())
|
||||||
|
{
|
||||||
|
auto stk = cse.back();
|
||||||
|
std::vector<uint8_t>& 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<EmbedStream>(gc,stk->callable->file,n));
|
||||||
|
|
||||||
|
gc->BarrierEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw VMException("Can't read chunk.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool InterperterThread::PushResource(GC* gc)
|
bool InterperterThread::PushResource(GC* gc)
|
||||||
{
|
{
|
||||||
@@ -7012,7 +7040,22 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto env = cse.back()->env;
|
auto env = cse.back()->env;
|
||||||
if(!env->GetRootEnvironment()->HandleException(gc,env, _res2))
|
if(!env->GetRootEnvironment()->HandleException(gc,env, _res2))
|
||||||
throw VMByteCodeException(gc,_res2);
|
throw VMByteCodeException(gc,_res2,cse.back());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::PushResourceDirectory(GC* gc)
|
||||||
|
{
|
||||||
|
std::vector<CallStackEntry*>& 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<EmbedDirectory>(gc,dict));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -7167,6 +7210,24 @@ namespace Tesses::CrossLang {
|
|||||||
auto stk = cse.back();
|
auto stk = cse.back();
|
||||||
|
|
||||||
stk->Push(gc,Undefined());
|
stk->Push(gc,Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::LineInfo(GC* gc)
|
||||||
|
{
|
||||||
|
GCList ls(gc);
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
auto file = stk->Pop(ls);
|
||||||
|
auto line = stk->Pop(ls);
|
||||||
|
|
||||||
|
//Set the fields in this cse
|
||||||
|
GetObject(file,stk->srcfile);
|
||||||
|
GetObject(line,stk->srcline);
|
||||||
|
|
||||||
|
//TODO: implement lines (this will make the language work until we get it rigged up)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool InterperterThread::PushFalse(GC* gc)
|
bool InterperterThread::PushFalse(GC* gc)
|
||||||
@@ -7867,6 +7928,9 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
CallStackEntry* cse = new CallStackEntry();
|
CallStackEntry* cse = new CallStackEntry();
|
||||||
cse->mustReturn=false;
|
cse->mustReturn=false;
|
||||||
|
cse->srcline = -1;
|
||||||
|
cse->srcfile = "";
|
||||||
|
cse->thread=nullptr;
|
||||||
GC* _gc = ls.GetGC();
|
GC* _gc = ls.GetGC();
|
||||||
ls.Add(cse);
|
ls.Add(cse);
|
||||||
_gc->Watch(cse);
|
_gc->Watch(cse);
|
||||||
@@ -7877,6 +7941,9 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
CallStackEntry* cse = new CallStackEntry();
|
CallStackEntry* cse = new CallStackEntry();
|
||||||
cse->mustReturn=false;
|
cse->mustReturn=false;
|
||||||
|
cse->srcline = -1;
|
||||||
|
cse->srcfile = "";
|
||||||
|
cse->thread=nullptr;
|
||||||
GC* _gc = ls->GetGC();
|
GC* _gc = ls->GetGC();
|
||||||
ls->Add(cse);
|
ls->Add(cse);
|
||||||
_gc->Watch(cse);
|
_gc->Watch(cse);
|
||||||
@@ -7886,6 +7953,7 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
CallStackEntry* cse = CallStackEntry::Create(ls);
|
CallStackEntry* cse = CallStackEntry::Create(ls);
|
||||||
|
cse->thread = this;
|
||||||
cse->callable = closure;
|
cse->callable = closure;
|
||||||
cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env;
|
cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env;
|
||||||
cse->ip = 0;
|
cse->ip = 0;
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ static opcode opcodes[256]={
|
|||||||
&InterperterThread::JumpIfContinue,
|
&InterperterThread::JumpIfContinue,
|
||||||
&InterperterThread::JumpIfDefined,
|
&InterperterThread::JumpIfDefined,
|
||||||
&InterperterThread::DeclareConstVariable,
|
&InterperterThread::DeclareConstVariable,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::LineInfo,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::PushResourceStream,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::PushResourceDirectory,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
|
|||||||
Reference in New Issue
Block a user