985 lines
28 KiB
C++
985 lines
28 KiB
C++
|
#include "parser.hpp"
|
||
|
#include <algorithm>
|
||
|
#include <cstring>
|
||
|
namespace BoxScript
|
||
|
{
|
||
|
void IApplicationState::AddThreadOwner()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
void IApplicationState::RemoveThreadOwner()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
void SubscopeApplicationState::AddThreadOwner()
|
||
|
{
|
||
|
this->state->AddThreadOwner();
|
||
|
this->threads++;
|
||
|
}
|
||
|
void SubscopeApplicationState::RemoveThreadOwner()
|
||
|
{
|
||
|
this->state->RemoveThreadOwner();
|
||
|
if(this->threads <= 0)
|
||
|
{
|
||
|
delete this;
|
||
|
}
|
||
|
}
|
||
|
ApplicationState::ApplicationState()
|
||
|
{
|
||
|
this->isRunning=true;
|
||
|
this->NoBoxes=0;
|
||
|
this->NoExpressions=0;
|
||
|
this->NoStreams=0;
|
||
|
}
|
||
|
int64_t ApplicationState::CreateBox(string text)
|
||
|
{
|
||
|
int64_t boxId=this->NoBoxes++;
|
||
|
if(this->boxes.count(boxId) <= 0)
|
||
|
{
|
||
|
this->boxes.insert({boxId,{vector<int64_t>(), false}});
|
||
|
}
|
||
|
for(int i =0;i<text.length();i++)
|
||
|
{
|
||
|
this->boxes[boxId].first.push_back(text[i]);
|
||
|
}
|
||
|
|
||
|
return boxId;
|
||
|
}
|
||
|
|
||
|
Expression* ApplicationState::Calln(int64_t e)
|
||
|
{
|
||
|
if(this->expressions.count(e) > 0)
|
||
|
{
|
||
|
return expressions[e];
|
||
|
}
|
||
|
return new ConstantNumber("0");
|
||
|
}
|
||
|
int64_t ApplicationState::ReadByteFromStream(int64_t streamId)
|
||
|
{
|
||
|
Stream* strm = GetStream(streamId);
|
||
|
return strm->ReadByte();
|
||
|
}
|
||
|
int64_t ApplicationState::CreateBufferedStream(int64_t existingStreamId)
|
||
|
{
|
||
|
Stream* strm = GetStream(existingStreamId);
|
||
|
return CreateStream(new BufferedStream(strm));
|
||
|
}
|
||
|
int64_t ApplicationState::e2n(Expression* e)
|
||
|
{
|
||
|
int64_t eId = this->NoExpressions++;
|
||
|
this->expressions.insert({eId,e});
|
||
|
return eId;
|
||
|
}
|
||
|
string ApplicationState::BoxToString(int64_t boxId)
|
||
|
{
|
||
|
string s ="";
|
||
|
if(boxes.count(boxId) == 0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(int i =0;i<boxes[boxId].first.size();i++)
|
||
|
{
|
||
|
char c = (char)(boxes[boxId].first[i] % 256);
|
||
|
s+= c;
|
||
|
}
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
int64_t ApplicationState::CreateBox(int boxLen)
|
||
|
{
|
||
|
int64_t i = NoBoxes++;
|
||
|
if(this->boxes.count(i) <= 0)
|
||
|
{
|
||
|
this->boxes.insert({i,{vector<int64_t>(), false}});
|
||
|
}
|
||
|
this->boxes[i].first.reserve(boxLen);
|
||
|
return i;
|
||
|
}
|
||
|
void ApplicationState::AddRuntimeFunction(string str,internal_func func)
|
||
|
{
|
||
|
if(!HasRuntimeFunction(str))
|
||
|
{
|
||
|
runtime_funcs.insert({str,func});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ApplicationState::DestroyBox(int64_t boxId)
|
||
|
{
|
||
|
if(boxes.count(boxId) == 0) return;
|
||
|
if(!boxes[boxId].second)
|
||
|
{
|
||
|
boxes[boxId].first.clear();
|
||
|
boxes.erase(boxId);
|
||
|
}
|
||
|
}
|
||
|
int64_t ApplicationState::CreateStream(Stream* strm)
|
||
|
{
|
||
|
int64_t i = NoStreams++;
|
||
|
streams.insert({i,strm});
|
||
|
return i;
|
||
|
}
|
||
|
int64_t ApplicationState::GetBoxValue(int64_t bId,int index)
|
||
|
{
|
||
|
if(boxes.count(bId) == 0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}else
|
||
|
{
|
||
|
if(index>boxes[bId].first.size())
|
||
|
{
|
||
|
throw exception();
|
||
|
}else{
|
||
|
return boxes[bId].first[index];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::SetBoxValue(int64_t bId,int index,int64_t value)
|
||
|
{
|
||
|
if(value > 2147483647) throw exception();
|
||
|
|
||
|
if(boxes.count(bId) == 0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(boxes[bId].second) throw new exception();
|
||
|
if(index > boxes[bId].first.size())
|
||
|
{
|
||
|
throw exception();
|
||
|
}else{
|
||
|
boxes[bId].first[index] = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
bool ApplicationState::HasVariable(string name)
|
||
|
{
|
||
|
return variables.count(name) > 0;
|
||
|
}
|
||
|
int64_t ApplicationState::GetVariable(string name)
|
||
|
{
|
||
|
if(variables.count(name) > 0)
|
||
|
{
|
||
|
return variables[name];
|
||
|
}else{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
IApplicationState* ApplicationState::NewScope()
|
||
|
{
|
||
|
return new SubscopeApplicationState(this);
|
||
|
}
|
||
|
void ApplicationState::SetVariable(string name,int64_t value)
|
||
|
{
|
||
|
if(variables.count(name) > 0)
|
||
|
{
|
||
|
variables[name]=value;
|
||
|
}else{
|
||
|
variables.insert({name,value});
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::ClearBox(int64_t bId)
|
||
|
{
|
||
|
if(boxes.count(bId) == 0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(boxes[bId].second) throw exception();
|
||
|
boxes[bId].first.clear();
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::AddToBox(int64_t bId,int64_t value)
|
||
|
{
|
||
|
if(boxes.count(bId) == 0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}else
|
||
|
{
|
||
|
if(boxes[bId].second) throw exception();
|
||
|
boxes[bId].first.push_back(value);
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::RemoveFromBox(int64_t bId,int64_t value)
|
||
|
{
|
||
|
if(boxes.count(bId)==0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(boxes[bId].second) throw exception();
|
||
|
vector<int64_t>::iterator itr= find(boxes[bId].first.begin(),boxes[bId].first.end(),value);
|
||
|
if(itr < boxes[bId].first.end())
|
||
|
{
|
||
|
boxes[bId].first.erase(itr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::RemoveAtFromBox(int64_t bId,int index)
|
||
|
{
|
||
|
if(boxes.count(bId)==0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(boxes[bId].second) throw exception();
|
||
|
vector<int64_t>::iterator itr= boxes[bId].first.begin() + index;
|
||
|
if(itr < boxes[bId].first.end())
|
||
|
{
|
||
|
boxes[bId].first.erase(itr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::InsertToBox(int64_t bId,int index,int64_t value)
|
||
|
{
|
||
|
if(boxes.count(bId)==0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(boxes[bId].second) throw exception();
|
||
|
vector<int64_t>::iterator itr= boxes[bId].first.begin() + index;
|
||
|
if(itr != boxes[bId].first.end())
|
||
|
{
|
||
|
boxes[bId].first.insert(itr,value);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
int64_t ApplicationState::BoxLength(int64_t boxId)
|
||
|
{
|
||
|
if(boxes.count(boxId)==0)
|
||
|
{
|
||
|
throw exception();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return boxes[boxId].first.size();
|
||
|
}
|
||
|
}
|
||
|
bool ApplicationState::HasRuntimeFunction(string str)
|
||
|
{
|
||
|
return runtime_funcs.count(str) > 0;
|
||
|
}
|
||
|
internal_func ApplicationState::GetRuntimeFunction(string str)
|
||
|
{
|
||
|
return runtime_funcs[str];
|
||
|
}
|
||
|
int64_t ApplicationState::ExecuteFunction(string str,vector<Expression*> expressions)
|
||
|
{
|
||
|
if(!HasFunction(str)) return 0;
|
||
|
//var func=methods[str]
|
||
|
IApplicationState* res = NewScope();
|
||
|
res->AddThreadOwner();
|
||
|
for(int i = 0;i<min(expressions.size(),methods[str].first.size());i++)
|
||
|
{
|
||
|
res->SetVariable(methods[str].first[i],expressions[i]->Evaluate(res));
|
||
|
}
|
||
|
int64_t result= methods[str].second->Evaluate(res);
|
||
|
res->RemoveThreadOwner();
|
||
|
return result;
|
||
|
}
|
||
|
int64_t ApplicationState::CreateBoxPermanent(string text)
|
||
|
{
|
||
|
int64_t boxId=this->NoBoxes++;
|
||
|
if(this->boxes.count(boxId) <= 0)
|
||
|
{
|
||
|
this->boxes.insert({boxId,{vector<int64_t>(), true}});
|
||
|
}
|
||
|
for(int i =0;i<text.length();i++)
|
||
|
{
|
||
|
this->boxes[boxId].first.push_back(text[i]);
|
||
|
}
|
||
|
|
||
|
return boxId;
|
||
|
}
|
||
|
bool ApplicationState::HasFunction(string str)
|
||
|
{
|
||
|
return methods.count(str) > 0;
|
||
|
}
|
||
|
void ApplicationState::AddFunction(string str,vector<string> args,Expression* exp)
|
||
|
{
|
||
|
if(!HasFunction(str))
|
||
|
{
|
||
|
methods.insert({str,{args,exp}});
|
||
|
}
|
||
|
}
|
||
|
void ApplicationState::CopyStream(int64_t src,int64_t dest)
|
||
|
{
|
||
|
if(streams.count(src) == 0 || streams.count(dest) == 0) return;
|
||
|
GetStream(src)->CopyTo(GetStream(dest));
|
||
|
}
|
||
|
Stream* ApplicationState::GetStream(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) throw exception();
|
||
|
return streams[streamId];
|
||
|
}
|
||
|
void ApplicationState::CloseStream(int64_t streamId)
|
||
|
{
|
||
|
|
||
|
if(streams.count(streamId)==0) throw exception();
|
||
|
streams[streamId]->Close();
|
||
|
delete streams[streamId];
|
||
|
streams.erase(streamId);
|
||
|
|
||
|
}
|
||
|
void ApplicationState::WriteToStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return;
|
||
|
Stream* strm=GetStream(streamId);
|
||
|
if(!strm->CanWrite())return;
|
||
|
size_t len2=boxes[boxId].first.size();
|
||
|
len2-=offset;
|
||
|
int64_t len3=min(len,(int64_t)len2);
|
||
|
uint8_t data[len3];
|
||
|
for(int64_t i = 0;i<len3;i++)
|
||
|
{
|
||
|
uint8_t byte=(uint8_t)boxes[boxId].first[i+offset];
|
||
|
data[i] = byte;
|
||
|
}
|
||
|
strm->Write(data,(size_t)len3);
|
||
|
}
|
||
|
int64_t ApplicationState::ReadFromStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return 0;
|
||
|
Stream* strm=GetStream(streamId);
|
||
|
if(boxes[boxId].second || !strm->CanRead()) return 0;
|
||
|
size_t len2=boxes[boxId].first.size();
|
||
|
len2-=offset;
|
||
|
int64_t len3=min(len,(int64_t)len2);
|
||
|
uint8_t data[len3];
|
||
|
len3=strm->Read(data,len3);
|
||
|
for(int64_t i = 0;i<len3;i++)
|
||
|
{
|
||
|
boxes[boxId].first[i+offset]=data[i];
|
||
|
}
|
||
|
return len3;
|
||
|
}
|
||
|
void ApplicationState::SetStreamPosition(int64_t streamId,int64_t streamPos)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return;
|
||
|
Stream* strm=GetStream(streamId);
|
||
|
if(!strm->CanSeek()) return;
|
||
|
strm->SetPosition(streamPos);
|
||
|
}
|
||
|
int64_t ApplicationState::GetStreamLength(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return 0;
|
||
|
Stream* strm=GetStream(streamId);
|
||
|
return strm->GetLength();
|
||
|
}
|
||
|
int64_t ApplicationState::GetStreamPosition(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return 0;
|
||
|
Stream* strm=GetStream(streamId);
|
||
|
if(!strm->CanSeek()) return 0;
|
||
|
return strm->GetPosition();
|
||
|
}
|
||
|
bool ApplicationState::CanRead(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return false;
|
||
|
return GetStream(streamId)->CanRead();
|
||
|
}
|
||
|
bool ApplicationState::CanWrite(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return false;
|
||
|
return GetStream(streamId)->CanWrite();
|
||
|
}
|
||
|
bool ApplicationState::CanSeek(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return false;
|
||
|
return GetStream(streamId)->CanSeek();
|
||
|
}
|
||
|
void ApplicationState::FlushStream(int64_t streamId)
|
||
|
{
|
||
|
if(streams.count(streamId) == 0) return;
|
||
|
GetStream(streamId)->Flush();
|
||
|
}
|
||
|
|
||
|
#pragma region SubscopeApplicationState
|
||
|
SubscopeApplicationState::SubscopeApplicationState(IApplicationState* _state)
|
||
|
{
|
||
|
this->threads=0;
|
||
|
this->state=_state;
|
||
|
}
|
||
|
internal_func SubscopeApplicationState::GetRuntimeFunction(string str)
|
||
|
{
|
||
|
return this->state->GetRuntimeFunction(str);
|
||
|
}
|
||
|
void SubscopeApplicationState::FlushStream(int64_t stream)
|
||
|
{
|
||
|
this->state->FlushStream(stream);
|
||
|
}
|
||
|
void SubscopeApplicationState::DestroyBox(int64_t id)
|
||
|
{
|
||
|
this->state->DestroyBox(id);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::e2n(Expression* e)
|
||
|
{
|
||
|
return this->state->e2n(e);
|
||
|
}
|
||
|
Expression* SubscopeApplicationState::Calln(int64_t e)
|
||
|
{
|
||
|
return this->state->Calln(e);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::CreateStream(Stream* strm)
|
||
|
{
|
||
|
return this->state->CreateStream(strm);
|
||
|
}
|
||
|
void SubscopeApplicationState::CopyStream(int64_t strmSrc,int64_t strmDest)
|
||
|
{
|
||
|
this->state->CopyStream(strmSrc,strmDest);
|
||
|
}
|
||
|
void SubscopeApplicationState::CloseStream(int64_t streamId)
|
||
|
{
|
||
|
this->state->CloseStream(streamId);
|
||
|
}
|
||
|
void SubscopeApplicationState::WriteToStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)
|
||
|
{
|
||
|
this->state->WriteToStream(streamId,boxId,offset,len);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::ReadFromStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)
|
||
|
{
|
||
|
return this->state->ReadFromStream(streamId,boxId,offset,len);
|
||
|
}
|
||
|
void SubscopeApplicationState::SetStreamPosition(int64_t streamId,int64_t streamPos)
|
||
|
{
|
||
|
this->state->SetStreamPosition(streamId,streamPos);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::GetStreamPosition(int64_t streamId)
|
||
|
{
|
||
|
return this->state->GetStreamPosition(streamId);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::GetStreamLength(int64_t streamId)
|
||
|
{
|
||
|
return this->state->GetStreamLength(streamId);
|
||
|
}
|
||
|
bool SubscopeApplicationState::CanRead(int64_t streamId)
|
||
|
{
|
||
|
return this->state->CanRead(streamId);
|
||
|
}
|
||
|
bool SubscopeApplicationState::CanWrite(int64_t streamId)
|
||
|
{
|
||
|
return this->state->CanWrite(streamId);
|
||
|
}
|
||
|
bool SubscopeApplicationState::CanSeek(int64_t streamId)
|
||
|
{
|
||
|
return this->state->CanSeek(streamId);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::ExecuteFunction(string str,vector<Expression*> expressions)
|
||
|
{
|
||
|
return this->state->ExecuteFunction(str,expressions);
|
||
|
}
|
||
|
bool SubscopeApplicationState::HasRuntimeFunction(string str)
|
||
|
{
|
||
|
return this->state->HasRuntimeFunction(str);
|
||
|
}
|
||
|
bool SubscopeApplicationState::HasFunction(string str)
|
||
|
{
|
||
|
return this->state->HasFunction(str);
|
||
|
}
|
||
|
void SubscopeApplicationState::AddFunction(string str,vector<string> args,Expression* exp)
|
||
|
{
|
||
|
this->state->AddFunction(str,args,exp);
|
||
|
}
|
||
|
void SubscopeApplicationState::AddRuntimeFunction(string str,internal_func func)
|
||
|
{
|
||
|
this->state->AddRuntimeFunction(str,func);
|
||
|
}
|
||
|
string SubscopeApplicationState::BoxToString(int64_t boxId)
|
||
|
{
|
||
|
return this->state->BoxToString(boxId);
|
||
|
}
|
||
|
void SubscopeApplicationState::ClearBox(int64_t bId)
|
||
|
{
|
||
|
this->state->ClearBox(bId);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::ReadByteFromStream(int64_t streamId)
|
||
|
{
|
||
|
return this->state->ReadByteFromStream(streamId);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::CreateBufferedStream(int64_t existingStreamId)
|
||
|
{
|
||
|
return this->state->CreateBufferedStream(existingStreamId);
|
||
|
}
|
||
|
void SubscopeApplicationState::AddToBox(int64_t bId,int64_t value)
|
||
|
{
|
||
|
this->state->AddToBox(bId,value);
|
||
|
}
|
||
|
void SubscopeApplicationState::RemoveFromBox(int64_t bId,int64_t value)
|
||
|
{
|
||
|
this->state->RemoveFromBox(bId,value);
|
||
|
}
|
||
|
void SubscopeApplicationState::RemoveAtFromBox(int64_t bId,int index)
|
||
|
{
|
||
|
this->state->RemoveAtFromBox(bId,index);
|
||
|
}
|
||
|
void SubscopeApplicationState::InsertToBox(int64_t bId,int index,int64_t value)
|
||
|
{
|
||
|
this->state->InsertToBox(bId,index,value);
|
||
|
}
|
||
|
void SubscopeApplicationState::SetBoxValue(int64_t bId,int index,int64_t value)
|
||
|
{
|
||
|
this->state->SetBoxValue(bId,index,value);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::BoxLength(int64_t boxId)
|
||
|
{
|
||
|
return this->state->BoxLength(boxId);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::CreateBox(int len)
|
||
|
{
|
||
|
return this->state->CreateBox(len);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::CreateBox(string text)
|
||
|
{
|
||
|
return this->state->CreateBox(text);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::CreateBoxPermanent(string text)
|
||
|
{
|
||
|
return this->state->CreateBoxPermanent(text);
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::GetBoxValue(int64_t bId, int index)
|
||
|
{
|
||
|
return this->state->GetBoxValue(bId,index);
|
||
|
}
|
||
|
bool SubscopeApplicationState::HasVariable(string name)
|
||
|
{
|
||
|
return variables.count(name) > 0 || (name.substr(0,4) != "cur." && this->state->HasVariable(name));
|
||
|
}
|
||
|
void SubscopeApplicationState::SetVariable(string name,int64_t value)
|
||
|
{
|
||
|
if(name.substr(0,4) != "cur." && state->HasVariable(name))
|
||
|
{
|
||
|
this->state->SetVariable(name,value);
|
||
|
}else{
|
||
|
if(this->variables.count(name) > 0)
|
||
|
{
|
||
|
variables[name]=value;
|
||
|
}else{
|
||
|
variables.insert({name,value});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
int64_t SubscopeApplicationState::GetVariable(string name)
|
||
|
{
|
||
|
if(name.substr(0,4) != "cur." && state->HasVariable(name))
|
||
|
{
|
||
|
return this->state->GetVariable(name);
|
||
|
}else{
|
||
|
if(this->variables.count(name) > 0) return this->variables[name];
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
IApplicationState* SubscopeApplicationState::NewScope()
|
||
|
{
|
||
|
return new SubscopeApplicationState(this);
|
||
|
}
|
||
|
#pragma endregion
|
||
|
|
||
|
|
||
|
void Stream::CopyTo(Stream* strm)
|
||
|
{
|
||
|
uint8_t buffer[4096];
|
||
|
size_t read;
|
||
|
do
|
||
|
{
|
||
|
read = this->Read(buffer,4096);
|
||
|
strm->Write(buffer,read);
|
||
|
} while (read != 0);
|
||
|
|
||
|
}
|
||
|
|
||
|
ExpressionStream::ExpressionStream(IApplicationState* state,vector<Expression*> expressions)
|
||
|
{
|
||
|
this->st = state;
|
||
|
this->exp = exp;
|
||
|
|
||
|
}
|
||
|
void ExpressionStream::Write(uint8_t* data,size_t len)
|
||
|
{
|
||
|
int64_t box = st->CreateBox((int64_t)len);
|
||
|
IApplicationState* newSc = st->NewScope();
|
||
|
newSc->AddThreadOwner();
|
||
|
newSc->SetVariable("stream_count_value",len);
|
||
|
newSc->SetVariable("stream_buffer",box);
|
||
|
|
||
|
for(size_t i = 0;i<len;i++)
|
||
|
{
|
||
|
st->AddToBox(box,data[i]);
|
||
|
}
|
||
|
exp[1]->Evaluate(newSc);
|
||
|
newSc->DestroyBox(box);
|
||
|
newSc->RemoveThreadOwner();
|
||
|
}
|
||
|
size_t ExpressionStream::Read(uint8_t* data,size_t len)
|
||
|
{
|
||
|
int64_t box = st->CreateBox((int64_t)len);
|
||
|
IApplicationState* newSc = st->NewScope();
|
||
|
newSc->AddThreadOwner();
|
||
|
newSc->SetVariable("stream_count_value",len);
|
||
|
newSc->SetVariable("stream_buffer",box);
|
||
|
size_t read = (size_t)exp[0]->Evaluate(newSc);
|
||
|
for(size_t i = 0;i<min(read,len);i++)
|
||
|
{
|
||
|
uint8_t v = (uint8_t)st->GetBoxValue(box,(int)i);
|
||
|
data[i]=v;
|
||
|
}
|
||
|
newSc->DestroyBox(box);
|
||
|
newSc->RemoveThreadOwner();
|
||
|
return min(read,len);
|
||
|
}
|
||
|
int64_t ExpressionStream::GetPosition()
|
||
|
{
|
||
|
//3
|
||
|
return exp[3]->Evaluate(st);
|
||
|
}
|
||
|
int64_t ExpressionStream::GetLength()
|
||
|
{
|
||
|
//4
|
||
|
return exp[4]->Evaluate(st) > 0;
|
||
|
}
|
||
|
void ExpressionStream::SetPosition(int64_t pos)
|
||
|
{
|
||
|
//2
|
||
|
IApplicationState* newSc = st->NewScope();
|
||
|
newSc->AddThreadOwner();
|
||
|
newSc->SetVariable("stream_length_value",pos);
|
||
|
exp[2]->Evaluate(newSc);
|
||
|
newSc->RemoveThreadOwner();
|
||
|
}
|
||
|
void ExpressionStream::Flush()
|
||
|
{
|
||
|
//8
|
||
|
exp[8]->Evaluate(st);
|
||
|
}
|
||
|
void ExpressionStream::Close()
|
||
|
{
|
||
|
//9
|
||
|
exp[9]->Evaluate(st);
|
||
|
}
|
||
|
bool ExpressionStream::CanRead()
|
||
|
{
|
||
|
//5
|
||
|
return exp[5]->Evaluate(st) > 0;
|
||
|
}
|
||
|
bool ExpressionStream::CanWrite()
|
||
|
{
|
||
|
//6
|
||
|
return exp[6]->Evaluate(st) > 0;
|
||
|
}
|
||
|
bool ExpressionStream::CanSeek()
|
||
|
{
|
||
|
//7
|
||
|
return exp[7]->Evaluate(st) > 0;
|
||
|
}
|
||
|
FileStream::FileStream(FILE* fs,bool canRead,bool canWrite,bool canSeek,bool ownFile)
|
||
|
{
|
||
|
this->f=fs;
|
||
|
this->cr = canRead;
|
||
|
this->cw = canWrite;
|
||
|
this->cs = canSeek;
|
||
|
this->own=ownFile;
|
||
|
}
|
||
|
bool FileStream::CanSeek()
|
||
|
{
|
||
|
return this->cs;
|
||
|
}
|
||
|
bool FileStream::CanRead()
|
||
|
{
|
||
|
return this->cr;
|
||
|
}
|
||
|
bool FileStream::CanWrite()
|
||
|
{
|
||
|
return this->cw;
|
||
|
}
|
||
|
void FileStream::Write(uint8_t* data,size_t len)
|
||
|
{
|
||
|
if(!cw) return;
|
||
|
fwrite(data,1,len,f);
|
||
|
}
|
||
|
size_t FileStream::Read(uint8_t* data,size_t len)
|
||
|
{
|
||
|
if(!cr) return 0;
|
||
|
return fread(data,1,len,f);
|
||
|
}
|
||
|
void FileStream::Flush()
|
||
|
{
|
||
|
fflush(f);
|
||
|
}
|
||
|
void FileStream::Close()
|
||
|
{
|
||
|
if(own)
|
||
|
fclose(f);
|
||
|
}
|
||
|
int64_t FileStream::GetPosition()
|
||
|
{
|
||
|
if(!cs) return 0;
|
||
|
return (int64_t)ftello(f);
|
||
|
}
|
||
|
int64_t FileStream::GetLength()
|
||
|
{
|
||
|
if(!cs) return 0;
|
||
|
fpos_t pos;
|
||
|
|
||
|
|
||
|
fgetpos(f,&pos);
|
||
|
fseeko(f,0,SEEK_END);
|
||
|
int64_t len= (int64_t)ftello(f);
|
||
|
fsetpos(f,&pos);
|
||
|
return len;
|
||
|
}
|
||
|
void FileStream::SetPosition(int64_t pos)
|
||
|
{
|
||
|
if(!cs) return;
|
||
|
fseeko(f,(off_t)pos,SEEK_SET);
|
||
|
}
|
||
|
|
||
|
void Parse(ListNode* node,vector<Lexer::LexToken> tokens)
|
||
|
{
|
||
|
int i = 0;
|
||
|
ParseNode(node,tokens,&i,true);
|
||
|
}
|
||
|
ListNode* Parse(vector<Lexer::LexToken> tokens)
|
||
|
{
|
||
|
ListNode* node = new ListNode();
|
||
|
Parse(node,tokens);
|
||
|
return node;
|
||
|
}
|
||
|
void ParseNode(ListNode* node,vector<Lexer::LexToken> tokens,int* i)
|
||
|
{
|
||
|
ParseNode(node,tokens,i,false);
|
||
|
}
|
||
|
void ParseNode(ListNode* node,vector<Lexer::LexToken> tokens,int* i,bool root)
|
||
|
{
|
||
|
node->root = root;
|
||
|
while(*i < tokens.size() && tokens[*i].type != Lexer::RBRACE)
|
||
|
{
|
||
|
if(tokens[*i].type == Lexer::SEMI) (*i)++;
|
||
|
if(*i+2 < tokens.size() && tokens[*i+1].type == Lexer::EQUALS )
|
||
|
{
|
||
|
string varname = tokens[*i].text;
|
||
|
*i=*i+2;
|
||
|
node->nodes.push_back(new SetVariableNode(ParseExpression(tokens,i),varname));
|
||
|
if(!root && *i<tokens.size() && tokens[*i].type == Lexer::RBRACE) break;
|
||
|
(*i)++;
|
||
|
}
|
||
|
else if(*i+1 < tokens.size() && tokens[*i+1].type == Lexer::LPAREN)
|
||
|
{
|
||
|
node->nodes.push_back(ParseExpression(tokens,i));
|
||
|
if(!root && *i<tokens.size() && tokens[*i].type == Lexer::RBRACE) break;
|
||
|
(*i)++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
node->nodes.push_back(ParseExpression(tokens,i));
|
||
|
if(!root && *i<tokens.size() && tokens[*i].type == Lexer::RBRACE) break;
|
||
|
(*i)++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Expression* ParseExpression(vector<Lexer::LexToken> tokens,int* i)
|
||
|
{
|
||
|
Expression* res = ParseTerm(tokens,i);
|
||
|
while(*i < tokens.size() && (tokens[*i].type == Lexer::PLUS||tokens[*i].type == Lexer::MINUS))
|
||
|
{
|
||
|
if(*i < tokens.size() && tokens[*i].type == Lexer::PLUS)
|
||
|
{
|
||
|
(*i)++;
|
||
|
res = (Expression*)new AddNode(res,ParseTerm(tokens,i));
|
||
|
}
|
||
|
if(*i < tokens.size() && tokens[*i].type == Lexer::MINUS)
|
||
|
{
|
||
|
(*i)++;
|
||
|
res = (Expression*)new MinusNode(res,ParseTerm(tokens,i));
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
Expression* ParseTerm(vector<Lexer::LexToken> tokens,int* i)
|
||
|
{
|
||
|
Expression* res = ParseFactor(tokens,i);
|
||
|
while(*i < tokens.size() && (tokens[*i].type == Lexer::MULTIPLY||tokens[*i].type == Lexer::DIVIDE ||tokens[*i].type == Lexer::MOD))
|
||
|
{
|
||
|
if(*i < tokens.size() && tokens[*i].type == Lexer::MULTIPLY)
|
||
|
{
|
||
|
(*i)++;
|
||
|
res = (Expression*)new MultiplyNode(res,ParseFactor(tokens,i));
|
||
|
}
|
||
|
if(*i < tokens.size() && tokens[*i].type == Lexer::DIVIDE)
|
||
|
{
|
||
|
(*i)++;
|
||
|
res = (Expression*)new DivideNode(res,ParseFactor(tokens,i));
|
||
|
}
|
||
|
if(*i < tokens.size() && tokens[*i].type == Lexer::MOD)
|
||
|
{
|
||
|
(*i)++;
|
||
|
res = (Expression*)new ModulusNode(res,ParseFactor(tokens,i));
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
Expression* ParseFactor(vector<Lexer::LexToken> tokens,int* i)
|
||
|
{
|
||
|
if(*i>=tokens.size()) throw exception();
|
||
|
Lexer::LexToken token = tokens[*i];
|
||
|
if(token.type == Lexer::LPAREN)
|
||
|
{
|
||
|
(*i)++;
|
||
|
Expression* res = ParseExpression(tokens,i);
|
||
|
if(*i>=tokens.size()) throw exception();
|
||
|
if(tokens[*i].type != Lexer::RPAREN) throw exception();
|
||
|
(*i)++;
|
||
|
return res;
|
||
|
}
|
||
|
if(token.type == Lexer::LBRACE)
|
||
|
{
|
||
|
(*i)++;
|
||
|
ListNode* res = new ListNode();
|
||
|
ParseNode(res,tokens,i,false);
|
||
|
if(*i>=tokens.size()) throw exception();
|
||
|
if(tokens[*i].type != Lexer::RBRACE) throw exception();
|
||
|
(*i)++;
|
||
|
return (Expression*)res;
|
||
|
}
|
||
|
if(token.type == Lexer::IDENTIFER)
|
||
|
{
|
||
|
(*i)++;
|
||
|
if(*i<tokens.size() && tokens[*i].type == Lexer::LPAREN)
|
||
|
{
|
||
|
vector<Expression*> funcArgs;
|
||
|
(*i)++;
|
||
|
while(*i<tokens.size() && tokens[*i].type != Lexer::RPAREN)
|
||
|
{
|
||
|
if(tokens[*i].type == Lexer::COMMA) (*i)++;
|
||
|
funcArgs.push_back(ParseExpression(tokens,i));
|
||
|
}
|
||
|
(*i)++;
|
||
|
return (Expression*)new FunctionCallNode(token.text,funcArgs);
|
||
|
}else{
|
||
|
return (Expression*)new VariableGetValueNode(token.text);
|
||
|
}
|
||
|
}
|
||
|
if(token.type == Lexer::STRING)
|
||
|
{
|
||
|
(*i)++;
|
||
|
return (Expression*)new StringNode(token.text);
|
||
|
}
|
||
|
if(token.type == Lexer::NUMBER)
|
||
|
{
|
||
|
(*i)++;
|
||
|
return (Expression*)new ConstantNumber(token.text);
|
||
|
}
|
||
|
throw exception();
|
||
|
}
|
||
|
void ApplicationState::StopRunning()
|
||
|
{
|
||
|
std::vector<Expression*> exp;
|
||
|
this->isRunning=(bool)this->ExecuteFunction("stopinterrupt",exp);
|
||
|
}
|
||
|
void ApplicationState::ExitIfNotRunning()
|
||
|
{
|
||
|
if(!isRunning)
|
||
|
{
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
void SubscopeApplicationState::StopRunning()
|
||
|
{
|
||
|
this->state->StopRunning();
|
||
|
}
|
||
|
void SubscopeApplicationState::ExitIfNotRunning()
|
||
|
{
|
||
|
this->state->ExitIfNotRunning();
|
||
|
}
|
||
|
|
||
|
#pragma region "BufferedStream"
|
||
|
BufferedStream::BufferedStream(Stream* parent)
|
||
|
{
|
||
|
|
||
|
this->strm = parent;
|
||
|
|
||
|
}
|
||
|
int64_t Stream::ReadByte()
|
||
|
{
|
||
|
uint8_t buffer[1];
|
||
|
return this->Read(buffer,1) > 0 ? buffer[0] : -1;
|
||
|
}
|
||
|
int64_t BufferedStream::ReadByte()
|
||
|
{
|
||
|
if(pos<min((int)this->readIn,4096))
|
||
|
{
|
||
|
return (int64_t)this->buffer[this->pos];
|
||
|
}else{
|
||
|
this->readIn=this->strm->Read(this->buffer,4096);
|
||
|
this->pos = 0;
|
||
|
|
||
|
if(this->readIn > 0)
|
||
|
{
|
||
|
return this->buffer[this->pos++];
|
||
|
}else{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
void BufferedStream::Write(uint8_t* data,size_t len)
|
||
|
{
|
||
|
this->strm->Write(data,len);
|
||
|
}
|
||
|
size_t BufferedStream::Read(uint8_t* data,size_t len)
|
||
|
{
|
||
|
if(this->pos<min((int)this->readIn,4096) && this->pos > 0)
|
||
|
{
|
||
|
int _len=min((int)this->readIn-this->pos,(int)len);
|
||
|
memcpy(data,this->buffer + this->pos,_len);
|
||
|
this->pos+=_len;
|
||
|
return _len;
|
||
|
}else{
|
||
|
return this->strm->Read(data,len);
|
||
|
}
|
||
|
}
|
||
|
int64_t BufferedStream::GetPosition()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
int64_t BufferedStream::GetLength()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
void BufferedStream::SetPosition(int64_t pos)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
void BufferedStream::Flush()
|
||
|
{
|
||
|
this->strm->Flush();
|
||
|
}
|
||
|
void BufferedStream::Close()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
bool BufferedStream::CanRead()
|
||
|
{
|
||
|
return this->strm->CanRead();
|
||
|
}
|
||
|
bool BufferedStream::CanWrite()
|
||
|
{
|
||
|
return this->strm->CanWrite();
|
||
|
}
|
||
|
bool BufferedStream::CanSeek()
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
#pragma endregion
|
||
|
};
|