First commit

This commit is contained in:
Mike Nolan 2022-11-30 21:27:30 -06:00
commit 9a8ad9985d
20 changed files with 4594 additions and 0 deletions

60
.gitignore vendored Normal file
View File

@ -0,0 +1,60 @@
# http://www.gnu.org/software/automake
Makefile.in
/ar-lib
/mdate-sh
/py-compile
/test-driver
/ylwrap
.deps/
.dirstamp
# http://www.gnu.org/software/autoconf
autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/config.cache
/config.guess
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1
# https://www.gnu.org/software/libtool/
/ltmain.sh
# http://www.gnu.org/software/texinfo
/texinfo.tex
# http://www.gnu.org/software/m4/
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
# Generated Makefile
# (meta build system like autotools,
# can automatically generate from config.status script
# (which is called by configure script))
Makefile
Footer
!wii/Makefile
wii/boot.elf
wii/boot.dol
wii/build
/boxscript
*.o

17
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/SDL2"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

33
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/source/a.out",
"args": ["/media/mike/BOOTMII/BoxScript/webide/app.bs"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}

58
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,58 @@
{
"files.associations": {
"*.tcc": "cpp",
"string": "cpp",
"iostream": "cpp",
"vector": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"map": "cpp",
"unordered_map": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"chrono": "cpp",
"ctime": "cpp",
"ratio": "cpp",
"thread": "cpp",
"filesystem": "cpp",
"codecvt": "cpp",
"iomanip": "cpp"
}
}

12
Makefile.am Normal file
View File

@ -0,0 +1,12 @@
AM_CXXFLAGS = -std=c++17
AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = boxscript
boxscript_SOURCES = \
source/pcapp.cpp \
source/parser.cpp \
source/dirent.cpp \
source/expressions.cpp \
source/lexer.cpp \
source/networkstream.cpp \
source/runtimefuncs.cpp

127
config.h Normal file
View File

@ -0,0 +1,127 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1
/* Define to 1 if you have the `gethostbyname' function. */
#define HAVE_GETHOSTBYNAME 1
/* Define to 1 if you have the `inet_ntoa' function. */
#define HAVE_INET_NTOA 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `curl' library (-lcurl). */
#define HAVE_LIBCURL 1
/* Define to 1 if you have the `pthread' library (-lpthread). */
#define HAVE_LIBPTHREAD 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkdir' function. */
#define HAVE_MKDIR 1
/* Define to 1 if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if the system has the type `_Bool'. */
#define HAVE__BOOL 1
/* Name of package */
#define PACKAGE "boxscript"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME "boxscript"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "boxscript VERSION"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "boxscript"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "VERSION"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "VERSION"
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT32_T */
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT8_T */
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef int64_t */
/* Define to `long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint16_t */
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint32_t */
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint8_t */

123
config.h.in~ Normal file
View File

@ -0,0 +1,123 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#undef HAVE_FSEEKO
/* Define to 1 if you have the `gethostbyname' function. */
#undef HAVE_GETHOSTBYNAME
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkdir' function. */
#undef HAVE_MKDIR
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef int64_t
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#undef uint16_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#undef uint8_t

36
configure.ac Normal file
View File

@ -0,0 +1,36 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([boxscript], [VERSION], [])
AC_CONFIG_SRCDIR([source/dirent.cpp])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
#AC_CHECK_LIB([m], [main])
AC_CHECK_LIB([pthread],[pthread_create])
AC_CHECK_LIB([curl],[curl_easy_init])
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/socket.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL
AC_TYPE_INT64_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT8_T
# Checks for library functions.
AC_FUNC_FSEEKO
AC_CHECK_FUNCS([gethostbyname inet_ntoa mkdir socket])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

56
source/dirent.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "parser.hpp"
#include <dirent.h>
#include <sys/stat.h>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
std::vector<std::pair<std::string,bool>> get_entries(std::string path)
{
std::vector<std::pair<std::string,bool>> entries;
#if defined(GEKKO)
DIR* dir = opendir(path.c_str());
if(dir == NULL)
{
return entries;
}
struct dirent* entry;
entry = readdir(dir);
while(entry != NULL)
{
entries.push_back({entry->d_name,entry->d_type == DT_DIR});
entry = readdir(dir);
}
closedir(dir);
#else
for (const auto & entry : fs::directory_iterator(path))
entries.push_back({entry.path().filename().c_str(),entry.is_directory()});
#endif
return entries;
}
std::vector<std::string> get_files(std::string path)
{
std::vector<std::string> files;
for(auto f : get_entries(path))
{
if(f.first!="." && f.first != ".." && !f.second )
{
files.push_back(f.first);
}
}
return files;
}
std::vector<std::string> get_directories(std::string path)
{
std::vector<std::string> files;
for(auto f : get_entries(path))
{
if(f.first!="." && f.first != ".." && f.second )
{
files.push_back(f.first);
}
}
return files;
}

258
source/expressions.cpp Normal file
View File

@ -0,0 +1,258 @@
#include "parser.hpp"
namespace BoxScript
{
#pragma region "ConstantNumber"
ConstantNumber::ConstantNumber(string num)
{
this->num=stoll(num);
}
int64_t ConstantNumber::Evaluate(IApplicationState* state)
{
return this->num;
}
string ConstantNumber::GetNodeName()
{
return "ConstantNumber";
}
#pragma endregion
#pragma region "VariableGetValueNode"
string VariableGetValueNode::GetName()
{
return this->var;
}
string VariableGetValueNode::GetNodeName()
{
return "VariableGetValueNode";
}
VariableGetValueNode::VariableGetValueNode(string var)
{
this->var = var;
}
int64_t VariableGetValueNode::Evaluate(IApplicationState* state)
{
return state->GetVariable(this->var);
}
#pragma endregion
#pragma region "StringNode"
string StringNode::GetText()
{
return this->text;
}
string StringNode::GetNodeName()
{
return "StringNode";
}
StringNode::StringNode(string var)
{
this->boxId=-1;
this->text=var;
}
int64_t StringNode::Evaluate(IApplicationState* state)
{
if(boxId > -1)
return boxId;
boxId = state->CreateBoxPermanent(text);
return boxId;
}
#pragma endregion
#pragma region "SetVariableNode"
SetVariableNode::~SetVariableNode()
{
delete this->e;
}
string SetVariableNode::GetNodeName()
{
return "SetVariableNode";
}
SetVariableNode::SetVariableNode(Expression* expression,string name)
{
this->e = expression;
this->vname =name;
}
int64_t SetVariableNode::Evaluate(IApplicationState* state)
{
int64_t v = e->Evaluate(state);
state->SetVariable(vname,v);
return 0;
}
#pragma endregion
#pragma region "FunctionCallNode"
FunctionCallNode::~FunctionCallNode()
{
for(auto node: this->expressions)
{
delete node;
}
}
string FunctionCallNode::GetNodeName()
{
return "FunctionCallNode";
}
FunctionCallNode::FunctionCallNode(string _name,vector<Expression*> exps)
{
this->name = _name;
this->expressions =exps;
}
int64_t FunctionCallNode::Evaluate(IApplicationState* state)
{
if(state->HasRuntimeFunction(name))
{
return state->GetRuntimeFunction(name)(state,expressions);
}
if(state->HasFunction(name))
{
return state->ExecuteFunction(name,expressions);
}
return 0;
}
#pragma endregion
#pragma region "AddNode"
AddNode::~AddNode()
{
delete left;
delete right;
}
string AddNode::GetNodeName()
{
return "AddNode";
}
AddNode::AddNode(Expression* _left,Expression* _right)
{
this->left=_left;
this->right = _right;
}
int64_t AddNode::Evaluate(IApplicationState* state)
{
return this->left->Evaluate(state) + this->right->Evaluate(state);
}
#pragma endregion
#pragma region "MinusNode"
MinusNode::~MinusNode()
{
delete left;
delete right;
}
string MinusNode::GetNodeName()
{
return "MinusNode";
}
MinusNode::MinusNode(Expression* _left,Expression* _right)
{
this->left=_left;
this->right = _right;
}
int64_t MinusNode::Evaluate(IApplicationState* state)
{
return this->left->Evaluate(state) - this->right->Evaluate(state);
}
#pragma endregion
#pragma region "MultiplyNode"
MultiplyNode::~MultiplyNode()
{
delete left;
delete right;
}
string MultiplyNode::GetNodeName()
{
return "MultiplyNode";
}
MultiplyNode::MultiplyNode(Expression* _left,Expression* _right)
{
this->left=_left;
this->right = _right;
}
int64_t MultiplyNode::Evaluate(IApplicationState* state)
{
return this->left->Evaluate(state) * this->right->Evaluate(state);
}
#pragma endregion
#pragma region "DivideNode"
DivideNode::~DivideNode()
{
delete left;
delete right;
}
string DivideNode::GetNodeName()
{
return "DivideNode";
}
DivideNode::DivideNode(Expression* _left,Expression* _right)
{
this->left=_left;
this->right = _right;
}
int64_t DivideNode::Evaluate(IApplicationState* state)
{
return this->left->Evaluate(state) / this->right->Evaluate(state);
}
#pragma endregion
#pragma region "ModulusNode"
ModulusNode::~ModulusNode()
{
delete left;
delete right;
}
string ModulusNode::GetNodeName()
{
return "ModulusNode";
}
ModulusNode::ModulusNode(Expression* _left,Expression* _right)
{
this->left=_left;
this->right = _right;
}
int64_t ModulusNode::Evaluate(IApplicationState* state)
{
return this->left->Evaluate(state) % this->right->Evaluate(state);
}
#pragma endregion
#pragma region "ListNode"
void ListNode::DisableScope()
{
this->root=true;
}
ListNode::~ListNode()
{
for(auto node : nodes)
{
delete node;
}
}
string ListNode::GetNodeName()
{
return "ListNode";
}
int64_t ListNode::Evaluate(IApplicationState* state)
{
int64_t res=0;
IApplicationState* s=state;
if(!root)
{
s=s->NewScope();
s->AddThreadOwner();
}
for(auto node : nodes)
{
state->ExitIfNotRunning();
res= node->Evaluate(state);
}
if(!root)
{
s->RemoveThreadOwner();
}
return res;
}
#pragma endregion
void Expression::DisableScope()
{
}
};

293
source/lexer.cpp Normal file
View File

@ -0,0 +1,293 @@
#include "lexer.hpp"
namespace BoxScript::Lexer
{
LexToken::LexToken()
{
this->text="";
this->type = ERROR;
}
LexToken::LexToken(std::string _text)
{
this->text = _text;
if(_text.size() > 0)
{
this->type=_text[0] >= '0' && _text[0] <= '9' ? NUMBER : IDENTIFER;
}
else{
this->type = ERROR;
}
}
class Lexer
{
private:
std::string text;
int filePos;
void read_char(char* chr,bool* esc)
{
int txt = text[filePos++];
if(txt == '\\')
{
txt = text[filePos++];
if(txt == 'x')
{
std::string txt="0x";
filePos+=2;
for(int i = 0;i<2;i++)
{
txt += text[filePos++];
}
*chr= (char)std::stol(txt,0,0);
}else
{
if(txt == 'n')
{
*chr= '\n';
}else
if(txt == 'r')
{
*chr='\r';
}else
if(txt == 't')
{
*chr='\t';
}else{
*chr = (char)txt;
}
}
*esc=true;
}
else{
*esc=false;
*chr=(char)txt;
}
}
std::string read_string()
{
std::string b="";
while(true)
{
char chr='\0';
bool esc=false;
read_char(&chr,&esc);
if(chr == '\"' && !esc)
{
break;
}
b+=chr;
}
return b;
}
public:
Lexer(std::string _text)
{
this->text=_text;
this->filePos=0;
}
std::vector<LexToken> Lex()
{
std::vector<LexToken> tokens;
std::string b="";
while(filePos < text.length())
{
char c = text[filePos++];
if(c == '\"')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
std::string str = read_string();
LexToken token;
token.text = str;
token.type = STRING;
tokens.push_back(token);
}else if(c == '#')
{
while(text[filePos++] != '\n');
}
else
if(c == '\'')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
char chr='\0';
bool esc;
read_char(&chr,&esc);
LexToken token;
token.text="";
token.text += chr;
token.type = NUMBER;
tokens.push_back(token);
}else if(c == '+')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="+";
token.type = PLUS;
tokens.push_back(token);
}else if(c == '-')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="-";
token.type = MINUS;
tokens.push_back(token);
}else if(c == '+')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="*";
token.type = MULTIPLY;
tokens.push_back(token);
}
else if(c == '/')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="/";
token.type = DIVIDE;
tokens.push_back(token);
}else if(c == '%')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="%";
token.type = MOD;
tokens.push_back(token);
}
else if(c == '{')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="{";
token.type = LBRACE;
tokens.push_back(token);
}
else if(c == '}')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="}";
token.type = RBRACE;
tokens.push_back(token);
}
else if(c == '(')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="(";
token.type = LPAREN;
tokens.push_back(token);
}
else if(c == ')')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text=")";
token.type = RPAREN;
tokens.push_back(token);
}
else if(c == '=')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text="=";
token.type = EQUALS;
tokens.push_back(token);
}
else if(c == ',')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text=",";
token.type = COMMA;
tokens.push_back(token);
}
else if(c == ';')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
LexToken token;
token.text=";";
token.type = SEMI;
tokens.push_back(token);
}
else if(c == '\n' || c == ' ' || c == '\t')
{
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
}else{
b += c;
}
}
if(b.length() > 0)
{
tokens.push_back(LexToken(b));
b="";
}
return tokens;
}
};
std::vector<LexToken> Lex(std::string text)
{
Lexer l(text);
return l.Lex();
}
};

34
source/lexer.hpp Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <string>
#include <vector>
namespace BoxScript::Lexer
{
enum LexTokenType
{
PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
LPAREN,
RPAREN,
IDENTIFER,
NUMBER,
EQUALS,
COMMA,
ERROR,
SEMI,
LBRACE,
RBRACE,
STRING
};
class LexToken
{
public:
std::string text;
LexTokenType type;
LexToken();
LexToken(std::string _text);
};
std::vector<LexToken> Lex(std::string text);
};

352
source/networkstream.cpp Normal file
View File

@ -0,0 +1,352 @@
#include "parser.hpp"
#include <cstring>
#if defined(GEKKO)
int net_initialized = 0;
char bba_local_ip[16];
char bba_netmask[16];
char bba_gateway[16];
#if defined(HW_DOL)
#include <ogc/exi.h>
int bba_exists = 0;
unsigned int exi_get_id(int chn, int dev)
{
u32 cid = 0;
EXI_GetID(chn,dev,&cid);
return cid;
}
int exi_bba_exists()
{
return exi_get_id(EXI_CHANNEL_0,EXI_DEVICE_2) == EXI_BBA_ID;
}
#endif
#endif
namespace BoxScript
{
void sockets_free()
{
#if defined(HW_RVL) && defined(LIBWIISOCKET)
wiisocket_deinit();
#elif defined(HW_RVL) && !defined(LIBWIISOCKET)
net_deinit();
#elif defined(_WIN32) || defined(WIN32)
WSACleanup();
#endif
}
int NetworkInit()
{
#if defined(LIBWIISOCKET)
return wiisocket_init();
#endif
#if defined(GEKKO) && !defined(LIBWIISOCKET)
int res;
#if defined(HW_DOL)
bba_exists = exi_bba_exists();
if(bba_exists && !net_initialized) {
#else
if(!net_initialized){
#endif
res = if_config(bba_local_ip, bba_netmask, bba_gateway, true,20);
if(res >= 0 && strcmp("255.255.255.255", bba_local_ip)) {
net_initialized = 1;
}
else {
net_initialized = 0;
}
}
#elif defined(_WIN32) || defined(WIN32)
int err= WSAStartup(0x202, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we */
/* requested. */
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
#else
#endif
return 0;
}
NetworkStream::NetworkStream(SOCKET i)
{
this->fd = i;
}
void NetworkStream::Write(uint8_t* data,size_t len)
{
#if defined(OGC_NETWORKING)
net_send(this->fd,data,len,0);
#else
int flags=0;
#if __linux__
flags=MSG_NOSIGNAL;
#endif
send(this->fd,data,len,flags);
#endif
}
size_t NetworkStream::Read(uint8_t* data,size_t len)
{
#if defined(OGC_NETWORKING)
ssize_t v=(ssize_t)net_recv(this->fd,data,len,0);
if(v < 0) return 0;
return (size_t)v;
#else
int flags=0;
#if __linux__
flags=MSG_NOSIGNAL;
#endif
ssize_t v=recv(this->fd,data,len,flags);
if(v < 0) return 0;
return (size_t)v;
#endif
}
int64_t NetworkStream::GetPosition()
{
return 0;
}
int64_t NetworkStream::GetLength()
{
return 0;
}
void NetworkStream::SetPosition(int64_t pos)
{
}
void NetworkStream::Flush()
{
}
void NetworkStream::Close()
{
#if defined(OGC_NETWORKING)
net_close(this->fd);
#else
close(this->fd);
#endif
}
bool NetworkStream::CanRead()
{
return true;
}
bool NetworkStream::CanWrite()
{
return true;
}
bool NetworkStream::CanSeek()
{
return false;
}
struct hostent* _______ghbn(string ip)
{
#if defined(GEKKO) && !defined(LIBWIISOCKET)
return net_gethostbyname(ip.c_str());
#else
return gethostbyname(ip.c_str());
#endif
}
NetworkStream* NetClient(string ip,int64_t port,SOCKET fd)
{
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons((uint16_t)port);
if (inet_aton( ip.c_str(), &serv_addr.sin_addr)
<= 0) {
struct hostent* host=_______ghbn(ip);
struct in_addr **addr_list;
addr_list = (struct in_addr **)host->h_addr_list;
if(host->h_length > 0)
{
memcpy(&serv_addr.sin_addr,addr_list[0],sizeof(struct in_addr));
}else{
return NULL;
}
}
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if(net_connect(fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in)))
{
return NULL;
}
#else
if(connect(fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in)))
{
return NULL;
}
#endif
return new NetworkStream(fd);
}
SOCKET NetServerInit(string ip,int64_t port,int fd)
{
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (inet_aton( ip.c_str(), &serv_addr.sin_addr)
<= 0) {
struct hostent* host=_______ghbn(ip);
struct in_addr **addr_list;
addr_list = (struct in_addr **)host->h_addr_list;
if(host->h_length > 0)
{
memcpy(&serv_addr.sin_addr,addr_list[0],sizeof(struct in_addr));
}else{
throw exception();
}
}
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if(net_bind(fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in))< 0)
{
printf("bind error, is your computer already listening on that port\n");
throw exception();
}
if(net_listen(fd,100) > 0)
{
printf("listen error");
throw exception();
}
#else
if(bind(fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in))< 0)
{
printf("bind error, is your computer already listening on that port\n");
throw exception();
}
if(listen(fd,100) > 0)
{
printf("listen error");
throw exception();
}
#endif
return fd;
}
SOCKET TcpServerInit(string ip,int64_t port)
{
SOCKET fd;
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if ((fd = net_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
#else
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
#endif
return NetServerInit(ip,port,fd);
}
SOCKET UdpServerInit(string ip,int64_t port)
{
SOCKET fd;
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if ((fd = net_socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
#else
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
#endif
return NetServerInit(ip,port,fd);
}
Stream* AcceptClient(SOCKET fd,string* ip)
{
struct sockaddr_in clt_addr;
socklen_t clt_addr_len = sizeof(struct sockaddr_in);
#if defined(GEKKO) && !defined(LIBWIISOCKET)
int cltFd=net_accept(fd,(struct sockaddr*)&clt_addr,&clt_addr_len);
#else
#if defined(_WIN32) || defined(WIN32)
SOCKET cltFd=accept(fd,(struct sockaddr*)&clt_addr,&clt_addr_len);
#else
int cltFd=accept(fd,(struct sockaddr*)&clt_addr,&clt_addr_len);
#endif
#endif
ip->append(inet_ntoa(clt_addr.sin_addr));
return new NetworkStream(cltFd);
}
NetworkStream* TcpClient(string ip,int64_t port)
{
#if defined(_WIN32) || defined(WIN32)
SOCKET fd;
#else
int fd;
#endif
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if ((fd = net_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return NULL;
}
#else
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return NULL;
}
#endif
return NetClient(ip,port,fd);
}
NetworkStream* UdpClient(string ip,int64_t port)
{
#if defined(_WIN32) || defined(WIN32)
SOCKET fd;
#else
int fd;
#endif
#if defined(GEKKO) && !defined(LIBWIISOCKET)
if ((fd = net_socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("\n Socket creation error \n");
return NULL;
}
#else
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("\n Socket creation error \n");
return NULL;
}
#endif
return NetClient(ip,port,fd);
}
};

984
source/parser.cpp Normal file
View File

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

537
source/parser.hpp Normal file
View File

@ -0,0 +1,537 @@
#pragma once
#define _FILE_OFFSET_BITS 64
#include <string>
#include <cstdint>
#include <vector>
#include <unordered_map>
#include <cstdbool>
#include <atomic>
#include "config.h"
#include "lexer.hpp"
#if defined(GEKKO) && !defined(LIBWIISOCKET)
#define OGC_NETWORKING
#include <network.h>
typedef int SOCKET;
#elif defined(_WIN32) || defined(WIN32)
#define WINDOWS_NETWORKING
#include <conio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
WSADATA wsaData;
#else
typedef int SOCKET;
#define SYS_SOCKET_NETWORKING
#if defined(HW_RVL) && defined(LIBWIISOCKET)
#include <wiisocket.h>
#endif
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
using namespace std;
namespace BoxScript
{
class Expression;
class Stream;
class IApplicationState;
class ConstantNumber;
class Expression
{
public:
virtual void DisableScope();
virtual string GetNodeName()=0;
virtual int64_t Evaluate(IApplicationState* state)=0;
};
class Stream
{
public:
void CopyTo(Stream* strm);
virtual int64_t ReadByte();
virtual void Write(uint8_t* data,size_t len)=0;
virtual size_t Read(uint8_t* data,size_t len)=0;
virtual int64_t GetPosition()=0;
virtual int64_t GetLength()=0;
virtual void SetPosition(int64_t pos)=0;
virtual void Flush()=0;
virtual void Close()=0;
virtual bool CanRead()=0;
virtual bool CanWrite()=0;
virtual bool CanSeek()=0;
};
class BufferedStream : public Stream
{
private:
Stream* strm;
int16_t pos=-1;
int16_t readIn=-1;
uint8_t buffer[4096];
public:
BufferedStream(Stream* parent);
int64_t ReadByte();
void Write(uint8_t* data,size_t len);
size_t Read(uint8_t* data,size_t len);
int64_t GetPosition();
int64_t GetLength();
void SetPosition(int64_t pos);
void Flush();
void Close();
bool CanRead();
bool CanWrite();
bool CanSeek();
};
class NetworkStream : public Stream
{
private:
SOCKET fd;
public:
NetworkStream(SOCKET i);
void Write(uint8_t* data,size_t len);
size_t Read(uint8_t* data,size_t len);
int64_t GetPosition();
int64_t GetLength();
void SetPosition(int64_t pos);
void Flush();
void Close();
bool CanRead();
bool CanWrite();
bool CanSeek();
};
typedef int64_t (*internal_func)(IApplicationState* state,vector<Expression*> expressions);
class IApplicationState
{
public:
virtual void StopRunning()=0;
virtual void ExitIfNotRunning()=0;
virtual void AddThreadOwner();
virtual void RemoveThreadOwner();
virtual void FlushStream(int64_t stream)=0;
virtual void DestroyBox(int64_t id)=0;
virtual int64_t e2n(Expression* e)=0;
virtual Expression* Calln(int64_t e)=0;
virtual int64_t CreateStream(Stream* strm)=0;
virtual internal_func GetRuntimeFunction(string str)=0;
virtual void CopyStream(int64_t strmSrc,int64_t strmDest)=0;
virtual void CloseStream(int64_t streamId)=0;
virtual void WriteToStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)=0;
virtual int64_t ReadFromStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len)=0;
virtual int64_t ReadByteFromStream(int64_t streamId)=0;
virtual int64_t CreateBufferedStream(int64_t existingStreamId)=0;
virtual void SetStreamPosition(int64_t streamId,int64_t streamPos)=0;
virtual int64_t GetStreamPosition(int64_t streamId)=0;
virtual int64_t GetStreamLength(int64_t streamId)=0;
virtual bool CanRead(int64_t streamId)=0;
virtual bool CanWrite(int64_t streamId)=0;
virtual bool CanSeek(int64_t streamId)=0;
virtual int64_t ExecuteFunction(string str,vector<Expression*> expressions)=0;
virtual bool HasRuntimeFunction(string str)=0;
virtual bool HasFunction(string str)=0;
virtual void AddFunction(string str,vector<string> args,Expression* exp)=0;
virtual void AddRuntimeFunction(string str,internal_func func)=0;
virtual string BoxToString(int64_t boxId)=0;
virtual void ClearBox(int64_t bId)=0;
virtual void AddToBox(int64_t bId,int64_t value)=0;
virtual void RemoveFromBox(int64_t bId,int64_t value)=0;
virtual void RemoveAtFromBox(int64_t bId,int index)=0;
virtual void InsertToBox(int64_t bId,int index,int64_t value)=0;
virtual void SetBoxValue(int64_t bId,int index,int64_t value)=0;
virtual void SetVariable(string name,int64_t value)=0;
virtual int64_t GetVariable(string name)=0;
virtual int64_t BoxLength(int64_t boxId)=0;
virtual int64_t CreateBox(int len)=0;
virtual int64_t CreateBox(string text)=0;
virtual int64_t CreateBoxPermanent(string text)=0;
virtual int64_t GetBoxValue(int64_t bId, int index)=0;
virtual bool HasVariable(string name)=0;
virtual IApplicationState* NewScope()=0;
};
class ApplicationState : public IApplicationState
{
private:
unordered_map<int64_t,pair<vector<int64_t>,bool>> boxes;
unordered_map<int64_t,Expression*> expressions;
unordered_map<int64_t,Stream*> streams;
unordered_map<string,int64_t> variables;
unordered_map<string,pair<vector<string>,Expression*>> methods;
unordered_map<string,internal_func> runtime_funcs;
atomic_int64_t NoBoxes;
atomic_int64_t NoStreams;
atomic_int64_t NoExpressions;
atomic_bool isRunning;
public:
void StopRunning();
void ExitIfNotRunning();
ApplicationState();
internal_func GetRuntimeFunction(string str);
void FlushStream(int64_t stream);
void DestroyBox(int64_t id);
int64_t e2n(Expression* e);
Expression* Calln(int64_t e);
int64_t CreateStream(Stream* strm);
void CopyStream(int64_t strmSrc,int64_t strmDest);
void CloseStream(int64_t streamId);
void WriteToStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len);
int64_t ReadFromStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len);
void SetStreamPosition(int64_t streamId,int64_t streamPos);
int64_t GetStreamPosition(int64_t streamId);
int64_t GetStreamLength(int64_t streamId);
bool CanRead(int64_t streamId);
bool CanWrite(int64_t streamId);
bool CanSeek(int64_t streamId);
int64_t ExecuteFunction(string str,vector<Expression*> expressions);
bool HasRuntimeFunction(string str);
bool HasFunction(string str);
void AddFunction(string str,vector<string> args,Expression* exp);
void AddRuntimeFunction(string str,internal_func func);
string BoxToString(int64_t boxId);
void ClearBox(int64_t bId);
void AddToBox(int64_t bId,int64_t value);
void RemoveFromBox(int64_t bId,int64_t value);
void RemoveAtFromBox(int64_t bId,int index);
void InsertToBox(int64_t bId,int index,int64_t value);
int64_t ReadByteFromStream(int64_t streamId);
int64_t CreateBufferedStream(int64_t existingStreamId);
void SetBoxValue(int64_t bId,int index,int64_t value);
void SetVariable(string name,int64_t value);
int64_t GetVariable(string name);
int64_t BoxLength(int64_t boxId);
int64_t CreateBox(int len);
int64_t CreateBox(string text);
int64_t CreateBoxPermanent(string text);
int64_t GetBoxValue(int64_t bId, int index);
bool HasVariable(string name);
IApplicationState* NewScope();
private:
Stream* GetStream(int64_t id);
};
class SubscopeApplicationState : public IApplicationState
{
private:
atomic_char threads;
IApplicationState* state;
unordered_map<string,int64_t> variables;
public:
void StopRunning();
void ExitIfNotRunning();
void AddThreadOwner();
void RemoveThreadOwner();
SubscopeApplicationState(IApplicationState* _state);
void FlushStream(int64_t stream);
void DestroyBox(int64_t id);
int64_t e2n(Expression* e);
Expression* Calln(int64_t e);
int64_t CreateStream(Stream* strm);
void CopyStream(int64_t strmSrc,int64_t strmDest);
void CloseStream(int64_t streamId);
void WriteToStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len);
int64_t ReadByteFromStream(int64_t streamId);
int64_t CreateBufferedStream(int64_t existingStreamId);
int64_t ReadFromStream(int64_t streamId,int64_t boxId,int64_t offset,int64_t len);
void SetStreamPosition(int64_t streamId,int64_t streamPos);
int64_t GetStreamPosition(int64_t streamId);
int64_t GetStreamLength(int64_t streamId);
bool CanRead(int64_t streamId);
bool CanWrite(int64_t streamId);
bool CanSeek(int64_t streamId);
int64_t ExecuteFunction(string str,vector<Expression*> expressions);
internal_func GetRuntimeFunction(string str);
bool HasRuntimeFunction(string str);
bool HasFunction(string str);
void AddFunction(string str,vector<string> args,Expression* exp);
void AddRuntimeFunction(string str,internal_func func);
string BoxToString(int64_t boxId);
void ClearBox(int64_t bId);
void AddToBox(int64_t bId,int64_t value);
void RemoveFromBox(int64_t bId,int64_t value);
void RemoveAtFromBox(int64_t bId,int index);
void InsertToBox(int64_t bId,int index,int64_t value);
void SetBoxValue(int64_t bId,int index,int64_t value);
void SetVariable(string name,int64_t value);
int64_t GetVariable(string name);
int64_t BoxLength(int64_t boxId);
int64_t CreateBox(int len);
int64_t CreateBox(string text);
int64_t CreateBoxPermanent(string text);
int64_t GetBoxValue(int64_t bId, int index);
bool HasVariable(string name);
IApplicationState* NewScope();
};
class ConstantNumber : public Expression
{
private:
int64_t num;
public:
string GetNodeName();
ConstantNumber(string num);
int64_t Evaluate(IApplicationState* state);
};
/*public class VariableGetValueNode : Expression
{
public string Name {get{return var;}}
string var;
public VariableGetValueNode(string var)
{
this.var=var;
}
public override long Evaluate(IApplicationState state)
{
return state.GetVariable(var);
}
}*/
class VariableGetValueNode : public Expression
{
private:
string var;
public:
string GetName();
string GetNodeName();
VariableGetValueNode(string var);
int64_t Evaluate(IApplicationState* state);
};
#pragma region "StringNode"
class StringNode : public Expression
{
private:
string text;
int64_t boxId;
public:
string GetText();
string GetNodeName();
StringNode(string var);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "SetVariableNode"
class SetVariableNode : public Expression
{
private:
Expression* e;
string vname;
public:
~SetVariableNode();
string GetNodeName();
SetVariableNode(Expression* expression,string name);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "FunctionCallNode"
class FunctionCallNode :public Expression
{
private:
string name;
vector<Expression*> expressions;
public:
~FunctionCallNode();
string GetNodeName();
FunctionCallNode(string _name,vector<Expression*> exps);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "AddNode"
class AddNode : public Expression
{
public:
~AddNode();
Expression* left;
Expression* right;
string GetNodeName();
AddNode(Expression* left,Expression* right);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "MinusNode"
class MinusNode : public Expression
{
public:
~MinusNode();
Expression* left;
Expression* right;
string GetNodeName();
MinusNode(Expression* left,Expression* right);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "MultiplyNode"
class MultiplyNode : public Expression
{
public:
~MultiplyNode();
Expression* left;
Expression* right;
string GetNodeName();
MultiplyNode(Expression* left,Expression* right);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "DivideNode"
class DivideNode : public Expression
{
public:
~DivideNode();
Expression* left;
Expression* right;
string GetNodeName();
DivideNode(Expression* left,Expression* right);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "ModulusNode"
class ModulusNode : public Expression
{
public:
~ModulusNode();
Expression* left;
Expression* right;
string GetNodeName();
ModulusNode(Expression* left,Expression* right);
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
#pragma region "ListNode"
class ListNode : public Expression
{
public:
~ListNode();
bool root;
void DisableScope();
vector<Expression*> nodes;
string GetNodeName();
int64_t Evaluate(IApplicationState* state);
};
#pragma endregion
NetworkStream* TcpClient(string ip,int64_t port);
NetworkStream* UdpClient(string ip,int64_t port);
class ExpressionStream : public Stream
{
private:
IApplicationState* st;
vector<Expression*> exp;
public:
ExpressionStream(IApplicationState* state,vector<Expression*> expressions);
void Write(uint8_t* data,size_t len);
size_t Read(uint8_t* data,size_t len);
int64_t GetPosition();
int64_t GetLength();
void SetPosition(int64_t pos);
void Flush();
void Close();
bool CanRead();
bool CanWrite();
bool CanSeek();
};
class FileStream : public Stream
{
private:
FILE* f;
bool cr,cw,cs,own;
public:
FileStream(FILE* fs,bool canRead,bool canWrite,bool canSeek,bool ownFile);
void Write(uint8_t* data,size_t len);
size_t Read(uint8_t* data,size_t len);
int64_t GetPosition();
int64_t GetLength();
void SetPosition(int64_t pos);
void Flush();
void Close();
bool CanRead();
bool CanWrite();
bool CanSeek();
};
SOCKET TcpServerInit(string ip,int64_t port);
SOCKET UdpServerInit(string ip,int64_t port);
Stream* AcceptClient(SOCKET fd,string* ip);
void Parse(ListNode* node,vector<Lexer::LexToken> tokens);
ListNode* Parse(vector<Lexer::LexToken> tokens);
void ParseNode(ListNode* node,vector<Lexer::LexToken> tokens,int* i);
void ParseNode(ListNode* node,vector<Lexer::LexToken> tokens,int* i,bool root);
Expression* ParseExpression(vector<Lexer::LexToken> tokens,int* i);
Expression* ParseTerm(vector<Lexer::LexToken> tokens,int* i);
Expression* ParseFactor(vector<Lexer::LexToken> tokens,int* i);int NetworkInit();
};
void RegisterMainRuntimeFunctions(BoxScript::IApplicationState* state);
void DestroyApp(int);
std::vector<std::string> get_files(std::string path);
std::vector<std::string> get_directories(std::string path);
std::vector<std::pair<std::string,bool>> get_entries(std::string path);
#if defined(GEKKO)
void clear_screen_ogc();
#endif

47
source/pcapp.cpp Normal file
View File

@ -0,0 +1,47 @@
#if !defined(GEKKO)
#include "lexer.hpp"
#include "parser.hpp"
#include <filesystem>
namespace fs = std::filesystem;
using namespace BoxScript;
ListNode* _root_node;
std::string read_file(std::string name)
{
FILE* f=fopen(name.c_str(),"r");
std::string text="";
while(true)
{
int read = fgetc(f);
if(read == EOF) break;
text += (char)read;
}
fclose(f);
return text;
}
#if !defined(LIBRARY)
int main(int argc,char** argv)
{
if(argc < 2) return 1;
_root_node = new BoxScript::ListNode();
for(int i = 1;i<argc;i++){
std::vector<BoxScript::Lexer::LexToken> tokens=BoxScript::Lexer::Lex(read_file(argv[i]));
BoxScript::Parse(_root_node,tokens);
}
BoxScript::ApplicationState* state=new BoxScript::ApplicationState();
RegisterMainRuntimeFunctions(state);
_root_node->Evaluate(state);
DestroyApp(0);
}
#endif
void DestroyApp(int a)
{
delete _root_node;
exit(a);
}
#endif

1186
source/runtimefuncs.cpp Normal file

File diff suppressed because it is too large Load Diff

233
source/wiiapp.cpp Normal file
View File

@ -0,0 +1,233 @@
#if defined(GEKKO)
#include "lexer.hpp"
#include "parser.hpp"
#include <cstdio>
#include <cstdlib>
#include <gccore.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fat.h>
#if defined(HW_RVL)
#include <wiiuse/wpad.h>
#endif
#include <ogc/pad.h>
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
BoxScript::ListNode* _root_node;
void clear_screen_ogc()
{
VIDEO_ClearFrameBuffer(rmode,xfb,0);
}
int appstate=0;
std::string read_file(std::string name)
{
FILE* f=fopen(name.c_str(),"r");
std::string text="";
while(true)
{
int read = fgetc(f);
if(read == EOF) break;
text += (char)read;
}
fclose(f);
return text;
}
bool DirExists(std::string path)
{
DIR* dir;
bool exists = false;
dir = opendir(path.c_str());
if(dir != NULL)
{
exists=true;
(void)closedir(dir);
}
return exists;
}
void LoadSubscripts(BoxScript::ListNode* nodes,std::string path)
{
std::vector<std::string> files = get_files(path);
for(std::string file : files)
{
std::string newPath = path + "/" + file;
std::vector<BoxScript::Lexer::LexToken> tokens=BoxScript::Lexer::Lex(read_file(newPath));
BoxScript::Parse(nodes,tokens);
}
}
void PrintElement(std::string text,bool checked)
{
printf("\t[%c] %s\n",checked ? '*' : ' ', text.c_str());
}
void LoadScript(BoxScript::ListNode* nodes)
{
if(!DirExists("/BoxScript"))
{
mkdir("/BoxScript",0755);
}
if(DirExists("/BoxScript/Autoboot"))
{
if(DirExists("/BoxScript/Autoboot/deps"))
LoadSubscripts(nodes,"/BoxScript/Autoboot/deps");
std::vector<BoxScript::Lexer::LexToken> tokens=BoxScript::Lexer::Lex(read_file("/BoxScript/Autoboot/app.bs"));
BoxScript::Parse(nodes,tokens);
}else{
std::vector<std::string> dirs= get_directories("/BoxScript");
int item=0;
while(appstate != -1)
{
#if defined(HW_RVL)
WPAD_ScanPads();
#endif
PAD_ScanPads();
if(PAD_ButtonsDown(0) & PAD_BUTTON_UP)
{
item--;
if(item < 0)
{
item = dirs.size()-1;
}
}
if(PAD_ButtonsDown(0) & PAD_BUTTON_DOWN)
{
item++;
if(item >= dirs.size())
{
item=0;
}
}
if(PAD_ButtonsDown(0) & PAD_BUTTON_A)
{
break;
}
#if defined(HW_RVL)
if(WPAD_ButtonsDown(0) & WPAD_BUTTON_UP)
{
item--;
if(item < 0)
{
item = dirs.size()-1;
}
}
if(WPAD_ButtonsDown(0) & WPAD_BUTTON_DOWN)
{
item++;
if(item >= dirs.size())
{
item=0;
}
}
if(WPAD_ButtonsDown(0) & WPAD_BUTTON_A)
{
break;
}
#endif
clear_screen_ogc();
printf("\x1b[2;2H");
printf("\n\n");
printf("\tBoxScript 1.0 Wii Version\n");
int indexOnScreen = item % 14;
int screenOffset = (item - indexOnScreen);
int i=0;
for(i = 0;i<14;i++)
{
if(screenOffset + i < dirs.size())
PrintElement(dirs[i+screenOffset],i == indexOnScreen);
}
//printf("\tNo Items: %i",i);
VIDEO_WaitVSync();
}
if(appstate == -1) exit(0);
if(DirExists("/BoxScript/" + dirs[item]))
LoadSubscripts(nodes,"/BoxScript/" + dirs[item] + "/deps");
std::vector<BoxScript::Lexer::LexToken> tokens=BoxScript::Lexer::Lex(read_file("/BoxScript/" + dirs[item] + "/app.bs"));
BoxScript::Parse(nodes,tokens);
}
}
BoxScript::ApplicationState* state;
void WiiResetPressed(unsigned int a,void* ptr)
{
if(appstate <= 0)
{
appstate= -1;
}else{
state->StopRunning();
}
}
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
BoxScript::NetworkInit();
fatInitDefault();
SYS_SetResetCallback(WiiResetPressed);
// Initialise the video system
VIDEO_Init();
PAD_Init();
#if defined(HW_RVL)
WPAD_Init();
#endif
// This function initialises the attached controllers
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
// The console understands VT terminal escape codes
// This positions the cursor on row 2, column 0
// we can use variables for this with format codes too
// e.g. printf ("\x1b[%d;%dH", row, column );
printf("\x1b[2;2H");
_root_node = new BoxScript::ListNode();
LoadScript(_root_node);
appstate=1;
state=new BoxScript::ApplicationState();
RegisterMainRuntimeFunctions(state);
_root_node->Evaluate(state);
DestroyApp(0);
}
void DestroyApp(int a)
{
delete _root_node;
exit(a);
}
#endif

138
wii/Makefile Normal file
View File

@ -0,0 +1,138 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := boot
BUILD := build
SOURCES := ../source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lwiisocket -lfat -lwiiuse -lbte -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS)/wii $(PORTLIBS)/ppc
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := -L$(LIBOGC_LIB) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
$(OFILES_SOURCES) : $(HFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o %_jpg.h : %.jpg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

10
wii/include/config.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
//#define HAVE_LIBSDL2
//#define HAVE_LIBCURL
//#define HAVE_GRRLIB
#if defined(HW_RVL)
#define LIBWIISOCKET
#endif