From 6dd5e3a7b7f721b90a209f59f7755f3484749ce3 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Mon, 23 Sep 2024 20:31:12 -0500 Subject: [PATCH] Finished WWWGen --- file.twss | 11 - main.twss | 8 - templater.cpp | 37 - tessesscriptengine.hpp | 4233 --------------------------------- tesseswebserver.cpp | 41 - tesseswebserver.hpp | 1142 --------- tesseswebserverfeatures.hpp | 7 - wwwroot/cgi-bin/add-todo.twss | 11 +- wwwroot/deinit.twss | 3 + wwwroot/index.twss | 6 +- wwwroot/init.twss | 39 +- 11 files changed, 54 insertions(+), 5484 deletions(-) delete mode 100644 file.twss delete mode 100644 main.twss delete mode 100644 templater.cpp delete mode 100644 tessesscriptengine.hpp delete mode 100644 tesseswebserver.cpp delete mode 100644 tesseswebserver.hpp delete mode 100644 tesseswebserverfeatures.hpp diff --git a/file.twss b/file.twss deleted file mode 100644 index 248a524..0000000 --- a/file.twss +++ /dev/null @@ -1,11 +0,0 @@ - \ No newline at end of file diff --git a/main.twss b/main.twss deleted file mode 100644 index e48704b..0000000 --- a/main.twss +++ /dev/null @@ -1,8 +0,0 @@ - -John - diff --git a/templater.cpp b/templater.cpp deleted file mode 100644 index f51b5ef..0000000 --- a/templater.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "tesseswebserver.hpp" -TESSESWEBSERVER_STATIC_DECLARATION -using namespace Tesses::WebServer; -using namespace Tesses::WebServer::ScriptEngine; - - - -int main(int argc,char** argv) -{ - RootEnvironment* rEnv = new RootEnvironment(); - rEnv->print = [](ScriptType arg)-> void { - - std::cout << ConvertToString(arg); - }; - - BytecodeCompiler bcc(ScriptParser::Parse("file.twss")); - bcc.Compile(); - auto rf = bcc.file->rootFunction; - rf->env = rEnv; - rf->isRoot=true; - for(auto f : bcc.file->functions) - { - auto rf2 = f.second; - rf2->env = rEnv; - rf2->isRoot=false; - - - - - rEnv->SetValue(f.first,ObjectType(f.second)); - } - - rf->Execute(rEnv,{}); - - - -} \ No newline at end of file diff --git a/tessesscriptengine.hpp b/tessesscriptengine.hpp deleted file mode 100644 index f800069..0000000 --- a/tessesscriptengine.hpp +++ /dev/null @@ -1,4233 +0,0 @@ -#pragma once - -#include "tesseswebserver.hpp" - - -#if defined(INCLUDED_FROM_TESSESWEBSERVER_H) -namespace ScriptEngine -#else -namespace Tesses::WebServer::ScriptEngine -#endif -{ - class Instruction - { - public: - virtual int Length()=0; - virtual void Write(uint8_t* buffer)=0; - virtual ~Instruction() - { - - } - const static uint8_t ADD = 0; - const static uint8_t SUB = 1; - const static uint8_t TIMES = 2; - const static uint8_t DIVIDE = 3; - const static uint8_t MOD = 4; - const static uint8_t LEFTSHIFT = 5; - const static uint8_t RIGHTSHIFT = 6; - const static uint8_t LESSTHAN = 7; - const static uint8_t GREATERTHAN = 8; - const static uint8_t LESSTHANEQUALTO = 9; - const static uint8_t GREATERTHANEQUALTO = 10; - const static uint8_t EQUALS = 11; - const static uint8_t NOTEQUALS = 12; - const static uint8_t BITWISEOR = 13; - const static uint8_t BITWISEAND = 14; - const static uint8_t BITWISENOT = 15; - const static uint8_t EXCLUSIVEOR = 16; - const static uint8_t LOGICALNOT = 17; - const static uint8_t NEGATIVE = 18; - const static uint8_t GETVARIABLE = 19; - const static uint8_t SETVARIABLE = 20; - const static uint8_t GETFIELD = 21; - const static uint8_t SETFIELD = 22; - const static uint8_t GETARRAY = 23; - const static uint8_t SETARRAY = 24; - const static uint8_t PUSH_STRING = 25; - const static uint8_t PUSH_CHAR = 26; - const static uint8_t PUSH_LONG = 27; - const static uint8_t PUSH_DOUBLE = 28; - const static uint8_t SET_LOOP = 29; //for scoping reasons - const static uint8_t GET_LOOP = 30; - const static uint8_t DESTROY_LOOP = 31; - const static uint8_t CALL_FUNC = 32; - const static uint8_t CALL_METHOD = 33; - const static uint8_t PRINT = 34; - const static uint8_t JMPC = 35; - const static uint8_t JMP = 36; - const static uint8_t POP = 37; - const static uint8_t RET = 38; - const static uint8_t SCOPE_BEGIN = 39; - const static uint8_t SCOPE_END = 40; - const static uint8_t GET_GLOBAL_VARIABLE = 41; - const static uint8_t SET_GLOBAL_VARIABLE = 42; - const static uint8_t GET_CALLER_VARIABLE = 43; - const static uint8_t SET_CALLER_VARIABLE = 44; - const static uint8_t DECLARE_VARIABLE = 45; - const static uint8_t PUSH_NULL = 46; - const static uint8_t PUSH_UNDEFINED = 47; - const static uint8_t PUSH_FALSE = 48; - const static uint8_t PUSH_TRUE = 49; - const static uint8_t ITTR = 50; - - #if defined(DEBUG) - virtual void Print() - { - - } - #endif - }; - class Object { - - public: - - virtual std::string ToString() - { - return ""; - } - virtual bool ToBool() - { - return false; - } - virtual bool CanDestroy() - { - return true; - } - - virtual ~Object() - { - - } - }; - - class Undefined { - - - }; - class Null - { - - }; - - - class ObjectType { - public: - Object* data; - ObjectType(Object* o) - { - this->data = o; - } - }; - - - typedef std::variant IttrType; - - - - - class IttrKVP { - public: - IttrType ittr; - int64_t index; - }; - - - typedef std::variant ScriptType; - class Ittr : public Object { - public: - IttrType ittr; - int64_t index; - }; - - - inline bool Equals(ScriptType& left, ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return true; - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return true; - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto objLeft = std::get(left).data; - auto objRight = std::get(right).data; - if(objLeft == objRight) - return true; - } - return false; - } - inline bool ConvertToBool(ScriptType& st) - { - if(std::holds_alternative(st)) - { - return std::get(st).size() > 0; - } - if(std::holds_alternative(st)) - { - return std::get(st) != 0; - } - if(std::holds_alternative(st)) - { - return std::get(st) != 0; - } - if(std::holds_alternative(st)) - { - return std::get(st); - } - if(std::holds_alternative(st)) - { - return std::get(st) != 0; - } - if(std::holds_alternative(st)) - { - return std::get(st).data->ToBool(); - } - return false; - } - inline ScriptType IttrGetValue(ScriptType& st); - inline std::string IttrGetKey(ScriptType& st); - inline std::string ConvertToString(ScriptType& st); - inline std::string ConvertToString(ScriptType& st) - { - if(std::holds_alternative(st)) - { - auto v = IttrGetValue(st); - - return IttrGetKey(st) + ": " + ConvertToString(v); - } - - if(std::holds_alternative(st)) - { - return "null"; - } - if(std::holds_alternative(st)) - { - return std::get(st); - } - if(std::holds_alternative(st)) - { - return std::to_string(std::get(st)); - } - if(std::holds_alternative(st)) - { - return std::to_string(std::get(st)); - } - if(std::holds_alternative(st)) - { - return std::get(st) ? "true" : "false"; - } - if(std::holds_alternative(st)) - { - return std::string({std::get(st)}); - } - if(std::holds_alternative(st)) - { - return std::get(st).data->ToString(); - } - - return "undefined"; - } - - class RootEnvironment; - - class Environment { - public: - std::function print; - virtual bool HasObject(std::string key) = 0; - virtual bool HasObjectRecurse(std::string key) = 0; - virtual ScriptType GetValue(std::string key) = 0; - virtual void SetValue(std::string key,ScriptType val) = 0; - virtual Environment* GetRoot()=0; - virtual Environment* GetParent()=0; - virtual Environment* GetGlobal() - { - return this->GetRoot()->GetGlobal(); - } - virtual void Declare(std::string key,ScriptType val) - { - SetValue(key,val); - } - Environment* GetSub(); - virtual ~Environment() - { - - } - }; - - class SubEnvironment : public Environment - { - Environment* parent; - public: - std::map items; - SubEnvironment(Environment* env) - { - this->parent = env; - } - Environment* GetParent() - { - return parent; - } - Environment* GetRoot() - { - return parent->GetRoot(); - } - - bool HasObject(std::string key) - { - return items.count(key) > 0; - } - bool HasObjectRecurse(std::string key) - { - if(items.count(key) > 0) return true; - - return this->parent->HasObjectRecurse(key); - } - ScriptType GetValue(std::string key) - { - if(HasObject(key)) - { - return items[key]; - } - return this->parent->GetValue(key); - } - void SetValue(std::string key,ScriptType val) - { - if(HasObject(key)) - { - items[key] = val; - return; - } - if(this->parent->HasObjectRecurse(key)) - { - this->parent->SetValue(key,val); - } - items[key] = val; - } - void Declare(std::string key,ScriptType val) - { - this->items[key] = val; - } - }; - - inline Environment* Environment::GetSub() - { - SubEnvironment* env = new SubEnvironment(this); - env->print = this->print; - return env; - } - class CallableObject : public Object - { - public: - bool useGlobalEnv=false; - - virtual bool FirstArgumentIsThis() - { - return false; - } - - bool CanDestroy() - { - return false; - } - - virtual ScriptType Execute(Environment* callerEnv,std::vector args) - { - return Null(); - } - - ScriptType Execute(Environment* callerEnv,std::initializer_list args) - { - return Execute(callerEnv,std::vector(args)); - } - - std::string ToString() - { - return ""; - } - bool ToBool() - { - return true; - } - - }; - - class ExternalFunction : public CallableObject { - public: - std::function)> callback; - bool firstArgIsThis; - bool FirstArgumentIsThis() - { - return firstArgIsThis; - } - ExternalFunction(std::function)> callback,bool firstArgIsThis=false) - { - this->callback = callback; - this->firstArgIsThis = firstArgIsThis; - } - ScriptType Execute(Environment* callerEnv,std::vector args) - { - return callback(callerEnv,args); - } - - ~ExternalFunction() - { - - } - }; - - class InternalFunction; - - class List : public Object { - public: - std::vector items; - std::string ToString() - { - return ""; - } - bool ToBool() - { - return items.size() > 0; - } - }; - - class Dictionary : public Object { - public: - std::vector> items; - std::string ToString() - { - return ""; - } - bool ToBool() - { - return items.size() > 0; - } - bool HasValue(std::string key) - { - for(auto item : items) - if(item.first == key) return true; - return false; - } - ScriptType GetValue(std::string key) - { - for(auto item : items) - if(item.first == key) return item.second; - return Undefined(); - } - - void SetValue(std::string key, ScriptType& value) - { - if(std::holds_alternative(value)) - { - for(auto item = items.cbegin();item <= items.cend();item++) - { - auto myItem = *item; - if(myItem.first == key) - { - items.erase(item); - return; - } - } - } - else - { - - for(auto item : items) - { - if(item.first == key) - { - item.second = value; - return; - } - } - - items.push_back(std::pair(key,value)); - } - } - }; - - inline ScriptType CreateIttrFor(ScriptType& st) - { - if(std::holds_alternative(st)) - { - Ittr* ittr =new Ittr(); - ittr->index = -1; - ittr->ittr = std::get(st); - ObjectType t(ittr); - return t; - } - if(std::holds_alternative(st)) - { - auto ot = std::get(st).data; - auto ls = dynamic_cast(ot); - auto dict = dynamic_cast(ot); - if(ls != nullptr) - { - Ittr* ittr=new Ittr(); - ittr->index = -1; - ittr->ittr = ObjectType(ls); - ObjectType t(ittr); - return t; - } - if(dict != nullptr) - { - Ittr* ittr=new Ittr(); - ittr->index = -1; - ittr->ittr = ObjectType(dict); - ObjectType t(ittr); - return t; - } - } - return Null(); - } - - inline bool IttrMoveNext(ScriptType& st) - { - if(std::holds_alternative(st)) - { - auto objIttr = std::get(st).data; - auto ittr = dynamic_cast(objIttr); - if(ittr == nullptr) return false; - if(std::holds_alternative(ittr->ittr)) - { - std::string str = std::get(ittr->ittr); - if(ittr->index >= -1 && ittr->index + 1 < str.size()) - { - (ittr->index)++; - return true; - } - } - if(std::holds_alternative(ittr->ittr)) - { - auto ot = std::get(ittr->ittr).data; - auto ls = dynamic_cast(ot); - auto dict = dynamic_cast(ot); - - if(ls != nullptr) - { - if(ittr->index >= -1 && ittr->index + 1 < ls->items.size()) - { - (ittr->index)++; - return true; - } - } - if(dict != nullptr) - { - if(ittr->index >= -1 && ittr->index + 1 < dict->items.size()) - { - (ittr->index)++; - return true; - } - } - } - } - return false; - } - - inline ScriptType IttrCurrent(ScriptType& st) - { - if(std::holds_alternative(st)) - { - auto objIttr = std::get(st).data; - auto ittr = dynamic_cast(objIttr); - if(ittr == nullptr) return Null(); - if(std::holds_alternative(ittr->ittr)) - { - std::string str = std::get(ittr->ittr); - if(ittr->index >= 0 && ittr->index < str.size()) - { - return str[ittr->index]; - } - } - if(std::holds_alternative(ittr->ittr)) - { - auto ot = std::get(ittr->ittr).data; - auto ls = dynamic_cast(ot); - auto dict = dynamic_cast(ot); - - if(ls != nullptr) - { - if(ittr->index >= 0 && ittr->index < ls->items.size()) - { - return ls->items[ittr->index]; - } - } - if(dict != nullptr) - { - if(ittr->index >= 0 && ittr->index < dict->items.size()) - { - IttrKVP kvp; - kvp.index = ittr->index; - kvp.ittr = ittr->ittr; - return kvp; - } - } - } - } - return Null(); - } - inline std::string IttrGetKey(ScriptType& st) - { - if(std::holds_alternative(st)) - { - auto ittr = std::get(st); - - if(std::holds_alternative(ittr.ittr)) - { - auto ot = std::get(ittr.ittr).data; - auto dict = dynamic_cast(ot); - - - if(dict != nullptr) - { - if(ittr.index >= 0 && ittr.index < dict->items.size()) - { - return dict->items[ittr.index].first; - } - } - } - } - return std::string({}); - } - - inline ScriptType IttrGetValue(ScriptType& st) - { - if(std::holds_alternative(st)) - { - auto ittr = std::get(st); - - if(std::holds_alternative(ittr.ittr)) - { - auto ot = std::get(ittr.ittr).data; - auto dict = dynamic_cast(ot); - - - if(dict != nullptr) - { - if(ittr.index >= 0 && ittr.index < dict->items.size()) - { - return dict->items[ittr.index].second; - } - } - } - } - return Null(); - } - inline ScriptType TypeOf(Environment* env, std::vector args); - class RootEnvironment : public Environment - { - std::vector fns; - public: - RootEnvironment() - { - DeclareFunctions(); - } - Environment* global=nullptr; - std::map items; - Environment* GetRoot() - { - return this; - } - Environment* GetGlobal() - { - if(global != nullptr) return global; - return this; - } - Environment* GetParent() - { - return this; - } - bool HasObject(std::string key) - { - return items.count(key) > 0; - } - bool HasObjectRecurse(std::string key) - { - return items.count(key) > 0; - } - ScriptType GetValue(std::string key) - { - return items[key]; - } - void SetValue(std::string key,ScriptType val) - { - items[key] = val; - } - void Free(ScriptType t,bool tree=false) - { - - if(std::holds_alternative(t)) - { - auto myObj=std::get(t); - - if(tree) - { - auto ls = dynamic_cast(myObj.data); - auto dict = dynamic_cast(myObj.data); - if(ls != nullptr) - { - for(auto item : ls->items) - Free(item,true); - } - if(dict != nullptr) - { - for(auto item : dict->items) - Free(item.second,true); - } - } - if(myObj.data != nullptr && myObj.data->CanDestroy()) - delete myObj.data; - } - } - void DeclareFunctions() - { - DeclareFunction("dictionary",[this](Environment* env, std::vector args)-> ScriptType { - Dictionary* dict=new Dictionary(); - ObjectType ot(dict); - return ot; - }); - DeclareFunction("list",[this](Environment* env, std::vector args)-> ScriptType { - List* list=new List(); - ObjectType ot(list); - return ot; - }); - DeclareFunction("typeof",TypeOf); - DeclareFunction("free",[this](Environment* env, std::vector args)-> ScriptType { - if(args.size() > 0) - { - Free(args[0]); - } - return Null(); - }); - - DeclareFunction("free_tree",[this](Environment* env, std::vector args)-> ScriptType { - if(args.size() > 0) - { - Free(args[0],true); - } - return Null(); - }); - } - void DeclareFunction(std::string name,std::function)> method) - { - ExternalFunction* item = new ExternalFunction(method); - - fns.push_back(item); - - ObjectType ot(item); - SetValue(name,ot); - } - ~RootEnvironment() - { - - for(auto item : fns) - delete item; - - } - }; - - class ChunkExecuter - { - uint8_t* bytecode; - size_t bytecodeLength; - std::vector* args; - size_t ip=0; - std::stack stack; - Environment* env; - public: - ChunkExecuter(Environment* env,uint8_t* bytecode,size_t bytecodeLength,std::vector* args) - { - this->bytecode = bytecode; - this->bytecodeLength = bytecodeLength; - this->args = args; - this->env = env; - } - - ScriptType Pop() - { - if(stack.empty()) throw std::exception(); - ScriptType t = stack.top(); - - - stack.pop(); - return t; - } - template - T PopSpecific() - { - auto p = Pop(); - - if(std::holds_alternative(p)) - { - return std::get(p); - } - else - { - std::vector args; - args.push_back(p); - auto v = TypeOf(env,args); - this->env->print("IP: "); - this->env->print((int64_t)ip); - this->env->print("Unexpected type: "); - this->env->print(v); - this->env->print(" with value "); - this->env->print(p); - this->env->print("\n"); - - - throw std::exception(); - } - } - int64_t PopLong() - { - auto val = PopSpecific(); - - - return val; - } - std::string PopString() - { - auto val = PopSpecific(); - return val; - } - - - ScriptType Mod(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) % std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return fmod(std::get(left), (double)std::get(right)); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return fmod((double)std::get(left), std::get(right)); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return fmod(std::get(left),std::get(right)); - } - - return Null(); - } - - ScriptType Divide(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) / std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) / (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) / std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) / std::get(right); - } - - return Null(); - } - - - ScriptType Times(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) * std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) * (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) * std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) * std::get(right); - } - - return Null(); - } - ScriptType GreaterThan(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) > std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) > (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) > std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) > std::get(right); - } - - return Null(); - } - ScriptType LessThan(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) < std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) < (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) < std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) < std::get(right); - } - - return Null(); - } - - ScriptType GreaterThanEqualsTo(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) >= std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) >= (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) >= std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) >= std::get(right); - } - - return Null(); - } - ScriptType LessThanEqualsTo(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) <= std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) <= (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) <= std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) <= std::get(right); - } - - return Null(); - } - - - - ScriptType Sub(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) - std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) - (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) - std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) - std::get(right); - } - - return Null(); - } - - ScriptType Add(ScriptType& left,ScriptType& right) - { - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + (double)std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return (double)std::get(left) + std::get(right); - } - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::to_string(std::get(left)) + std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::to_string(std::get(right)); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::to_string(std::get(left)) + std::get(right); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::to_string(std::get(right)); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) + std::string({std::get(right)}); - } - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::string({std::get(left)}) + std::get(right); - } - return Null(); - } - - ScriptType CallMethod(ScriptType& member, std::string key, std::vector& args) - { - - - if(std::holds_alternative(member)) - { - if(key == "toString") - { - return "undefined"; - } - } - if(std::holds_alternative(member)) - { - if(key == "toString") - { - return "null"; - } - } - if(std::holds_alternative(member)) - { - auto obj = std::get(member).data; - auto ls = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - auto ittr = dynamic_cast(obj); - if(ittr != nullptr) - { - if(key == "current") - { - return IttrCurrent(member); - } - if(key == "movenext") - { - return IttrMoveNext(member); - } - - } - if(ls != nullptr) - { - if(key == "add" && args.size() > 0) - { - ls->items.push_back(args[0]); - } - else if(key == "remove" && args.size() > 0) - { - for(auto ittr = ls->items.cbegin();ittritems.cend();ittr++) - { - auto item = *ittr; - if(Equals(item,args[0])) - { - ls->items.erase(ittr); - break; - } - } - } - else if(key == "indexof" && args.size() > 0) - { - int64_t index = -1; - for(auto ittr = ls->items.cbegin();ittritems.cend();ittr++) - { - auto item = *ittr; - if(Equals(item,args[0])) - { - break; - } - index++; - } - - return index; - } - else if(key == "insert" && args.size() > 1) - { - auto index = args[0]; - if(std::holds_alternative(index)) - { - auto myIndex=std::get(index); - if(myIndex >= 0 && myIndex <= ls->items.size()) - { - ls->items.insert(ls->items.cbegin() + myIndex,{args[1]}); - } - } - } - else if(key == "removeat" && args.size() > 0) - { - auto index = args[0]; - if(std::holds_alternative(index)) - { - auto myIndex=std::get(index); - if(myIndex >= 0 && myIndex < ls->items.size()) - { - ls->items.erase(ls->items.cbegin() + myIndex); - } - } - } - else if(key == "count" || key == "length") - { - return (int64_t)ls->items.size(); - } - else if(key == "clear") { - ls->items.clear(); - } - else if(key == "at" && args.size() > 0) - { - auto index = args[0]; - if(std::holds_alternative(index)) - { - auto myIndex=std::get(index); - if(myIndex >= 0 && myIndex < ls->items.size()) - { - return ls->items.at((size_t)myIndex); - } - } - } - else if(key == "set" && args.size() > 1) - { - auto index = args[0]; - if(std::holds_alternative(index)) - { - auto myIndex=std::get(index); - if(myIndex >= 0 && myIndex < ls->items.size()) - { - return ls->items[(size_t)myIndex]=args[1]; - } - } - } - } - - if(dict != nullptr) - { - auto item = dict->GetValue(key); - if(std::holds_alternative(item)) - { - auto fnt = std::get(item).data; - auto fn = dynamic_cast(fnt); - if(fn != nullptr) - { - if(fn->FirstArgumentIsThis()) - args.insert(args.cbegin(),{member}); - - - return fn->Execute(this->env,args); - } - } - if(key == "toString" && args.size() == 0) - { - return std::string({}); - } - } - } - if(std::holds_alternative(member)) - { - if(key == "toString") - { - return std::to_string(std::get(member)); - } - if(key == "toDouble") - { - return (double)std::get(member); - } - if(key == "toDoubleBits") - { - return std::bit_cast(std::get(member)); - } - if(key == "toChar") - { - return (char)std::get(member); - } - } - if(std::holds_alternative(member)) - { - std::string myStr=std::get(member); - if(key == "toString") - { - return myStr; - } - if(key == "length" || key == "count") - { - return (int64_t)myStr.size(); - } - if(key == "toLower") - { - std::transform(myStr.begin(),myStr.end(),myStr.begin(),::tolower); - return myStr; - } - if(key == "toUpper") - { - std::transform(myStr.begin(),myStr.end(),myStr.begin(),::toupper); - return myStr; - } - } - if(std::holds_alternative(member)) - { - if(key == "toString") - { - return std::string({std::get(member)}); - } - if(key == "toLong") - { - return (int64_t)std::get(member); - } - if(key == "toLower") - { - return (char)std::tolower(std::get(member)); - } - if(key == "toUpper") - { - return (char)std::toupper(std::get(member)); - } - } - if(std::holds_alternative(member)) - { - if(key == "toString") - { - return std::to_string(std::get(member)); - } - if(key == "toLong") - { - return (int64_t)std::get(member); - } - if(key == "toLongBits") - { - return std::bit_cast(std::get(member)); - } - } - - return Undefined(); - } - - ScriptType SetField(ScriptType& instance,std::string name,ScriptType& value) - { - - if(std::holds_alternative(instance)) - { - auto inst = std::get(instance).data; - - auto dict = dynamic_cast(inst); - - if(dict != nullptr) - { - auto myFuncObj = dict->GetValue(std::string("set") + name); - - if(std::holds_alternative(myFuncObj)) - { - auto myFuncObj2 = std::get(myFuncObj).data; - auto callbl = dynamic_cast(myFuncObj2); - if(callbl != nullptr) - { - if(callbl->FirstArgumentIsThis()) - { - return callbl->Execute(env,{instance,value}); - } - else - { - return callbl->Execute(env,{value}); - } - } - } - - - dict->SetValue(name,value); - } - } - return value; - } - - ScriptType GetField(ScriptType& instance, std::string name) - { - if(std::holds_alternative(instance)) - { - auto str = std::get(instance); - if(name == "length" || name == "count") - { - return (int64_t)str.size(); - } - } - if(std::holds_alternative(instance)) - { - if(name == "key") - { - return IttrGetKey(instance); - } - - if(name == "value") - { - return IttrGetValue(instance); - } - } - if(std::holds_alternative(instance)) - { - auto inst = std::get(instance).data; - auto ls = dynamic_cast(inst); - auto dict = dynamic_cast(inst); - if(ls != nullptr) - { - if(name == "length" || name == "count") - { - return (int64_t)ls->items.size(); - } - } - if(dict != nullptr) - { - auto myFuncObj = dict->GetValue(std::string("get") + name); - - if(std::holds_alternative(myFuncObj)) - { - auto myFuncObj2 = std::get(myFuncObj).data; - auto callbl = dynamic_cast(myFuncObj2); - if(callbl != nullptr) - { - if(callbl->FirstArgumentIsThis()) - { - return callbl->Execute(env,{instance}); - } - else - { - return callbl->Execute(env,{}); - } - } - } - - - return dict->GetValue(name); - } - } - return Undefined(); - } - - ScriptType Execute(Environment* callerEnv,std::vector __args) - { - // std::cout << __args.size() << " " << this->args->size() << std::endl; - if(__args.size() != this->args->size()) - { - callerEnv->print("Expected " + std::to_string((int64_t)this->args->size()) + " args, got " + std::to_string((int64_t)__args.size()) + " args.\n"); - throw std::exception(); - } - - for(size_t i = 0;i<__args.size();i++) - { - - env->Declare(this->args->at(i),__args[i]); - } - - - int scopes=0; - std::stack loops; - - while(ip < bytecodeLength) - { - uint8_t instruction = bytecode[ip]; - - ip++; - switch(instruction) - { - case Instruction::PUSH_FALSE: - { - stack.push(false); - } - break; - case Instruction::PUSH_TRUE: - { - stack.push(true); - } - break; - case Instruction::PUSH_NULL: - { - stack.push(Null()); - } - break; - case Instruction::PUSH_UNDEFINED: - { - stack.push(Undefined()); - } - break; - case Instruction::PUSH_CHAR: - { - if(ip + 1 <= bytecodeLength) - { - stack.push((char)bytecode[ip++]); - } - else - { - throw std::exception(); - } - } - break; - case Instruction::CALL_FUNC: - { - int64_t lng=PopLong(); - std::vector _args; - for(int i = 0;i(std::get(fCall).data); - if(myF != nullptr) - { - stack.push(myF->Execute(env,_args)); - - } - else - { - stack.push(Null()); - } - } - break; - case Instruction::CALL_METHOD: - { - int64_t lng=PopLong(); - std::vector _args; - for(int i = 0;iGetValue(str); - stack.push(v); - } - break; - case Instruction::SET_CALLER_VARIABLE: - { - auto v = Pop(); - auto str = PopString(); - callerEnv->SetValue(str,v); - stack.push(v); - } - break; - case Instruction::GET_GLOBAL_VARIABLE: - { - auto str = PopString(); - auto v = env->GetGlobal()->GetValue(str); - stack.push(v); - } - break; - case Instruction::SET_GLOBAL_VARIABLE: - { - auto v = Pop(); - auto str = PopString(); - env->GetGlobal()->SetValue(str,v); - stack.push(v); - } - break; - case Instruction::GETVARIABLE: - { - auto str = PopString(); - - auto v = env->GetValue(str); - stack.push(v); - } - break; - case Instruction::SETVARIABLE: - { - auto v = Pop(); - auto str = PopString(); - env->SetValue(str,v); - stack.push(v); - } - break; - case Instruction::DECLARE_VARIABLE: - { - auto v = Pop(); - auto str = PopString(); - env->Declare(str,v); - stack.push(v); - } - break; - case Instruction::PRINT: - { - auto v = Pop(); - - callerEnv->print(v); - } - break; - case Instruction::SCOPE_BEGIN: - { - scopes++; - env = env->GetSub(); - } - break; - case Instruction::SCOPE_END: - { - Environment* env2 = env; - env=env2->GetParent(); - if(env != env2) - { - delete env2; - } - scopes--; - } - break; - case Instruction::SET_LOOP: - { - loops.push(scopes); - } - break; - case Instruction::GET_LOOP: - { - int myLoops = loops.top(); - - while(scopes > myLoops) - { - Environment* env2 = env; - env=env2->GetParent(); - if(env != env2) - { - delete env2; - } - - scopes--; - } - } - break; - case Instruction::DESTROY_LOOP: - { - int myLoops = loops.top(); - loops.pop(); - - while(scopes > myLoops) - { - Environment* env2 = env; - env=env2->GetParent(); - if(env != env2) - { - delete env2; - } - - scopes--; - } - } - break; - case Instruction::RET: - { - auto val = Pop(); - while(scopes > 0) - { - Environment* env2 = env; - env=env2->GetParent(); - if(env != env2) - { - delete env2; - } - - scopes--; - } - - return val; - } - break; - case Instruction::JMP: - { - if(ip + 4 <= bytecodeLength) - { - - - size_t len = ((size_t)bytecode[ip++] << 24); - len |= ((size_t)bytecode[ip++] << 16); - len |= ((size_t)bytecode[ip++] << 8); - len |= (size_t)bytecode[ip++]; - if(len < bytecodeLength) - ip = len; - else - { - std::cout << "Jump failed" << std::endl; - throw std::exception(); - } - } - } - break; - case Instruction::JMPC: - { - if(ip + 4 <= bytecodeLength) - { - - - size_t len = ((size_t)bytecode[ip++] << 24); - len |= ((size_t)bytecode[ip++] << 16); - len |= ((size_t)bytecode[ip++] << 8); - len |= (size_t)bytecode[ip++]; - if(len < bytecodeLength) - { - auto v = Pop(); - if(ConvertToBool(v)) - ip = len; - - } - else - { - std::cout << "Jump failed" << std::endl; - throw std::exception(); - } - } - } - break; - case Instruction::ITTR: - { - auto ittr=Pop(); - stack.push(CreateIttrFor(ittr)); - } - break; - case Instruction::GETFIELD: - { - std::string name = PopString(); - auto instance = Pop(); - stack.push(GetField(instance,name)); - } - break; - case Instruction::SETFIELD: - { - auto val = Pop(); - std::string name = PopString(); - auto instance = Pop(); - stack.push(SetField(instance,name,val)); - } - break; - } - } - while(scopes > 0) - { - Environment* env2 = env; - env=env2->GetParent(); - if(env != env2) - { - delete env2; - } - - scopes--; - } - return Null(); - } - }; - - class InternalFunction : public CallableObject - { - public: - bool isRoot=false; - uint8_t* bytecode; - size_t bytecodeLength; - std::vector args; - Environment* env; - bool FirstArgumentIsThis() - { - return args.size() > 0 && args[0] == "this"; - } - ScriptType Execute(Environment* callerEnv,std::vector args) - { - Environment* env2 = isRoot ? env : env->GetSub(); - ChunkExecuter exec(env2,bytecode,bytecodeLength,&this->args); - - - auto ret=exec.Execute(callerEnv,args); - - if(!isRoot) delete env2; - return ret; - } - }; - - - - class LexToken { - public: - std::string text; - bool isString; - bool isChar; - - LexToken(std::string text) - { - this->text = text; - this->isString = false; - this->isChar = false; - } - - LexToken(std::string text,bool isString) - { - this->text = text; - this->isString = isString; - this->isChar = !isChar; - } - - LexToken(const LexToken& tkn) - { - this->text = tkn.text; - this->isString = tkn.isString; - this->isChar = tkn.isChar; - } - }; - - class Node { - public: - virtual bool IsExpression() { - return false; - } - virtual ~Node() - { - - } - }; - - class Expression : public Node { - public: - bool IsExpression() - { - return true; - } - }; - - class OneExpression : public Expression { - public: - Node* node; - OneExpression(Node* node) - { - this->node = node; - } - }; - - class TwoExpression : public Expression { - public: - Node* left; - Node* right; - TwoExpression(Node* left,Node* right) - { - this->left = left; - this->right = right; - } - }; - - #define LIST_OF_CONST_EXPRESSIONS \ - NODE(bool,Bool) \ - NODE(std::string,String) \ - NODE(int64_t,Long) \ - NODE(double,Double) \ - NODE(char,Char) - - - - #define LIST_OF_ONE_EXPRESSIONS \ - NODE(PostfixIncrement) \ - NODE(PostfixDecrement) \ - NODE(PrefixIncrement) \ - NODE(PrefixDecrement) \ - NODE(BitwiseNot) \ - NODE(LogicalNot) \ - NODE(Negative) \ - NODE(CompoundAssign) \ - NODE(Global) \ - NODE(Caller) \ - NODE(Var) - - #define LIST_OF_TWO_EXPRESSIONS \ - NODE(Add) \ - NODE(Sub) \ - NODE(Times) \ - NODE(Divide) \ - NODE(Mod) \ - NODE(LeftShift) \ - NODE(RightShift) \ - NODE(LessThan) \ - NODE(GreaterThan) \ - NODE(LessThanEqualTo) \ - NODE(GreaterThanEqualTo) \ - NODE(Equals) \ - NODE(NotEquals) \ - NODE(BitwiseOr) \ - NODE(BitwiseAnd) \ - NODE(ExclusiveOr) \ - NODE(LogicalOr) \ - NODE(LogicalAnd) \ - NODE(Assign) - - - #define NODE(_node) class _node##Expression : public OneExpression { \ - public: \ - _node##Expression(Node* n) : OneExpression(n) {} ~_node##Expression() {delete node;} \ - }; - LIST_OF_ONE_EXPRESSIONS - #undef NODE - - #define NODE(node) class node##Expression : public TwoExpression { \ - public: \ - node##Expression(Node* n,Node* n2) : TwoExpression(n,n2) {} ~node##Expression() {delete left; delete right;} \ - }; - LIST_OF_TWO_EXPRESSIONS - #undef NODE - - #define NODE(ttype,tname) class Const##tname##Expression : public Expression { \ - public: \ - ttype value; \ - Const##tname##Expression(ttype v) \ - { \ - this->value = v; \ - }\ - }; - LIST_OF_CONST_EXPRESSIONS - #undef NODE - - class ConstNullExpression : public Expression {}; - class ConstUndefinedExpression : public Expression {}; - - class GetVariableExpression : public Expression { - public: - std::string name; - GetVariableExpression(std::string name) - { - this->name = name; - } - }; - - class IfNode : public Node { - public: - Node* cond; - Node* yes; - Node* no; - IfNode(Node* cond,Node* yes,Node* no) - { - this->cond = cond; - this->yes = yes; - this->no = no; - } - ~IfNode() - { - delete cond; - delete yes; - delete no; - } - }; - class TernaryExpression : public Expression { - public: - Node* cond; - Node* yes; - Node* no; - TernaryExpression(Node* cond,Node* yes,Node* no) - { - this->cond = cond; - this->yes = yes; - this->no = no; - } - ~TernaryExpression() - { - delete cond; - delete yes; - delete no; - } - }; - - class WhileNode : public Node { - public: - Node* cond; - Node* body; - bool isDo; - WhileNode(Node* cond,Node* body, bool isDo) - { - this->cond = cond; - this->body = body; - this->isDo = isDo; - } - ~WhileNode() - { - delete cond; - delete body; - } - }; - - class ForNode : public Node { - public: - Node* init; - Node* cond; - Node* inc; - Node* body; - ForNode(Node* init,Node* cond,Node* inc,Node* body) - { - this->init = init; - this->cond = cond; - this->inc = inc; - this->body = body; - } - ~ForNode() - { - delete init; - delete cond; - delete inc; - delete body; - } - }; - - class PrintNode : public Node { - public: - Node* expr; - PrintNode(Node* expr) - { - this->expr = expr; - } - ~PrintNode() - { - delete expr; - } - }; - - class EachNode : public Node { - public: - Node* item; - Node* list; - Node* body; - EachNode(Node* item,Node* list,Node* body) - { - this->item = item; - this->list = list; - this->body = body; - } - ~EachNode() - { - delete item; - delete list; - delete body; - } - }; - - class FunctionDeclarationNode : public Node { - public: - Node* nameAndArgs; - Node* body; - FunctionDeclarationNode(Node* nameAndArgs,Node* body) - { - this->nameAndArgs = nameAndArgs; - this->body = body; - } - ~FunctionDeclarationNode() - { - delete nameAndArgs; - delete body; - } - }; - - class FunctionCallExpression : public Expression - { - public: - std::vector args; - Node* name; - FunctionCallExpression(Node* name) { - this->name = name; - } - ~FunctionCallExpression() - { - for(auto item : args) - { - delete item; - } - delete name; - } - }; - - class GetMemberExpression : public Expression - { - public: - std::string name; - Node* parent; - GetMemberExpression(Node* parent,std::string name) - { - this->parent = parent; - this->name = name; - } - ~GetMemberExpression() - { - delete parent; - } - }; - class GetArrayExpression : public Expression - { - public: - Node* expr; - Node* parent; - GetArrayExpression(Node* parent,Node* expr) - { - this->parent = parent; - this->expr = expr; - } - ~GetArrayExpression() - { - delete expr; - delete parent; - } - }; - - class ReturnNode : public Node { - public: - Node* retVal; - ReturnNode(Node* retVal) - { - this->retVal = retVal; - } - ~ReturnNode() - { - delete retVal; - } - }; - - class BreakNode : public Node {}; - class ContinueNode : public Node {}; - - class ScopeNode : public Node { - public: - std::vector items; - bool rootScope; - ~ScopeNode() - { - for(auto item : items) - delete item; - } - }; - - class ScriptParser - { - size_t i = 0; - std::vector tokens; - std::filesystem::path path; - - - - static std::string Template(std::filesystem::path file) - { - //convert anything out of to print ""; statements - - std::string myRealBuf = {}; - - bool inCode = false; - std::string buffer={}; - - FILE* fs = fopen(file.c_str(),"rb"); - if(fs == NULL) return ""; - - uint8_t sliding_buffer[7]; - - size_t len=0; - - auto advance = [&sliding_buffer,&len,&fs]()-> bool { - if(len > 0) - { - len--; - for(size_t i = 0;i 0; - }; - - auto flush = [&buffer,&myRealBuf,&inCode]() -> void { - if(buffer.size() == 0) return; - if(inCode) - { - myRealBuf.append(buffer); - } - else - { - myRealBuf.append("print \""); - for(auto item : buffer) - { - switch(item) - { - case '\0': - myRealBuf.append("\\0"); - break; - case '\n': - myRealBuf.append("\\n"); - break; - case '\r': - myRealBuf.append("\\r"); - break; - case '\f': - myRealBuf.append("\\f"); - break; - case '\t': - myRealBuf.append("\\t"); - break; - case '\v': - myRealBuf.append("\\v"); - break; - case '\b': - myRealBuf.append("\\b"); - break; - case '\a': - myRealBuf.append("\\a"); - break; - case '\x1B': - myRealBuf.append("\\e"); - break; - case '\"': - case '\'': - case '\\': - myRealBuf.push_back('\\'); - myRealBuf.push_back(item); - break; - default: - myRealBuf.push_back(item); - break; - } - } - - myRealBuf.append("\";"); - } - buffer = {}; - }; - - while(advance()) - { - if(memcmp(sliding_buffer,"",3) == 0) - { - flush(); - inCode=false; - for(int i = 0;i<3;i++) - if(advance() == false) break; - if(len == 0) break; - } - - buffer.push_back((char)sliding_buffer[0]); - } - flush(); - fclose(fs); - return myRealBuf; - } - - static void Lex(std::filesystem::path file,std::vector& tokens) - { - std::string text = Template(file); - - size_t offset = 0; - - int peeked = -1; - - auto peek = [&text,&offset,&peeked]() -> int { - if(peeked > -1) return peeked; - - if(offset < text.size()) - { - peeked = text[offset]; - offset++; - return peeked; - } - return -1; - }; - - auto read = [&text,&offset,&peeked]() -> int { - if(peeked != -1) - { - int myPeek = peeked; - peeked=-1; - return myPeek; - } - - if(offset < text.size()) - { - int c = text[offset]; - offset++; - return c; - } - return -1; - }; - int myRead=-1; - int myPeek=-1; - - std::string buf={}; - - auto flush = [&buf,&tokens]()-> void { - if(buf.size() > 0) - { - tokens.push_back(LexToken(buf)); - buf.clear(); - } - }; - - auto read_chr_ = [&read]()-> std::pair - { - int myC = read(); - if(myC == '\\') - { - myC = read(); - - if(myC == 'n') - { - return std::pair('\n',true); - } - else if(myC == 'r') - { - return std::pair('\r',true); - } - else if(myC == 'v') - { - return std::pair('\v',true); - } - else if(myC == 't') - { - return std::pair('\t',true); - } - else if(myC == 'b') - { - return std::pair('\b',true); - } - else if(myC == 'a') - { - return std::pair('\a',true); - } - else if(myC == 'e') - { - return std::pair('\x1B',true); - } - else if(myC == '0') - { - return std::pair('\0',true); - } - else if(myC == 'x') - { - int x1 = read(); - int x2 = read(); - - return std::pair(((HttpUtils::hex_char_to_nibble(x1) << 4) & 0xF) | (HttpUtils::hex_char_to_nibble(x2) & 0xF),true); - } - else { - return std::pair(myC,true); - } - } - return std::pair(myC,false); - }; - - auto read_string = [&read_chr_,&tokens]()-> void { - std::pair c; - std::string myStr = {}; - while((c = read_chr_()).first != -1) - { - if(c.first == '\"' && !c.second) break; - myStr.push_back((char)c.first); - } - - tokens.push_back(LexToken(myStr,true)); - }; - - auto read_char = [&read_chr_,&tokens,&read]()-> void { - auto v = read_chr_(); - if(v.first != -1) - { - tokens.push_back(LexToken(std::string({(char)v.first}),false)); - } - read(); - }; - - while((myRead = read()) != -1) - { - myPeek = peek(); - - switch(myRead) - { - case '/': - flush(); - if(myPeek == '/') - { - while(true) - { - myRead = read(); - if(myRead == -1) throw std::exception(); - if(myRead == '\n') break; - } - } - else if(myPeek == '*') - { - read(); - while(true) - { - myRead = read(); - if(myRead == -1) throw std::exception(); - if(myRead == '*') - { - myRead = read(); - if(myRead == '/') break; - } - } - } - else if(myPeek == '=') - { - read(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - else - { - tokens.push_back(LexToken(std::string({(char)myRead}))); - } - break; - case '\"': - flush(); - read_string(); - break; - case '\'': - flush(); - read_char(); - break; - case '<': - case '>': - { - if(myPeek == myRead) - { - read(); - flush(); - int myPeek2 = peek(); - - if(myPeek2 == '=') - { - read(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek,'='}))); - } - else{ - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - } - else if(myPeek == '=') - { - read(); - flush(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - else - { - flush(); - tokens.push_back(LexToken(std::string({(char)myRead}))); - } - } - - break; - case '+': - case '-': - case '|': - case '&': - { - if(myPeek == myRead) - { - read(); - flush(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - else if(myPeek == '=') - { - read(); - flush(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - else - { - flush(); - tokens.push_back(LexToken(std::string({(char)myRead}))); - } - } - - break; - case '^': - case '*': - case '%': - case '=': - case '!': - { - if(myPeek == '=') - { - read(); - flush(); - tokens.push_back(LexToken(std::string({(char)myRead,(char)myPeek}))); - } - else - { - flush(); - tokens.push_back(LexToken(std::string({(char)myRead}))); - } - } - break; - case '?': - case '.': - case ';': - case ':': - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - case ',': - flush(); - tokens.push_back(LexToken(std::string({(char)myRead}))); - break; - case '\r': - case '\n': - case '\t': - case ' ': - flush(); - break; - default: - buf.push_back((char)myRead); - break; - - } - } - } - - bool NextTokenIs(std::string val, bool take=true) - { - //std::cout << val << " == " << tokens[i].text << std::endl; - if(i >= tokens.size()) return false; - if(!tokens[i].isChar && !tokens[i].isString && tokens[i].text == val) - { - if(take) i++; - - return true; - } - return false; - } - - ScriptParser(std::filesystem::path path) - { - Lex(path,tokens); - this->path = path; - } - - - - - void Ensure(std::string val) - { - - - if(i >= tokens.size()) throw std::exception(); - - - if(!tokens[i].isChar && !tokens[i].isString && tokens[i].text == val) - { - i++; - return; - } - - throw std::exception(); - } - - bool IsAnyOf(std::initializer_list tkns, std::string& txt) - { - if(this->i >= this->tokens.size()) return false; - for(auto item : tkns) - { - if(this->tokens[i].isString) continue; - if(this->tokens[i].isChar) continue; - if(this->tokens[i].text.compare(item) == 0) - { - this->i++; - txt = item; - return true; - } - } - return false; - } - Node* ParseValue() - { - if(i>=tokens.size()) throw std::exception(); - if(tokens[i].isString) - { - auto val=tokens[i].text; - i++; - return new ConstStringExpression(val); - } - if(tokens[i].isChar) - { - auto val = tokens[i].text; - i++; - return new ConstCharExpression(val[0]); - } - - std::string token = tokens[i].text; - - - i++; - - bool hasNumber=true; - int64_t lngNum = 0; - - if(token.size() == 1 && token[0] == '0') - { - lngNum = 0; - } - else - if(token.size() > 0 && token[0] == '0') - { - if(token.size() > 1 && token[1] == 'x') - { - lngNum = std::stoll(token.substr(2),nullptr,16); - } - else if(token.size() > 1 && token[1] == 'b') - { - lngNum = std::stoll(token.substr(2),nullptr,2); - } - else - { - lngNum = std::stoll(token.substr(1),nullptr,8); - } - - } - else if(token.size() > 0 && token[0] >= '0' && token[0] <= '9') - { - lngNum=std::stoll(token,nullptr,10); - } - else - { - hasNumber = false; - } - - Node* val = nullptr; - - - - if(hasNumber && this->NextTokenIs(".",false) && i+1 < tokens.size() && !tokens[i+1].isChar && !tokens[i+1].isString) - { - std::string myToken = tokens[i+1].text; - if(myToken.size() > 0 && myToken[0] >= '0' && myToken[0] <= '9') - { - i+=2; - std::string myN = std::to_string(lngNum) + "." + myToken; - - double v = std::stod(myN,nullptr); - - val = new ConstDoubleExpression(v); - } - else - { - val = new ConstLongExpression(lngNum); - } - } - else if(hasNumber) - { - val = new ConstLongExpression(lngNum); - } - else { - if(token == "(") - { - val = ParseExpression(); - Ensure(")"); - } - if(token == "true") - { - val = new ConstBoolExpression(true); - } - else if(token == "false") - { - val = new ConstBoolExpression(false); - } - else if(token == "null") - { - val = new ConstNullExpression(); - } - else if(token == "undefined") - { - val = new ConstUndefinedExpression(); - } - else if(token == "var") - { - if(i>=tokens.size()) throw std::exception(); - if(tokens[i].isString) throw std::exception(); - if(tokens[i].isChar) throw std::exception(); - val = new VarExpression(new GetVariableExpression(tokens[i].text)); - i++; - - } - else if(token == "global") - { - if(i>=tokens.size()) throw std::exception(); - if(tokens[i].isString) throw std::exception(); - if(tokens[i].isChar) throw std::exception(); - val = new GlobalExpression(new GetVariableExpression(tokens[i].text)); - i++; - } - else if(token == "caller") - { - if(i>=tokens.size()) throw std::exception(); - if(tokens[i].isString) throw std::exception(); - if(tokens[i].isChar) throw std::exception(); - val = new CallerExpression(new GetVariableExpression(tokens[i].text)); - i++; - } - else { - - val = new GetVariableExpression(token); - } - } - std::string myT; - while(IsAnyOf({".","[","("},myT)) - { - if(myT == ".") - { - if(i>=tokens.size()) throw std::exception(); - if(tokens[i].isChar || tokens[i].isString) throw std::exception(); - std::string name = tokens[i].text; - i++; - val = new GetMemberExpression(val, name); - } - if(myT == "[") - { - Node* expr=ParseExpression(); - Ensure("]"); - val = new GetArrayExpression(val,expr); - } - if(myT == "(") - { - auto fcall = new FunctionCallExpression(val); - while(!NextTokenIs(")",false)) - { - fcall->args.push_back(ParseExpression()); - if(!NextTokenIs(")",false)) - Ensure(","); - } - Ensure(")"); - val = fcall; - } - } - - return val; - } - Node* ParseUnary() - { - if(NextTokenIs("-")) - { - return new NegativeExpression(ParseUnary()); - } - if(NextTokenIs("~")) - { - return new BitwiseNotExpression(ParseUnary()); - } - if(NextTokenIs("!")) - { - return new LogicalNotExpression(ParseUnary()); - } - if(NextTokenIs("--")) - { - return new PrefixDecrementExpression(ParseUnary()); - } - if(NextTokenIs("++")) - { - return new PrefixIncrementExpression(ParseUnary()); - } - - - return ParseValue(); - } - Node* ParseFactor() - { - Node* v = ParseUnary(); - std::string tok; - while(IsAnyOf({"*","/","%"},tok)) - { - if(tok == "*") - v = new TimesExpression(v,ParseUnary()); - if(tok == "/") - v = new DivideExpression(v,ParseUnary()); - if(tok == "%") - v = new ModExpression(v,ParseUnary()); - } - return v; - } - Node* ParseSum() - { - Node* v = ParseFactor(); - std::string tok; - while(IsAnyOf({"+","-"},tok)) - { - if(tok == "+") - v = new AddExpression(v,ParseFactor()); - if(tok == "-") - v = new SubExpression(v,ParseFactor()); - } - return v; - } - Node* ParseShift() - { - Node* v = ParseSum(); - std::string tok; - while(IsAnyOf({"<<",">>"},tok)) - { - if(tok == "<<") - v = new LeftShiftExpression(v,ParseSum()); - if(tok == ">>") - v = new RightShiftExpression(v,ParseSum()); - } - return v; - } - Node* ParseRel() - { - Node* v = ParseShift(); - std::string tok; - while(IsAnyOf({"<",">","<=",">="},tok)) - { - if(tok == "<") - v = new LessThanExpression(v,ParseShift()); - if(tok == ">") - v = new GreaterThanExpression(v,ParseShift()); - if(tok == "<=") - v = new LessThanEqualToExpression(v,ParseShift()); - if(tok == ">=") - v = new GreaterThanEqualToExpression(v,ParseShift()); - } - return v; - } - Node* ParseEq() - { - Node* v = ParseRel(); - std::string tok; - while(IsAnyOf({"!=","=="},tok)) - { - if(tok == "!=") - v = new NotEqualsExpression(v,ParseRel()); - if(tok == "==") - v = new EqualsExpression(v,ParseRel()); - } - return v; - } - Node* ParseBAnd() - { - Node* v = ParseEq(); - while(NextTokenIs("&")) - { - v = new BitwiseAndExpression(v,ParseEq()); - } - return v; - } - Node* ParseXOr() - { - Node* v = ParseBAnd(); - while(NextTokenIs("^")) - { - v = new ExclusiveOrExpression(v,ParseBAnd()); - } - return v; - } - Node* ParseBOr() - { - Node* v = ParseXOr(); - while(NextTokenIs("|")) - { - v = new BitwiseOrExpression(v,ParseXOr()); - } - return v; - } - Node* ParseLAnd() - { - Node* v = ParseBOr(); - while(NextTokenIs("&&")) - { - v = new LogicalAndExpression(v,ParseBOr()); - } - return v; - } - - Node* ParseLOr() - { - Node* v = ParseLAnd(); - while(NextTokenIs("||")) - { - v = new LogicalOrExpression(v,ParseLAnd()); - } - return v; - } - - Node* ParseTernary() - { - Node* cond = ParseLOr(); - if(NextTokenIs("?")) - { - Node* yes = ParseTernary(); - Ensure(":"); - Node* no = ParseTernary(); - return new TernaryExpression(cond,yes,no); - } - return cond; - } - - Node* ParseExpression() - { - Node* v = ParseTernary(); - std::string t; - while(IsAnyOf({"=","+=","-=","*=","/=","%=","<<=",">>=","&=","^=","|="},t)) - { - if(t == "=") - { - v = new AssignExpression(v,ParseTernary()); - } - if (t == "+=") - { - v = new CompoundAssignExpression(new AddExpression(v,ParseTernary())); - } - if (t == "-=") - { - v = new CompoundAssignExpression(new SubExpression(v,ParseTernary())); - } - if (t == "*=") - { - v = new CompoundAssignExpression(new TimesExpression(v,ParseTernary())); - } - if (t == "/=") - { - v = new CompoundAssignExpression(new DivideExpression(v,ParseTernary())); - } - if (t == "%=") - { - v = new CompoundAssignExpression(new ModExpression(v,ParseTernary())); - } - if (t == "<<=") - { - v = new CompoundAssignExpression(new LeftShiftExpression(v,ParseTernary())); - } - if (t == ">>=") - { - v = new CompoundAssignExpression(new RightShiftExpression(v,ParseTernary())); - } - if (t == "&=") - { - v = new CompoundAssignExpression(new BitwiseAndExpression(v,ParseTernary())); - } - if (t == "^=") - { - v = new CompoundAssignExpression(new ExclusiveOrExpression(v,ParseTernary())); - } - if (t == "|=") - { - v = new CompoundAssignExpression(new BitwiseOrExpression(v,ParseTernary())); - } - } - return v; - } - - - Node* ParseNode(bool rootNode=false) - { - if(NextTokenIs("{") || rootNode) - { - - ScopeNode* sn = new ScopeNode(); - sn->rootScope = rootNode; - - while(this->i < this->tokens.size() && !NextTokenIs("}")) - { - sn->items.push_back(ParseNode()); - - NextTokenIs(";"); - } - return sn; - } - - if(NextTokenIs("include")) - { - - if(i < tokens.size()) - { - std::filesystem::path par = this->path.parent_path(); - - std::string file = tokens[i].text; - i++; - Ensure(";"); - - ScriptParser p(par / file); - - return p.ParseNode(true); - } - } - if(NextTokenIs("print")) - { - Node* n=new PrintNode(ParseExpression()); - Ensure(";"); - return n; - } - if(NextTokenIs("return")) - { - Node* n=new ReturnNode(ParseExpression()); - Ensure(";"); - return n; - } - if(NextTokenIs("break")) - { - Ensure(";"); - return new BreakNode(); - } - if(NextTokenIs("continue")) - { - Ensure(";"); - return new ContinueNode(); - } - if(NextTokenIs("if")) - { - Ensure("("); - Node* cond = ParseExpression(); - Ensure(")"); - - Node* yes = nullptr; - - if(!NextTokenIs("else",false)) - { - yes = ParseNode(); - NextTokenIs(";"); - } - - Node* no = nullptr; - - if(NextTokenIs("else")) - { - no = ParseNode(); - NextTokenIs(";"); - } - - return new IfNode(cond,yes,no); - } - if(NextTokenIs("for")) - { - Ensure("("); - - Node* init = nullptr; - Node* cond = nullptr; - Node* inc = nullptr; - - if(!NextTokenIs(";",false)) - { - init = ParseExpression(); - } - Ensure(";"); - if(!NextTokenIs(";",false)) - { - cond = ParseExpression(); - } - Ensure(";"); - if(!NextTokenIs(")",false)) - { - inc = ParseExpression(); - } - Ensure(")"); - - Node* body = ParseNode(); - NextTokenIs(";"); - - return new ForNode(init,cond,inc,body); - } - if(NextTokenIs("while")) - { - Ensure("("); - Node* cond = ParseExpression(); - Ensure(")"); - Node* body = ParseNode(); - NextTokenIs(";"); - return new WhileNode(cond,body,false); - } - if(NextTokenIs("do")) - { - Ensure("("); - Node* cond = ParseExpression(); - Ensure(")"); - Node* body = ParseNode(); - NextTokenIs(";"); - return new WhileNode(cond,body,true); - } - if(NextTokenIs("each")) - { - Ensure("("); - Node* list = ParseExpression(); - Node* item = nullptr; - - if(NextTokenIs(":")) - { - item = list; - list = ParseExpression(); - } - else - { - item = new GetVariableExpression("item"); - } - Ensure(")"); - Node* body = ParseNode(); - NextTokenIs(";"); - return new EachNode(item,list,body); - } - if(NextTokenIs("func")) - { - Node* fn = ParseExpression(); - Node* body = ParseNode(); - NextTokenIs(";"); - - return new FunctionDeclarationNode(fn,body); - } - Node* n= ParseExpression(); - Ensure(";"); - return n; - } - - - public: - static Node* Parse(std::filesystem::path path) - { - ScriptParser p(path); - return p.ParseNode(true); - } - - }; - - inline ScriptType TypeOf(Environment* env, std::vector args) - { - - if(args.size() > 0) - { - auto item = args[0]; - if(std::holds_alternative(item)) - { - return "char"; - } - if(std::holds_alternative(item)) - { - return "string"; - } - if(std::holds_alternative(item)) - { - return "long"; - } - if(std::holds_alternative(item)) - { - return "double"; - } - - if(std::holds_alternative(item)) - { - return "ittrkvp"; - } - if(std::holds_alternative(item)) - { - return "bool"; - } - if(std::holds_alternative(item)) - { - return "undefined"; - } - if(std::holds_alternative(item)) - { - return "null"; - } - if(std::holds_alternative(item)) - { - auto ot = std::get(item).data; - auto ls = dynamic_cast(ot); - auto dict = dynamic_cast(ot); - auto ifunc = dynamic_cast(ot); - auto efunc = dynamic_cast(ot); - auto ittr = dynamic_cast(ot); - if(ittr != nullptr) return "ittr"; - if(ls != nullptr) return "list"; - if(dict != nullptr) return "dictionary"; - if(ifunc != nullptr) return "internal_function"; - if(efunc != nullptr) return "external_function"; - } - } - return Null(); - - } - - class BytecodeFile { - public: - std::map functions; - InternalFunction* rootFunction; - - ~BytecodeFile() - { - delete rootFunction; - for(auto item : functions) - { - delete item.second; - } - } - }; - - #if defined(DEBUG) - #define INSTRUCTION_NAME(INAME) case Instruction:: INAME : printf("%s",#INAME); break; -#endif - - - class SimpleInstruction : public Instruction - { - public: - uint8_t instruction; - SimpleInstruction(uint8_t instruction) - { - this->instruction = instruction; - } - int Length() - { - return 1; - } - void Write(uint8_t* buffer) - { - buffer[0] = instruction; - } - #if defined(DEBUG) - void Print() - { - switch(instruction) - { - INSTRUCTION_NAME(ADD) - INSTRUCTION_NAME(SUB) - INSTRUCTION_NAME(TIMES) - INSTRUCTION_NAME(DIVIDE) - INSTRUCTION_NAME(MOD) - INSTRUCTION_NAME(LEFTSHIFT) - INSTRUCTION_NAME(RIGHTSHIFT) - INSTRUCTION_NAME(LESSTHAN) - INSTRUCTION_NAME(GREATERTHAN) - INSTRUCTION_NAME(GREATERTHANEQUALTO) - INSTRUCTION_NAME(LESSTHANEQUALTO) - INSTRUCTION_NAME(PRINT) - INSTRUCTION_NAME(SCOPE_BEGIN) - INSTRUCTION_NAME(SCOPE_END) - INSTRUCTION_NAME(POP) - INSTRUCTION_NAME(GETVARIABLE) - INSTRUCTION_NAME(SETVARIABLE) - INSTRUCTION_NAME(GETFIELD) - INSTRUCTION_NAME(SETFIELD) - INSTRUCTION_NAME(CALL_METHOD) - INSTRUCTION_NAME(CALL_FUNC) - INSTRUCTION_NAME(DESTROY_LOOP) - INSTRUCTION_NAME(ITTR) - INSTRUCTION_NAME(SET_LOOP) - INSTRUCTION_NAME(GET_LOOP) - default: - printf("UNKNOWN: %i\n",(int)instruction); - break; - } - printf("\n"); - } - #endif - }; - - class LabelInstruction : public Instruction - { - std::string label; - public: - LabelInstruction(std::string label) - { - this->label = label; - } - std::string GetLabel() - { - return label; - } - void SetLabel(std::string lbl) - { - label = lbl; - } - int Length() - { - return 0; - } - void Write(uint8_t* buffer) - { - - } - #if defined(DEBUG) - void Print() - { - printf("%s:\n",label.c_str()); - } - #endif - }; - - class LabelableInstruction : public Instruction - { - public: - virtual std::string GetLabel()=0; - virtual void SetLabel(std::string lbl)=0; - virtual int GetPosition()=0; - virtual void SetPosition(int pos)=0; - }; - - class JumpInstruction : public LabelableInstruction - { - std::string label; - int position; - uint8_t instr; - public: - JumpInstruction(uint8_t instr,std::string label) - { - this->instr = instr; - this->label = label; - this->position = 0; - } - std::string GetLabel() - { - return label; - } - void SetLabel(std::string lbl) - { - label = lbl; - } - int GetPosition() - { - return position; - } - void SetPosition(int pos) - { - this->position = pos; - } - int Length() {return 5;} - void Write(uint8_t* buffer) - { - buffer[0] = instr; - buffer[1] = (uint8_t)((position >> 24) & 0xFF); - buffer[2] = (uint8_t)((position >> 16) & 0xFF); - buffer[3] = (uint8_t)((position >> 8) & 0xFF); - buffer[4] = (uint8_t)(position & 0xFF); - } - - #if defined(DEBUG) - void Print() - { - switch(instr) - { - INSTRUCTION_NAME(JMP) - INSTRUCTION_NAME(JMPC) - } - printf(" %s [%i]\n", label.c_str(),this->position); - } - - #endif - }; - - class LongInstruction : public Instruction { - - public: - int64_t value; - LongInstruction(int64_t value) - { - this->value = value; - } - int Length() - { - return 9; - } - void Write(uint8_t* buffer) - { - buffer[0] = Instruction::PUSH_LONG; - buffer[1] = (uint8_t)((value >> 56) & 0xFF); - buffer[2] = (uint8_t)((value >> 48) & 0xFF); - buffer[3] = (uint8_t)((value >> 40) & 0xFF); - buffer[4] = (uint8_t)((value >> 32) & 0xFF); - buffer[5] = (uint8_t)((value >> 24) & 0xFF); - buffer[6] = (uint8_t)((value >> 16) & 0xFF); - buffer[7] = (uint8_t)((value >> 8) & 0xFF); - buffer[8] = (uint8_t)(value & 0xFF); - } - #if defined(DEBUG) - void Print() - { - std::cout << "PUSH_LONG " << value << std::endl; - } - #endif - }; - class CharInstruction : public Instruction { - public: - char value; - CharInstruction(char c) - { - this->value = c; - } - int Length() - { - return 2; - } - - void Write(uint8_t* buffer) - { - buffer[0] = Instruction::PUSH_CHAR; - buffer[1] = value; - } - #if defined(DEBUG) - void Print() - { - std::cout << "PUSH_CHAR \'" << value << "\'" << std::endl; - } - #endif - }; - class StringInstruction : public Instruction { - - public: - std::string value; - StringInstruction(std::string value) - { - this->value = value; - } - int Length() - { - return 5+value.size(); - } - void Write(uint8_t* buffer) - { - buffer[0] = Instruction::PUSH_STRING; - auto sz = this->value.size(); - buffer[1] = (uint8_t)((sz >> 24) & 0xFF); - buffer[2] = (uint8_t)((sz >> 16) & 0xFF); - buffer[3] = (uint8_t)((sz >> 8) & 0xFF); - buffer[4] = (uint8_t)(sz & 0xFF); - for(size_t i = 0;i __eachs; - - int jmpId = 0; - std::string NewJumpId() - { - std::string s = "__compGen" + std::to_string(jmpId); - jmpId++; - return s; - } - void ExpressionPop(Node* n,std::vector& instructions) - { - if(n == nullptr) return; - if(n->IsExpression()) - instructions.push_back(new SimpleInstruction(Instruction::POP)); - } - Node* n; - void GenerateFree(Node* _n,std::vector& instructions) - { - GetVariableExpression fnName("free"); - FunctionCallExpression fcE(&fnName); - fcE.args.push_back(_n); - Compile(&fcE,instructions); - instructions.push_back(new SimpleInstruction(Instruction::POP)); - fcE.args.clear(); - fcE.name=nullptr; - } - void Compile(Node* n,std::vector& instructions) - { - if(n==nullptr) return; - auto addExpr = dynamic_cast(n); - auto subExpr = dynamic_cast(n); - auto timesExpr = dynamic_cast(n); - auto divExpr = dynamic_cast(n); - auto modExpr = dynamic_cast(n); - auto lsExpr = dynamic_cast(n); - auto rsExpr = dynamic_cast(n); - auto ltExpr = dynamic_cast(n); - auto gtExpr = dynamic_cast(n); - auto lteExpr = dynamic_cast(n); - auto gteExpr = dynamic_cast(n); - auto funcDecl = dynamic_cast(n); - auto varDecl = dynamic_cast(n); - auto lnotExpr = dynamic_cast(n); - - auto scope = dynamic_cast(n); - - auto print = dynamic_cast(n); - auto lng = dynamic_cast(n); - auto str = dynamic_cast(n); - - auto assign = dynamic_cast(n); - auto compound = dynamic_cast(n); - - auto varGet = dynamic_cast(n); - auto memGet = dynamic_cast(n); - auto arrGet = dynamic_cast(n); - auto gblGet = dynamic_cast(n); - auto callerGet = dynamic_cast(n); - - auto fCall = dynamic_cast(n); - - auto ifNode = dynamic_cast(n); - auto ternary = dynamic_cast(n); - auto whileNode = dynamic_cast(n); - auto breakNode = dynamic_cast(n); - auto cont = dynamic_cast(n); - auto eachLoop = dynamic_cast(n); - auto forLoop = dynamic_cast(n); - auto lOr = dynamic_cast(n); - auto lAnd = dynamic_cast(n); - auto retNode = dynamic_cast(n); - auto boolExpr = dynamic_cast(n); - auto nullExpr = dynamic_cast(n); - auto undefinedExpr = dynamic_cast(n); - auto chrExpr = dynamic_cast(n); - auto equalsExpr = dynamic_cast(n); - auto notEqualsExpr = dynamic_cast(n); - if(equalsExpr != nullptr) - { - Compile(equalsExpr->left,instructions); - Compile(equalsExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::EQUALS)); - } - if(notEqualsExpr != nullptr) - { - Compile(notEqualsExpr->left,instructions); - Compile(notEqualsExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::NOTEQUALS)); - } - - if(chrExpr != nullptr) - { - instructions.push_back(new CharInstruction(chrExpr->value)); - } - if(boolExpr != nullptr) - { - instructions.push_back(new SimpleInstruction(boolExpr->value ? Instruction::PUSH_TRUE : Instruction::PUSH_FALSE)); - } - if(nullExpr != nullptr) - { - instructions.push_back(new SimpleInstruction(Instruction::PUSH_NULL)); - } - if(undefinedExpr != nullptr) - { - instructions.push_back(new SimpleInstruction(Instruction::PUSH_UNDEFINED)); - } - if(retNode != nullptr) - { - while(!this->__eachs.empty()) - { - auto item = this->__eachs.top(); - GetVariableExpression gve(item); - GenerateFree(&gve,instructions); - this->__eachs.pop(); - } - Compile(retNode->retVal,instructions); - instructions.push_back(new SimpleInstruction(Instruction::RET)); - } - if(lnotExpr != nullptr) - { - Compile(lnotExpr->node,instructions); - instructions.push_back(new SimpleInstruction(Instruction::LOGICALNOT)); - } - if(lOr != nullptr) - { - std::string end = this->NewJumpId(); - std::string pushTrue = this->NewJumpId(); - Compile(lOr->left,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,pushTrue)); - Compile(lOr->right,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(pushTrue)); - instructions.push_back(new SimpleInstruction(Instruction::PUSH_TRUE)); - instructions.push_back(new LabelInstruction(end)); - } - if(lAnd != nullptr) - { - std::string end = this->NewJumpId(); - std::string pushFalse = this->NewJumpId(); - std::string hndl = this->NewJumpId(); - Compile(lAnd->left,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,hndl)); - instructions.push_back(new JumpInstruction(Instruction::JMP,pushFalse)); - instructions.push_back(new LabelInstruction(hndl)); - Compile(lAnd->right,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(pushFalse)); - instructions.push_back(new SimpleInstruction(Instruction::PUSH_FALSE)); - instructions.push_back(new LabelInstruction(end)); - } - if(breakNode != nullptr) - { - if( _brk.size() > 0) - { - instructions.push_back(new SimpleInstruction(Instruction::GET_LOOP)); - instructions.push_back(new JumpInstruction(Instruction::JMP,_brk)); - } else { - throw std::exception(); - } - } - if(cont != nullptr) - { - if(_cont.size() > 0) - { - instructions.push_back(new SimpleInstruction(Instruction::GET_LOOP)); - instructions.push_back(new JumpInstruction(Instruction::JMP, _cont)); - } - else { - throw std::exception(); - } - } - if(forLoop != nullptr) - { - instructions.push_back(new SimpleInstruction(Instruction::SET_LOOP)); - Compile(forLoop->init,instructions); - ExpressionPop(forLoop->init,instructions); - std::string oldcont = _cont; - std::string oldbrk = _brk; - - std::string end = NewJumpId(); - std::string begin = NewJumpId(); - std::string yes = NewJumpId(); - - std::string cont = NewJumpId(); - - _cont = cont; - _brk = end; - - - instructions.push_back(new LabelInstruction(begin)); - Compile(forLoop->cond,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,yes)); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(yes)); - Compile(forLoop->body,instructions); - ExpressionPop(forLoop->body,instructions); - instructions.push_back(new LabelInstruction(cont)); - Compile(forLoop->inc,instructions); - ExpressionPop(forLoop->inc,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,begin)); - instructions.push_back(new LabelInstruction(end)); //used for break - instructions.push_back(new SimpleInstruction(Instruction::DESTROY_LOOP)); - - _cont = oldcont; - _brk = oldbrk; - } - if(eachLoop != nullptr) - { - - instructions.push_back(new SimpleInstruction(Instruction::SET_LOOP)); - std::string eachIttr = NewJumpId(); - __eachs.push(eachIttr); - instructions.push_back(new StringInstruction(eachIttr)); - Compile(eachLoop->list,instructions); - instructions.push_back(new SimpleInstruction(Instruction::ITTR)); - instructions.push_back(new SimpleInstruction(Instruction::SETVARIABLE)); - instructions.push_back(new SimpleInstruction(Instruction::POP)); - std::string oldcont = _cont; - std::string oldbrk = _brk; - std::string yes = NewJumpId(); - std::string end = NewJumpId(); - std::string begin = NewJumpId(); - - _cont = begin; - _brk = end; - - instructions.push_back(new LabelInstruction(begin)); - GetVariableExpression var(eachIttr); - GetMemberExpression mem(&var,"movenext"); - FunctionCallExpression ce(&mem); - Compile(&ce,instructions); - ce.name = nullptr; - mem.parent=nullptr; - - instructions.push_back(new JumpInstruction(Instruction::JMPC,yes)); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(yes)); - GetMemberExpression mem2(&var,"current"); - FunctionCallExpression ce2(&mem2); - AssignExpression assignExpr(eachLoop->item,&ce2); - - - Compile(&assignExpr,instructions); - ExpressionPop(&assignExpr,instructions); - - mem2.parent=nullptr; - ce2.name=nullptr; - - assignExpr.left=nullptr; - assignExpr.right = nullptr; - Compile(eachLoop->body,instructions); - ExpressionPop(eachLoop->body,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,begin)); - instructions.push_back(new LabelInstruction(end)); - __eachs.pop(); - - GenerateFree(&var,instructions); - instructions.push_back(new SimpleInstruction(Instruction::DESTROY_LOOP)); - - _cont = oldcont; - _brk = oldbrk; - } - if(whileNode != nullptr) - { - if(whileNode->isDo) - { - instructions.push_back(new SimpleInstruction(Instruction::SET_LOOP)); - std::string oldcont = _cont; - std::string oldbrk = _brk; - - std::string end = NewJumpId(); - std::string begin = NewJumpId(); - - _cont = begin; - _brk = end; - instructions.push_back(new LabelInstruction(begin)); - Compile(whileNode->body,instructions); - ExpressionPop(whileNode->body,instructions); - - - Compile(whileNode->cond,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,begin)); - instructions.push_back(new LabelInstruction(end)); //used for break - - instructions.push_back(new SimpleInstruction(Instruction::DESTROY_LOOP)); - - _cont = oldcont; - _brk = oldbrk; - } - else - { - instructions.push_back(new SimpleInstruction(Instruction::SET_LOOP)); - std::string oldcont = _cont; - std::string oldbrk = _brk; - std::string yes = NewJumpId(); - std::string end = NewJumpId(); - std::string begin = NewJumpId(); - - _cont = begin; - _brk = end; - - instructions.push_back(new LabelInstruction(begin)); - Compile(whileNode->cond,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,yes)); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(yes)); - Compile(whileNode->body,instructions); - ExpressionPop(whileNode->body,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,begin)); - instructions.push_back(new LabelInstruction(end)); - - instructions.push_back(new SimpleInstruction(Instruction::DESTROY_LOOP)); - - _cont = oldcont; - _brk = oldbrk; - } - } - - if(ifNode != nullptr) - { - std::string yes = NewJumpId(); - std::string end = NewJumpId(); - Compile(ifNode->cond,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,yes)); - Compile(ifNode->no,instructions); - ExpressionPop(ifNode->no,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(yes)); - Compile(ifNode->yes,instructions); - ExpressionPop(ifNode->yes,instructions); - instructions.push_back(new LabelInstruction(end)); - } - if(ternary != nullptr) - { - std::string yes = NewJumpId(); - std::string end = NewJumpId(); - - Compile(ternary->cond,instructions); - instructions.push_back(new JumpInstruction(Instruction::JMPC,yes)); - Compile(ternary->no,instructions); - - instructions.push_back(new JumpInstruction(Instruction::JMP,end)); - instructions.push_back(new LabelInstruction(yes)); - Compile(ternary->yes,instructions); - - instructions.push_back(new LabelInstruction(end)); - } - - if(compound != nullptr) - { - auto twoNode = dynamic_cast(compound->node); - if(twoNode != nullptr) - { - AssignExpression aE(twoNode->left,twoNode); - Compile(&aE,instructions); - aE.left = nullptr; - aE.right = nullptr; - } - } - - if(addExpr != nullptr) - { - Compile(addExpr->left,instructions); - Compile(addExpr->right,instructions); - - instructions.push_back(new SimpleInstruction(Instruction::ADD)); - } - - if(subExpr != nullptr) - { - Compile(subExpr->left,instructions); - Compile(subExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SUB)); - } - if(timesExpr != nullptr) - { - Compile(timesExpr->left,instructions); - Compile(timesExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::TIMES)); - } - if(divExpr != nullptr) - { - Compile(divExpr->left,instructions); - Compile(divExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::DIVIDE)); - } - if(modExpr != nullptr) - { - Compile(modExpr->left,instructions); - Compile(modExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::MOD)); - } - if(lsExpr != nullptr) - { - Compile(lsExpr->left,instructions); - Compile(lsExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::LEFTSHIFT)); - } - if(rsExpr != nullptr) - { - Compile(rsExpr->left,instructions); - Compile(rsExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::RIGHTSHIFT)); - } - if(ltExpr != nullptr) - { - Compile(ltExpr->left,instructions); - Compile(ltExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::LESSTHAN)); - } - if(gtExpr != nullptr) - { - Compile(gtExpr->left,instructions); - Compile(gtExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::GREATERTHAN)); - } - if(lteExpr != nullptr) - { - Compile(lteExpr->left,instructions); - Compile(lteExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::LESSTHANEQUALTO)); - } - if(gteExpr != nullptr) - { - Compile(gteExpr->left,instructions); - Compile(gteExpr->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::GREATERTHANEQUALTO)); - } - if(funcDecl != nullptr) - { - auto fcall = dynamic_cast(funcDecl->nameAndArgs); - if(fcall != nullptr) - { - auto fname = dynamic_cast(fcall->name); - - if(fname != nullptr) - { - - - auto fn = new InternalFunction(); - this->file->functions[fname->name] = fn; - - - - for(auto arg : fcall->args) - { - auto argTXT = dynamic_cast(arg); - if(argTXT != nullptr) - { - fn->args.push_back(argTXT->name); - } - - } - - Compile(funcDecl->body,fn); - } - - } - - } - if(scope != nullptr) - { - if(!scope->rootScope) - instructions.push_back(new SimpleInstruction(Instruction::SCOPE_BEGIN)); - - for(auto no : scope->items) - { - Compile(no,instructions); - ExpressionPop(no,instructions); - } - - if(!scope->rootScope) - instructions.push_back(new SimpleInstruction(Instruction::SCOPE_END)); - - } - if(lng != nullptr) - { - - instructions.push_back(new LongInstruction(lng->value)); - } - if(str != nullptr) - { - - instructions.push_back(new StringInstruction(str->value)); - } - if(print != nullptr) - { - Compile(print->expr,instructions); - instructions.push_back(new SimpleInstruction(Instruction::PRINT)); - } - if(varDecl != nullptr) - { - auto gvn = dynamic_cast(varDecl->node); - if(gvn != nullptr) - { - instructions.push_back(new StringInstruction(gvn->name)); - instructions.push_back(new SimpleInstruction(Instruction::PUSH_NULL)); - instructions.push_back(new SimpleInstruction(Instruction::DECLARE_VARIABLE)); - } - - - } - - if(assign != nullptr) - { - GetVariableExpression* gVar = dynamic_cast(assign->left); - GetMemberExpression* gMem = dynamic_cast(assign->left); - GetArrayExpression* gArray = dynamic_cast(assign->left); - VarExpression* vDecl = dynamic_cast(assign->left); - GlobalExpression* gGbl = dynamic_cast(assign->left); - CallerExpression* gCaller = dynamic_cast(assign->left); - if(gVar != nullptr) - { - instructions.push_back(new StringInstruction(gVar->name)); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SETVARIABLE)); - } - if(gMem != nullptr) - { - - Compile(gMem->parent,instructions); - instructions.push_back(new StringInstruction(gMem->name)); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SETFIELD)); - } - - if(gArray != nullptr) - { - - Compile(gArray->parent,instructions); - Compile(gArray->expr,instructions); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SETARRAY)); - } - - if(gGbl != nullptr) - { - gVar = dynamic_cast(gGbl->node); - if(gVar != nullptr) - { - instructions.push_back(new StringInstruction(gVar->name)); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SET_GLOBAL_VARIABLE)); - } - } - - if(gCaller != nullptr) - { - gVar = dynamic_cast(gCaller->node); - if(gVar != nullptr) - { - instructions.push_back(new StringInstruction(gVar->name)); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::SET_CALLER_VARIABLE)); - } - } - if(vDecl != nullptr) - { - gVar = dynamic_cast(vDecl->node); - if(gVar != nullptr) - { - instructions.push_back(new StringInstruction(gVar->name)); - Compile(assign->right,instructions); - instructions.push_back(new SimpleInstruction(Instruction::DECLARE_VARIABLE)); - } - } - } - - if(varGet != nullptr) - { - instructions.push_back(new StringInstruction(varGet->name)); - instructions.push_back(new SimpleInstruction(Instruction::GETVARIABLE)); - } - - if(gblGet != nullptr) - { - varGet = dynamic_cast(gblGet->node); - if(varGet != nullptr) - { - instructions.push_back(new StringInstruction(varGet->name)); - instructions.push_back(new SimpleInstruction(Instruction::GET_GLOBAL_VARIABLE)); - } - } - if(callerGet != nullptr) - { - varGet = dynamic_cast(callerGet->node); - if(varGet != nullptr) - { - instructions.push_back(new StringInstruction(varGet->name)); - instructions.push_back(new SimpleInstruction(Instruction::GET_CALLER_VARIABLE)); - } - } - - if(memGet != nullptr) - { - Compile(memGet->parent,instructions); - instructions.push_back(new StringInstruction(memGet->name)); - instructions.push_back(new SimpleInstruction(Instruction::GETFIELD)); - } - - if(arrGet != nullptr) - { - Compile(arrGet->parent,instructions); - Compile(arrGet->expr,instructions); - instructions.push_back(new SimpleInstruction(Instruction::GETARRAY)); - } - if(fCall != nullptr) - { - auto field = dynamic_cast(fCall->name); - if(field != nullptr) - { - Compile(field->parent,instructions); - instructions.push_back(new StringInstruction(field->name)); - for(auto item : fCall->args) - Compile(item,instructions); - instructions.push_back(new LongInstruction(fCall->args.size())); - instructions.push_back(new SimpleInstruction(Instruction::CALL_METHOD)); - } - else - { - Compile(fCall->name,instructions); - for(auto item : fCall->args) - Compile(item,instructions); - - - instructions.push_back(new LongInstruction(fCall->args.size())); - instructions.push_back(new SimpleInstruction(Instruction::CALL_FUNC)); - } - } - } - void Compile(Node* n, InternalFunction* func) - { - std::vector instructions; - Compile(n,instructions); - int length=0; - std::map lbls; - for(auto item : instructions) - { - auto lbl = dynamic_cast(item); - if(lbl != nullptr) - lbls[lbl->GetLabel()] = length; - length += item->Length(); - } - - func->bytecodeLength = length; - func->bytecode = new uint8_t[length]; - - uint8_t* buffer = func->bytecode; - #if defined(DEBUG) - printf("INSTRUCTIONS:\n\n"); - #endif - size_t len2=0; - for(auto item : instructions) - { - auto lblable = dynamic_cast(item); - if(lblable != nullptr) - { - lblable->SetPosition(lbls[lblable->GetLabel()]); - } - item->Write(buffer); - buffer += item->Length(); - - #if defined(DEBUG) - printf("OFFSET %i\n",(int)len2); - item->Print(); - #endif - len2+=item->Length(); - - delete item; - } - - #if defined(DEBUG) - printf("\n\nEND OF INSTRUCTIONS\n\n"); - #endif - instructions.clear(); - } - public: - BytecodeFile* file; - BytecodeCompiler(Node* root) - { - this->n = root; - file=new BytecodeFile(); - file->rootFunction = new InternalFunction(); - file->rootFunction->isRoot=true; - - - } - - - - void Compile() - { - Compile(n,file->rootFunction); - } - - - }; - - - - - -} \ No newline at end of file diff --git a/tesseswebserver.cpp b/tesseswebserver.cpp deleted file mode 100644 index f769125..0000000 --- a/tesseswebserver.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "tesseswebserver.hpp" -TESSESWEBSERVER_STATIC_DECLARATION -using namespace Tesses::WebServer; -using namespace Tesses::WebServer::ScriptEngine; - -class DummyServer : public IServer -{ - public: - bool Handle(ServerContext* ctx) - { - std::string resp = {}; - - for(auto param : ctx->queryParams.GetAll()) - { - resp.append(param.first); - resp.append(": "); - resp.append(param.second); - resp.append("\r\n"); - } - - ctx->SetContentType("text/plain")->SendText(resp); - return true; - } -}; - -int main(int argc,char** argv) -{ - - - - - - HttpServerListener::Init(); - - IServer* myServer = new DummyServer(); - - HttpServerListener::Listen(myServer,3000); - - - -} \ No newline at end of file diff --git a/tesseswebserver.hpp b/tesseswebserver.hpp deleted file mode 100644 index ced9a86..0000000 --- a/tesseswebserver.hpp +++ /dev/null @@ -1,1142 +0,0 @@ -#pragma once -//#define GEKKO -#include "tesseswebserverfeatures.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(USE_JANSSON) -#include -#endif - -#if defined(USE_CURL) -#include -#include -#endif - -#if defined(USE_SQLITE3) -#include -#endif - -#if defined(USE_MBEDTLS) -#include -#endif - -#if defined(DEBUG) - - #define DEBUGOUT(...) printf(__VA_ARGS__) -#else - #define DEBUGOUT(...) -#endif - -#if defined(GEKKO) -#include -#include - -#if defined(HW_RVL) && defined(USE_WIISOCKETS) - #include - #include -#else - #include - #define socket net_socket - #define bind net_bind - #define listen net_listen - #define recv net_recv - #define send net_send - #define close net_close -#endif - -#else -#include -#include -#include -#include -#endif - -namespace Tesses::WebServer { - -#if defined(GEKKO) -typedef void* THREAD_RETURN_TYPE; - -#define THREAD_DEFAULT_RETURN_TYPE (NULL) - -typedef THREAD_RETURN_TYPE (*callback)(void* arg); -#else -typedef int THREAD_RETURN_TYPE; - -#define THREAD_DEFAULT_RETURN_TYPE 0 - -typedef THREAD_RETURN_TYPE (*callback)(void* arg); - - -#endif - -class Statics { - public: - #if defined(GEKKO) - std::vector joined_threads; - mutex_t mtx; - #else - mtx_t mtx; - #endif - std::atomic isRunning; -}; -extern Tesses::WebServer::Statics tesses_webserver_statics; -class Thread { - #if defined(GEKKO) - lwp_t thrd; - std::atomic hasExited; - callback cb; - void* arg; - - #else - thrd_t thrd; - - - #endif - public: - - static void Init() - { - #if defined(GEKKO) - LWP_MutexInit(&tesses_webserver_statics.mtx,true); - #else - mtx_init(&tesses_webserver_statics.mtx,mtx_recursive); - #endif - } - - Thread(callback cb,void* arg,uint32_t stackSize) - { - #if defined(GEKKO) - this->hasExited=false; - this->cb = cb; - this->arg = arg; - LWP_CreateThread(&this->thrd,HANDLER,arg,NULL,stackSize,80); - #else - thrd_create(&thrd,cb,arg); - #endif - } - #if defined(GEKKO) - static THREAD_RETURN_TYPE HANDLER(void* arg) - { - Thread* thrd = (Thread*)arg; - THREAD_RETURN_TYPE t = thrd->cb(arg); - thrd->hasExited=true; - return t; - } - #endif - - int Join(THREAD_RETURN_TYPE* retType) - { - #if defined(GEKKO) - return LWP_JoinThread(this->thrd,retType); - #else - return thrd_join(this->thrd,retType); - #endif - } - - void Detach() - { - #if defined(GEKKO) - Lock(); - tesses_webserver_statics.joined_thrads.push_back(this); - Unlock(); - #else - thrd_detach(this->thrd); - delete this; - #endif - } - - static void Lock() - { - #if defined(GEKKO) - LWP_MutexLock(tesses_webserver_statics.mtx); - #else - mtx_lock(&tesses_webserver_statics.mtx); - #endif - } - static void Unlock() - { - #if defined(GEKKO) - LWP_MutexUnlock(tesses_webserver_statics.mtx); - #else - mtx_unlock(&tesses_webserver_statics.mtx); - #endif - } - - - - static void CleanThreads() - { - #if defined(GEKKO) - Lock(); - for(auto i = tesses_webserver_statics.joined_threads.begin();ihasExited) - { - THREAD_RETURN_TYPE arg; - item->Join(&arg); - delete item; - tesses_webserver_statics.joined_threads.erase(i); - i--; - } - } - Unlock(); - #endif - } -}; - -class Stream { - public: - virtual ssize_t Read(uint8_t* buffer,size_t len)=0; - virtual ssize_t Write(uint8_t* buffer,size_t len)=0; - - virtual void Seek(uint64_t offset,int whence) - { - - } - - virtual int64_t Position() - { - return 0; - } - - virtual bool CanSeek() - { - return false; - } - - void WriteBlock(uint8_t* buffer,size_t len) - { - size_t read; - do{ - read = 1024; - if(len < 1024) - read = len; - if(read > 0) - read=this->Write(buffer,read); - - - - buffer += read; - len -= read; - } while(read > 0); - } - - virtual int64_t Length() - { - return -1; - } - virtual ~Stream() - { - - } - - int ReadByte() - { - uint8_t byte; - if(Read(&byte,1) == 0) return -1; - - return byte; - } - - std::string ReadLine() - { - std::string str = {}; - int c = ReadByte(); - while(c != '\n' && c != -1) - { - if(c != '\r') - { - str.push_back((char)c); - } - c = ReadByte(); - } - - DEBUGOUT("ReadLine: %s\n",str.c_str()); - - return str; - } -}; - - -class FileStream : public Stream -{ - private: - FILE* f; - bool canSeek; - bool owns; - public: - - FileStream(std::string filename, std::string mode) - { - this->f = fopen(filename.c_str(),mode.c_str()); - this->canSeek=true; - this->owns=true; - } - - FileStream(FILE* f,bool canSeek,bool owns) - { - this->f = f; - this->canSeek = canSeek; - this->owns = owns; - } - - ssize_t Read(uint8_t* buffer,size_t len) - { - return (ssize_t)fread(buffer,1,len,this->f); - - } - - ssize_t Write(uint8_t* buffer, size_t len) - { - return (ssize_t)fwrite(buffer,1,len,this->f); - } - int64_t Position() - { - #if(_FILE_OFFSET_BITS == 64) - #if defined(WIN32) - return (int64_t)_ftelli64(this->f); - #else - return (int64_t)ftello(this->f); - #endif - #else - return (int64_t)ftell(this->f); - #endif - } - - void Seek(uint64_t offset,int whence) - { - #if(_FILE_OFFSET_BITS == 64) - #if defined(WIN32) - _ftelli64(this->f,(__int64)offset,whence); - #else - fseeko(this->f,(off_t)offset,whence); - #endif - #else - fseek(this->f,(long)offset,whence); - #endif - } -}; - -class SocketStream : public Stream { - int sock; - public: - SocketStream(int sock) - { - this->sock = sock; - } - ssize_t Read(uint8_t* buffer,size_t len) - { - ssize_t r= recv(this->sock,buffer,len,0); - return r; - } - ssize_t Write(uint8_t* buffer,size_t len) - { - return send(this->sock,buffer,len,0); - } - ~SocketStream() - { - close(sock); - } -}; -typedef enum StatusCode { - Continue=100, - SwitchingProtocols=101, - Processing=102, - EarlyHints=103, - OK=200, - Created=201, - Accepted=202, - NonAuthoritativeInformation=203, - NoContent=204, - ResetContent=205, - PartialContent=206, - MultiStatus=207, - AlreadyReported=208, - IMUsed=226, - MultipleChoices=300, - MovedPermanently=301, - Found=302, - SeeOther=303, - NotModified=304, - UseProxy=305, - TemporaryRedirect=307, - PermanentRedirect=308, - BadRequest=400, - Unauthorized=401, - PaymentRequired=402, - Forbidden=403, - NotFound=404, - MethodNotAllowed=405, - NotAcceptable=406, - ProxyAuthenticationRequired=407, - RequestTimeout=408, - Conflict=409, - Gone=410, - LengthRequired=411, - PreconditionFailed=412, - PayloadTooLarge=413, - URITooLong=414, - UnsupportedMediaType=415, - RangeNotSatisfiable=416, - ExpectationFailed=417, - ImATeapot=418, - MisdirectedRequest=421, - UnprocessableContent=422, - Locked=423, - FailedDependency=424, - TooEarly=425, - UpgradeRequired=426, - PreconditionRequired=428, - TooManyRequests=429, - RequestHeaderFieldsTooLarge=431, - UnavailableForLegalReasons=451, - InternalServerError=500, - NotImplemented=501, - BadGateway=502, - ServiceUnavailable=503, - GatewayTimeout=504, - HTTPVersionNotSupported=505, - VariantAlsoNegotiates=506, - InsufficientStorage=507, - LoopDetected=508, - NotExtended=510, - NetworkAuthenticationRequired=511 -} StatusCode; - - -class HttpUtils { - - - public: - static char nibble_to_hex_char(uint8_t number) - { - if(number >= 0 && number <= 9) - { - return '0'+number; - } - if(number >= 0xA && number <= 0xF) - { - return (char)(55+number); - } - return '0'; - } - static uint8_t hex_char_to_nibble(char c) - { - if(c >= '0' && c <= '9') - return c - '0'; - - if(c >= 'A' && c <= 'F') - return (c-'A')+0xA; - - if(c >= 'a' && c <= 'f') - return (c-'a')+0xA; - return 0; - } - static std::vector> QueryParamsDecode(std::string query) - { - std::vector> strs; - for(auto item : SplitString(query,"&")) - { - std::vector ss=SplitString(item,"=",2); - if(ss.size() >= 1) - { - std::string value = {}; - if(ss.size() == 2) - { - value = UrlDecode(ss[1]); - } - strs.push_back(std::pair(ss[0],value)); - } - } - return strs; - } - - static std::string QueryParamsEncode(std::vector> query) - { - std::string s={}; - bool first = true; - for(auto item : query) - { - if(!first) - { - s.push_back('&'); - } - s.insert(s.size(),item.first); - s.push_back('='); - s.insert(s.size(),UrlEncode(item.second)); - first=false; - } - return s; - } - - static std::string UrlDecode(std::string v) - { - std::string s = {}; - - for(size_t i = 0;i= 'A' && item <= 'Z') - s.push_back(item); - else if(item >= 'a' && item <= 'z') - s.push_back(item); - else if(item >= '0' && item <= '9') - s.push_back(item); - else if(item == '-' || item == '_' || item == '.' || item == '~') - s.push_back(item); - else - { - s.push_back('%'); - s.push_back(nibble_to_hex_char((item >> 4) & 0xF)); - s.push_back(nibble_to_hex_char((item) & 0xF)); - } - } - return s; - } - static std::string UrlPathDecode(std::string v) - { - std::string s = {}; - - for(size_t i = 0;i= 'A' && item <= 'Z') - s.push_back(item); - else if(item >= 'a' && item <= 'z') - s.push_back(item); - else if(item >= '0' && item <= '9') - s.push_back(item); - else if(item == '-' || item == '_' || item == '.' || item == '~') - s.push_back(item); - else - { - s.push_back('%'); - s.push_back(nibble_to_hex_char((item >> 4) & 0xF)); - s.push_back(nibble_to_hex_char((item) & 0xF)); - } - } - return s; - } - - static std::vector SplitString(std::string text, std::string delimiter,std::size_t maxCnt = std::string::npos) - { - std::vector strs; - std::size_t i = 1; - while(text.length() > 0) - { - if(i == maxCnt) - { - strs.push_back(text); - break; - } - std::size_t index= text.find_first_of(delimiter); - - - - if(index == std::string::npos) - { - strs.push_back(text); - break; - } - else - { - std::string left = text.substr(0,index); - - text = text.substr(index+delimiter.size()); - - strs.push_back(left); - } - i++; - } - return strs; - } - static std::string HtmlEncode(std::string html) - { - std::string myHtml = {}; - for(auto item : html) - { - if(item == '\"') - { - myHtml.append("""); - } - else if(item == '\'') - { - myHtml.append("'"); - } - else if(item == '&') - { - myHtml.append("&"); - } - else if(item == '<') - { - myHtml.append("<"); - } - else if(item == '>') - { - myHtml.append(">"); - } - else - { - myHtml.push_back(item); - } - } - return myHtml; - } - static std::string StatusCodeString(StatusCode code) - { - switch(code) - { - case StatusCode::Continue: - return "Continue"; - case StatusCode::SwitchingProtocols: - return "Switching Protocols"; - case StatusCode::Processing: - return "Processing"; - case StatusCode::EarlyHints: - return "Early Hints"; - case StatusCode::OK: - return "OK"; - case StatusCode::Created: - return "Created"; - case StatusCode::Accepted: - return "Accepted"; - case StatusCode::NonAuthoritativeInformation: - return "Non-Authoritative Information"; - case StatusCode::NoContent: - return "No Content"; - case StatusCode::ResetContent: - return "Reset Content"; - case StatusCode::PartialContent: - return "PartialContent"; - case StatusCode::MultiStatus: - return "Multi-Status"; - case StatusCode::AlreadyReported: - return "Already Reported"; - case StatusCode::IMUsed: - return "IM Used"; - case StatusCode::MultipleChoices: - return "Multiple Choices"; - case StatusCode::MovedPermanently: - return "Moved Permanently"; - case StatusCode::Found: - return "Found"; - case StatusCode::SeeOther: - return "See Other"; - case StatusCode::NotModified: - return "Not Modified"; - case StatusCode::UseProxy: - return "Use Proxy"; - case StatusCode::TemporaryRedirect: - return "Temporary Redirect"; - case StatusCode::PermanentRedirect: - return "Permanent Redirect"; - case StatusCode::BadRequest: - return "Bad Request"; - case StatusCode::Unauthorized: - return "Unauthorized"; - case StatusCode::PaymentRequired: - return "Payment Required"; - case StatusCode::Forbidden: - return "Forbidden"; - case StatusCode::NotFound: - return "Not Found"; - case StatusCode::MethodNotAllowed: - return "Method Not Allowed"; - case StatusCode::NotAcceptable: - return "Not Acceptable"; - case StatusCode::ProxyAuthenticationRequired: - return "Proxy Authentication Required"; - case StatusCode::RequestTimeout: - return "Request Timeout"; - case StatusCode::Conflict: - return "Conflict"; - case StatusCode::Gone: - return "Gone"; - case StatusCode::LengthRequired: - return "Length Required"; - case StatusCode::PreconditionFailed: - return "Precondition Failed"; - case StatusCode::PayloadTooLarge: - return "Payload Too Large"; - case StatusCode::URITooLong: - return "URI Too Long"; - case StatusCode::UnsupportedMediaType: - return "Unsupported Media Type"; - case StatusCode::RangeNotSatisfiable: - return "Range Not Satisfiable"; - case StatusCode::ExpectationFailed: - return "Expectation Failed"; - case StatusCode::ImATeapot: - return "I'm a teapot"; - case StatusCode::MisdirectedRequest: - return "Misdirected Request"; - case StatusCode::UnprocessableContent: - return "Unprocessable Content"; - case StatusCode::Locked: - return "Locked"; - case StatusCode::FailedDependency: - return "Failed Dependency"; - case StatusCode::TooEarly: - return "Too Early"; - case StatusCode::UpgradeRequired: - return "Upgrade Required"; - case StatusCode::PreconditionRequired: - return "Precondition Required"; - case StatusCode::TooManyRequests: - return "Too Many Requests"; - case StatusCode::RequestHeaderFieldsTooLarge: - return "Request Header Fields Too Large"; - case StatusCode::UnavailableForLegalReasons: - return "Unavailable For Legal Reasons"; - case StatusCode::InternalServerError: - return "Internal Server Error"; - case StatusCode::NotImplemented: - return "Not Implemented"; - case StatusCode::ServiceUnavailable: - return "Service Unavailable"; - case StatusCode::GatewayTimeout: - return "Gateway Timeout"; - case StatusCode::HTTPVersionNotSupported: - return "HTTP Version Not Supported"; - case StatusCode::VariantAlsoNegotiates: - return "Variant Also Negotiates"; - case StatusCode::InsufficientStorage: - return "Insufficient Storage"; - case StatusCode::LoopDetected: - return "Loop Detected"; - case StatusCode::NotExtended: - return "Not Extended"; - case StatusCode::NetworkAuthenticationRequired: - return "Network Authentication Required"; - default: - return ""; - } - } -}; - -class QueryParams { - private: - std::vector> items; - public: - void Add(std::string key, std::string value) - { - Add(std::pair(key,value)); - } - void Add(std::pair pair) - { - items.push_back(pair); - } - void Add(std::vector>& items) - { - for(auto item : items) - this->items.push_back(item); - } - std::vector>& GetAll() - { - return this->items; - } - void Get(std::vector& v, std::string key) - { - for(auto item : this->items) - if(item.first == key) - v.push_back(item.second); - } - void Set(std::string key,std::string value) - { - Clear(key); - Add(key,value); - } - - - void Set(std::pair item) - { - Set(item.first,item.second); - } - - void Set(std::string key, std::vector& value) - { - Clear(key); - for(auto item : value) - Add(key,item); - } - - bool TryGetFirst(std::string key,std::string& val) - { - for(auto item : this->items) - if(item.first == key) - { - val = item.second; - return true; - } - return false; - } - void Clear(std::string key) - { - - for(auto item = items.begin();itemstrm = strm; - std::string firstLine = strm->ReadLine(); - DEBUGOUT("READ Request line\n"); - std::vector firstLineA=HttpUtils::SplitString(firstLine," ",4); - DEBUGOUT("Split Request line\n"); - - if(firstLineA.size() == 4 || firstLineA.size() < 3) - { - DEBUGOUT("Request line does not have 3 entries\n"); - this->ok=false; - } - else - { - this->ok=false; - method = firstLineA[0]; - std::vector p = HttpUtils::SplitString(firstLineA[1],"?",2); - if(p.size() >= 1) - { - this->ok = true; - this->originalPath = p[0]; - DEBUGOUT("Path %s\n",this->originalPath.c_str()); - this->path = originalPath; - if(p.size() == 2) - { - auto qp=HttpUtils::QueryParamsDecode(p[1]); - this->queryParams.Add(qp); - } - } - version = firstLineA[2]; - responseVersion=version; - std::string line; - while((line=strm->ReadLine()).size() > 0) - { - std::vector header=HttpUtils::SplitString(line,": ",2); - if(header.size() == 2) - { - this->requestHeaders.Add(std::pair(header[0],header[1])); - } - } - - } - - - - } - bool CanHandleRequest() - { - return this->ok; - } - - std::string method; - std::string originalPath; - std::string path; - std::string version; - - std::string responseVersion; - - bool ConnectionOpen() - { - std::string keep_alive; - if(requestHeaders.TryGetFirst("Connection",keep_alive)) - { - return keep_alive.compare("keep-alive") == 0; - } - return false; - } - - QueryParams queryParams; - QueryParams requestHeaders; - QueryParams responseHeaders; - - StatusCode statusCode=StatusCode::OK; - - void SendHeaders() - { - std::string headers = responseVersion + " " + std::to_string((int)statusCode) + " " + HttpUtils::StatusCodeString(statusCode) + "\r\n"; - - for(auto header : responseHeaders.GetAll()) - { - headers += header.first + ": " + header.second + "\r\n"; - } - headers += "\r\n"; - this->strm->WriteBlock((uint8_t*)headers.c_str(),headers.size()); - - } - - void SendErrorPage(bool showPath) - { - std::string errorHtml = showPath ? ("File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "

" + HttpUtils::HtmlEncode(this->originalPath) + "

") : ""; - - SetContentType("text/html")->SendText(errorHtml); - } - - ServerContext* SetContentType(std::string contentType) - { - return this->SetHeader("Content-Type",contentType); - } - - ServerContext* SetHeader(std::string key,std::string value) - { - this->responseHeaders.Set(key,value); - return this; - } - - void SendBytes(uint8_t* buffer,size_t len) - { - this->SetHeader("Content-Length",std::to_string(len))->SendHeaders(); - this->strm->WriteBlock(buffer,len); - } - - void SendText(std::string text) - { - SendBytes((uint8_t*)text.c_str(),text.size()); - } - - void SendNotFound() - { - statusCode = StatusCode::NotFound; - SendErrorPage(true); - } - void SendBadRequest() - { - statusCode = StatusCode::BadRequest; - SendErrorPage(false); - } - - ~ServerContext() - { - if(!ConnectionOpen()) - delete strm; - } -}; - -class IServer { - public: - virtual bool Handle(ServerContext* ctx)=0; -}; - - -#if defined(USE_SCRIPT_ENGINE) - #define INCLUDED_FROM_TESSESWEBSERVER_H - #include "tessesscriptengine.hpp" - #undef INCLUDED_FROM_TESSESWEBSERVER_H -#endif - -class HttpServerListener { - - - static THREAD_RETURN_TYPE HandleRequestOnThread(void* arg) - { - DEBUGOUT("Started thread\n"); - void** args = (void**)arg; - IServer* svr= static_cast(args[0]); - Stream* strm = static_cast(args[1]); - - delete args; - - HandleRequest(svr,strm); - - return THREAD_DEFAULT_RETURN_TYPE; - } - - public: - - static void Init() - { - tesses_webserver_statics.isRunning=true; - Thread::Init(); - } - - - - static void HandleRequest(IServer* server,Stream* strm) - { - start: - ServerContext* ctx = new ServerContext(strm); - - if(!ctx->CanHandleRequest()) - { - ctx->SendBadRequest(); - delete ctx; - return; - } - - if(!server->Handle(ctx)) - ctx->SendNotFound(); - - - if(ctx->ConnectionOpen()) - { - delete ctx; - goto start; - } - - delete ctx; - - - } - - - - static void ListenWithBoundSocket(IServer* server,int boundAndListeningSocket) - { - printf("\033[31mAlmost ready to listen\033[0m\n"); - while(tesses_webserver_statics.isRunning) - { - struct sockaddr addr; - socklen_t addrlen; - int a = accept(boundAndListeningSocket, &addr, &addrlen); - - void** myArg = new void*[2]; - - myArg[0] = static_cast(server); - myArg[1] = static_cast(new SocketStream(a)); - - - Thread* thread = new Thread(HandleRequestOnThread,myArg,512000); - thread->Detach(); - - /*ServerContext* ctx = ReadHeaders(a); - - if(!server->Handle(ctx)) - ctx->SendNotFound(); - - delete ctx; - - - close(a); - */ - } - } - static void Listen(IServer* server, unsigned int domain,const struct sockaddr* addr, socklen_t addrlen) - { - int s=socket(domain,SOCK_STREAM,0); - if(s == -1) - { - printf("Socket error\n"); - - throw std::exception(); - } - if(bind(s,addr,addrlen) == -1) - { - printf("Bind error\n"); - throw std::exception(); - } - - if(listen(s,10) == -1) - { - printf("Listen error\n"); - throw std::exception(); - } - ListenWithBoundSocket(server,s); - } - - static void Listen(IServer* server, int port) - { - struct sockaddr_in addr; - memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons((uint16_t)port); - addr.sin_addr.s_addr = 0; - - Listen(server,AF_INET,(struct sockaddr*)&addr,(socklen_t)sizeof(addr)); - } - - static void DoJobs() - { - #if defined(GEKKO) - Thread::CleanThreads(); - #endif - } - - static void Stop() - { - - } -}; - -#define TESSESWEBSERVER_STATIC_DECLARATION Tesses::WebServer::Statics Tesses::WebServer::tesses_webserver_statics; - - - -} \ No newline at end of file diff --git a/tesseswebserverfeatures.hpp b/tesseswebserverfeatures.hpp deleted file mode 100644 index 58ea23f..0000000 --- a/tesseswebserverfeatures.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define USE_SCRIPT_ENGINE -#define USE_MBEDTLS -#define USE_CURL -#define USE_SQLITE3 -#define USE_JANSSON \ No newline at end of file diff --git a/wwwroot/cgi-bin/add-todo.twss b/wwwroot/cgi-bin/add-todo.twss index 05a9e99..d5c9ee4 100644 --- a/wwwroot/cgi-bin/add-todo.twss +++ b/wwwroot/cgi-bin/add-todo.twss @@ -1,8 +1,13 @@ \ No newline at end of file diff --git a/wwwroot/deinit.twss b/wwwroot/deinit.twss index a60b3e1..04fa5ad 100644 --- a/wwwroot/deinit.twss +++ b/wwwroot/deinit.twss @@ -1,3 +1,6 @@ \ No newline at end of file diff --git a/wwwroot/index.twss b/wwwroot/index.twss index b320bcc..5697a8e 100644 --- a/wwwroot/index.twss +++ b/wwwroot/index.twss @@ -15,11 +15,15 @@
    -
  • +
  • x
diff --git a/wwwroot/init.twss b/wwwroot/init.twss index 3e43948..1d95b6d 100644 --- a/wwwroot/init.twss +++ b/wwwroot/init.twss @@ -1,3 +1,40 @@ \ No newline at end of file