Objects Initial

This commit is contained in:
IlushaShurupov 2023-07-24 21:55:19 +03:00
parent 00bc875846
commit 803ce23169
76 changed files with 7895 additions and 17 deletions

View file

@ -24,3 +24,5 @@ add_subdirectory(Externals)
add_subdirectory(Connection) add_subdirectory(Connection)
add_subdirectory(Graphics) add_subdirectory(Graphics)
#add_subdirectory(Objects)

View file

@ -20,42 +20,111 @@ namespace tp {
template<typename tType, ualni tSize> template<typename tType, ualni tSize>
class ConstSizeBuffer { class ConstSizeBuffer {
SelCopyArg<tType> Arg; typedef SelCopyArg<tType> Arg;
private: private:
tType mBuff[tSize]; tType mBuff[tSize];
ualni mLoad = 0;
public: public:
ConstSizeBuffer() = default; ConstSizeBuffer() = default;
public: public:
[[nodiscard]] ualni size() const { return tSize; } [[nodiscard]] ualni size() const { return mLoad; }
[[nodiscard]] ualni getBuffSize() const { return tSize; }
tType& first() { tType& first() {
return *mBuff; DEBUG_ASSERT(mLoad)
} return *mBuff;
const tType& first() const {
return *mBuff;
} }
tType& last() { const tType& first() const {
return mBuff[tSize - 1]; DEBUG_ASSERT(mLoad)
return *mBuff;
} }
const tType& last() const { tType& last() {
return mBuff[tSize - 1]; DEBUG_ASSERT(mLoad)
return mBuff[mLoad - 1];
}
const tType& last() const {
DEBUG_ASSERT(mLoad)
return mBuff[mLoad - 1];
} }
tType& operator[](ualni aIdx) { tType& operator[](ualni aIdx) {
DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize) DEBUG_ASSERT(aIdx >= 0 && aIdx < mLoad)
return mBuff[aIdx]; return mBuff[aIdx];
} }
const tType& operator[](ualni aIdx) const { const tType& operator[](ualni aIdx) const {
DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize) DEBUG_ASSERT(aIdx >= 0 && aIdx < mLoad)
return mBuff[aIdx]; return mBuff[aIdx];
} }
void append(Arg data) {
ASSERT(mLoad != tSize)
new (&mBuff[mLoad]) tType(data);
mLoad++;
}
void pop() {
DEBUG_ASSERT(mLoad)
mBuff[mLoad].~tType();
mLoad--;
}
ConstSizeBuffer& operator=(const tp::init_list<tType>& init) {
for (auto arg : init) {
append(arg);
}
return *this;
}
public:
class IteratorPointer {
protected:
tType* mIter;
public:
IteratorPointer() = default;
tType& operator->() { return *mIter; }
const tType& operator->() const { return *mIter; }
};
class IteratorReference {
protected:
tType* mIter;
public:
IteratorReference() = default;
tType* operator->() { return mIter; }
const tType* operator->() const { return mIter; }
};
class Iterator : public TypeSelect<TypeTraits<tType>::isPointer, IteratorPointer, IteratorReference>::Result {
public:
explicit Iterator(tType* iter) { this->mIter = iter; }
const Iterator& operator*() const { return *this; }
Iterator& operator++() {
this->mIter++;
return *this;
}
bool operator==(const Iterator& left) const { return left.mIter == this->mIter; }
bool operator!=(const Iterator& left) const { return left.mIter != this->mIter; }
};
[[nodiscard]] Iterator begin() const {
return Iterator(mBuff);
}
[[nodiscard]] Iterator end() const {
return Iterator(mBuff + mLoad);
}
}; };
template< template<
@ -150,6 +219,14 @@ namespace tp {
} }
public: public:
Buffer& operator=(const tp::init_list<tType>& init) {
// TODO : optimize
for (auto arg : init) {
append(arg);
}
return *this;
}
void append(Arg data) { void append(Arg data) {
if (mLoad == mSize) resizeBuffer(tResizePolicy(mSize)); if (mLoad == mSize) resizeBuffer(tResizePolicy(mSize));
new (&mBuff[mLoad]) tType(data); new (&mBuff[mLoad]) tType(data);
@ -183,6 +260,53 @@ namespace tp {
for (ualni i = 0; i < mLoad; i++) new (mBuff + i) tType(); for (ualni i = 0; i < mLoad; i++) new (mBuff + i) tType();
} }
public:
class IteratorPointer {
protected:
tType* mIter;
public:
IteratorPointer() = default;
tType& operator->() { return *mIter; }
const tType& operator->() const { return *mIter; }
};
class IteratorReference {
protected:
tType* mIter;
public:
IteratorReference() = default;
tType* operator->() { return mIter; }
const tType* operator->() const { return mIter; }
};
class Iterator : public TypeSelect<TypeTraits<tType>::isPointer, IteratorPointer, IteratorReference>::Result {
public:
explicit Iterator(tType* iter) { this->mIter = iter; }
const Iterator& operator*() const { return *this; }
tType& data() {
return *this->mIter;
}
Iterator& operator++() {
this->mIter++;
return *this;
}
bool operator==(const Iterator& left) const { return left.mIter == this->mIter; }
bool operator!=(const Iterator& left) const { return left.mIter != this->mIter; }
};
[[nodiscard]] Iterator begin() const {
return Iterator(mBuff);
}
[[nodiscard]] Iterator end() const {
return Iterator(mBuff + mLoad);
}
private: private:
void resizeBuffer(ualni newSize) { void resizeBuffer(ualni newSize) {
DEBUG_ASSERT(newSize >= mLoad) DEBUG_ASSERT(newSize >= mLoad)

31
Objects/CMakeLists.txt Normal file
View file

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.2)
set(CMAKE_CXX_STANDARD 23)
project(Objects)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_link_libraries(${PROJECT_NAME} PUBLIC Strings Math Tokenizer CommandLine Connection)
### -------------------------- Applications -------------------------- ###
add_executable(osc ./applications/Compiler.cpp)
add_executable(osi ./applications/Interpreter.cpp)
target_link_libraries(osc ${PROJECT_NAME})
target_link_libraries(osi ${PROJECT_NAME})
### -------------------------- Tests -------------------------- ###
enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)

20
Objects/README.md Normal file
View file

@ -0,0 +1,20 @@
Objects
Objects are simple structures with run-time type information attached. <br>
## Features
- Encapsulates most of the basic [types](https://github.com/IlyaShurupov/types.git) into primitives.
- Has its own scripting language to manipulate those objects at run-time.
- Can save and load any object at any point in execution.
## TODO
- Dubug information support
- Run-time error handling
- Dead code elimination & optimization
## Building
1. [Types](https://github.com/IlyaShurupov/types.git) repository must be in the same directory.
2. Export the parent path to the system variables.
```
setx SRC_DIR "parent path"
```

View file

@ -0,0 +1,49 @@
#include "Compiler/Compiler.h"
#include "primitives/primitives.h"
#include "MethodObject/MethodObject.h"
#include "log.h"
using namespace osc;
using namespace tp;
using namespace obj;
int main(int argc, char* argv[]) {
tp::alloc_init();
string::Initialize();
Logger::init();
objects_init();
primitives_define_types();
MethodObject::Initialize();
{
Compiler compiler;
tp::string script;
RelAssert(argc == 2 && "Invalid Arguments");
script.loadFile(argv[1]);
compiler.compile(script);
GLog->write("oscc : compilation finished", 1);
}
try {
MethodObject::UnInitialize();
objects_finalize();
primitives_uninitialize();
Logger::deinit();
string::UnInitialize();
tp::alloc_uninit();
}
catch (...) {
tp::terminate();
}
}

View file

@ -0,0 +1,58 @@
#include "MethodObject/methodobject.h"
#include "primitives/primitives.h"
#include "Interpreter/Interpreter.h"
#include "log.h"
using namespace osc;
using namespace tp;
using namespace obj;
int main(int argc, char* argv[]) {
tp::alloc_init();
string::Initialize();
Logger::init();
objects_init();
primitives_define_types();
MethodObject::Initialize();
{
time_ms load_start = get_time();
RelAssert(argc == 2 && "Invalid Arguments");
auto obj = NDO->load(argv[1]);
RelAssert(obj && "Failed to Load the File");
RelAssert(obj->type == &MethodObject::TypeData && "Innvalid file content");
Interpreter interp;
NDO_CASTV(MethodObject, obj, method);
RelAssert(method->mScript && "Innvalid file content");
time_ms load_end = get_time();
GLog->write("\noscvm - execution started\n");
time_ms exec_start = get_time();
interp.exec(&method->mScript->mBytecode);
time_ms exec_end = get_time();
auto exec_time = (exec_end - exec_start);
auto load_time = (load_end - load_start);
GLog->write(sfmt("\noscvm - execution finished (Load : %f Exec : %f)", load_time, exec_time));
}
try {
MethodObject::UnInitialize();
objects_finalize();
primitives_uninitialize();
Logger::deinit();
string::UnInitialize();
tp::alloc_uninit();
} catch (...) {
tp::terminate();
}
}

View file

@ -0,0 +1,148 @@
#include "NewPlacement.hpp"
#include "compiler/constants.h"
#include "primitives/primitives.h"
#include "primitives/methodobject.h"
using namespace obj;
using namespace tp;
using namespace BCgen;
ConstObject::ConstObject() {}
ConstObject::ConstObject(obj::Object* mObj) : mObj(mObj) {}
ConstObjectsPool::~ConstObjectsPool() {
if (mDelete) {
for (auto obj : mStrings) {
obj::NDO->destroy(obj->val->mObj);
}
for (auto obj : mIntegers) {
obj::NDO->destroy(obj->val->mObj);
}
for (auto obj : mFloats) {
obj::NDO->destroy(obj->val->mObj);
}
for (auto obj : mMethods) {
obj::NDO->destroy(obj->val->mObj);
}
if (mBoolFalse.mObj) {
obj::NDO->destroy(mBoolFalse.mObj);
}
if (mBoolTrue.mObj) {
obj::NDO->destroy(mBoolTrue.mObj);
}
}
for (auto obj : mStrings) {
delete obj->val;
}
for (auto obj : mIntegers) {
delete obj->val;
}
for (auto obj : mFloats) {
delete obj->val;
}
}
ConstObject* ConstObjectsPool::registerObject(obj::Object* obj) {
ConstObject* out = new ConstObject(obj);
mTotalObjects++;
return out;
}
ConstObject* ConstObjectsPool::get(tp::alni val) {
auto idx = mIntegers.presents(val);
ConstObject* const_obj = NULL;
if (idx) {
const_obj = mIntegers.getSlotVal(idx);
}
else {
const_obj = registerObject(IntObject::create(val));
mIntegers.put(val, const_obj);
}
return const_obj;
}
ConstObject* ConstObjectsPool::get(tp::String val) {
auto idx = mStrings.presents(val);
ConstObject* const_obj = NULL;
if (idx) {
const_obj = mStrings.getSlotVal(idx);
}
else {
const_obj = registerObject(StringObject::create(val));
mStrings.put(val, const_obj);
}
return const_obj;
}
ConstObject* ConstObjectsPool::get(tp::alnf val) {
auto idx = mFloats.presents(val);
ConstObject* const_obj = NULL;
if (idx) {
const_obj = mFloats.getSlotVal(idx);
}
else {
const_obj = registerObject(FloatObject::create(val));
mFloats.put(val, const_obj);
}
return const_obj;
}
ConstObject* ConstObjectsPool::get(bool val) {
if (val) {
if (!mBoolTrue.mObj) {
mBoolTrue.mObj = BoolObject::create(val);
mTotalObjects++;
}
return &mBoolTrue;
}
else {
if (!mBoolFalse.mObj) {
mBoolFalse.mObj = BoolObject::create(val);
mTotalObjects++;
}
return &mBoolFalse;
}
}
ConstObject* ConstObjectsPool::addMethod(tp::String method_id, obj::Object* method) {
ASSERT(NDO_CAST(MethodObject, method) && "Object is not a method object");
ASSERT(!mMethods.presents(method_id) && "Method Redefinition");
auto out = registerObject(method);
mMethods.put(method_id, out);
return out;
}
void ConstObjectsPool::save(tp::Buffer<ConstData>& out) {
out.reserve(mTotalObjects);
tp::alni data_idx = 0;
for (auto obj : mMethods) {
out[data_idx] = obj->val->mObj;
obj->val->mConstIdx = data_idx;
data_idx++;
}
for (auto obj : mStrings) {
out[data_idx] = obj->val->mObj;
obj->val->mConstIdx = data_idx;
data_idx++;
}
for (auto obj : mIntegers) {
out[data_idx] = obj->val->mObj;
obj->val->mConstIdx = data_idx;
data_idx++;
}
for (auto obj : mFloats) {
out[data_idx] = obj->val->mObj;
obj->val->mConstIdx = data_idx;
data_idx++;
}
if (mBoolFalse.mObj) {
out[data_idx] = mBoolFalse.mObj;
mBoolFalse.mConstIdx = data_idx;
data_idx++;
}
if (mBoolTrue.mObj) {
out[data_idx] = mBoolTrue.mObj;
mBoolTrue.mConstIdx = data_idx;
}
mDelete = false;
}

View file

@ -0,0 +1,70 @@
#include "NewPlacement.hpp"
#include "compiler/expression.h"
using namespace obj;
using namespace BCgen;
Expression::Expression() {}
Expression::Expression(Type type) : mType(type) {}
ExpressionChild* Expression::ExprChild(tp::String id) {
return new ExpressionChild(this, id);
}
ExpressionCall* Expression::ExprCall(tp::init_list<Expression*> args) {
return new ExpressionCall(this, args);
}
ExpressionLocal* obj::BCgen::ExprLocal(tp::String id) {
return new ExpressionLocal(id);
}
ExpressionSelf* obj::BCgen::ExprSelf() {
return new ExpressionSelf();
}
ExpressionNew* obj::BCgen::ExprNew(tp::String type) {
return new ExpressionNew(type);
}
ExpressionAriphm* obj::BCgen::ExprAriphm(Expression* left, Expression* right, OpCode type) {
return new ExpressionAriphm(left, right, type);
}
ExpressionFunc* obj::BCgen::ExprFunc(tp::String id) {
return new ExpressionFunc(id);
}
ExpressionBoolean* obj::BCgen::ExprBool(Expression* left, Expression* right, obj::OpCode type) {
return new ExpressionBoolean(left, right, ExpressionBoolean::BoolType(type));
}
ExpressionBoolean* obj::BCgen::ExprBoolNot(Expression* invert) {
return new ExpressionBoolean(invert);
}
ExpressionBoolean::ExpressionBoolean(Expression* left, Expression* right, BoolType type)
: Expression(Type::BOOLEAN), mLeft(left), mRight(right), mBoolType(type) {
}
ExpressionBoolean::ExpressionBoolean(Expression* invert)
: Expression(Type::BOOLEAN), mLeft(invert), mBoolType(BoolType::NOT){
}
ExpressionCall::ExpressionCall(Expression * mParent, tp::init_list<Expression*> args) : Expression(Type::CALL), mParent(mParent) {
mArgs = args;
}
ExpressionNew::ExpressionNew(tp::String type) : Expression(Type::NEW), mNewType(type) {}
ExpressionLocal::ExpressionLocal(tp::String id) : Expression(Type::LOCAL), mLocalId(id) {}
ExpressionSelf::ExpressionSelf() : Expression(Type::SELF) {}
ExpressionChild::ExpressionChild(Expression* mParent, tp::String id) : Expression(Type::CHILD), mParent(mParent), mLocalId(id) {}
ExpressionAriphm::ExpressionAriphm(Expression* left, Expression* right, OpCode type) : Expression(Type::ARIPHM), mLeft(left), mRight(right), mOpType(type) {}
ExpressionFunc::ExpressionFunc(tp::String id) : Expression(Type::FUNC), mFuncId(id) {}
ExpressionConst::ExpressionConst(tp::String val) : Expression(Type::CONST), mConstType(STR), str(val) {}
ExpressionConst::ExpressionConst(const char* val) : Expression(Type::CONST), mConstType(STR), str(val) {}
ExpressionConst::ExpressionConst(tp::int4 val) : Expression(Type::CONST), mConstType(INT), integer(val) {}
ExpressionConst::ExpressionConst(tp::flt4 val) : Expression(Type::CONST), mConstType(FLT), floating(val) {}
ExpressionConst::ExpressionConst(tp::alni val) : Expression(Type::CONST), mConstType(INT), integer(val) {}
ExpressionConst::ExpressionConst(tp::alnf val) : Expression(Type::CONST), mConstType(FLT), floating(val) {}
ExpressionConst::ExpressionConst(bool val) : Expression(Type::CONST), mConstType(BOOL), boolean(val) {}

View file

@ -0,0 +1,556 @@
#include "NewPlacement.hpp"
#include "compiler/function.h"
#include "primitives/primitives.h"
#include "primitives/methodobject.h"
#include "Logging.hpp"
#include "parser/parser.h"
using namespace obj;
using namespace tp;
using namespace obj;
using namespace BCgen;
void obj::BCgen::Genereate(ByteCode& out, StatementScope* body) {
auto root = FunctionDefinition();
root.inst(Instruction(OpCode::SCOPE_IN));
for (auto child_stm : body->mStatements) {
root.EvalStatement(child_stm.data());
}
root.inst(Instruction(OpCode::SCOPE_OUT));
root.generateByteCode(out);
}
ConstObject* FunctionDefinition::defineLocal(tp::String id) {
auto idx = mLocals.presents(id);
//RelAssert(!idx && "Local Redefinition");
auto const_str_id = mConstants.get(id);
mLocals.put(id, const_str_id);
return const_str_id;
}
FunctionDefinition::FunctionDefinition(tp::String function_id, tp::Buffer<tp::String> args, FunctionDefinition* prnt) {
mFunctionId = function_id;
inst(Instruction(OpCode::SAVE_ARGS, args.size(), 1));
for (auto id : args) {
ASSERT(!mLocals.presents(id.data()) && "Argument Redefinition");
auto const_data = mConstants.get(id.data());
mArgsOrder.pushBack(const_data);
mLocals.put(id.data(), const_data);
inst(Instruction(const_data));
}
}
void FunctionDefinition::EvalStatement(Statement* stm) {
switch (stm->mType) {
case Statement::Type::IGNORE: {
auto stm_ignore = (StatementIgnore*)stm;
EvalExpr(stm_ignore->mExpr);
inst(OpCode::IGNORE);
break;
}
case Statement::Type::WHILE: {
auto stm_while = (StatementWhile*)stm;
auto check_mark = inst(Instruction());
EvalExpr(stm_while->mCondition);
auto jump_if_inst = inst(Instruction(NULL, Instruction::InstType::JUMP_IF_NOT));
if (stm_while->mScope) {
EvalStatement(stm_while->mScope);
}
auto jump_inst = inst(Instruction(NULL, Instruction::InstType::JUMP));
auto end_mark = inst(Instruction());
jump_if_inst->data.mInstTarget = end_mark;
jump_inst->data.mInstTarget = check_mark;
break;
}
case Statement::Type::IF: {
auto stm_if = (StatementIf*)stm;
EvalExpr(stm_if->mCondition);
auto jump_if_inst = inst(Instruction(NULL, Instruction::InstType::JUMP_IF_NOT));
if (stm_if->mOnTrue) {
EvalStatement(stm_if->mOnTrue);
}
auto jump_inst = inst(Instruction(NULL, Instruction::InstType::JUMP));
auto else_mark = inst(Instruction());
if (stm_if->mOnFalse) {
EvalStatement(stm_if->mOnFalse);
}
auto end_mark = inst(Instruction());
jump_if_inst->data.mInstTarget = else_mark;
jump_inst->data.mInstTarget = end_mark;
break;
}
case Statement::Type::SCOPE: {
auto stm_scope = (StatementScope*)stm;
if (stm_scope->mPushToScopeStack) {
inst(Instruction(OpCode::SCOPE_IN));
}
for (auto child_stm : stm_scope->mStatements) {
EvalStatement(child_stm.data());
}
if (stm_scope->mPushToScopeStack) {
inst(Instruction(OpCode::SCOPE_OUT));
}
break;
}
case Statement::Type::DEF_FUNC: {
auto stm_func_def = (StatementFuncDef*) stm;
FunctionDefinition func(stm_func_def->mFunctionId, stm_func_def->mArgs, this);
// define method as local
auto idx = mLocals.presents(func.mFunctionId);
ASSERT(!idx && "Local Redefinition with function name");
mLocals.put(func.mFunctionId, mConstants.get(func.mFunctionId));
// create and register const func object
auto function_obj = NDO_CAST(MethodObject, NDO->create("method"));
auto method_const_obj = mConstants.addMethod(func.mFunctionId, function_obj);
for (auto child_stm : stm_func_def->mStatements) {
func.EvalStatement(child_stm.data());
}
func.generateByteCode(function_obj->mScript->mBytecode);
inst(Instruction(OpCode::LOAD_CONST, method_const_obj));
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(func.mFunctionId)));
inst(Instruction(OpCode::DEF_LOCAL));
break;
}
case Statement::Type::CLASS_DEF: {
// do the function definition
auto stm_class_def = (StatementClassDef*)stm;
FunctionDefinition func(stm_class_def->mClassId, {}, this);
// define method as local
auto idx = mLocals.presents(func.mFunctionId);
ASSERT(!idx && "Local Redefinition with function name");
mLocals.put(func.mFunctionId, mConstants.get(func.mFunctionId));
// create and register const func object
auto function_obj = NDO_CAST(MethodObject, NDO->create("method"));
auto method_const_obj = mConstants.addMethod(func.mFunctionId, function_obj);
// compile function
for (auto child_stm : stm_class_def->mScope->mStatements) {
// check for return statements
ASSERT(child_stm.data()->mType != Statement::Type::RET && "return statements are not allowed in class definition");
func.EvalStatement(child_stm.data());
}
// create one last instruction - constructing class from function execution state
func.inst(Instruction(OpCode::CLASS_CONSTRUCT));
func.generateByteCode(function_obj->mScript->mBytecode);
inst(Instruction(OpCode::LOAD_CONST, method_const_obj));
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(func.mFunctionId)));
inst(Instruction(OpCode::DEF_LOCAL));
break;
}
case Statement::Type::DEF_LOCAL: {
auto stm_local_def = (StatementLocalDef*)stm;
if (!stm_local_def->mIsConstExpr) {
auto const_id = defineLocal(stm_local_def->mLocalId);
EvalExpr(stm_local_def->mNewExpr);
inst(Instruction(OpCode::LOAD_CONST, const_id));
inst(Instruction(OpCode::DEF_LOCAL));
} else {
tp::String type;
switch (stm_local_def->mConstExpr->mConstType) {
case ExpressionConst::BOOL: {
type = "bool";
break;
}
case ExpressionConst::INT: {
type = "int";
break;
}
case ExpressionConst::FLT: {
type = "float";
break;
}
case ExpressionConst::STR: {
type = "str";
break;
}
default: {
ASSERT(0 && "Cantbe");
}
}
auto new_expr = new ExpressionNew(type);
EvalStatement(StmDefLocal(stm_local_def->mLocalId, new_expr));
EvalExpr(stm_local_def->mConstExpr);
inst(Instruction(OpCode::LOAD_LOCAL, mConstants.get(stm_local_def->mLocalId)));
inst(Instruction(OpCode::OBJ_COPY));
}
break;
}
case Statement::Type::COPY: {
auto stm_cp = (StatementCopy*)stm;
EvalExpr(stm_cp->mRight);
EvalExpr(stm_cp->mLeft);
inst(Instruction(OpCode::OBJ_COPY));
break;
}
case Statement::Type::PRINT: {
auto stm_prnt = (StatementPrint*)stm;
EvalExpr(stm_prnt->mTarget);
inst(Instruction(OpCode::PRINT));
break;
}
case Statement::Type::RET: {
auto stm_ret = (StatementReturn*)stm;
if (stm_ret->mRet) {
EvalExpr(stm_ret->mRet);
inst(Instruction(OpCode::RETURN_OBJ));
} else {
inst(Instruction(OpCode::RETURN));
}
break;
}
default:
ASSERT(0)
}
delete stm;
}
void FunctionDefinition::EvalExpr(Expression* expr) {
switch (expr->mType) {
case Expression::Type::BOOLEAN: {
auto boolean = (ExpressionBoolean*)expr;
if (boolean->mBoolType == ExpressionBoolean::BoolType::NOT) {
EvalExpr(boolean->mLeft);
inst(OpCode::NOT);
} else {
EvalExpr(boolean->mRight);
EvalExpr(boolean->mLeft);
inst(OpCode(boolean->mBoolType));
}
break;
}
case Expression::Type::FUNC: {
auto func = (ExpressionFunc*)expr;
//RelAssert(mConstants.mMethods.presents(func->mFuncId) && "No such function");
inst(Instruction(OpCode::LOAD_LOCAL, mConstants.get(func->mFuncId)));
break;
}
case Expression::Type::ARIPHM: {
auto ariphm = (ExpressionAriphm*)expr;
EvalExpr(ariphm->mRight);
EvalExpr(ariphm->mLeft);
inst(Instruction(ariphm->mOpType));
break;
}
case Expression::Type::NEW: {
auto create_new = (ExpressionNew*)expr;
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(create_new->mNewType)));
inst(Instruction(OpCode::OBJ_CREATE));
break;
}
case Expression::Type::LOCAL: {
auto local = (ExpressionLocal*)expr;
// RelAssert(mLocals.presents(local->mLocalId) && "undefined local");
inst(Instruction(OpCode::LOAD_LOCAL, mConstants.get(local->mLocalId)));
break;
}
case Expression::Type::CONST: {
auto constobj = (ExpressionConst*)expr;
switch (constobj->mConstType) {
case ExpressionConst::STR: {
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(constobj->str)));
break;
}
case ExpressionConst::INT: {
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(constobj->integer)));
break;
}
case ExpressionConst::FLT: {
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(constobj->floating)));
break;
}
case ExpressionConst::BOOL: {
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(constobj->boolean)));
break;
}
};
break;
}
case Expression::Type::CHILD: {
auto child = (ExpressionChild*)expr;
EvalExpr(child->mParent);
inst(Instruction(OpCode::LOAD_CONST, mConstants.get(child->mLocalId)));
inst(Instruction(OpCode::CHILD, child->mMethod, 1));
break;
}
case Expression::Type::SELF: {
inst(Instruction(OpCode::SELF));
break;
}
case Expression::Type::CALL: {
auto call = (ExpressionCall*)expr;
inst(Instruction(OpCode::PUSH_ARGS, call->mArgs.size(), 1));
for (auto arg : call->mArgs) {
EvalExpr(arg.data());
}
EvalExpr(call->mParent);
inst(Instruction(OpCode::CALL));
break;
}
default:
ASSERT(0)
}
delete expr;
}
tp::alni instSize(const Instruction& inst) {
switch (inst.mInstType) {
case Instruction::InstType::JUMP:
case Instruction::InstType::JUMP_IF_NOT:
case Instruction::InstType::JUMP_IF: {
// 2 bytes for offset 1 byte for instrtuction
return 3;
}
case Instruction::InstType::PURE_CONST: {
return 2;
}
case Instruction::InstType::EXEC: {
tp::alni out = 1;
switch (inst.mArgType) {
case Instruction::ArgType::PARAM: {
out += inst.mParamBytes;
return out;
}
case Instruction::ArgType::CONST: {
out += 2;
if (inst.mConstData2) {
out += 2;
}
return out;
}
case Instruction::ArgType::NO_ARG: {
return out;
}
default: {
ASSERT(0);
}
}
}
case Instruction::InstType::NONE: {
return 0;
}
default: {
ASSERT(0);
}
}
ASSERT(0);
return 0;
}
void writeConst(ByteCode& out, tp::alni& idx, tp::uint2 data) {
for (auto byte : tp::Range(sizeof(tp::uint2))) {
out.mInstructions[idx] = OpCode((tp::int1)(data >> byte * 8));
idx++;
}
}
void writeParam(ByteCode& out, tp::alni& idx, tp::int1* data, tp::alni size) {
for (auto byte : tp::Range(size)) {
out.mInstructions[idx] = OpCode(data[byte]);
idx++;
}
}
tp::alni calcOffset(tp::List<Instruction>::Node* jump_inst, tp::List<Instruction>::Node* to) {
tp::alni offset = 0;
bool reversed = jump_inst->data.mInstIdx > to->data.mInstIdx;
auto iter_node = reversed ? jump_inst : jump_inst->next;
while (iter_node != to) {
offset += instSize(iter_node->data);
iter_node = reversed ? iter_node->prev : iter_node->next;
}
if (reversed) {
offset += instSize(iter_node->data);
}
return reversed ? -offset : offset;
}
void FunctionDefinition::generateByteCode(ByteCode& out) {
out.~ByteCode();
new (&out) ByteCode();
mConstants.save(out.mConstants);
tp::alni inst_len = 0;
for (auto inst_iter : mInstructions) {
inst_len += instSize(inst_iter.data());
}
out.mInstructions.reserve(inst_len);
tp::alni idx = 0;
for (auto inst_iter : mInstructions) {
auto inst = inst_iter.data();
switch (inst.mInstType) {
case Instruction::InstType::JUMP_IF:
case Instruction::InstType::JUMP_IF_NOT:
case Instruction::InstType::JUMP: {
tp::alni offset = calcOffset(inst_iter.node(), inst.mInstTarget);
if (offset == 0) {
out.mInstructions[idx] = OpCode::NONE;
idx += 3;
break;
}
if (inst.mInstType == Instruction::InstType::JUMP_IF) {
if (offset > 0) {
out.mInstructions[idx] = OpCode::JUMP_IF;
}
else {
out.mInstructions[idx] = OpCode::JUMP_IF_R;
}
}
else if (inst.mInstType == Instruction::InstType::JUMP_IF_NOT) {
if (offset > 0) {
out.mInstructions[idx] = OpCode::JUMP_IF_NOT;
}
else {
out.mInstructions[idx] = OpCode::JUMP_IF_NOT_R;
}
}
else {
if (offset > 0) {
out.mInstructions[idx] = OpCode::JUMP;
}
else {
out.mInstructions[idx] = OpCode::JUMP_R;
}
}
idx++;
tp::alni offset_mod = abs(offset);
tp::uint2 offset_param = (tp::uint2)offset_mod;
writeParam(out, idx, (tp::int1*)&offset_param, 2);
break;
}
case Instruction::InstType::PURE_CONST: {
writeConst(out, idx, (tp::uint2)inst.mConstData->mConstIdx);
break;
}
case Instruction::InstType::EXEC: {
out.mInstructions[idx] = inst.mOp;
idx++;
switch (inst.mArgType) {
case Instruction::ArgType::PARAM: {
writeParam(out, idx, (tp::int1*) &inst.mParam, inst.mParamBytes);
break;
}
case Instruction::ArgType::CONST: {
writeConst(out, idx, (tp::uint2)inst.mConstData->mConstIdx);
if (inst.mConstData2) {
writeConst(out, idx, (tp::uint2)inst.mConstData2->mConstIdx);
}
break;
}
case Instruction::ArgType::NO_ARG: {
break;
}
default:{
ASSERT(0);
}
}
break;
}
default: {
ASSERT(0);
}
case Instruction::InstType::NONE: {}
}
}
}
tp::List<Instruction>::Node* FunctionDefinition::inst(Instruction inst) {
mInstructions.pushBack(inst);
auto out = &mInstructions.last()->data;
out->mInstIdx = mInstructions.length() - 1;
return mInstructions.last();
}
static Parser* sParger = NULL;
void obj::BCgen::init() {
ASSERT(!sParger);
if (!sParger) {
sParger = new Parser();
}
}
void obj::BCgen::deinit() {
ASSERT(sParger);
if (sParger) {
delete sParger;
}
}
bool obj::BCgen::Compile(obj::MethodObject* method) {
ASSERT(method);
ASSERT(sParger);
if (!sParger) return false;
auto script = method->mScript->mReadable->val;
auto res = sParger->parse(script);
if (res.err) {
auto loc = res.err->get_err_location(script.read());
// TODO : print parse error
// tp::gLogeer->write(tp::sfmt("Parser Error (%i,%i): \n", loc.head, loc.tail), true, tp::Logger::LogEntry::ERR);
// tp::GLog->write(res.err->mDescr, true, tp::Logger::LogEntry::ERR);
return false;
}
BCgen::Genereate(method->mScript->mBytecode, res.scope);
delete res.scope;
return true;
}

View file

@ -0,0 +1,29 @@
#include "compiler/instruction.h"
using namespace obj;
using namespace tp;
using namespace BCgen;
Instruction::Instruction(OpCode op) : mOp(op), mArgType(ArgType::NO_ARG), mInstType(InstType::EXEC) {}
Instruction::Instruction() : mInstType(InstType::NONE) {}
Instruction::Instruction(ConstObject* constData)
: mConstData(constData), mInstType(InstType::PURE_CONST) {}
Instruction::Instruction(OpCode op, ConstObject* constData)
: mOp(op), mConstData(constData), mArgType(ArgType::CONST), mInstType(InstType::EXEC) {
}
Instruction::Instruction(OpCode op, ConstObject* constData, ConstObject* constData2)
: mOp(op), mConstData(constData), mConstData2(constData2), mArgType(ArgType::CONST), mInstType(InstType::EXEC) {
}
Instruction::Instruction(OpCode op, tp::alni param, tp::alni nBytes)
: mOp(op), mParam(param), mArgType(ArgType::PARAM), mParamBytes(nBytes), mInstType(InstType::EXEC) {
}
Instruction::Instruction(tp::List<Instruction>::Node* inst, InstType jump_type): mInstTarget(inst) {
mInstType = jump_type;
}

View file

@ -0,0 +1,116 @@
#include "NewPlacement.hpp"
#include "compiler/statement.h"
using namespace obj;
using namespace BCgen;
StatementFuncDef::StatementFuncDef(tp::String function_id, tp::init_list<tp::String> args, tp::init_list<Statement*> statements) {
mType = Type::DEF_FUNC;
mArgs = args;
mStatements = statements;
mFunctionId = function_id;
}
StatementLocalDef::StatementLocalDef(tp::String id, Expression* value) : mLocalId(id), mNewExpr(value) {
mType = Type::DEF_LOCAL;
}
StatementLocalDef::StatementLocalDef(tp::String id, ExpressionConst* value) : mLocalId(id), mConstExpr(value), mIsConstExpr(true) {
mType = Type::DEF_LOCAL;
}
StatementCopy::StatementCopy(Expression* left, Expression* right) : mLeft(left), mRight(right) {
mType = Type::COPY;
}
StatementReturn::StatementReturn() {
mType = Type::RET;
}
StatementReturn::StatementReturn(Expression* ret) : mRet(ret) {
mType = Type::RET;
}
StatementPrint::StatementPrint(Expression* target) : mTarget(target) {
mType = Type::PRINT;
}
StatementScope::StatementScope(tp::init_list<Statement*> statements, bool aPushToScopeStack) {
mType = Type::SCOPE;
mStatements = statements;
mPushToScopeStack = aPushToScopeStack;
}
StatementIf::StatementIf(Expression* condition, StatementScope* on_true, StatementScope* on_false) {
mType = Type::IF;
mOnFalse = on_false;
mOnTrue = on_true;
mCondition = condition;
}
StatementWhile::StatementWhile(Expression* condition, StatementScope* scope) {
mType = Type::WHILE;
mScope = scope;
mCondition = condition;
}
StatementIgnore::StatementIgnore(Expression* expr) {
mType = Type::IGNORE;
mExpr = expr;
}
StatementClassDef::StatementClassDef(tp::String class_id, StatementScope* scope) {
mClassId = class_id;
mScope = scope;
mType = Type::CLASS_DEF;
}
// helpers
StatementFuncDef* obj::BCgen::StmDefFunc(tp::String id, tp::init_list<tp::String> args, tp::init_list<Statement*> stms) {
return new StatementFuncDef(id, args, stms);
}
StatementLocalDef* obj::BCgen::StmDefLocal(tp::String id, Expression* value) {
if (value->mType == Expression::Type::CONST) {
return new StatementLocalDef(id, (ExpressionConst*)value);
}
return new StatementLocalDef(id, value);
}
StatementCopy* obj::BCgen::StmCopy(Expression* left, Expression* right) {
return new StatementCopy(left, right);
}
StatementPrint* obj::BCgen::StmPrint(Expression* target) {
return new StatementPrint(target);
}
StatementReturn* obj::BCgen::StmReturn() {
return new StatementReturn();
}
StatementReturn* obj::BCgen::StmReturn(Expression* obj) {
return new StatementReturn(obj);
}
StatementIf* obj::BCgen::StmIf(Expression* condition, StatementScope* on_true, StatementScope* on_false) {
return new StatementIf(condition, on_true, on_false);
}
StatementScope* obj::BCgen::StmScope(tp::init_list<Statement*> statements, bool aPushToScopeStack = false) {
return new StatementScope(statements, aPushToScopeStack);
}
StatementWhile* obj::BCgen::StmWhile(Expression* condition, StatementScope* scope) {
return new StatementWhile(condition, scope);
}
StatementIgnore* obj::BCgen::StmIgnore(Expression* expr) {
return new StatementIgnore(expr);
}
StatementClassDef* obj::BCgen::StmClassDef(tp::String id, StatementScope* scope) {
return new StatementClassDef(id, scope);
}

View file

@ -0,0 +1,250 @@
#include "NewPlacement.hpp"
#include "core/object.h"
#include "primitives/nullobject.h"
#include "primitives/classobject.h"
#include "primitives/methodobject.h"
#include "interpreter/interpreter.h"
#include "compiler/function.h"
namespace obj {
Object* ObjectMemAllocate(const ObjectType* type);
void ObjectMemDeallocate(Object* in);
objects_api* NDO = NULL;
void hierarchy_copy(Object* self, const Object* in, const ObjectType* type);
void hierarchy_construct(Object* self, const ObjectType* type);
objects_api::objects_api() {
tp::memSetVal(sl_callbacks, SAVE_LOAD_MAX_CALLBACK_SLOTS * sizeof(save_load_callbacks*), 0);
interp = new Interpreter();
}
objects_api::~objects_api() {
delete interp;
}
void objects_api::define(ObjectType* type) {
MODULE_SANITY_CHECK(gModuleObjects);
DEBUG_ASSERT(NDO && "using uninitialize objects api");
DEBUG_ASSERT(!types.presents(type->name) && "Type Redefinition");
types.put(type->name, type);
type->type_methods.init();
}
Object* objects_api::create(const tp::String& name) {
MODULE_SANITY_CHECK(gModuleObjects);
const ObjectType* type = types.get(name);
Object* obj_instance = ObjectMemAllocate(type);
if (!obj_instance) {
return NULL;
}
hierarchy_construct(obj_instance, obj_instance->type);
setrefc(obj_instance, 0);
NDO_CASTV(ClassObject, obj_instance, classobj);
if (classobj) {
auto idx = classobj->members->presents("__init__");
DEBUG_ASSERT(idx);
if (idx) {
auto constructor_obj = classobj->members->getSlotVal(idx);
NDO_CASTV(MethodObject, constructor_obj, constructor_method);
if (constructor_method) {
interp->execAll(constructor_method, classobj);
}
}
}
return obj_instance;
}
Object* objects_api::copy(Object* self, const Object* in) {
if (self->type != in->type) {
return NULL;
}
hierarchy_copy(self, in, self->type);
return self;
}
bool objects_api::compare(Object* first, Object* second) {
if (first->type == second->type) {
if (first->type->comparison) {
return first->type->comparison(first, second);
}
// raw data comparison
return tp::memCompare(first, second, first->type->size) == 0;
}
return false;
}
Object* objects_api::instatiate(Object* in) {
obj::Object* obj = NDO->create(in->type->name);
NDO->copy(obj, in);
return obj;
}
void objects_api::set(Object* self, tp::alni val) {
if (self->type->convesions && self->type->convesions->from_int) {
self->type->convesions->from_int(self, val);
return;
}
}
void objects_api::set(Object* self, tp::alnf val) {
if (self->type->convesions && self->type->convesions->from_float) {
self->type->convesions->from_float(self, val);
return;
}
}
void objects_api::set(Object* self, tp::String val) {
if (self->type->convesions && self->type->convesions->from_string) {
self->type->convesions->from_string(self, val);
return;
}
}
tp::alni objects_api::toInt(Object* self) {
DEBUG_ASSERT(self->type->convesions && self->type->convesions->to_int);
return self->type->convesions->to_int(self);
}
tp::alnf objects_api::toFloat(Object* self) {
DEBUG_ASSERT(self->type->convesions && self->type->convesions->to_float);
return self->type->convesions->to_float(self);
}
bool objects_api::toBool(Object* self) {
if (self->type->convesions && self->type->convesions->to_int) {
return (bool) self->type->convesions->to_int(self);
}
return true;
}
tp::String objects_api::toString(Object* self) {
DEBUG_ASSERT(self->type->convesions && self->type->convesions->to_string);
return self->type->convesions->to_string(self);
}
void objects_api::destroy(Object* in) {
if (!in) {
return;
}
#ifdef OBJECT_REF_COUNT
ObjectMemHead* mh = NDO_MEMH_FROM_NDO(in);
if (mh->refc > 1) {
mh->refc--;
return;
}
#endif
NDO_CASTV(ClassObject, in, classobj);
if (classobj) {
auto idx = classobj->members->presents("__del__");
DEBUG_ASSERT(idx);
if (idx) {
auto constructor_obj = classobj->members->getSlotVal(idx);
NDO_CASTV(MethodObject, constructor_obj, constructor_method);
if (constructor_method) {
interp->execAll(constructor_method, classobj);
}
}
}
for (const ObjectType* iter = in->type; iter; iter = iter->base) {
if (iter->destructor) {
iter->destructor(in);
}
}
ObjectMemDeallocate(in);
}
#ifdef OBJECT_REF_COUNT
tp::halni objects_api::getrefc(Object* in) {
ObjectMemHead* mh = NDO_MEMH_FROM_NDO(in);
return (tp::halni)mh->refc;
}
void objects_api::refinc(Object* in) {
ObjectMemHead* mh = NDO_MEMH_FROM_NDO(in);
mh->refc++;
}
void objects_api::setrefc(Object* in, tp::halni refc) {
ObjectMemHead* mh = NDO_MEMH_FROM_NDO(in);
mh->refc = refc;
}
#endif
void hierarchy_copy(Object* self, const Object* in, const ObjectType* type) {
if (type->base) {
hierarchy_copy(self, in, type->base);
}
if (type->copy) {
type->copy(self, in);
}
}
void hierarchy_construct(Object* self, const ObjectType* type) {
if (type->base) {
hierarchy_construct(self, type->base);
}
if (type->constructor) {
type->constructor(self);
}
}
Object* ndo_cast(const Object* in, const ObjectType* to_type) {
const ObjectType* typeiter = in->type;
while (typeiter) {
if (typeiter == to_type) {
return (Object*) in;
}
typeiter = typeiter->base;
}
return NULL;
}
objects_api* objects_init() {
if (!NDO) {
NDO = new objects_api();
}
obj::BCgen::init();
return NDO;
}
void objects_finalize() {
if (NDO) {
delete NDO;
}
obj::BCgen::deinit();
}
};

View file

@ -0,0 +1,411 @@
#include "core/object.h"
#include "HeapAllocatorGlobal.hpp"
#include <malloc.h>
namespace obj {
ObjectMemHead* bottom = nullptr;
struct ObjectsFileHeader {
char name[10] = {0};
char version[10] = {0};
ObjectsFileHeader(bool default_val = true) {
if (default_val) {
tp::memCopy(&name, "objects", tp::String::Logic::calcLength("objects") + 1);
tp::memCopy(&version, "0", tp::String::Logic::calcLength("0") + 1);
}
}
};
Object* ObjectMemAllocate(const ObjectType* type) {
ObjectMemHead* memh = (ObjectMemHead*) tp::HeapAllocGlobal::allocate(type->size + sizeof(ObjectMemHead));
if (!memh) {
return NULL;
}
memh->down = NULL;
memh->flags = NULL;
#ifdef OBJECT_REF_COUNT
memh->refc = (tp::alni) 1;
#endif
if (bottom) {
bottom->down = memh;
}
memh->up = bottom;
bottom = memh;
NDO_FROM_MEMH(memh)->type = type;
return NDO_FROM_MEMH(memh);
}
void ObjectMemDeallocate(Object* in) {
ObjectMemHead* memh = ((ObjectMemHead*) in) - 1;
if (memh->up) {
memh->up->down = memh->down;
}
if (memh->down) {
memh->down->up = memh->up;
} else {
bottom = memh->up;
}
tp::HeapAllocGlobal::deallocate(memh);
}
struct ObjectFileHead {
Object* load_head_adress = 0;
tp::halni refc = 0;
};
tp::int1* loaded_file = nullptr;
void objects_api::clear_object_flags() {
// clear all object flags
for (ObjectMemHead* iter = bottom; iter; iter = iter->up) {
iter->flags = -1;
}
}
tp::alni& getObjectFlags(Object* in) {
return NDO_MEMH_FROM_NDO(in)->flags;
}
tp::alni objsize_ram_util(Object* self, const ObjectType* type) {
tp::alni out = 0;
if (type->allocated_size) {
out += type->allocated_size(self);
} else {
out += type->size - sizeof(ObjectType*);
}
if (type->base) {
out += objsize_ram_util(self, type->base);
} else {
out += sizeof(ObjectType*);
}
return out;
}
tp::alni objects_api::objsize_ram(Object* self) {
return objsize_ram_util(self, self->type);
}
tp::alni objects_api::objsize_ram_recursive_util(Object* self, const ObjectType* type, bool different_object) {
tp::alni out = 0;
if (different_object) {
if (getObjectFlags(self) == 1) {
return 0;
}
getObjectFlags(self) = 1;
}
if (type->allocated_size_recursive) {
out += type->allocated_size_recursive(self);
} else {
if (type->allocated_size) {
out += type->allocated_size(self);
} else {
out += type->size - sizeof(ObjectType*);
}
}
if (type->base) {
out += objsize_ram_recursive_util(self, type->base, false);
} else {
out += sizeof(ObjectType*);
}
return out;
}
tp::alni objects_api::objsize_ram_recursive(Object* self) {
clear_object_flags();
return objsize_ram_recursive_util(self, self->type);
}
tp::alni objsize_file_util(Object* self, const ObjectType* type) {
tp::alni out = 0;
if (type->save_size) {
out += type->save_size(self);
}
if (type->base) {
out += objsize_file_util(self, type->base);
}
return out;
}
tp::alni objects_api::objsize_file(Object* self) {
return objsize_file_util(self, self->type);
}
tp::alni objsize_file_recursive_util(Object* self, const ObjectType* type) {
tp::alni out = 0;
getObjectFlags(self) = 1;
if (type->save_size) {
out += type->save_size(self);
}
if (type->childs_retrival) {
tp::Buffer<Object*> childs = type->childs_retrival(self);
for (auto child : childs) {
if (getObjectFlags(child.data()) != 1) {
out += objsize_file_recursive_util(child.data(), child.data()->type);
}
}
}
if (type->base) {
out += objsize_file_recursive_util(self, type->base);
}
return out;
}
tp::alni objects_api::objsize_file_recursive(Object* self) {
clear_object_flags();
return objsize_file_recursive_util(self, self->type);
}
void object_recursive_save(Archiver& ndf, Object* self, const ObjectType* type) {
if (type->base) {
object_recursive_save(ndf, self, type->base);
}
// automatically offsets for parent type to write
if (type->save) {
type->save(self, ndf);
}
}
tp::alni objects_api::save(Archiver& ndf, Object* in) {
// if already saved return file_adress
if (NDO_MEMH_FROM_NDO(in)->flags != -1) {
return NDO_MEMH_FROM_NDO(in)->flags;
}
// save write adress for parent save function call
tp::alni tmp_adress = ndf.adress;
// save requested object to first available adress
tp::alni save_adress = ndf.avl_adress;
// save file_adress in memhead
NDO_MEMH_FROM_NDO(in)->flags = save_adress;
// update write adress
ndf.adress = save_adress;
// save file object header
ObjectFileHead ofh = { 0, getrefc(in) };
ndf.write(&ofh);
tp::String(in->type->name).save(&ndf);
// allocate for object file header
ndf.avl_adress += sizeof(ObjectFileHead) + tp::String::Logic::calcLength(in->type->name) + 1;
// calc max size needed for saving all hierarchy of types
tp::alni file_alloc_size = objsize_file_util(in, in->type);
// offes first available adress
ndf.avl_adress += file_alloc_size;
object_recursive_save(ndf, in, in->type);
// restore adress for parent save function
ndf.adress = tmp_adress;
// return addres of saved object in file space
return save_adress;
}
void object_recursive_load(Archiver& ndf, Object* out, const ObjectType* type) {
if (type->base) {
object_recursive_load(ndf, out, type->base);
}
// automatically offsets for parent type to read
if (type->load) {
type->load(ndf, out);
}
}
Object* objects_api::load(Archiver& ndf, tp::alni file_adress) {
// check if already saved
if (((ObjectFileHead*) (loaded_file + file_adress))->load_head_adress) {
return ((ObjectFileHead*) (loaded_file + file_adress))->load_head_adress;
}
// save read adress
tp::alni parent_file_adress = ndf.adress;
// set read adress
ndf.adress = file_adress;
ObjectFileHead ofh;
ndf.read<ObjectFileHead>(&ofh);
tp::String type_name;
type_name.load(&ndf);
const ObjectType* object_type = NDO->types.get(type_name);
Object* out = ObjectMemAllocate(object_type);
if (!out) {
return NULL;
}
setrefc(out, ofh.refc);
// save heap adress in "loaded_file"
((ObjectFileHead*) (loaded_file + file_adress))->load_head_adress = out;
// loads recursivelly
object_recursive_load(ndf, out, object_type);
// restore read adress for parent call to continue
ndf.adress = parent_file_adress;
// return heap memory adress
return out;
}
bool objects_api::save(Object* in, tp::String path, bool compressed) {
Archiver ndf(path.read(), Archiver::SAVE);
if (!ndf.opened) {
return false;
}
clear_object_flags();
// save vesion info
ObjectsFileHeader header;
ndf.write(&header);
ndf.avl_adress = ndf.adress;
// pre allocate
for (tp::alni i = 0; i < SAVE_LOAD_MAX_CALLBACK_SLOTS; i++) {
if (sl_callbacks[i]) {
DEBUG_ASSERT(sl_callbacks[i]->size);
ndf.avl_adress += sl_callbacks[i]->size(sl_callbacks[i]->self, ndf);
}
}
// presave
for (tp::alni i = 0; i < SAVE_LOAD_MAX_CALLBACK_SLOTS; i++) {
if (sl_callbacks[i] && sl_callbacks[i]->pre_save) {
sl_callbacks[i]->pre_save(sl_callbacks[i]->self, ndf);
}
}
save(ndf, in);
// postsave
for (tp::alni i = 0; i < SAVE_LOAD_MAX_CALLBACK_SLOTS; i++) {
if (sl_callbacks[i] && sl_callbacks[i]->post_save) {
sl_callbacks[i]->post_save(sl_callbacks[i]->self, ndf);
}
}
ndf.disconnect();
// TODO : add compression
/*
if (compressed) {
auto temp = path + ".bz2";
tp::compressF2F(path.read(), temp.cstr());
File::remove(path.read());
File::rename(temp.cstr(), path.read());
}
*/
return true;
}
Object* objects_api::load(tp::String path) {
/*
auto temp_file_name = path + ".unz";
bool unz_res = tp::decompressF2F(path.cstr(), temp_file_name.cstr());
if (!unz_res) {
return NULL;
}
File ndf(temp_file_name.cstr(), tp::osfile_openflags::LOAD);
*/
Archiver ndf(path.read(), Archiver::LOAD);
if (!ndf.opened) {
return NULL;
}
// check for compability
ObjectsFileHeader current_header;
ObjectsFileHeader loaded_header(false);
ndf.read(&loaded_header);
if (!tp::memEqual(&current_header, &loaded_header, sizeof(ObjectsFileHeader))) {
return NULL;
}
ndf.adress = 0;
loaded_file = (tp::int1*) malloc(ndf.size());
ndf.read_bytes(loaded_file, ndf.size());
ndf.adress = sizeof(ObjectsFileHeader);
// preload
for (tp::alni i = 0; i < SAVE_LOAD_MAX_CALLBACK_SLOTS; i++) {
if (sl_callbacks[i] && sl_callbacks[i]->pre_load) {
sl_callbacks[i]->pre_load(sl_callbacks[i]->self, ndf);
}
}
Object* out = load(ndf, ndf.adress);
// post
for (tp::alni i = 0; i < SAVE_LOAD_MAX_CALLBACK_SLOTS; i++) {
if (sl_callbacks[i] && sl_callbacks[i]->post_save) {
sl_callbacks[i]->post_load(sl_callbacks[i]->self, ndf);
}
}
free(loaded_file);
/*
ndf.close();
if (unz_res == NULL) {
File::remove(temp_file_name.cstr());
}
*/
setrefc(out, 0);
return out;
}
void objects_api::add_sl_callbacks(save_load_callbacks* in) {
sl_callbacks[sl_callbacks_load_idx] = in;
sl_callbacks_load_idx++;
}
};

View file

@ -0,0 +1,265 @@
#include "NewPlacement.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "core/scriptsection.h"
using namespace obj;
ScriptSection* gScriptSection = NULL;
struct script_data_head {
tp::alni refc = 0;
tp::alni store_adress = 0;
};
void set_script_head_store_adress(Script* in, tp::alni address) {
((script_data_head*)in - 1)->store_adress = address;
}
tp::alni get_script_head_store_adress(Script* in) {
return ((script_data_head*)in - 1)->store_adress;
}
Script* ScriptSection::createScript() {
auto sdhead = (script_data_head*)tp::HeapAllocGlobal::allocate(sizeof(script_data_head) + sizeof(Script));
auto out = (Script*)(sdhead + 1);
if (!sdhead) {
return NULL;
}
sdhead->refc = 1;
sdhead->store_adress = -1;
mScripts.pushBack(out);
new (out) Script();
out->mReadable = obj::StringObject::create("");
obj::NDO->refinc(out->mReadable);
return out;
}
void ScriptSection::delete_script(Script* script) {
script->~Script();
obj::NDO->destroy(script->mReadable);
tp::HeapAllocGlobal::deallocate((((script_data_head*)script) - 1));
}
void ScriptSection::reference_script(Script* script) {
(((script_data_head*)script) - 1)->refc++;
}
void ScriptSection::abandonScript(Script* script) {
if ((((script_data_head*)script) - 1)->refc > 1) {
(((script_data_head*)script) - 1)->refc--;
}
else {
// ISSUE : on delete list structure is outdated
// FIXME : use pool alloc with ref count
// forwarding to global destruction
//delete_script(script);
}
}
void ScriptSection::changeScript(Script** current_script, Script** new_script) {
abandonScript(*current_script);
reference_script(*new_script);
*current_script = *new_script;
}
tp::alni ScriptSection::get_script_file_adress(Script* in) {
return get_script_head_store_adress(in);
}
tp::alni ScriptSection::save_script_table_to_file_size(ScriptSection* self, Archiver& file) {
tp::alni size = 0;
size += 5; // header
size += sizeof(tp::alni); // scripts length
for (auto iter : self->mScripts) {
set_script_head_store_adress(iter.data(), file.adress + size);
size += sizeof(tp::alni); // scripts string obj ref
size += sizeof(tp::alni); // constants length
for (auto const_obj : iter->mBytecode.mConstants) {
size += sizeof(tp::alni); // constant object addres
}
// instructions
size += iter->mBytecode.mInstructions.saveSize();
}
size += sizeof(tp::alni); // objects mem offset
size += 5; // header
return size;
}
void ScriptSection::save_script_table_to_file(ScriptSection* self, Archiver& file) {
// header
file.write_bytes("/scr/", 5);
// scripts length
tp::alni scripts_count = self->mScripts.length();
file.write<tp::alni>(&scripts_count);
for (auto iter : self->mScripts) {
// scripts string obj ref
auto obj_addres = obj::NDO->save(file, iter->mReadable);
file.write(&obj_addres);
// constants length
tp::alni consts_count = iter->mBytecode.mConstants.size();
file.write<tp::alni>(&consts_count);
for (auto const_obj : iter->mBytecode.mConstants) {
// constant object addres
auto obj_addres = obj::NDO->save(file, const_obj.data());
file.write(&obj_addres);
}
// mInstructions
iter->mBytecode.mInstructions.save(file);
}
// header
file.write_bytes("/scr/", 5);
tp::alni objects_mem_offset = file.avl_adress;
file.write<tp::alni>(&objects_mem_offset);
}
void load_constants(ScriptSection* self, Archiver& file, tp::alni start_addr) {
auto addres = file.adress;
file.adress = start_addr;
file.adress += 5; // header
tp::alni scripts_count;
file.read<tp::alni>(&scripts_count);
for (tp::alni i = 0; i < scripts_count; i++) {
auto script = self->get_scritp_from_file_adress(file.adress);
// script text
tp::alni str_addr;
file.read<tp::alni>(&str_addr);
script->mReadable = NDO_CAST(obj::StringObject, obj::NDO->load(file, str_addr));
file.adress += sizeof(tp::alni); // constants length
for (auto const_obj : script->mBytecode.mConstants) {
tp::alni consts_addr;
file.read<tp::alni>(&consts_addr);
const_obj.data() = obj::NDO->load(file, consts_addr);
}
// instructions
file.adress += script->mBytecode.mInstructions.saveSize();
}
file.adress = addres;
}
void ScriptSection::load_script_table_from_file(ScriptSection* self, Archiver& file) {
for (auto iter : self->mScripts) {
set_script_head_store_adress(iter.data(), -1);
}
auto section_start_addr = file.adress;
// header
file.adress += 5;
// scripts length
tp::alni scripts_count;
file.read<tp::alni>(&scripts_count);
for (tp::alni i = 0; i < scripts_count; i++) {
auto new_script = self->createScript();
set_script_head_store_adress(new_script, file.adress);
// scripts text
file.adress += sizeof(tp::alni);
// constants length
tp::alni consts_count;
file.read<tp::alni>(&consts_count);
new_script->mBytecode.mConstants.reserve(consts_count);
for (tp::alni j = 0; j < consts_count; j++) {
// constant object addres
tp::alni consts_addr;
file.read<tp::alni>(&consts_addr);
// skiping
//new_script->mBytecode.mConstants[j] = obj::NDO->load(file, consts_addr);
}
// mInstructions
new_script->mBytecode.mInstructions.load(file);
}
load_constants(self, file, section_start_addr);
// header
file.adress += 5;
tp::alni objects_mem_offset;
file.read<tp::alni>(&objects_mem_offset);
file.adress = objects_mem_offset;
}
Script* ScriptSection::get_scritp_from_file_adress(tp::alni file_adress) {
for (auto iter : mScripts) {
if (get_script_head_store_adress(iter.data()) == file_adress) {
return iter.data();
}
}
return NULL;
}
ScriptSection::~ScriptSection() {
for (auto iter : mScripts) {
delete_script(iter.data());
}
}
obj::save_load_callbacks ScriptSection::slcb_script_section = {
.self = gScriptSection,
.pre_save = (obj::pre_save_callback*)ScriptSection::save_script_table_to_file,
.size = (obj::slcb_size_callback*)ScriptSection::save_script_table_to_file_size,
.pre_load = (obj::pre_load_callback*)ScriptSection::load_script_table_from_file,
.post_save = NULL,
.post_load = NULL,
};
void ScriptSection::initialize() {
ASSERT(!gScriptSection);
gScriptSection = new ScriptSection();
ASSERT(obj::NDO && "Forgot to initialize objects?");
slcb_script_section.self = gScriptSection;
obj::NDO->add_sl_callbacks(&slcb_script_section);
}
void ScriptSection::uninitialize() {
ASSERT(gScriptSection);
delete gScriptSection;
}
ScriptSection* ScriptSection::globalHandle() {
return gScriptSection;
}

View file

@ -0,0 +1,81 @@
#include "NewPlacement.hpp"
#include "core/typegroups.h"
#include "core/object.h"
using namespace obj;
obj::TypeGroups::TypeGroups() : is_group(true) {
new (&childs) Dict();
}
obj::TypeGroups::TypeGroups(bool is_group) : is_group(is_group) {
if (is_group) {
new (&childs) Dict();
} else {
type = NULL;
}
}
bool obj::TypeGroups::isGroup() { return is_group; }
obj::TypeGroups::Dict* obj::TypeGroups::getChilds() {
DEBUG_ASSERT(is_group);
return &childs;
}
void obj::TypeGroups::setType(ObjectType* type) {
DEBUG_ASSERT(!is_group);
this->type = type;
}
void obj::TypeGroups::addType(ObjectType* type, tp::init_list<const char*> path, tp::alni cur_dir_idx) {
DEBUG_ASSERT(is_group);
tp::alni dir_len = (tp::alni) path.size();
if (dir_len == cur_dir_idx) {
TypeGroups* type_ref = new TypeGroups(false);
type_ref->setType(type);
childs.put(type->name, type_ref);
return;
}
TypeGroups* group = NULL;
tp::alni index = 0;
for (auto dir : path) {
if (index != cur_dir_idx) {
index++;
continue;
}
auto child_idx = childs.presents(dir);
if (child_idx) {
group = childs.getSlotVal(child_idx);
} else {
group = new TypeGroups(true);
childs.put(dir, group);
}
group->addType(type, path, cur_dir_idx + 1);
break;
}
}
const obj::ObjectType* obj::TypeGroups::getType() {
DEBUG_ASSERT(!is_group);
return type;
}
obj::TypeGroups::~TypeGroups() {
if (is_group) {
for (auto& child : childs) {
delete child->val;
}
childs.~Map();
}
}

View file

@ -0,0 +1,138 @@
#include "NewPlacement.hpp"
#include "core/typemethods.h"
#include "primitives/nullobject.h"
#include "primitives/typeobject.h"
#include "primitives/floatobject.h"
#include "interpreter/interpreter.h"
using namespace obj;
TypeMethod obj::gDefaultTypeMethods[] = {
{
.nameid = "type",
.descr = "retrieves typeobject",
.exec = [](const TypeMethod* tm) {
tm->ret.obj = TypeObject::create(tm->self->type);
},
.ret = { "typeobject", NULL },
},
{
.nameid = "to_str",
.descr = "converts to string",
.exec = [](const TypeMethod* tm) {
if (tm->self->type->convesions && tm->self->type->convesions->to_string) {
tm->ret.obj = StringObject::create(NDO->toString(tm->self));
}
},
.ret = { "string object", NULL },
},
{
.nameid = "to_float",
.descr = "converts to float",
.exec = [](const TypeMethod* tm) {
if (tm->self->type->convesions && tm->self->type->convesions->to_float) {
tm->ret.obj = FloatObject::create(NDO->toFloat(tm->self));
}
},
.ret = { "string object", NULL },
},
};
tp::int2 TypeMethods::presents(tp::String id) const {
for (tp::int2 idx = 0; idx < mNMethods; idx++) {
if (id == methods[idx]->nameid) {
return idx;
}
}
tp::int2 idx = 0;
for (auto& tm : gDefaultTypeMethods) {
if (id == tm.nameid) {
return { tp::int2(idx + MAX_TYPE_METHODS) };
}
idx++;
}
return -1;
}
TypeMethods::LookupKey TypeMethods::presents(const ObjectType* type, tp::string id) {
tp::int2 depth = 0;
tp::int2 idx = 0;
for (auto iter_type = type; iter_type; iter_type = iter_type->base) {
idx = iter_type->type_methods.presents(id);
if (idx != -1) {
break;
}
depth++;
}
return { idx, depth};
}
const TypeMethod* TypeMethods::getMethod(tp::int2 key) const {
if (key < MAX_TYPE_METHODS) {
return methods[key];
}
return &gDefaultTypeMethods[key - MAX_TYPE_METHODS];
}
const TypeMethod* TypeMethods::getMethod(const ObjectType* type, LookupKey key) {
auto type_iter = type;
for (auto idx = 0; idx < key.type_depth; idx++) {
type_iter = type_iter->base;
}
return type_iter->type_methods.getMethod(key.key);
}
void TypeMethods::init() {
while (methods[mNMethods]) {
mNMethods++;
}
for (tp::int1 i = 0; i < mNMethods; i++) {
methods[i]->init();
}
// initialize and use finate state automata to lookup methods
}
tp::halni TypeMethods::nMethods() const {
return mNMethods;
}
void TypeMethod::operator()(Interpreter* interp) const{
for (auto i = 1; i <= mNargs; i++) {
args[mNargs - i].obj = interp->mOperandsStack.getOperand();
//NDO->refinc(args[i].obj);
ASSERT(args[mNargs - i].obj && "expected an argument");
}
ASSERT(!interp->mOperandsStack.getOperand() && "args remained");
interp->mOperandsStack.getOperand();
self = interp->mLastParent;
exec(this);
if (ret.obj) {
interp->mOperandsStack.push(ret.obj);
interp->mScopeStack.addTempReturn(ret.obj);
}
else {
interp->mOperandsStack.push(NDO_NULL_REF);
}
}
void TypeMethod::init() {
while (args[mNargs].descr) {
mNargs++;
}
}

View file

@ -0,0 +1,40 @@
#include "NewPlacement.hpp"
#include "interpreter/callstack.h"
#include "interpreter/bytecode.h"
#include "primitives/methodobject.h"
using namespace obj;
void CallStack::enter(const CallStack::CallFrame& frame) {
if (mStack.size()) {
auto& last_frame = mStack.last();
last_frame.mIp = last_frame.mMethod->mScript->mBytecode.mInstructionIdx;
}
frame.mMethod->mScript->mBytecode.mArgumentsLoaded = 0;
frame.mMethod->mScript->mBytecode.mInstructionIdx = 0;
obj::NDO->refinc(frame.mMethod);
mStack.append(frame);
}
void CallStack::leave() {
auto frame = mStack.last();
obj::NDO->destroy(frame.mMethod);
mStack.pop();
if (mStack.size()) {
auto& last_frame = mStack.last();
last_frame.mMethod->mScript->mBytecode.mInstructionIdx = last_frame.mIp;
}
}
ByteCode* CallStack::getBytecode() {
return &mStack.last().mMethod->mScript->mBytecode;
}
tp::halni CallStack::len() const {
return mStack.size();
}

View file

@ -0,0 +1,573 @@
#include "NewPlacement.hpp"
#include "interpreter/interpreter.h"
#include "primitives/primitives.h"
#include "Logging.hpp"
#include "Timing.hpp"
using namespace obj;
inline tp::uint1 read_byte(ByteCode* bytecode) {
auto out = (tp::uint1)bytecode->mInstructions[bytecode->mInstructionIdx];
bytecode->mInstructionIdx++;
return out;
}
// exeption for opcodes
// reads 2 bytes from instructions in order to load constant onto operands stack
tp::uint2 loadConstDataIdx(ByteCode* bytecode) {
tp::uint2 out = 0;
out |= ((tp::uint2) read_byte(bytecode));
out |= ((tp::uint2) read_byte(bytecode) << 8);
return out;
}
// exeption for opcodes
// reads 2 bytes from instructions in order to load constant onto operands stack
void skip_param(ByteCode* bytecode) {
bytecode->mInstructionIdx += 2;
}
tp::uint2 param(ByteCode* bytecode) {
return loadConstDataIdx(bytecode);
}
void Interpreter::exec(obj::MethodObject* method, obj::ClassObject* self, obj::DictObject* globals, tp::init_list<GlobalDef> globals2) {
if (!method->mScript->mBytecode.mInstructions.size()) {
return;
}
mCallStack.enter({ NULL, method, 0 });
mCallStack.mStack.last().mSelf = self;
stepBytecodeIn();
if (globals) {
for (auto glb : globals->getItems()) {
mScopeStack.addLocal(glb->val, glb->key);
}
}
for (auto global_def : globals2) {
mScopeStack.addLocal(global_def.obj, global_def.id);
}
}
bool Interpreter::finished() {
return !mCallStack.len();
}
void Interpreter::stepBytecode() {
tp::halni call_depth = mCallStack.len();
do {
stepBytecodeIn();
if (finished()) {
return;
}
} while (call_depth != mCallStack.len());
}
void Interpreter::stepBytecodeOut() {
if (finished()) {
return;
}
tp::halni call_depth = mCallStack.len();
if (!call_depth) {
return;
}
do {
stepBytecodeIn();
if (finished()) {
return;
}
} while (call_depth - 1 != mCallStack.len());
}
void Interpreter::stepBytecodeIn() {
using namespace obj;
using namespace tp;
DEBUG_BREAK(finished());
auto bytecode = mCallStack.getBytecode();
if (bytecode->mInstructionIdx >= (tp::ualni) bytecode->mInstructions.size()) {
// just return
if (mScopeStack.mIdx) {
mScopeStack.leaveScope();
}
mCallStack.leave();
if (mCallStack.len()) {
mOperandsStack.push(NDO_NULL_REF);
}
return;
}
auto opcode = bytecode->mInstructions[bytecode->mInstructionIdx];
bytecode->mInstructionIdx++;
switch (opcode) {
case OpCode::NONE: {
break;
}
case OpCode::HALT: {
while (true) {
tp::sleep(3);
}
break;
}
case OpCode::TERMINATE: {
//tp::terminate(0);
}
case OpCode::IGNORE: {
NDO->destroy(mOperandsStack.getOperand());
break;
}
case OpCode::LOAD_CONST: {
auto idx = loadConstDataIdx(bytecode);
auto const_obj = bytecode->mConstants[idx];
mOperandsStack.push(const_obj);
break;
}
case OpCode::LOAD_LOCAL: {
auto idx = loadConstDataIdx(bytecode);
auto const_obj = bytecode->mConstants[idx];
NDO_CASTV(StringObject, const_obj, local_id);
ASSERT(local_id && "Invalid Object Type");
auto local = mScopeStack.getLocal(local_id->val);
mOperandsStack.push(local);
break;
}
case OpCode::SCOPE_IN: {
mScopeStack.enterScope(true);
break;
}
case OpCode::JUMP: {
bytecode->mInstructionIdx += param(bytecode);
break;
}
case OpCode::JUMP_IF: {
auto cond = mOperandsStack.getOperand();
if (NDO->toBool(cond)) {
bytecode->mInstructionIdx += param(bytecode);
} else {
skip_param(bytecode);
}
break;
}
case OpCode::JUMP_IF_NOT: {
auto cond = mOperandsStack.getOperand();
if (!NDO->toBool(cond)) {
bytecode->mInstructionIdx += param(bytecode);
} else {
skip_param(bytecode);
}
break;
}
case OpCode::JUMP_R: {
bytecode->mInstructionIdx -= param(bytecode);
break;
}
case OpCode::JUMP_IF_R: {
auto cond = mOperandsStack.getOperand();
if (NDO->toBool(cond)) {
bytecode->mInstructionIdx -= param(bytecode);
} else {
skip_param(bytecode);
}
break;
}
case OpCode::JUMP_IF_NOT_R: {
auto cond = mOperandsStack.getOperand();
if (!NDO->toBool(cond)) {
bytecode->mInstructionIdx -= param(bytecode);
} else {
skip_param(bytecode);
}
break;
}
case OpCode::SCOPE_OUT: {
mScopeStack.leaveScope();
break;
}
case OpCode::PRINT: {
auto obj = mOperandsStack.getOperand();
if (obj->type->convesions && obj->type->convesions->to_string) {
auto str = NDO->toString(obj);
gLogger->write(str, true);
} else {
gLogger->write(String(obj->type->name), true);
}
break;
}
case OpCode::OBJ_CREATE_LOCAL: {
auto type = mOperandsStack.getOperand<StringObject>();
auto id = mOperandsStack.getOperand<StringObject>();
mScopeStack.addLocal(NDO->create(type->val), id->val);
break;
}
case OpCode::DEF_LOCAL: {
auto id = mOperandsStack.getOperand<StringObject>();
auto obj = mOperandsStack.getOperand();
mScopeStack.addLocal(obj, id->val);
NDO->refinc(obj);
//mScopeStack.popTemp();
break;
}
case OpCode::OBJ_CREATE: {
auto type = mOperandsStack.getOperand<StringObject>();
Object* new_obj = NULL;
// basic types
auto idx = NDO->types.presents(type->val);
if (idx) {
auto new_obj = NDO->create(type->val);
mOperandsStack.push(new_obj);
mScopeStack.addTemp(new_obj);
break;
}
// class creation
auto local_class = mScopeStack.getLocal(type->val);
NDO_CASTV(MethodObject, local_class, method);
ASSERT(method);
// class is a function - execute it as a constructor
// PUSH_ARGS protocol
tp::uint2 len = 0;
mOperandsStack.push((Object*)len);
mOperandsStack.push(NULL);
// CALL protocol
mScopeStack.enterScope(false);
mCallStack.enter({ NULL, method, 0 });
break;
}
case OpCode::CLASS_CONSTRUCT: {
auto class_obj = (ClassObject*)NDO->create("class");
for (auto local : mScopeStack.getCurrentScope()->mLocals) {
class_obj->addMember(local->val, local->key);
}
mOperandsStack.push(class_obj);
mScopeStack.addTempReturn(class_obj);
mScopeStack.leaveScope();
mCallStack.leave();
return;
}
case OpCode::RETURN: {
//mScopeStack.addTempReturn(NDO_NULL_REF);
mScopeStack.leaveScope();
mCallStack.leave();
if (mCallStack.len()) {
mOperandsStack.push(NDO_NULL_REF);
}
break;
}
case OpCode::PUSH_ARGS: {
// Layout of OperandsStack:
// ....
// +1) length : to chech number of args
// +2) NULL : stop saving args
// +3) object1
// +4) object2
// ...
tp::uint2 len = read_byte(bytecode);
mOperandsStack.push((Object*) len);
mOperandsStack.push(NULL);
break;
}
case OpCode::SAVE_ARGS: {
tp::uint2 args_len = read_byte(bytecode);
auto argument = mOperandsStack.getOperand();
while (argument) {
NDO->refinc(argument);
auto argument_id = bytecode->mConstants[loadConstDataIdx(bytecode)];
NDO_CASTV(StringObject, argument_id, id);
DEBUG_ASSERT(id);
mScopeStack.addLocal(argument, id->val);
bytecode->mArgumentsLoaded++;
argument = mOperandsStack.getOperand();
}
tp::uint2 saved_len = tp::uint2 (tp::ualni (mOperandsStack.getOperand()));
ASSERT(args_len == saved_len && "invalid number of arguments passefd");
break;
}
case OpCode::RETURN_OBJ: {
if (mCallStack.len() > 1) {
auto ret = mOperandsStack.getOperand();
mOperandsStack.push(ret);
mScopeStack.addTempReturn(ret);
}
mScopeStack.leaveScope();
mCallStack.leave();
break;
}
case OpCode::CALL: {
auto obj = mOperandsStack.getOperand();
if (!mIsTypeMethod) {
NDO_CASTV(MethodObject, obj, method);
mScopeStack.enterScope(false);
mCallStack.enter({ NULL, method, 0 });
// push self
mCallStack.mStack.last().mSelf = mLastParent;
break;
}
(*mTypeMethod)(this);
mIsTypeMethod = false;
mTypeMethod = NULL;
break;
}
case OpCode::OBJ_ADD: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
ASSERT(left->type == right->type && "addition of different types is not implemented");
ASSERT(left->type->ariphmetics && left->type->ariphmetics->add && "cannot add object of this type");
auto res = NDO->instatiate(left);
res->type->ariphmetics->add(res, right);
mScopeStack.addTemp(res);
mOperandsStack.push(res);
break;
}
case OpCode::OBJ_SUB: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
ASSERT(left->type == right->type && "addition of different types is not implemented");
ASSERT(left->type->ariphmetics && left->type->ariphmetics->add && "cannot add object of this type");
auto res = NDO->instatiate(left);
res->type->ariphmetics->sub(res, right);
mScopeStack.addTemp(res);
mOperandsStack.push(res);
break;
}
case OpCode::OBJ_MUL: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
ASSERT(left->type == right->type && "addition of different types is not implemented");
ASSERT(left->type->ariphmetics && left->type->ariphmetics->add && "cannot add object of this type");
auto res = NDO->instatiate(left);
res->type->ariphmetics->mul(res, right);
mScopeStack.addTemp(res);
mOperandsStack.push(res);
break;
}
case OpCode::OBJ_DIV: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
ASSERT(left->type == right->type && "addition of different types is not implemented");
ASSERT(left->type->ariphmetics && left->type->ariphmetics->add && "cannot add object of this type");
auto res = NDO->instatiate(left);
res->type->ariphmetics->div(res, right);
mScopeStack.addTemp(res);
mOperandsStack.push(res);
break;
}
case OpCode::OBJ_COPY: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
NDO->copy(left, right);
break;
}
case OpCode::CHILD: {
auto child_id = mOperandsStack.getOperand<StringObject>();
auto parent = mOperandsStack.getOperand();
bool is_method = read_byte(bytecode);
Object* child = NULL;
TypeMethods::LookupKey tm_key;
if (is_method) {
tm_key = TypeMethods::presents(parent->type, child_id->val);
}
if (tm_key) {
mTypeMethod = TypeMethods::getMethod(parent->type, tm_key);
mIsTypeMethod = true;
} else {
NDO_CASTV(ClassObject, parent, class_obj);
ASSERT(class_obj && "not a class object");
auto idx = class_obj->members->presents(child_id->val);
ASSERT(idx && "No child with such id");
child = class_obj->members->getSlotVal(idx);
}
//mScopeStack.addTemp(obj);
mOperandsStack.push(child);
mLastParent = parent;
break;
}
case OpCode::SELF: {
//mScopeStack.addTemp(obj);
ASSERT(mCallStack.mStack.last().mSelf);
mOperandsStack.push(mCallStack.mStack.last().mSelf);
break;
}
case OpCode::OBJ_LOAD: {
auto path = mOperandsStack.getOperand<StringObject>();
auto obj = NDO->load(path->val);
mScopeStack.addTemp(obj);
mOperandsStack.push(obj);
break;
}
case OpCode::OBJ_SAVE: {
auto path = mOperandsStack.getOperand<StringObject>();
auto target = mOperandsStack.getOperand();
NDO->save(target, path->val);
break;
}
case OpCode::AND: {
auto left = NDO->toBool(mOperandsStack.getOperand());
auto right = NDO->toBool(mOperandsStack.getOperand());
auto out = BoolObject::create(left && right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::OR: {
auto left = NDO->toBool(mOperandsStack.getOperand());
auto right = NDO->toBool(mOperandsStack.getOperand());
auto out = BoolObject::create(left || right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::NOT: {
auto inv = NDO->toBool(mOperandsStack.getOperand());
auto out = BoolObject::create(!inv);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::NOT_EQUAL: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
auto out = BoolObject::create(!NDO->compare(left, right));
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::EQUAL: {
auto left = mOperandsStack.getOperand();
auto right = mOperandsStack.getOperand();
auto out = BoolObject::create(NDO->compare(left, right));
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::MORE: {
auto left = NDO->toFloat(mOperandsStack.getOperand());
auto right = NDO->toFloat(mOperandsStack.getOperand());
auto out = BoolObject::create(left > right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::LESS: {
auto left = NDO->toFloat(mOperandsStack.getOperand());
auto right = NDO->toFloat(mOperandsStack.getOperand());
auto out = BoolObject::create(left < right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::EQUAL_OR_MORE: {
auto left = NDO->toFloat(mOperandsStack.getOperand());
auto right = NDO->toFloat(mOperandsStack.getOperand());
auto out = BoolObject::create(left >= right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
case OpCode::EQUAL_OR_LESS: {
auto left = NDO->toFloat(mOperandsStack.getOperand());
auto right = NDO->toFloat(mOperandsStack.getOperand());
auto out = BoolObject::create(left <= right);
mScopeStack.addTemp(out);
mOperandsStack.push(out);
break;
}
default: {
ASSERT("Invalid OpCode");
}
}
}
void Interpreter::execAll(obj::MethodObject* method, obj::ClassObject* self, obj::DictObject* globals, tp::init_list<GlobalDef> globals2) {
if (!method->mScript->mBytecode.mInstructions.size()) {
return;
}
exec(method, self, globals, globals2);
while (!finished()) {
stepBytecodeIn();
}
}

View file

@ -0,0 +1,384 @@
#include "Utils.hpp"
#include "interpreter/opcodes.h"
namespace obj {
OpcodeInfos gOpcodeInfos;
};
using namespace obj;
#define CONST_IDX_BYTES 2
#define OP(opcode, name, desc, ops, params) \
add(opcode, { #name, #desc, ops, params } );
OpcodeInfos::OperandsInfo::OperandsInfo() {}
OpcodeInfos::OperandsInfo::OperandsInfo(tp::init_list<Operand> list) {
DEBUG_ASSERT(MAX_OPERANDS >= list.size());
for (auto item : list) {
buff[len] = item;
len++;
}
}
OpcodeInfos::ParamsInfo::ParamsInfo() {}
OpcodeInfos::ParamsInfo::ParamsInfo(tp::init_list<Param> list) {
DEBUG_ASSERT(MAX_PARAMS >= list.size());
for (auto item : list) {
buff[len] = item;
len++;
}
}
tp::uint1 OpcodeInfos::OpInfo::opsize() {
tp::uint1 out = 1;
for (auto i = 0; i < params.len; i++) {
out += params.buff[i].bytes;
}
return out;
}
OpcodeInfos::OpcodeInfos() {
add(OpCode::NONE, { "NONE", "Does Nothing" });
add(OpCode::HALT, { "HALT", "Halts for 3 sec" });
add(OpCode::TERMINATE, { "TERMINATE", "Terminates the process" });
add(OpCode::DEF_LOCAL, {
.name = "DEF LOCAL",
.desc = "Adds object to the locals",
.operands = {
{ "str", "local id" },
{ "any", "object to be local" }
}
}
);
add(OpCode::LOAD_CONST, {
.name = "LOAD CONST",
.desc = "Loads const object from the const pool",
.params = {
{ "const obj idx", CONST_IDX_BYTES },
}
}
);
add(OpCode::LOAD_LOCAL, {
.name = "LOAD LOCAL",
.desc = "Loads local object from the locals",
.params = {
{ "idx of const StringObject - represents name id", CONST_IDX_BYTES },
}
}
);
add(OpCode::IGNORE, {
.name = "IGNORE",
.desc = "Ignores returned object by destroying it",
}
);
add(OpCode::SCOPE_IN, {
.name = "SCOPE IN",
.desc = "Enters new scope",
}
);
add(OpCode::SCOPE_OUT, {
.name = "SCOPE OUT",
.desc = "Leaves current scope",
}
);
add(OpCode::CALL, {
.name = "CALL",
.desc = "Leaves current scope",
.operands = {
{ "method", "method object" },
}
}
);
add(OpCode::RETURN_OBJ, {
.name = "RETURN OBJ",
.desc = "Returns Operand",
.operands = {
{ "any", "object to be returned" },
}
}
);
add(OpCode::RETURN, {
.name = "RETURN",
.desc = "Returns Null Object",
}
);
add(OpCode::CHILD, {
.name = "CHILD",
.desc = "Retrieves child from class",
.operands = {
{ "str", "child id" },
{ "class", "parent class" },
},
.params = {
{ "is method ?", 1 }
}
}
);
add(OpCode::PUSH_ARGS, {
.name = "PUSH ARGS",
.desc = "Pushes Separator on the OperandsStack",
.params = {
{ "length to chech number of args", 1 }
}
}
);
add(OpCode::SAVE_ARGS, {
.name = "SAVE ARGS",
.desc = "Pushes operands to locals",
.params = {
{ "number of arguments in function defenition", 1 }
}
}
);
add(OpCode::OBJ_CREATE_LOCAL, {
.name = "CREATE LOCAL OBJ",
.desc = "creates object of given type and adds it to the locals",
.operands = {
{ "str", "types" },
{ "str", "name id" },
}
}
);
add(OpCode::OBJ_CREATE, {
.name = "CREATE OBJ",
.desc = "creates object of given type",
.operands = {
{ "str", "types" },
}
}
);
add(OpCode::OBJ_COPY, {
.name = "COPY",
.desc = "Copies objects",
.operands = {
{ "any", "self" },
{ "any", "target" },
}
}
);
add(OpCode::OBJ_SAVE, {
.name = "SAVE",
.desc = "Saves object to a file",
.operands = {
{ "str", "path" },
{ "any", "self" },
}
}
);
add(OpCode::OBJ_LOAD, {
.name = "LOAD",
.desc = "loads object from a file",
.operands = {
{ "str", "path" },
{ "any", "self" },
}
}
);
add(OpCode::OBJ_ADD, {
.name = "ADD",
.desc = "Adds objects of the same type that supports ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::OBJ_SUB, {
.name = "SUB",
.desc = "Subtruts objects of the same type that supports ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::OBJ_MUL, {
.name = "MUL",
.desc = "Multiplies objects of the same type that supports ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::OBJ_DIV, {
.name = "DIV",
.desc = "Divides objects of the same type that supports ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::AND, {
.name = "AND",
.desc = "Logical AND of objects of the same type that supports boolean ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::OR, {
.name = "OR",
.desc = "Logical OR of objects of the same type that supports boolean ariphmetics",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::EQUAL, {
.name = "EQUAL",
.desc = "Compares objects",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::NOT_EQUAL, {
.name = "NOT EQUAL",
.desc = "Compares objects and inverts the resault",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::MORE, {
.name = "MORE",
.desc = " > ",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::LESS, {
.name = "LESS",
.desc = " < ",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::EQUAL_OR_MORE, {
.name = "GRATER OR EQUAL",
.desc = " >= ",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::EQUAL_OR_LESS, {
.name = "LESS OR EQUAL",
.desc = " <= ",
.operands = {
{ "any", "left" },
{ "any", "right" },
}
}
);
add(OpCode::NOT, {
.name = "NOT",
.desc = "Inverts the object bolean representation",
.operands = {
{ "any", "self" },
}
}
);
add(OpCode::JUMP, {
.name = "JUMP",
.desc = "Offsets the instruction pointer",
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::JUMP_R, {
.name = "JUMP R",
.desc = "Offsets the instruction pointer in reversed direction",
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::JUMP_IF, {
.name = "JUMP IF",
.desc = "Offsets the instruction pointer if condition is met",
.operands = {
{ "any", "condition object" },
},
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::JUMP_IF_R, {
.name = "JUMP IF R",
.desc = "Offsets the instruction pointer in reversed direction if condition is met",
.operands = {
{ "any", "condition object" },
},
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::JUMP_IF_NOT, {
.name = "JUMP IF R",
.desc = "Offsets the instruction pointer if condition is NOT met",
.operands = {
{ "any", "condition object" },
},
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::JUMP_IF_NOT_R, {
.name = "JUMP IF R",
.desc = "Offsets the instruction pointer in reversed direction if condition is NOT met",
.operands = {
{ "any", "condition object" },
},
.params = {
{ "ip offset unsigned", 2 },
}
}
);
add(OpCode::PRINT, {
.name = "PRINT",
.desc = "Prints the object string representation",
.operands = {
{ "any", "self" },
}
}
);
add(OpCode::CLASS_CONSTRUCT, {
.name = "CLASS CONSTRUCT",
.desc = "Creates class from the function execution state",
}
);
add(OpCode::SELF, {
.name = "SELF",
.desc = "retrieves parent class of the current method",
}
);
}
OpcodeInfos::OpInfo OpcodeInfos::fetch(OpCode code) {
DEBUG_ASSERT((tp::alni)code >= 0 && (tp::alni)code < (tp::alni)OpCode::END_OPCODES);
return buff[(tp::alni)code];
}
void OpcodeInfos::add(OpCode code, const OpInfo& info) {
buff[(tp::alni)code] = info;
}

View file

@ -0,0 +1,30 @@
#include "interpreter/operandsstack.h"
using namespace obj;
OperandStack::OperandStack() {
mBuff = new Operand[MAX_STACK_SIZE];
mIdx = 0;
}
void OperandStack::push(Operand operand) {
ASSERT(MAX_STACK_SIZE - 1 > mIdx && "stack overflow");
mBuff[mIdx] = operand;
mIdx++;
}
void OperandStack::pop() {
ASSERT(mIdx != NULL && "stack overflow");
mIdx--;
}
Operand OperandStack::getOperand() {
auto ret = mBuff[mIdx - 1];
mIdx--;
return ret;
}
OperandStack::~OperandStack() {
delete[] mBuff;
}

View file

@ -0,0 +1,90 @@
#include "NewPlacement.hpp"
#include "interpreter/scopestack.h"
using namespace obj;
Scope::~Scope() {
for (auto local : mLocals) {
obj::NDO->destroy(local->val);
}
for (auto tmp : mTemps) {
obj::NDO->destroy(tmp.data());
}
}
obj::Object* ScopeStack::getLocalUtil(Scope& scope, tp::String* id) {
auto idx = scope.mLocals.presents(*id);
if (idx) {
return scope.mLocals.getSlotVal(idx);
}
else {
mIterIdx--;
Scope& parent_scope = mBuff[mIterIdx];
ASSERT(parent_scope.mChildReachable && "Undefined Local Reference");
return getLocalUtil(parent_scope, id);
}
}
ScopeStack::ScopeStack() {
mBuff = (Scope*) tp::HeapAllocGlobal::allocate(sizeof(Scope) * MAX_STACK_SIZE);
mIdx = 0;
mIterIdx = 0;
}
void ScopeStack::enterScope(bool aChildReachable) {
ASSERT(MAX_STACK_SIZE - 1 > mIdx && "stack overflow");
new (&mBuff[mIdx]) Scope();
mBuff[mIdx].mChildReachable = aChildReachable;
mIdx++;
}
void ScopeStack::leaveScope() {
ASSERT(mIdx != NULL && "stack overflow");
mBuff[mIdx - 1].~Scope();
mIdx--;
}
void ScopeStack::addTemp(obj::Object* tmp) {
obj::NDO->refinc(tmp);
mBuff[mIdx - 1].mTemps.pushBack(tmp);
}
void ScopeStack::popTemp() {
obj::NDO->destroy(mBuff[mIdx - 1].mTemps.last()->data);
mBuff[mIdx - 1].mTemps.popBack();
}
void ScopeStack::addTempReturn(obj::Object* ret) {
if (mIdx >= 2) {
obj::NDO->refinc(ret);
mBuff[mIdx - 2].mTemps.pushBack(ret);
}
}
void ScopeStack::addLocal(obj::Object* local, tp::String id) {
DEBUG_ASSERT(mIdx != 0 && "No scope given");
Scope::ObjDict& locals = mBuff[mIdx - 1].mLocals;
auto idx = locals.presents(id);
if (idx) {
obj::NDO->destroy(locals.getSlotVal(idx));
}
obj::NDO->refinc(local);
locals.put(id, local);
}
obj::Object* ScopeStack::getLocal(tp::String& str) {
mIterIdx = mIdx - 1;
return getLocalUtil(mBuff[mIdx - 1], &str);
}
Scope* ScopeStack::getCurrentScope() {
return &mBuff[mIdx - 1];
}
ScopeStack::~ScopeStack() {
tp::HeapAllocGlobal::deallocate(mBuff);
}

View file

@ -0,0 +1,904 @@
#include "Logging.hpp"
#include "List.hpp"
#include "parser/parser.h"
#include "compiler/function.h"
#include <cstdlib>
#define MAX_STREAM_LENGTH 1024 * 8 * 200
#define REQUIRE(expr, desc, on_catch) DEBUG_BREAK(mRes.err); if (!(expr)) { mRes.err = new Error(desc, mTok.getCursorPrev().mAdvancedOffset); on_catch; return NULL; }
#define CHECK(expr, on_catch) if (!(expr)) { on_catch; return NULL; }
#define CHECK_ERROR(value, on_catch) if (mRes.err || !value) { on_catch; return NULL; }
using namespace tp;
using namespace obj;
using namespace BCgen;
bool Parser::Token::isAriphm() {
switch (type) {
case Token::ADD:
case Token::SUB:
case Token::DIV:
case Token::MUL:
return true;
default:
return false;
}
}
bool Parser::Token::isBoolean() {
switch (type) {
case Token::EQUAL:
case Token::NOT_EQUAL:
case Token::BOOL_AND:
case Token::BOOL_OR:
case Token::MORE:
case Token::LESS:
case Token::QE_OR_MORE:
case Token::QE_OR_LESS:
return true;
default:
return false;
}
}
Parser::Parser() {
mTok.build({
{ "\n|\t| |\r", Token::SPACE },
{ "var", Token::VAR },
{ "class", Token::CLASS_DEF },
{ "self", Token::SELF },
{ "\\{", Token::SCOPE_IN },
{ "\\}", Token::SCOPE_OUT },
{ "=", Token::ASSIGN },
{ "def", Token::DEF_FUNC },
{ "<<", Token::PRINT },
{ "if", Token::IF },
{ "else", Token::ELSE },
{ "while", Token::WHILE },
{ "\\(", Token::BRACKET_IN },
{ "\\)", Token::BRACKET_OUT },
{ ",", Token::COMMA },
{ "new", Token::NEW },
{ "\\.", Token::CHILD },
{ "return", Token::RETURN },
{ "==", Token::EQUAL },
{ "!=", Token::NOT_EQUAL },
{ ">", Token::MORE },
{ "<", Token::LESS },
{ ">=", Token::QE_OR_MORE },
{ "<=", Token::QE_OR_LESS },
{ "!", Token::BOOL_NOT },
{ "&&", Token::BOOL_AND },
{ "\\|\\|", Token::BOOL_OR },
{ "\\+", Token::ADD },
{ "\\*", Token::MUL },
{ "\\-", Token::SUB },
{ "/", Token::DIV },
{ ";", Token::STM_END },
{ "true", Token::CONST_TRUE },
{ "false", Token::CONST_FALSE },
{ "((\\-)|(\\+))?[0-9]+i?", Token::CONST_INT },
{ "((\\-)|(\\+))?([0-9]+)(\\.)([0-9]*)?f?", Token::CONST_FLOAT },
{ "(/\\*){\\*-\\*}*(\\*/)", Token::COMMENT_BLOCK },
{ "\"{\"-\"}*\"", Token::CONST_STRING },
{ "([a-z]|[A-Z]|_)+([a-z]|[A-Z]|[0-9]|_)*", Token::ID },
});
}
tp::String to_string(const char* stream, tp::alni len) {
tp::String out;
out.reserve(len + 1);
tp::memcp(out.get_writable(), stream, len);
out.get_writable()[len] = '\0';
return out;
}
Parser::Token Parser::tokRead() {
Token out;
if (!tokInputLeft()) {
Token out;
out.type = Token::NO_TOKEN;
return out;
}
auto crs_start = mTok.getCursor();
out.type = mTok.readTok();
out.token = to_string(crs_start.str(), mTok.lastTokLEn());
switch (out.type) {
case Token::CONST_FALSE:
out.boolean = false;
break;
case Token::CONST_TRUE:
out.boolean = true;
break;
case Token::CONST_INT: {
char* p_end;
out.integer = std::strtol(out.token.read(), &p_end, 10);
DEBUG_ASSERT(out.token.read() != p_end);
break;
}
case Token::CONST_FLOAT: {
char* p_end;
out.floating = std::strtod(out.token.read(), &p_end);
DEBUG_ASSERT(out.token.read() != p_end);
break;
}
case Token::CONST_STRING: {
out.str = to_string(crs_start.str() + 1, mTok.lastTokLEn() - 2);
break;
}
}
return out;
}
Parser::Token Parser::tokLookup() {
auto crs = mTok.getCursor();
auto out = tokRead();
mTok.setCursor(crs);
return out;
}
bool Parser::tokInputLeft() {
auto type = mTok.lookupTok();
while (mTok.isInputLeft() && type == Token::SPACE || (type >= Token::__END__ && type <= Token::__START__)) {
mTok.skipTok();
type = mTok.lookupTok();
}
return type != Token::SOURCE_END_TOKEN;
}
void Parser::tokSkip() {
if (!tokInputLeft()) {
return;
}
mTok.skipTok();
}
Parser::Tokenizer::Cursor Parser::tokGetCursor() { return mTok.getCursor();}
void Parser::tokSetCursor(Tokenizer::Cursor crs) { mTok.setCursor(crs); }
Expression* Parser::parseExprCompound() {
CHECK(tokRead() == Token::BRACKET_IN, {});
auto ret = parseExpr();
CHECK_ERROR(ret, {});
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected Closing Bracket", {});
return ret;
}
Expression* Parser::parseExprNEW() {
CHECK(tokRead() == Token::NEW, {});
auto name = tokRead();
REQUIRE(name == Token::ID, "Expected Identifier", {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected opening brackets", {});
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected closing brackets", {});
return ExprNew(name.token);
}
Expression* Parser::parseExprLOCAL() {
auto local_id_tok = tokRead();
if (local_id_tok == Token::ID) {
return ExprLocal(local_id_tok.token);
}
else if (local_id_tok == Token::SELF) {
return ExprSelf();
}
return NULL;
}
Expression* Parser::parseExprCONST() {
auto tok = tokRead();
switch (tok) {
case Token::CONST_FALSE:
return ExprConst(false);
case Token::CONST_TRUE:
return ExprConst(true);
case Token::CONST_INT:
return ExprConst(tok.integer);
case Token::CONST_FLOAT:
return ExprConst(tok.floating);
case Token::CONST_STRING:
return ExprConst(tok.str);
default:
REQUIRE(0, "not a const Expr", {});
}
}
Expression* Parser::parseExprCHILD(Expression* prnt) {
CHECK(tokRead() == Token::CHILD, {});
auto id = tokRead();
REQUIRE(id == Token::ID, "Exprected Identifier", {});
return prnt->ExprChild(id.str);
}
Expression* Parser::parseExprCALL(Expression* prnt) {
CHECK(tokRead() == Token::BRACKET_IN, {});
List<Expression*> args;
READ_ARG:
Expression* expr = NULL;
auto tok = tokLookup();
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
if (tok != Token::BRACKET_OUT) {
expr = parseExpr();
CHECK_ERROR(expr, {
for (auto arg : args) {
delete arg.data();
}
});
args.pushBack(expr);
tok = tokLookup();
if (tok == Token::COMMA) {
tokSkip();
goto READ_ARG;
}
else if (tok != Token::BRACKET_OUT) {
for (auto arg : args) {
delete arg.data();
}
REQUIRE(0, "Expected A Closing Bracket", {});
}
}
tokSkip();
auto out = prnt->ExprCall({});
out->mArgs.reserve(args.length());
for (auto arg : args) {
out->mArgs[arg.idx()] = arg.data();
}
return out;
}
Expression* Parser::parseExprAriphm() {
tp::init_list<ExprType> expessions = {
ExprType::Compound,
ExprType::NEW,
ExprType::LOCAL,
ExprType::CONST,
};
Expression* left = parseExpr(expessions);
CHECK_ERROR(left, {});
Expression* ret = NULL;
PARSE:
Expression* right = NULL;
auto tok = tokLookup();
if (tok.isAriphm()) {
tokSkip();
right = parseExpr(expessions);
if (mRes.err) {
if (ret) {
goto PRECEDENCE;
}
delete left;
return NULL;
}
}
else {
CHECK(ret, {
delete left;
});
goto PRECEDENCE;
}
switch (tok) {
case Token::ADD:
ret = ExprAriphm(left, right, OpCode::OBJ_ADD);
break;
case Token::SUB:
ret = ExprAriphm(left, right, OpCode::OBJ_SUB);
break;
case Token::DIV:
ret = ExprAriphm(left, right, OpCode::OBJ_DIV);
break;
case Token::MUL:
ret = ExprAriphm(left, right, OpCode::OBJ_MUL);
}
left = ret;
goto PARSE;
PRECEDENCE:
// FIXME: Not Implemented
return ret;
}
Expression* Parser::parseExprBOOLEAN() {
tp::init_list<ExprType> expessions = {
ExprType::Compound,
ExprType::NEW,
ExprType::LOCAL,
ExprType::CONST,
ExprType::BOOLEAN_NOT,
};
Expression* left = parseExpr(expessions);
CHECK_ERROR(left, {});
Expression* ret = NULL;
PARSE:
Expression* right = NULL;
auto tok = tokLookup();
if (tok.isBoolean()) {
tokSkip();
right = parseExpr(expessions);
if (mRes.err) {
if (ret) {
goto PRECEDENCE;
}
delete left;
return NULL;
}
}
else {
CHECK(ret, {
delete left;
});
goto PRECEDENCE;
}
switch (tok) {
case Token::EQUAL:
ret = ExprBool(left, right, OpCode::EQUAL);
break;
case Token::NOT_EQUAL:
ret = ExprBool(left, right, OpCode::NOT_EQUAL);
break;
case Token::BOOL_AND:
ret = ExprBool(left, right, OpCode::AND);
break;
case Token::BOOL_OR:
ret = ExprBool(left, right, OpCode::OR);
break;
case Token::MORE:
ret = ExprBool(left, right, OpCode::MORE);
break;
case Token::LESS:
ret = ExprBool(left, right, OpCode::LESS);
break;
case Token::QE_OR_MORE:
ret = ExprBool(left, right, OpCode::EQUAL_OR_MORE);
break;
case Token::QE_OR_LESS:
ret = ExprBool(left, right, OpCode::EQUAL_OR_LESS);
}
left = ret;
goto PARSE;
PRECEDENCE:
// FIXME: Not Implemented
return ret;
}
Expression* Parser::parseExprBOOLEAN_NOT() {
CHECK(tokRead() == Token::BOOL_NOT, {});
tp::init_list<ExprType> exprs = {
ExprType::Compound,
ExprType::BOOLEAN,
ExprType::Ariphm,
ExprType::NEW,
ExprType::LOCAL,
ExprType::CONST,
};
auto out = parseExpr(exprs);
CHECK_ERROR(out, {});
return ExprBoolNot(out);
}
Expression* Parser::parseExprFUNC() {
auto op_tok = tokRead();
CHECK(op_tok == Token::ID, {});
return ExprFunc(op_tok.token);
}
// passed prnt isno longer responsability of callee
// suc : returns top level parent
// err : returns NULL
Expression* Parser::parseExprChain(Expression* prnt) {
PARSE_CHAIN:
auto tok = tokLookup();
switch (tok) {
case Token::CHILD: {
tokRead();
auto child_id = tokRead();
REQUIRE(child_id == Token::ID, "expected an id", {
delete prnt;
});
prnt = prnt->ExprChild(child_id.token);
goto PARSE_CHAIN;
}
case Token::BRACKET_IN: {
auto new_prnt = parseExprCALL(prnt);
CHECK_ERROR(new_prnt, {
delete prnt;
});
if (prnt->mType == Expression::Type::CHILD) {
((ExpressionChild*)prnt)->mMethod = true;
}
prnt = new_prnt;
goto PARSE_CHAIN;
}
}
return prnt;
}
Expression* Parser::parseExpr(tp::init_list<ExprType> expressions) {
Expression* out = NULL;
List<Error*> errors;
for (auto expr_type : expressions) {
auto crs = tokGetCursor();
switch (expr_type) {
case Parser::ExprType::BOOLEAN_NOT:
out = parseExprBOOLEAN_NOT();
break;
case Parser::ExprType::BOOLEAN:
out = parseExprBOOLEAN();
break;
case Parser::ExprType::Ariphm:
out = parseExprAriphm();
break;
case Parser::ExprType::NEW:
out = parseExprNEW();
break;
case Parser::ExprType::LOCAL:
out = parseExprLOCAL();
break;
case Parser::ExprType::CONST:
out = parseExprCONST();
break;
case Parser::ExprType::Compound:
out = parseExprCompound();
break;
}
if (out) {
break;
}
tokSetCursor(crs);
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
}
}
if (out) {
// check for child expression and calls
out = parseExprChain(out);
// check errors
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
goto ERRORS;
}
for (auto err : errors) {
delete err.data();
}
return out;
}
ERRORS:
Error* error = NULL;
tp::alni max_advanced = 0;
for (auto err : errors) {
if (err.data()->mAdvanecedIdx && err.data()->mAdvanecedIdx > max_advanced) {
max_advanced = err.data()->mAdvanecedIdx;
error = err.data();
}
}
if (error) {
mRes.err = new Error(*error);
for (auto err : errors) {
delete err.data();
}
return NULL;
}
REQUIRE(0, "Expected and expression", {});
}
Statement* Parser::parseStmCall() {
Expression* expr = parseExpr();
CHECK_ERROR(expr, {});
REQUIRE(expr->mType == Expression::Type::CALL,
"expression statement can only be function call", {
delete expr;
});
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmIgnore(expr);
}
Statement* Parser::parseStmDefFunc() {
CHECK(tokRead() == Token::DEF_FUNC, {});
List<tp::String> args;
auto name = tokRead();
REQUIRE(name == Token::ID, "Expected an Identifier", {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
READ_ARG:
auto tok = tokLookup();
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
if (tok == Token::ID) {
args.pushBack(tok.token);
tokSkip();
tok = tokLookup();
}
if (tok == Token::COMMA) {
tokSkip();
goto READ_ARG;
}
REQUIRE(tok == Token::BRACKET_OUT, "Expected Closing Bracket", {});
tokSkip();
auto func_def = StmDefFunc(name.token, {}, {});
func_def->mArgs.reserve(args.length());
for (auto iter : args) {
func_def->mArgs[iter.idx()] = iter.data();
}
StatementScope* scope = parseScope(true);
CHECK_ERROR(scope, {
delete func_def;
});
func_def->mStatements.reserve(scope->mStatements.size());
for (auto stm : scope->mStatements) {
func_def->mStatements[stm.idx()] = stm.data();
}
delete scope;
return func_def;
}
Statement* Parser::parseStmDefLocal() {
CHECK(tokRead() == Token::VAR, {});
auto tok = tokRead();
REQUIRE(tok == Token::ID, "Expected an Identifier", {});
REQUIRE(tokRead() == Token::ASSIGN, "Expected an assigment", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmDefLocal(tok.token, expr);
}
Statement* Parser::parseStmReturn() {
CHECK(tokRead() == Token::RETURN, {});
auto crs = tokGetCursor();
auto expr = parseExpr();
if (mRes.err) {
tokSetCursor(crs);
delete mRes.err;
mRes.err = NULL;
}
if (tokRead() != Token::STM_END) {
if (expr) delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return expr ? StmReturn(expr) : StmReturn();
}
Statement* Parser::parseStmPrint() {
CHECK(tokRead() == Token::PRINT, {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::STM_END) {
delete expr;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmPrint(expr);
}
Statement* Parser::parseStmIf() {
CHECK(tokRead() == Token::IF, {});
// single if
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::BRACKET_OUT) {
delete expr;
REQUIRE(0, "Expected Closing Bracket", {});
}
auto ontrue = parseScope(false);
CHECK_ERROR(ontrue, {});
// if-else
auto crs = tokGetCursor();
if (tokRead() == Token::ELSE) {
StatementScope* onfalse = parseScope(false);
CHECK_ERROR(onfalse, {
delete ontrue;
delete expr;
});
return StmIf(expr, ontrue, onfalse);
}
tokSetCursor(crs);
return StmIf(expr, ontrue, NULL);
}
Statement* Parser::parseStmWhile() {
CHECK(tokRead() == Token::WHILE, {});
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
auto expr = parseExpr();
CHECK_ERROR(expr, {});
if (tokRead() != Token::BRACKET_OUT) {
delete expr;
REQUIRE(0, "Expected Closing Bracket", {});
}
auto scope = parseScope(false);
CHECK_ERROR(scope, {});
return StmWhile(expr, scope);
}
Statement* Parser::parseStmCopy() {
auto left = parseExpr();
CHECK_ERROR(left, {});
CHECK(tokRead() == Token::ASSIGN, {});
auto right = parseExpr();
CHECK_ERROR(right, {
delete left;
});
if (tokRead() != Token::STM_END) {
delete left;
delete right;
REQUIRE(0, "Expected End Of Statement", {});
}
return StmCopy(left, right);
}
Statement* Parser::parseStmClassDef() {
CHECK(tokRead() == Token::CLASS_DEF, {});
auto id = tokRead();
REQUIRE(id == Token::ID, "Expected an Identifier", {});
auto scope = parseScope(true);
CHECK_ERROR(scope, {});
return StmClassDef(id.token, scope);
}
Statement* Parser::parseStm(tp::init_list<StmType> stm_types) {
Statement* out = NULL;
List<Error*> errors;
for (auto stm_type : stm_types) {
auto crs = tokGetCursor();
switch (stm_type) {
case StmType::DefFunc:
out = parseStmDefFunc();
break;
case StmType::DefLocal:
out = parseStmDefLocal();
break;
case StmType::Return:
out = parseStmReturn();
break;
case StmType::Print:
out = parseStmPrint();
break;
case StmType::If:
out = parseStmIf();
break;
case StmType::While:
out = parseStmWhile();
break;
case StmType::Copy:
out = parseStmCopy();
break;
case StmType::Call:
out = parseStmCall();
break;
case StmType::CLASS_DEF:
out = parseStmClassDef();
break;
}
if (out) {
break;
}
tokSetCursor(crs);
if (mRes.err) {
errors.pushBack(mRes.err);
mRes.err = NULL;
}
}
if (out) {
for (auto err : errors) {
delete err.data();
}
return out;
}
Error* error = NULL;
tp::alni max_advanced = 0;
for (auto err : errors) {
if (err.data()->mAdvanecedIdx && max_advanced < err.data()->mAdvanecedIdx) {
max_advanced = err.data()->mAdvanecedIdx;
error = err.data();
}
}
if (error) {
mRes.err = new Error(*error);
for (auto err : errors) {
delete err.data();
}
return NULL;
}
REQUIRE(0, "Exprected A Statement", {});
}
StatementScope* Parser::parseScope(bool aPushToScopeStack) {
CHECK(tokRead() == Token::SCOPE_IN, {});
auto out = new StatementScope({}, aPushToScopeStack);
List<Statement*> stms;
READ_STM:
auto crs = tokGetCursor();
auto tok = tokRead();
if (tok == Token::NO_TOKEN) {
delete out;
for (auto stm : stms) {
delete stm.data();
}
REQUIRE(0, "Missing Scope Closing Bracket", {});
}
if (tok != Token::SCOPE_OUT) {
tokSetCursor(crs);
auto stm = parseStm();
CHECK_ERROR(stm, {
delete out;
for (auto stm : stms) {
delete stm.data();
}
});
stms.pushBack(stm);
goto READ_STM;
}
out->mStatements.reserve(stms.length());
for (auto stm : stms) {
out->mStatements[stm.idx()] = stm.data();
}
return out;
}
Parser::Resault Parser::parse(const tp::String& oscript) {
mTok.bindSource(oscript.read());
mRes.scope = new StatementScope({}, true);
List<Statement*> stms;
do {
auto stm = parseStm();
if (mRes.err || !stm) { // catch
delete mRes.scope;
mRes.scope = NULL;
for (auto stm : stms) {
delete stm.data();
}
return mRes;
}
stms.pushBack(stm);
} while (tokInputLeft());
mRes.scope->mStatements.reserve(stms.length());
for (auto stm : stms) {
mRes.scope->mStatements[stm.idx()] = stm.data();
}
return mRes;
}

View file

@ -0,0 +1,78 @@
#include "NewPlacement.hpp"
#include "primitives/boolobject.h"
using namespace obj;
using namespace tp;
void BoolObject::constructor(BoolObject* self) {
self->val = false;
}
void BoolObject::copy(BoolObject* self, const BoolObject* in) {
self->val = in->val;
}
BoolObject* BoolObject::create(bool in) {
NDO_CASTV(BoolObject, NDO->create("bool"), out)->val = alni(in);
return out;
}
void BoolObject::from_int(BoolObject* self, alni in) {
self->val = in;
}
void BoolObject::from_float(BoolObject* self, alnf in) {
self->val = alni(bool(in));
}
void BoolObject::from_string(BoolObject* self, String in) {
self->val = alni(bool(in));
}
String BoolObject::to_string(BoolObject* self) {
return String(bool(self->val));
}
alni BoolObject::to_int(BoolObject* self) {
return self->val;
}
alnf BoolObject::to_float(BoolObject* self) {
return alnf(bool(self->val));
}
static alni save_size(BoolObject* self) {
return sizeof(alni);
}
static void save(BoolObject* self, Archiver& file_self) {
file_self.write<alni>(&self->val);
}
static void load(Archiver& file_self, BoolObject* self) {
file_self.read<alni>(&self->val);
}
struct ObjectTypeConversions BoolObjectTypeConversions = {
.from_int = (object_from_int) BoolObject::from_int,
.from_float = (object_from_float) BoolObject::from_float,
.from_string = (object_from_string) BoolObject::from_string,
.to_string = (object_to_string) BoolObject::to_string,
.to_int = (object_to_int) BoolObject::to_int,
.to_float = (object_to_float) BoolObject::to_float,
};
struct obj::ObjectType obj::BoolObject::TypeData = {
.base = NULL,
.constructor = (object_constructor) BoolObject::constructor,
.destructor = NULL,
.copy = (object_copy) BoolObject::copy,
.size = sizeof(BoolObject),
.name = "bool",
.convesions = &BoolObjectTypeConversions,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
};

View file

@ -0,0 +1,81 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/classobject.h"
#include "primitives/dictobject.h"
#include "primitives/nullobject.h"
using namespace obj;
using namespace tp;
void ClassObject::constructor(ClassObject* self) {
self->members = NDO_CAST(DictObject, NDO->create("dict"));
self->addMember(NDO_NULL, "__init__");
self->addMember(NDO_NULL, "__del__");
}
void ClassObject::copy(ClassObject* self, const ClassObject* blueprint) {
NDO->copy(self->members, blueprint->members);
}
void ClassObject::destructor(ClassObject* self) {
NDO->destroy(self->members);
}
void ClassObject::addMember(Object* obj, tp::String id) {
members->put(id, obj);
}
void ClassObject::createMember(tp::String type, tp::String id) {
auto newo = NDO->create(type);
members->put(id, newo);
}
alni ClassObject::save_size(ClassObject* self) {
return sizeof(alni); // dict object adress
}
void ClassObject::save(ClassObject* self, Archiver& file_self) {
// save dictobject
alni ndo_object_adress = NDO->save(file_self, self->members);
file_self.write<alni>(&ndo_object_adress);
}
void ClassObject::load(Archiver& file_self, ClassObject* self) {
alni ndo_object_adress;
file_self.read<alni>(&ndo_object_adress);
self->members = NDO_CAST(DictObject, NDO->load(file_self, ndo_object_adress));
}
tp::Buffer<Object*> childs_retrival(ClassObject* self) {
tp::Buffer<Object*> out;
out.append(self->members);
return out;
}
alni allocated_size(ClassObject* self) {
return sizeof(DictObject*);
}
alni allocated_size_recursive(ClassObject* self) {
alni out = sizeof(DictObject*);
out += NDO->objsize_ram_recursive_util(self->members, self->members->type);
return out;
}
struct ObjectType ClassObject::TypeData = {
.base = NULL,
.constructor = (object_constructor) ClassObject::constructor,
.destructor = (object_destructor) ClassObject::destructor,
.copy = (object_copy) ClassObject::copy,
.size = sizeof(ClassObject),
.name = "class",
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
.childs_retrival = (object_debug_all_childs_retrival) childs_retrival,
.allocated_size = (object_allocated_size) allocated_size,
.allocated_size_recursive = (object_allocated_size_recursive) allocated_size_recursive
};

View file

@ -0,0 +1,84 @@
#include "NewPlacement.hpp"
#include "primitives/colorobject.h"
using namespace obj;
using namespace tp;
void ColorObject::constructor(Object* self) {
NDO_CAST(ColorObject, self)->mCol = tp::RGBA(1.f);
}
void ColorObject::copy(ColorObject* self, const ColorObject* in) {
self->mCol = in->mCol;
}
ColorObject* ColorObject::create(tp::RGBA in) {
NDO_CASTV(ColorObject, NDO->create("RGBA"), out)->mCol = in;
return out;
}
void ColorObject::from_int(ColorObject* self, alni in) {
self->mCol = tp::RGBA((tp::halnf)tp::clamp(in, (tp::alni) 0, (tp::alni) 1));
}
void ColorObject::from_float(ColorObject* self, alnf in) {
NDO_CAST(ColorObject, self)->mCol = tp::RGBA(tp::clamp((tp::halnf)in, 0.f, 1.f));
}
String ColorObject::to_string(ColorObject* self) {
// auto &col = NDO_CAST(ColorObject, self)->mCol;
// return tp::sfmt("%i:%i:%i:%i", (tp::alni) (col.r * 255), (tp::alni)(col.g * 255), (tp::alni)(col.b * 255), (tp::alni)(col.a * 255));
// TODO : implement
return {};
}
static alni save_size(ColorObject* self) {
return sizeof(tp::RGBA);
}
static void save(ColorObject* self, Archiver& file_self) {
file_self.write<tp::RGBA>(&self->mCol);
}
static void load(Archiver& file_self, ColorObject* self) {
file_self.read<tp::RGBA>(&self->mCol);
}
struct ObjectTypeConversions ColorObjectTypeConversions = {
.from_int = (object_from_int) ColorObject::from_int,
.from_float = (object_from_float) ColorObject::from_float,
.from_string = NULL,
.to_string = (object_to_string) ColorObject::to_string,
.to_int = NULL,
.to_float = NULL,
};
void sub(ColorObject* self, ColorObject* in) {
self->mCol = in->mCol - self->mCol;
}
void add(ColorObject* self, ColorObject* in) {
self->mCol = in->mCol + self->mCol;
}
struct ObjectTypeAriphmetics ColorObject::TypeAriphm = {
.add = (object_add) add,
.sub = (object_sub) sub,
.mul = (object_mul) NULL,
.div = (object_div) NULL,
};
struct obj::ObjectType obj::ColorObject::TypeData = {
.base = NULL,
.constructor = ColorObject::constructor,
.destructor = NULL,
.copy = (object_copy) ColorObject::copy,
.size = sizeof(ColorObject),
.name = "RGBA",
.convesions = &ColorObjectTypeConversions,
.ariphmetics = &ColorObject::TypeAriphm,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
};

View file

@ -0,0 +1,232 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/dictobject.h"
#include "primitives/stringobject.h"
using namespace obj;
using namespace tp;
void DictObject::constructor(Object* self) {
NDO_CASTV(DictObject, self, dict);
new (&dict->items) Map<String, Object*>();
}
void DictObject::copy(Object* in, const Object* target) {
NDO_CASTV(DictObject, in, self);
NDO_CASTV(DictObject, target, src);
destructor(self);
constructor(self);
for (auto item : src->items) {
auto instance = NDO->instatiate(item->val);
self->items.put(item->key, instance);
}
}
void DictObject::destructor(Object* self) {
NDO_CASTV(DictObject, self, dict);
for (auto item : dict->items) {
NDO->destroy(item->val);
}
dict->items.~Map();
}
alni DictObject::save_size(DictObject* self) {
// calculate size needed
alni save_size = 0;
// number on entries
save_size += sizeof(alni);
for (auto item : self->items) {
// string length
save_size += (item->key.size() + 1) * sizeof(*item->key.read());
// object file adress
save_size += sizeof(alni);
}
return save_size;
}
void DictObject::save(DictObject* self, Archiver& file_self) {
// write size
alni len = self->items.size();
file_self.write<alni>(&len);
// save hashmap pairs
for (auto item : self->items) {
// item val
alni ndo_object_adress = NDO->save(file_self, item->val);
file_self.write<alni>(&ndo_object_adress);
// item key
item->key.save(&file_self);
}
}
void DictObject::load(Archiver& file_self, DictObject* self) {
new (&self->items) tp::Map<tp::String, Object*>();
alni len;
file_self.read<alni>(&len);
for (alni i = 0; i < len; i++) {
// read val
alni ndo_object_adress;
file_self.read<alni>(&ndo_object_adress);
Object* val = NDO->load(file_self, ndo_object_adress);
// read key value
String key;
key.load(&file_self);
// add to dictinary
self->items.put(key, val);
}
}
tp::Buffer<Object*> DictObject::childs_retrival(DictObject* self) {
tp::Buffer<Object*> out;
out.reserve(self->items.size());
ualni i = 0;
for (auto item : self->items) {
out[i] = item->val;
i++;
}
return out;
}
alni DictObject::allocated_size(DictObject* self) {
alni out = self->items.sizeAllocatedMem();
for (auto item : self->items) {
out += item->key.sizeAllocatedMem();
}
return out;
return 0;
}
alni DictObject::allocated_size_recursive(DictObject* self) {
alni out = allocated_size(self);
for (auto item : self->items) {
out += NDO->objsize_ram_recursive_util(item->val, item->val->type);
}
return out;
}
void DictObject::put(tp::String str, Object* obj) {
DEBUG_ASSERT(obj);
NDO->refinc(obj);
items.put(str, obj);
}
void DictObject::remove(tp::String str) {
auto idx = items.presents(str);
if (idx) {
NDO->destroy(items.getSlotVal(idx));
items.remove(str);
}
}
Object* DictObject::get(tp::String str) {
return items.get(str);
}
tp::Map<tp::String, Object*>::Idx DictObject::presents(tp::String str) {
return items.presents(str);
}
Object* DictObject::getSlotVal(tp::alni idx) {
return items.getSlotVal(idx);
}
const tp::Map<tp::String, Object*>& DictObject::getItems() const {
return items;
}
static auto tm_get = TypeMethod{
.nameid = "get",
.descr = "gets the object",
.args = {
{ "str key", NULL }
},
.exec = [](const TypeMethod* tm) {
auto const self = (DictObject*)tm->self;
auto str_key = tm->args[0].obj;
NDO_CASTV(StringObject, str_key, key);
ASSERT(key);
auto idx = self->presents(key->val);
if (idx) {
tm->ret.obj = self->getSlotVal(idx);
}
},
.ret = { "object", NULL }
};
static auto tm_put = TypeMethod{
.nameid = "put",
.descr = "puts the object into the dictinary",
.args = {
{ "key", NULL },
{ "object", NULL }
},
.exec = [](const TypeMethod* tm) {
auto const self = (DictObject*)tm->self;
auto str_key = tm->args[0].obj;
auto obj = tm->args[1].obj;
NDO_CASTV(StringObject, str_key, key);
ASSERT(key);
self->put(key->val, obj);
},
};
static auto tm_remove = TypeMethod{
.nameid = "remove",
.descr = "remove the object from the dictinary",
.args = {
{ "key", NULL },
},
.exec = [](const TypeMethod* tm) {
auto const self = (DictObject*)tm->self;
auto str_key = tm->args[0].obj;
NDO_CASTV(StringObject, str_key, key);
ASSERT(key);
self->remove(key->val);
},
};
struct obj::ObjectType DictObject::TypeData = {
.base = NULL,
.constructor = DictObject::constructor,
.destructor = DictObject::destructor,
.copy = DictObject::copy,
.size = sizeof(DictObject),
.name = "dict",
.save_size = (object_save_size)DictObject::save_size,
.save = (object_save)DictObject::save,
.load = (object_load)DictObject::load,
.childs_retrival = (object_debug_all_childs_retrival)DictObject::childs_retrival,
.allocated_size = (object_allocated_size)DictObject::allocated_size,
.allocated_size_recursive = (object_allocated_size_recursive)DictObject::allocated_size_recursive,
.type_methods = {
.methods = {
&tm_put,
&tm_remove,
&tm_get,
}
}
};

View file

@ -0,0 +1,182 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/enumobject.h"
#include <malloc.h>
using namespace obj;
using namespace tp;
void EnumObject::constructor(EnumObject* self) {
self->active = 0;
self->nentries = 0;
self->entries = NULL;
}
void obj::EnumObject::destructor(EnumObject* self) {
if (self->entries) free(self->entries);
}
void EnumObject::copy(EnumObject* self, const EnumObject* in) {
if (self->entries) free(self->entries);
self->active = in->active;
self->nentries = in->nentries;
self->entries = (alni*)malloc(self->nentries * ENV_ALNI_SIZE_B);
tp::memCopy(self->entries, in->entries, self->nentries * ENV_ALNI_SIZE_B);
}
void obj::EnumObject::init(tp::init_list<const char*> list) {
if (entries) free(entries);
active = 0;
nentries = (uhalni) list.size();
entries = (alni*) malloc(nentries * ENV_ALNI_SIZE_B);
tp::memSetVal(entries, nentries * ENV_ALNI_SIZE_B, 0);
alni* entry = entries;
for (auto elem : list) {
alni len = tp::String::Logic::calcLength(elem);
if (len > ENV_ALNI_SIZE_B - 1) len = ENV_ALNI_SIZE_B - 1;
tp::memCopy(entry, elem, len);
for (alni* chech_entry = entries; chech_entry != entry; chech_entry++) {
DEBUG_ASSERT(tp::memCompare(chech_entry, entry, ENV_ALNI_SIZE_B) != 0);
}
entry++;
}
}
const char* obj::EnumObject::getActiveName() {
return getItemName(active);
}
const char* obj::EnumObject::getItemName(tp::uhalni idx) {
DEBUG_ASSERT(entries && idx >= 0 && idx < nentries);
return (const char*) (entries + idx);
}
void EnumObject::from_int(EnumObject* self, alni in) {
if (self->entries && in >= 0 && in < self->nentries) {
self->active = uhalni(in);
}
}
void EnumObject::from_float(EnumObject* self, alnf in) {
if (self->entries && in >= 0 && in < self->nentries) {
self->active = uhalni(in);
}
}
void EnumObject::from_string(EnumObject* self, String in) {
if (self->entries) {
alni* entry = self->entries;
for (uhalni i = 0; i < self->nentries; i++) {
if (tp::String::Logic::isEqualLogic((const char*)entry, in.read())) {
self->active = i;
}
entry += 1;
}
}
}
String EnumObject::to_string(EnumObject* self) {
if (!self->entries) {
return tp::String();
}
auto val = (const char*)(&self->entries[self->active]);
return String(val);
}
alni EnumObject::to_int(EnumObject* self) {
if (!self->entries) {
return -1;
}
return alni(self->active);
}
alnf EnumObject::to_float(EnumObject* self) {
if (!self->entries) {
return -1;
}
return alnf(self->active);
}
static alni save_size(EnumObject* self) {
if (!self->entries) {
return sizeof(uhalni);
}
return sizeof(uhalni) + sizeof(uhalni) + sizeof(alni) * self->nentries;
}
static void save(EnumObject* self, Archiver& file_self) {
if (!self->entries) {
uhalni empty_code = -1;
file_self.write<uhalni>(&empty_code);
return;
}
file_self.write<uhalni>(&self->active);
file_self.write<uhalni>(&self->nentries);
file_self.write_bytes((tp::int1*) self->entries, self->nentries * ENV_ALNI_SIZE_B);
}
static void load(Archiver& file_self, EnumObject* self) {
file_self.read<uhalni>(&self->active);
if (self->active == -1) {
self->nentries = 0;
self->entries = NULL;
return;
}
file_self.read<uhalni>(&self->nentries);
self->entries = (alni*) malloc(self->nentries * ENV_ALNI_SIZE_B);
file_self.read_bytes((tp::int1*) self->entries, self->nentries * ENV_ALNI_SIZE_B);
}
bool obj::EnumObject::compare(EnumObject* first, EnumObject* second) {
return first->entries != NULL && second->entries != NULL && first->active == second->active;
}
EnumObject* obj::EnumObject::create(tp::init_list<const char*> list) {
auto enum_object = (EnumObject*)obj::NDO->create("enum");
enum_object->init(list);
return enum_object;
}
alni allocated_size(EnumObject* self) {
alni out = sizeof(uhalni) * 2 + sizeof(tp::alni*);
if (self->entries) {
out += self->nentries * sizeof(alni) * 2;
}
return out;
}
struct ObjectTypeConversions EnumObjectTypeConversions = {
.from_int = (object_from_int) EnumObject::from_int,
.from_float = (object_from_float) EnumObject::from_float,
.from_string = (object_from_string) EnumObject::from_string,
.to_string = (object_to_string) EnumObject::to_string,
.to_int = (object_to_int) EnumObject::to_int,
.to_float = (object_to_float) EnumObject::to_float,
};
struct obj::ObjectType obj::EnumObject::TypeData = {
.base = NULL,
.constructor = (object_constructor) EnumObject::constructor,
.destructor = (object_destructor) EnumObject::destructor,
.copy = (object_copy) EnumObject::copy,
.size = sizeof(EnumObject),
.name = "enum",
.convesions = &EnumObjectTypeConversions,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
.comparison = (object_compare) EnumObject::compare,
.allocated_size = (object_allocated_size) allocated_size,
};

View file

@ -0,0 +1,102 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/floatobject.h"
using namespace obj;
using namespace tp;
void FloatObject::constructor(FloatObject* self) {
self->val = 0;
}
void FloatObject::copy(FloatObject* self, const FloatObject* in) {
self->val = in->val;
}
FloatObject* FloatObject::create(alnf in) {
NDO_CASTV(FloatObject, NDO->create("float"), out)->val = alnf(in);
return out;
}
void FloatObject::from_int(FloatObject* self, alni in) {
self->val = alnf(in);
}
void FloatObject::from_float(FloatObject* self, alnf in) {
self->val = in;
}
void FloatObject::from_string(FloatObject* self, String in) {
self->val = alnf(in);
}
String FloatObject::to_string(FloatObject* self) {
return String(self->val);
}
alni FloatObject::to_int(FloatObject* self) {
return alni(self->val);
}
alnf FloatObject::to_float(FloatObject* self) {
return self->val;
}
static alni save_size(FloatObject* self) {
return sizeof(alnf);
}
static void save(FloatObject* self, Archiver& file_self) {
file_self.write<alnf>(&self->val);
}
static void load(Archiver& file_self, FloatObject* self) {
file_self.read<alnf>(&self->val);
}
struct ObjectTypeConversions FloatObjectTypeConversions = {
.from_int = (object_from_int) FloatObject::from_int,
.from_float = (object_from_float) FloatObject::from_float,
.from_string = (object_from_string) FloatObject::from_string,
.to_string = (object_to_string) FloatObject::to_string,
.to_int = (object_to_int) FloatObject::to_int,
.to_float = (object_to_float) FloatObject::to_float,
};
static void mul(FloatObject* self, FloatObject* in) {
self->val *= in->val;
}
static void sub(FloatObject* self, FloatObject* in) {
self->val -= in->val;
}
static void add(FloatObject* self, FloatObject* in) {
self->val += in->val;
}
static void divide(FloatObject* self, FloatObject* in) {
self->val /= in->val;
}
struct ObjectTypeAriphmetics FloatObject::TypeAriphm = {
.add = (object_add)add,
.sub = (object_sub)sub,
.mul = (object_mul)mul,
.div = (object_div)divide,
};
struct obj::ObjectType obj::FloatObject::TypeData = {
.base = NULL,
.constructor = (object_constructor) FloatObject::constructor,
.destructor = NULL,
.copy = (object_copy) FloatObject::copy,
.size = sizeof(FloatObject),
.name = "float",
.convesions = &FloatObjectTypeConversions,
.ariphmetics = &FloatObject::TypeAriphm,
.save_size = (object_save_size) save_size,
.save = (object_save) save,
.load = (object_load) load,
};

View file

@ -0,0 +1,82 @@
#include "NewPlacement.hpp"
#include "primitives/interpreterobject.h"
#include "primitives/linkobject.h"
#include "primitives/methodobject.h"
using namespace obj;
using namespace tp;
void InterpreterObject::constructor(InterpreterObject* self) {
new (&self->mInterpreter) Interpreter();
self->createMember("dict", "globals");
self->createMember("link", "target method");
}
void InterpreterObject::destructor(InterpreterObject* self) {
self->mInterpreter.~Interpreter();
}
void InterpreterObject::load(Archiver& file_self, InterpreterObject* self) {
new (&self->mInterpreter) Interpreter();
}
bool InterpreterObject::running() { return !mInterpreter.finished(); }
void InterpreterObject::exec(obj::ClassObject* self, tp::init_list<Interpreter::GlobalDef> globals) {
if (running()) {
return;
}
auto link_target = getMember<obj::LinkObject>("target method");
if (!link_target) {
return;
}
auto target = link_target->getLink();
if (!target) {
return;
}
NDO_CASTV(obj::MethodObject, target, method);
if (!method || !method->mScript->mBytecode.mInstructions.size()) {
return;
}
mInterpreter.execAll(method, self, getMember<obj::DictObject>("globals"), globals);
}
void InterpreterObject::debug() {
if (running()) {
return;
}
auto link_target = getMember<obj::LinkObject>("target method");
if (!link_target) {
return;
}
auto target = link_target->getLink();
if (!target) {
return;
}
NDO_CASTV(obj::MethodObject, target, method);
if (!method || !method->mScript->mBytecode.mInstructions.size()) {
return;
}
mInterpreter.exec(method, this, getMember<obj::DictObject>("globals"));
}
struct obj::ObjectType InterpreterObject::TypeData = {
.base = &ClassObject::TypeData,
.constructor = (object_constructor)InterpreterObject::constructor,
.destructor = (object_destructor)InterpreterObject::destructor,
.size = sizeof(InterpreterObject),
.name = "interpreter",
.load = (object_load)InterpreterObject::load,
};

View file

@ -0,0 +1,104 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/intobject.h"
using namespace obj;
using namespace tp;
void IntObject::constructor(Object* self) {
NDO_CAST(IntObject, self)->val = 0;
}
void IntObject::copy(IntObject* self, const IntObject* in) {
self->val = in->val;
}
IntObject* IntObject::create(alni in) {
NDO_CASTV(IntObject, NDO->create("int"), out)->val = in;
return out;
}
void IntObject::from_int(Object* self, alni in) {
NDO_CAST(IntObject, self)->val = in;
}
void IntObject::from_float(Object* self, alnf in) {
NDO_CAST(IntObject, self)->val = (alni)in;
}
void IntObject::from_string(Object* self, String in) {
NDO_CAST(IntObject, self)->val = alni(in);
}
String IntObject::to_string(Object* self) {
return String(NDO_CAST(IntObject, self)->val);
}
alni IntObject::to_int(Object* self) {
return alni(NDO_CAST(IntObject, self)->val);
}
alnf IntObject::to_float(Object* self) {
return alnf(NDO_CAST(IntObject, self)->val);
}
static alni save_size(IntObject* self) {
return sizeof(alni);
}
static void save(IntObject* self, Archiver& file_self) {
file_self.write<alni>(&self->val);
}
static void load(Archiver& file_self, IntObject* self) {
file_self.read<alni>(&self->val);
}
struct ObjectTypeConversions IntObjectTypeConversions = {
.from_int = IntObject::from_int,
.from_float = IntObject::from_float,
.from_string = IntObject::from_string,
.to_string = IntObject::to_string,
.to_int = IntObject::to_int,
.to_float = IntObject::to_float,
};
void divide(IntObject* self, IntObject* in) {
self->val /= in->val;
}
void mul(IntObject* self, IntObject* in) {
self->val *= in->val;
}
void sub(IntObject* self, IntObject* in) {
self->val -= in->val;
}
void add(IntObject* self, IntObject* in) {
self->val += in->val;
}
struct ObjectTypeAriphmetics IntObject::TypeAriphm = {
.add = (object_add) add,
.sub = (object_sub) sub,
.mul = (object_mul) mul,
.div = (object_div) divide,
};
struct obj::ObjectType obj::IntObject::TypeData = {
.base = NULL,
.constructor = IntObject::constructor,
.destructor = NULL,
.copy = (object_copy) IntObject::copy,
.size = sizeof(IntObject),
.name = "int",
.convesions = &IntObjectTypeConversions,
.ariphmetics = &IntObject::TypeAriphm,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
};

View file

@ -0,0 +1,132 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/linkobject.h"
using namespace obj;
using namespace tp;
void LinkObject::constructor(Object* self) {
NDO_CAST(LinkObject, self)->link = 0;
}
void LinkObject::destructor(LinkObject* self) {
if (self->link) NDO->destroy(self->link);
}
void LinkObject::copy(Object* self, const Object* in) {
NDO_CAST(LinkObject, self)->setLink(NDO_CAST(LinkObject, in)->link);
}
LinkObject* LinkObject::create(Object* in) {
NDO_CASTV(LinkObject, NDO->create("link"), out)->link = in;
return out;
}
alni LinkObject::save_size(LinkObject* self) {
return sizeof(alni);
}
void LinkObject::save(LinkObject* self, Archiver& file_self) {
if (self->link != NULL) {
alni link_object_save_adress = NDO->save(file_self, self->link);
file_self.write<alni>(&link_object_save_adress);
}
else {
alni null = -1;
file_self.write<alni>(&null);
}
}
void LinkObject::load(Archiver& file_self, LinkObject* self) {
alni saved_object_adress;
file_self.read<alni>(&saved_object_adress);
if (saved_object_adress == -1) {
self->link = NULL;
}
else {
self->link = NDO->load(file_self, saved_object_adress);
}
}
tp::Buffer<Object*> LinkObject::childs_retrival(LinkObject* self) {
tp::Buffer<Object*> out;
if (self->link) out.append(self->link);
return out;
}
alni LinkObject::allocated_size(LinkObject* self) {
return sizeof(Object*);
}
alni LinkObject::allocated_size_recursive(LinkObject* self) {
alni out = sizeof(Object*);
if (self->link) {
out += NDO->objsize_ram_recursive_util(self->link, self->link->type);
}
return out;
}
Object* LinkObject::getLink() {
return link;
}
void LinkObject::setLink(Object* obj) {
#ifdef OBJECT_REF_COUNT
if (link) NDO->destroy(link);
if (obj) NDO->refinc(obj);
#endif // OBJECT_REF_COUNT
link = obj;
}
static auto tm_set = TypeMethod{
.nameid = "set",
.descr = "sets the link",
.args = {
{ "target", NULL }
},
.exec = [](const TypeMethod* tm) {
auto const self = (LinkObject*)tm->self;
auto const target = tm->args[0].obj;
self->setLink(target);
}
};
static auto tm_get = TypeMethod{
.nameid = "get",
.descr = "gets the link",
.exec = [](const TypeMethod* tm) {
auto const self = (LinkObject*)tm->self;
auto link = self->getLink();
if (link) {
tm->ret.obj = link;
}
},
.ret = { "the link", NULL }
};
struct obj::ObjectType LinkObject::TypeData = {
.base = NULL,
.constructor = LinkObject::constructor,
.destructor = (object_destructor)LinkObject::destructor,
.copy = LinkObject::copy,
.size = sizeof(LinkObject),
.name = "link",
.convesions = NULL,
.save_size = (object_save_size)LinkObject::save_size,
.save = (object_save)LinkObject::save,
.load = (object_load)LinkObject::load,
.childs_retrival = (object_debug_all_childs_retrival)LinkObject::childs_retrival,
.allocated_size = (object_allocated_size)LinkObject::allocated_size,
.allocated_size_recursive = (object_allocated_size_recursive)LinkObject::allocated_size_recursive,
.type_methods = {
.methods = {
&tm_set,
&tm_get,
}
}
};

View file

@ -0,0 +1,135 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/listobject.h"
#include "primitives/intobject.h"
using namespace obj;
using namespace tp;
void ListObject::constructor(Object* in) {
NDO_CASTV(ListObject, in, self);
new (&self->items) List<Object*>();
}
void ListObject::copy(Object* in, const Object* target) {
NDO_CASTV(ListObject, in, self);
NDO_CASTV(ListObject, target, src);
destructor(in);
for (auto item : src->items) {
self->pushBack(NDO->instatiate(item.data()));
}
}
void ListObject::destructor(Object* in) {
NDO_CASTV(ListObject, in, self);
for (auto item : self->items) {
NDO->destroy(item.data());
}
self->items.removeAll();
}
alni ListObject::save_size(ListObject* self) {
alni len = self->items.length();
return (len + 1) * sizeof(alni);
}
void ListObject::save(ListObject* self, Archiver& file_self) {
alni len = self->items.length();
file_self.write<alni>(&len);
for (auto item : self->items) {
alni ndo_object_adress = NDO->save(file_self, item.data());
file_self.write<alni>(&ndo_object_adress);
}
}
void ListObject::load(Archiver& file_self, ListObject* self) {
new (&self->items) tp::List<Object*>();
alni len;
file_self.read<alni>(&len);
for (alni i = 0; i < len; i++) {
alni ndo_object_adress;
file_self.read<alni>(&ndo_object_adress);
self->items.pushBack(NDO->load(file_self, ndo_object_adress));
}
}
tp::Buffer<Object*> ListObject::childs_retrival(ListObject* self) {
tp::Buffer<Object*> out;
out.reserve(self->items.length());
ualni i = 0;
for (auto item : self->items) {
out[i] = item.data();
i++;
}
return out;
}
alni ListObject::allocated_size(ListObject* self) {
// return self->items.sizeAllocatedMem();
return {};
}
alni ListObject::allocated_size_recursive(ListObject* self) {
alni out = self->items.sizeAllocatedMem();
for (auto item : self->items) {
out += NDO->objsize_ram_recursive_util(item.data(), item->type);
}
return out;
}
void ListObject::pushBack(Object* obj) {
#ifdef OBJECT_REF_COUNT
obj::NDO->refinc(obj);
#endif // OBJECT_REF_COUNT
items.pushBack(obj);
}
void ListObject::pushFront(Object* obj) {
#ifdef OBJECT_REF_COUNT
obj::NDO->refinc(obj);
#endif // OBJECT_REF_COUNT
items.pushFront(obj);
}
void ListObject::delNode(tp::List<Object*>::Node* node) {
#ifdef OBJECT_REF_COUNT
obj::NDO->destroy(node->data);
#endif // OBJECT_REF_COUNT
items.deleteNode(node);
}
void ListObject::popBack() {
#ifdef OBJECT_REF_COUNT
auto obj = items.last();
if (obj) obj::NDO->destroy(obj->data);
#endif // OBJECT_REF_COUNT
items.popBack();
}
const tp::List<Object*>& ListObject::getItems() const {
return items;
}
struct obj::ObjectType obj::ListObject::TypeData = {
.base = NULL,
.constructor = ListObject::constructor,
.destructor = ListObject::destructor,
.copy = ListObject::copy,
.size = sizeof(ListObject),
.name = "list",
.convesions = NULL,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
.childs_retrival = (object_debug_all_childs_retrival) childs_retrival,
.allocated_size = (object_allocated_size) allocated_size,
.allocated_size_recursive = (object_allocated_size_recursive) allocated_size_recursive
};

View file

@ -0,0 +1,78 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/methodobject.h"
#include "core/scriptsection.h"
#include "compiler/function.h"
using namespace obj;
struct ObjectType MethodObject::TypeData = {
.base = NULL,
.constructor = (object_constructor)MethodObject::constructor,
.destructor = (object_destructor)MethodObject::destructor,
.copy = (object_copy)MethodObject::copy,
.size = sizeof(MethodObject),
.name = "method",
.convesions = NULL,
.save_size = (object_save_size)MethodObject::save_size,
.save = (object_save)MethodObject::save,
.load = (object_load)MethodObject::load,
};
void MethodObject::constructor(MethodObject* self) {
self->mScript = obj::ScriptSection::globalHandle()->createScript();
}
void MethodObject::copy(MethodObject* self, MethodObject* in) {
obj::ScriptSection::globalHandle()->changeScript(&self->mScript, &in->mScript);
}
void MethodObject::destructor(MethodObject* self) {
obj::ScriptSection::globalHandle()->abandonScript(self->mScript);
}
tp::alni MethodObject::save_size(MethodObject* self) {
// script_table_file_address & script string object address
return sizeof(tp::alni);
}
void MethodObject::save(MethodObject* self, Archiver& file_self) {
auto script_section = obj::ScriptSection::globalHandle();
// script_table_file_address
tp::alni script_table_file_address = script_section->get_script_file_adress(self->mScript);
file_self.write<tp::alni>(&script_table_file_address);
}
void MethodObject::load(Archiver& file_self, obj::MethodObject* self) {
auto script_section = obj::ScriptSection::globalHandle();
// script_table_file_address
tp::alni script_table_file_address;
file_self.read<tp::alni>(&script_table_file_address);
self->mScript = script_section->get_scritp_from_file_adress(script_table_file_address);
}
void MethodObject::Initialize() {
obj::ScriptSection::initialize();
NDO->define(&MethodObject::TypeData);
obj::NDO->type_groups.addType(&MethodObject::TypeData, { "Primitives" });
}
void MethodObject::UnInitialize() {
obj::ScriptSection::uninitialize();
}
void MethodObject::compile() {
BCgen::Compile(this);
}
MethodObject* MethodObject::create(tp::String script) {
auto out = (MethodObject*)NDO->create(MethodObject::TypeData.name);
out->mScript->mReadable->val = script;
out->compile();
return out;
}

View file

@ -0,0 +1,60 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/nullobject.h"
using namespace obj;
using namespace tp;
obj::NullObject* obj::NdoNull_globalInstance = NULL;
bool uninit_flag = false;
void NullObject::uninit() {
uninit_flag = true;
NDO->destroy(NdoNull_globalInstance);
}
void NullObject::destructor(Object* self) {
DEBUG_ASSERT(uninit_flag && "Only one the instance of NullObject exists and thus it can't be destroyed");
}
String to_string(NullObject* self) {
return "NULL";
}
alni to_int(NullObject* self) {
return 0;
}
alnf to_float(NullObject* self) {
return 0;
}
obj::TypeMethods* tm_construct() {
auto out = new obj::TypeMethods();
return out;
}
struct ObjectTypeConversions NullObjectTypeConversions = {
.from_int = NULL,
.from_float = NULL,
.from_string = NULL,
.to_string = (object_to_string) to_string,
.to_int = (object_to_int) to_int,
.to_float = (object_to_float) to_float,
};
struct ObjectType NullObject::TypeData = {
.base = NULL,
.constructor = NULL,
.destructor = NullObject::destructor,
.copy = NULL,
.size = sizeof(NullObject),
.name = "null",
.convesions = &NullObjectTypeConversions,
};

View file

@ -0,0 +1,83 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/primitives.h"
#include "Tokenizer.hpp"
void obj::primitives_uninitialize() {
obj::NullObject::uninit();
obj::MethodObject::UnInitialize();
}
void obj::primitives_define_types() {
using namespace obj;
using namespace tp;
static bool initialized = false;
if (initialized) {
return;
}
DEBUG_ASSERT(NDO && "Objects library is not initialized");
NDO->define(&DictObject::TypeData);
NDO->define(&IntObject::TypeData);
NDO->define(&LinkObject::TypeData);
NDO->define(&ListObject::TypeData);
NDO->define(&NullObject::TypeData);
NDO->define(&StringObject::TypeData);
NDO->define(&BoolObject::TypeData);
NDO->define(&FloatObject::TypeData);
NDO->define(&EnumObject::TypeData);
NDO->define(&ClassObject::TypeData);
NDO->define(&ColorObject::TypeData);
NDO->define(&InterpreterObject::TypeData);
NDO->define(&TypeObject::TypeData);
NDO->type_groups.addType(&DictObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&IntObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&LinkObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&ListObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&NullObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&StringObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&BoolObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&FloatObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&EnumObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&ClassObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&ColorObject::TypeData, {"Primitives"});
NDO->type_groups.addType(&InterpreterObject::TypeData, { "scripting" });
obj::MethodObject::Initialize();
initialized = true;
}
namespace obj {
objects_api* objects_init();
void objects_finalize();
};
static bool objInit() {
obj::objects_init();
obj::primitives_define_types();
return true;
}
static void objDeinit() {
obj::primitives_uninitialize();
obj::objects_finalize();
}
static tp::ModuleManifest* sModuleDependencies[] = {
// &tp::gModuleCompressor,
&tp::gModuleMath,
&tp::gModuleStrings,
&tp::gModuleTokenizer,
NULL
};
tp::ModuleManifest obj::gModuleObjects = tp::ModuleManifest("Objects", objInit, objDeinit, sModuleDependencies);

View file

@ -0,0 +1,97 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/stringobject.h"
using namespace obj;
using namespace tp;
void StringObject::constructor(Object* self) {
new (&NDO_CAST(StringObject, self)->val) String();
}
void StringObject::destructor(StringObject* self) {
self->val.~String();
}
void StringObject::copy(Object* self, const Object* in) {
NDO_CAST(StringObject, self)->val = NDO_CAST(StringObject, in)->val;
}
StringObject* StringObject::create(String in) {
NDO_CASTV(StringObject, NDO->create("str"), out)->val = in;
return out;
}
void StringObject::from_int(StringObject* self, alni in) {
// self->val = in;
}
void StringObject::from_float(StringObject* self, alnf in) {
// self->val = in;
}
void StringObject::from_string(StringObject* self, String in) {
// self->val = in;
}
String StringObject::to_string(StringObject* self) {
return self->val;
}
alni StringObject::to_int(StringObject* self) {
return alni(self->val);
}
alnf StringObject::to_float(StringObject* self) {
return alnf(self->val);
}
static alni save_size(StringObject* self) {
// return self->val.save_size();
return {};
}
static void save(StringObject* self, Archiver& file_self) {
self->val.save(&file_self);
}
static void load(Archiver& file_self, StringObject* self) {
new (&self->val) tp::String();
self->val.load(&file_self);
}
alni allocated_size(StringObject* self) {
// return self->val.sizeAllocatedMem();
return 0;
}
static bool compare_strings(StringObject* left, StringObject* right) {
return left->val == right->val;
}
struct ObjectTypeConversions StringObjectTypeConversions = {
.from_int = (object_from_int)StringObject::from_int,
.from_float = (object_from_float)StringObject::from_float,
.from_string = (object_from_string)StringObject::from_string,
.to_string = (object_to_string)StringObject::to_string,
.to_int = (object_to_int)StringObject::to_int,
.to_float = (object_to_float)StringObject::to_float,
};
struct obj::ObjectType StringObject::TypeData = {
.base = NULL,
.constructor = StringObject::constructor,
.destructor = (object_destructor)StringObject::destructor,
.copy = StringObject::copy,
.size = sizeof(StringObject),
.name = "str",
.convesions = &StringObjectTypeConversions,
.save_size = (object_save_size)save_size,
.save = (object_save)save,
.load = (object_load)load,
.comparison = (object_compare) compare_strings,
.allocated_size = (object_allocated_size) allocated_size,
};

View file

@ -0,0 +1,80 @@
#pragma once
#include "NewPlacement.hpp"
#include "primitives/typeobject.h"
#include "primitives/nullobject.h"
using namespace obj;
using namespace tp;
TypeObject* TypeObject::create(const ObjectType* type) {
NDO_CASTV(TypeObject, NDO->create("typeobject"), out);
out->mTypeRef = type;
return out;
}
static alni save_size(TypeObject* self) {
tp::String const nameid(self->mTypeRef->name);
return nameid.save_size();
}
static void save(TypeObject* self, Archiver& file_self) {
tp::String const nameid(self->mTypeRef->name);
nameid.save(&file_self);
}
static void load(Archiver& file_self, TypeObject* self) {
tp::String nameid;
nameid.load(&file_self);
auto idx = NDO->types.presents(nameid);
if (idx) {
self->mTypeRef = NDO->types.getSlotVal(idx);
}
else {
self->mTypeRef = &NullObject::TypeData;
}
}
static alni allocated_size(TypeObject* self) {
return sizeof(alni);
}
static void from_string(TypeObject* self, tp::String in) {
auto idx = NDO->types.presents(in);
if (idx) {
self->mTypeRef = NDO->types.getSlotVal(idx);
}
else {
self->mTypeRef = &NullObject::TypeData;
}
}
static String to_string(TypeObject* self) {
return self->mTypeRef->name;
}
bool comparator(TypeObject* left, TypeObject* right) {
return left->mTypeRef == right->mTypeRef;
}
static struct ObjectTypeConversions conversions = {
.from_string = (object_from_string) from_string,
.to_string = (object_to_string) to_string,
};
struct obj::ObjectType TypeObject::TypeData = {
.base = NULL,
//.constructor = (object_constructor) TypeObject::constructor,
.size = sizeof(TypeObject),
.name = "typeobject",
.convesions = &conversions,
.save_size = (object_save_size) save_size,
.save = (object_save) save,
.load = (object_load) load,
.comparison = (object_compare) comparator,
.allocated_size = (object_allocated_size) allocated_size,
};

View file

@ -0,0 +1,42 @@
#pragma once
#include "interpreter/bytecode.h"
#include "core/object.h"
namespace obj {
namespace BCgen {
struct ConstObject {
obj::Object* mObj = NULL;
tp::alni mConstIdx = 0;
ConstObject();
ConstObject(obj::Object* mObj);
};
struct ConstObjectsPool {
tp::Map<tp::String, ConstObject*> mMethods;
tp::Map<tp::String, ConstObject*> mStrings;
tp::Map<tp::alni, ConstObject*> mIntegers;
tp::Map<tp::alnf, ConstObject*> mFloats;
ConstObject mBoolTrue;
ConstObject mBoolFalse;
bool mDelete = true;
tp::alni mTotalObjects = 0;
ConstObject* get(tp::alni val);
ConstObject* get(tp::String val);
ConstObject* get(tp::alnf val);
ConstObject* get(bool val);
ConstObject* addMethod(tp::String method_id, obj::Object* method);
ConstObject* registerObject(obj::Object* obj);
void save(tp::Buffer<ConstData>& out);
~ConstObjectsPool();
};
};
};

View file

@ -0,0 +1,126 @@
#pragma once
#include "Strings.hpp"
#include "Buffer.hpp"
#include "interpreter/opcodes.h"
namespace obj {
namespace BCgen {
struct ExpressionChild;
struct ExpressionCall;
struct Expression {
enum class Type {
NONE,
NEW,
LOCAL,
CONST,
CHILD,
CALL,
ARIPHM,
FUNC,
BOOLEAN,
SELF,
} mType = Type::NONE;
bool mValueUsed = false;
Expression();
Expression(Type type);
ExpressionChild* ExprChild(tp::String id);
ExpressionCall* ExprCall(tp::init_list<Expression*> args);
};
struct ExpressionNew : public Expression {
tp::String mNewType;
ExpressionNew(tp::String type);
};
struct ExpressionLocal : public Expression {
tp::String mLocalId;
ExpressionLocal(tp::String id);
};
struct ExpressionFunc : public Expression {
tp::String mFuncId;
ExpressionFunc(tp::String id);
};
struct ExpressionChild : public Expression {
Expression* mParent = NULL;
tp::String mLocalId;
bool mMethod = false;
ExpressionChild(Expression* mParent, tp::String id);
};
struct ExpressionCall : public Expression {
Expression* mParent = NULL;
tp::Buffer<Expression*> mArgs;
ExpressionCall(Expression* mParent, tp::init_list<Expression*> args);
};
struct ExpressionAriphm : public Expression {
Expression* mLeft = NULL;
Expression* mRight = NULL;
OpCode mOpType;
ExpressionAriphm(Expression* left, Expression* right, OpCode type);
};
struct ExpressionBoolean : public Expression {
Expression* mLeft = NULL;
Expression* mRight = NULL;
enum class BoolType : tp::uint1 {
AND = 24U,
OR,
EQUAL,
NOT_EQUAL,
MORE,
LESS,
EQUAL_OR_MORE,
EQUAL_OR_LESS,
NOT,
} mBoolType;
ExpressionBoolean(Expression* left, Expression* right, BoolType type);
ExpressionBoolean(Expression* invert);
};
struct ExpressionConst : public Expression {
enum ConstType { STR, INT, BOOL, FLT } mConstType;
tp::String str;
tp::alni integer = 0;
tp::alnf floating = 0;
bool boolean = 0;
ExpressionConst(tp::String val);
ExpressionConst(const char* val);
ExpressionConst(tp::alni val);
ExpressionConst(tp::int4 val);
ExpressionConst(tp::flt4 val);
ExpressionConst(tp::alnf val);
ExpressionConst(bool val);
};
struct ExpressionSelf : public Expression {
ExpressionSelf();
};
ExpressionLocal* ExprLocal(tp::String id);
ExpressionSelf* ExprSelf();
ExpressionFunc* ExprFunc(tp::String id);
ExpressionNew* ExprNew(tp::String id);
ExpressionAriphm* ExprAriphm(Expression* left, Expression* right, OpCode type);
ExpressionBoolean* ExprBool(Expression* left, Expression* right, OpCode type);
ExpressionBoolean* ExprBoolNot(Expression* invert);
template <typename ConstType>
ExpressionConst* ExprConst(ConstType val) {
return new ExpressionConst(val);
}
};
};

View file

@ -0,0 +1,47 @@
#pragma once
#include "Strings.hpp"
#include "List.hpp"
#include "Map.hpp"
#include "instruction.h"
#include "statement.h"
#include "constants.h"
namespace obj {
struct MethodObject;
namespace BCgen {
struct FunctionDefinition {
FunctionDefinition* mPrnt = NULL;
// signature
tp::String mFunctionId;
tp::List<ConstObject*> mArgsOrder;
ConstObjectsPool mConstants;
tp::Map<tp::String, ConstObject*> mLocals;
tp::List<Instruction> mInstructions;
FunctionDefinition(tp::String function_id, tp::Buffer<tp::String> args, FunctionDefinition* prnt);
FunctionDefinition() {}
void generateByteCode(ByteCode& out);
tp::List<Instruction>::Node* inst(Instruction inst);
void EvalExpr(Expression* expr);
void EvalStatement(Statement* expr);
ConstObject* defineLocal(tp::String id);
};
void init();
void deinit();
void Genereate(ByteCode& out, StatementScope* body);
bool Compile(MethodObject* obj);
};
};

View file

@ -0,0 +1,52 @@
#pragma once
#include "interpreter/opcodes.h"
#include "core/object.h"
#include "List.hpp"
namespace obj {
namespace BCgen {
struct ConstObject;
struct Instruction {
OpCode mOp = OpCode::NONE;
enum class ArgType {
NO_ARG,
PARAM,
CONST,
} mArgType = ArgType::NO_ARG;
enum class InstType {
NONE,
JUMP,
JUMP_IF,
JUMP_IF_NOT,
EXEC,
PURE_CONST,
} mInstType = InstType::NONE;
tp::alni mParam = 0;
tp::alni mParamBytes = 1;
ConstObject* mConstData = NULL;
ConstObject* mConstData2 = NULL;
tp::alni mInstIdx = 0;
tp::List<Instruction>::Node* mInstTarget = NULL;
Instruction();
Instruction(ConstObject* constData);
Instruction(OpCode op);
Instruction(OpCode op, ConstObject* constData);
Instruction(OpCode op, ConstObject* constData, ConstObject* constData2);
Instruction(OpCode op, tp::alni param, tp::alni nBytes);
Instruction(tp::List<Instruction>::Node* inst, InstType jump_type);
};
};
};

View file

@ -0,0 +1,116 @@
#pragma once
#include "expression.h"
namespace obj {
namespace BCgen {
struct Statement {
enum class Type {
NONE,
SCOPE,
DEF_FUNC,
DEF_LOCAL,
RET,
PRINT,
COPY,
IF,
WHILE,
IGNORE,
CALL,
CLASS_DEF,
} mType = Type::NONE;
bool mValueUsed = false;
Statement() {}
Statement(Type type);
};
struct StatementScope : public Statement {
tp::Buffer<Statement*> mStatements;
bool mPushToScopeStack = false;
StatementScope(tp::init_list<Statement*> statements, bool aPushToScopeStack);
};
struct StatementFuncDef : public Statement {
tp::Buffer<tp::String> mArgs;
tp::String mFunctionId;
tp::Buffer<Statement*> mStatements;
StatementFuncDef(tp::String function_id, tp::init_list<tp::String> args, tp::init_list<Statement*> statements);
};
struct StatementLocalDef : public Statement {
tp::String mLocalId;
Expression* mNewExpr = NULL;
ExpressionConst* mConstExpr = NULL;
bool mIsConstExpr = false;
StatementLocalDef(tp::String id, Expression* value);
StatementLocalDef(tp::String id, ExpressionConst* value);
};
struct StatementCopy : public Statement {
Expression* mLeft = NULL;
Expression* mRight = NULL;
StatementCopy(Expression* left, Expression* right);
};
struct StatementReturn : public Statement {
Expression* mRet = NULL;
StatementReturn(Expression* ret);
StatementReturn();
};
struct StatementPrint : public Statement {
Expression* mTarget = NULL;
StatementPrint(Expression* mTarget);
};
struct StatementIgnore : public Statement {
Expression* mExpr = NULL;
StatementIgnore(Expression* expr);
};
struct StatementIf : public Statement {
Expression* mCondition = NULL;
StatementScope* mOnTrue = NULL;
StatementScope* mOnFalse = NULL;
StatementIf(Expression* condition, StatementScope* on_true, StatementScope* on_false);
};
struct StatementWhile : public Statement {
Expression* mCondition = NULL;
StatementScope* mScope = NULL;
StatementWhile(Expression* condition, StatementScope* scope);
};
struct StatementClassDef : public Statement {
tp::String mClassId;
StatementScope* mScope = NULL;
StatementClassDef(tp::String class_id, StatementScope* scope);
};
// Helpers
StatementFuncDef* StmDefFunc(tp::String id, tp::init_list<tp::String> args, tp::init_list<Statement*> stms);
StatementLocalDef* StmDefLocal(tp::String id, Expression* value);
StatementCopy* StmCopy(Expression* left, Expression* right);
StatementPrint* StmPrint(Expression* target);
StatementReturn* StmReturn(Expression* obj);
StatementReturn* StmReturn();
StatementIf* StmIf(Expression* condition, StatementScope* on_true, StatementScope* on_false);
StatementScope* StmScope(tp::init_list<Statement*> statements, bool aPushToScopeStack);
StatementWhile* StmWhile(Expression* condition, StatementScope* scope);
StatementIgnore* StmIgnore(Expression* expr);
StatementClassDef* StmClassDef(tp::String id, StatementScope* scope);
};
};

View file

@ -0,0 +1,226 @@
#pragma once
#include "Common.hpp"
#include "Map.hpp"
#include "List.hpp"
#include "Buffer.hpp"
#include "Strings.hpp"
#include "LocalConnection.hpp"
#include "core/typegroups.h"
#include "core/typemethods.h"
//#include "interpreter/interpreter.h"
/* Steps to create custom Object:
define name of object
define base type
define struct members
implement construct, destruct and copy methods */
#define OBJECT_REF_COUNT
#ifdef _DEBUG
#define NDO_CAST(cast_type, ptr) ((cast_type*)ndo_cast(ptr, &cast_type::TypeData))
#define NDO_CAST_ASSERT(cast_type, ptr) {assert(ndo_cast(ptr, &cast_type::TypeData))}
#else
#define NDO_CAST_ASSERT(cast_type, ptr) {assert(ndo_cast(ptr, &cast_type::TypeData))}
#define NDO_CAST(cast_type, ptr) ((cast_type*)ndo_cast(ptr, &cast_type::TypeData))
#endif
#define NDO_CASTV(cast_type, ptr, var_name) cast_type* var_name = NDO_CAST(cast_type, ptr); var_name
#define NDO_MEMH_FROM_NDO(ndo_ptr) (((ObjectMemHead*)ndo_ptr) - 1)
#define NDO_FROM_MEMH(ndo_ptr) ((Object*)(ndo_ptr + 1))
namespace obj {
class Archiver : public tp::LocalConnection {
public:
enum Type { SAVE, LOAD };
Archiver() = default;
Archiver(const char*, Type) {};
bool opened;
tp::ualni adress{};
// not yet writen address
// always offsets on write without specific address
tp::ualni avl_adress{};
void write_bytes(const tp::int1* in, tp::alni size, tp::alni adress = -1) {}
template <typename Type>
void write(Type* in, tp::alni adress = -1) {
write_bytes((tp::int1*) in, sizeof(Type), adress);
}
void read_bytes(tp::int1* in, tp::alni size, tp::alni adress = -1) {}
template <typename Type>
void read(Type* in, tp::alni adress = -1) {
read_bytes((tp::int1*) in, sizeof(Type), adress);
}
};
extern tp::ModuleManifest gModuleObjects;
extern struct objects_api* NDO;
struct ObjectMemHead {
ObjectMemHead* up;
ObjectMemHead* down;
tp::alni flags;
#ifdef OBJECT_REF_COUNT
tp::alni refc;
#endif
};
struct Object {
const struct ObjectType* type;
};
typedef void (*object_from_int)(Object* self, tp::alni in);
typedef void (*object_from_float)(Object* self, tp::alnf in);
typedef void (*object_from_string)(Object* self, tp::String in);
typedef tp::String(*object_to_string)(Object* self);
typedef tp::alni(*object_to_int)(Object* self);
typedef tp::alnf(*object_to_float)(Object* self);
struct ObjectTypeConversions {
object_from_int from_int;
object_from_float from_float;
object_from_string from_string;
object_to_string to_string;
object_to_int to_int;
object_to_float to_float;
};
typedef void (*object_add)(Object* self, Object* operand);
typedef void (*object_sub)(Object* self, Object* operand);
typedef void (*object_mul)(Object* self, Object* operand);
typedef void (*object_div)(Object* self, Object* operand);
struct ObjectTypeAriphmetics {
object_add add;
object_sub sub;
object_mul mul;
object_div div;
};
typedef void (*object_constructor)(Object* self);
typedef void (*object_destructor)(Object* self);
typedef void (*object_copy)(Object* self, const Object* target);
typedef tp::alni(*object_save_size)(Object* self);
typedef void (*object_save)(Object*, Archiver&);
typedef void (*object_load)(Archiver&, Object*);
typedef bool (*object_compare)(Object*, Object*);
typedef tp::Buffer<Object*> (*object_debug_all_childs_retrival)(Object*);
typedef tp::alni (*object_allocated_size)(Object*); // default value = type->size - sizeof(ObjectType*)
typedef tp::alni (*object_allocated_size_recursive)(Object*); // default value = object_allocated_size
struct ObjectType {
const ObjectType* base = NULL;
object_constructor constructor = NULL;
object_destructor destructor = NULL;
object_copy copy = NULL;
tp::alni size = NULL;
const char* name;
const ObjectTypeConversions* convesions = NULL;
const ObjectTypeAriphmetics* ariphmetics = NULL;
object_save_size save_size = NULL;
object_save save = NULL;
object_load load = NULL;
object_compare comparison = NULL;
void* vtable = NULL;
const char* description = NULL;
object_debug_all_childs_retrival childs_retrival = NULL;
object_allocated_size allocated_size = NULL;
object_allocated_size_recursive allocated_size_recursive = NULL;
TypeMethods type_methods;
};
#define SAVE_LOAD_MAX_CALLBACK_SLOTS 100
typedef void (pre_save_callback)(void* self, Archiver&);
typedef void (pre_load_callback)(void* self, Archiver&);
typedef void (post_save_callback)(void* self, Archiver&);
typedef void (post_load_callback)(void* self, Archiver&);
typedef tp::alni (slcb_size_callback)(void* self, Archiver&);
struct save_load_callbacks {
void* self;
pre_save_callback* pre_save;
slcb_size_callback* size;
pre_load_callback* pre_load;
post_save_callback* post_save;
post_load_callback* post_load;
};
struct objects_api {
tp::Map<tp::String, const ObjectType*> types;
obj::TypeGroups type_groups;
Interpreter* interp = NULL;
objects_api();
~objects_api();
void define(ObjectType* type);
Object* create(const tp::String& name);
Object* copy(Object* self, const Object* in);
bool compare(Object* first, Object* second);
Object* instatiate(Object*);
void set(Object* self, tp::alni val);
void set(Object* self, tp::alnf val);
void set(Object* self, tp::String val);
tp::alni toInt(Object* self);
tp::alnf toFloat(Object* self);
bool toBool(Object* self);
tp::String toString(Object* self);
void clear_object_flags();
void destroy(Object* in);
#ifdef OBJECT_REF_COUNT
void refinc(Object* in);
tp::halni getrefc(Object* in);
private:
void setrefc(Object* in, tp::halni refc);
public:
#endif
save_load_callbacks* sl_callbacks[SAVE_LOAD_MAX_CALLBACK_SLOTS];
tp::alni sl_callbacks_load_idx = 0;
void add_sl_callbacks(save_load_callbacks*);
tp::alni objsize_file(Object* self);
tp::alni objsize_file_recursive(Object* self);
tp::alni objsize_ram(Object* self);
tp::alni objsize_ram_recursive_util(Object* self, const ObjectType* type, bool different_object = true);
tp::alni objsize_ram_recursive(Object* self);
bool save(Object*, tp::String path, bool compressed = true);
Object* load(tp::String path);
tp::alni save(Archiver&, Object*);
Object* load(Archiver&, tp::alni file_adress);
};
Object* ndo_cast(const Object* in, const ObjectType* to_type);
template <typename Type>
Type* create() {
return (Type*)obj::NDO->create(Type::TypeData.name);
}
};

View file

@ -0,0 +1,36 @@
#pragma once
#include "primitives/methodobject.h"
namespace obj {
// global singleton API for method object to manage the script
struct ScriptSection {
tp::List<Script*> mScripts;
Script* createScript();
void changeScript(Script** current_script, Script** new_script);
void abandonScript(Script* script);
tp::alni get_script_file_adress(Script* in);
Script* get_scritp_from_file_adress(tp::alni file_adress);
~ScriptSection();
static void initialize();
static void uninitialize();
static ScriptSection* globalHandle();
private:
static obj::save_load_callbacks slcb_script_section;
void delete_script(Script* script);
void reference_script(Script* script);
static void save_script_table_to_file(ScriptSection* self, Archiver& file);
static void load_script_table_from_file(ScriptSection* self, Archiver& file);
static tp::alni save_script_table_to_file_size(ScriptSection* self, Archiver& file);
};
};

View file

@ -0,0 +1,40 @@
#pragma once
#include "Map.hpp"
#include "Strings.hpp"
namespace obj {
struct ObjectType;
struct objects_api;
class TypeGroups {
public:
typedef tp::Map<tp::String, obj::TypeGroups*> Dict;
TypeGroups();
friend struct obj::objects_api;
TypeGroups(bool is_group);
void addType(ObjectType* type, tp::init_list<const char*> path, tp::alni cur_arg = 0);
void setType(ObjectType* type);
bool isGroup();
Dict* getChilds();
const obj::ObjectType* getType();
~TypeGroups();
private:
bool is_group;
union {
Dict childs;
const obj::ObjectType* type;
};
};
};

View file

@ -0,0 +1,63 @@
#pragma once
#include "Buffer.hpp"
#include "Strings.hpp"
namespace obj {
struct Interpreter;
struct Object;
struct ObjectType;
struct TypeMethod {
enum { MAX_ARGS = 8 };
struct Arg {
const char* descr = NULL;
mutable Object* obj = NULL;
};
const char* nameid = NULL;
const char* descr = NULL;
mutable Object* self = NULL;
Arg args[MAX_ARGS];
tp::int1 mNargs = NULL;
void (*exec)(const TypeMethod* tm) = NULL;
mutable Arg ret;
void operator()(Interpreter* interp) const;
void init();
};
extern TypeMethod gDefaultTypeMethods[3];
struct TypeMethods {
enum : tp::int2 { MAX_TYPE_METHODS = 128 };
TypeMethod* methods[MAX_TYPE_METHODS];
tp::halni mNMethods = NULL;
struct LookupKey {
tp::int2 key = -1;
tp::int2 type_depth = -1;
operator bool() { return key != -1; }
};
static LookupKey presents(const ObjectType*, tp::String);
static const TypeMethod* getMethod(const ObjectType*, LookupKey);
void init();
tp::halni nMethods() const;
private:
tp::int2 presents(tp::String) const;
const TypeMethod* getMethod(tp::int2) const;
};
};

View file

@ -0,0 +1,28 @@
#pragma once
#include "opcodes.h"
#include "primitives/intobject.h"
#include "primitives/stringobject.h"
#include "Buffer.hpp"
#include "Strings.hpp"
namespace obj {
typedef Object* ConstData;
struct ByteCode {
tp::Buffer<ConstData> mConstants;
tp::Buffer<OpCode> mInstructions;
tp::ualni mInstructionIdx = 0;
tp::ualni mArgumentsLoaded = 0;
~ByteCode() {
for (auto const_obj : mConstants) {
NDO->destroy(const_obj.data());
}
}
};
};

View file

@ -0,0 +1,32 @@
#pragma once
#include "core/object.h"
#include "primitives/classobject.h"
#include "Map.hpp"
namespace obj {
struct MethodObject;
};
namespace obj {
struct ByteCode;
struct CallStack {
struct CallFrame {
enum { CALL_DEPTH = 1024 };
obj::Object* mSelf = NULL;
obj::MethodObject* mMethod = NULL;
tp::ualni mIp = 0;
};
void enter(const CallFrame& frame);
void leave();
ByteCode* getBytecode();
tp::halni len() const;
tp::ConstSizeBuffer<CallFrame, CallFrame::CALL_DEPTH> mStack;
};
};

View file

@ -0,0 +1,29 @@
#pragma once
#include "operandsstack.h"
#include "scopestack.h"
#include "callstack.h"
namespace obj {
struct Interpreter {
OperandStack mOperandsStack;
ScopeStack mScopeStack;
CallStack mCallStack;
obj::Object* mLastParent = NULL;
bool mIsTypeMethod = false;
const TypeMethod* mTypeMethod = NULL;
typedef struct { obj::Object* obj; tp::String id; } GlobalDef;
void exec(obj::MethodObject* method, obj::ClassObject* self = NULL, obj::DictObject* globals = NULL, tp::init_list<GlobalDef> globals2 = {});
void stepBytecode();
void stepBytecodeIn();
void stepBytecodeOut();
bool finished();
void execAll(obj::MethodObject* method, obj::ClassObject* self = NULL, obj::DictObject* globals = NULL, tp::init_list<GlobalDef> globals2 = {});
};
};

View file

@ -0,0 +1,158 @@
#pragma once
#include "Common.hpp"
// No Nested Scopes
// Opcodes:
// Opcode input can be:
// 0) No Input
// 1) operands from OperandsStack (Operand)
// 2) Index of bytecode->ConstData from bytecode->Instruction (ConstData)
// 3) Raw Bytes from bytecode->Instruction (Param)
namespace obj {
extern struct OpcodeInfos gOpcodeInfos;
enum class OpCode : tp::uint1 {
NONE = 0x00,
HALT,
TERMINATE,
DEF_LOCAL,
// Operand : String : local_id
// Operand : Any : object to be local
LOAD_CONST,
LOAD_LOCAL,
// ConstData : idx of const object
IGNORE,
SCOPE_IN,
SCOPE_OUT,
CALL,
RETURN_OBJ,
// Operand : Base : returned object
RETURN,
CHILD,
// Operand : String : child_id
// Operand : Base : parent
// Param : 1 bytes : is method?
PUSH_ARGS,
SAVE_ARGS,
// Param : nubber of args
OBJ_CREATE_LOCAL,
// Operand : String : type
// Operand : String : id
OBJ_CREATE,
// Operand : String : type
OBJ_COPY,
// Operand : Base: target
// Operand : Base: blueprint
OBJ_SAVE,
OBJ_LOAD,
// Operand : String : path
// Operand : Base : target
OBJ_ADD,
OBJ_SUB,
OBJ_MUL,
OBJ_DIV,
AND,
OR,
EQUAL,
NOT_EQUAL,
MORE,
LESS,
EQUAL_OR_MORE,
EQUAL_OR_LESS,
// Operand : Base: left
// Operand : Base: right
NOT,
// Operand : Base: inv
JUMP,
JUMP_R,
// Param : 2 bytes : offset
JUMP_IF,
JUMP_IF_R,
JUMP_IF_NOT,
JUMP_IF_NOT_R,
// Operand : Base: condition
// Param : 2 bytes : offset
PRINT,
// Operand : Base: target
CLASS_CONSTRUCT,
SELF,
// ...
END_OPCODES
};
struct OpcodeInfos {
struct OperandsInfo {
struct Operand {
const char* obj_type = nullptr;
const char* desc = nullptr;
};
enum { MAX_OPERANDS = 5 };
Operand buff[MAX_OPERANDS];
tp::halni len = 0;
OperandsInfo();
OperandsInfo(tp::init_list<Operand> list);
};
struct ParamsInfo {
struct Param {
const char* desc = nullptr;
tp::halni bytes = 1;
};
enum { MAX_PARAMS = 5 };
Param buff[MAX_PARAMS];
tp::halni len = 0;
ParamsInfo();
ParamsInfo(tp::init_list<Param> list);
};
struct OpInfo {
const char* name = nullptr;
const char* desc = nullptr;
OperandsInfo operands;
ParamsInfo params;
tp::uint1 opsize();
};
OpcodeInfos();
OpInfo fetch(OpCode code);
private:
OpInfo buff[(tp::alni)OpCode::END_OPCODES];
void add(OpCode code, const OpInfo& info);
};
}

View file

@ -0,0 +1,39 @@
#pragma once
#include "bytecode.h"
#include "core/object.h"
namespace obj {
// can be other aligned value as well
typedef obj::Object* Operand;
class OperandStack {
enum : tp::alni {
MAX_STACK_SIZE = 512
};
public:
Operand* mBuff;
tp::ualni mIdx;
OperandStack();
void push(Operand operand);
void pop();
Operand getOperand();
template <typename ObjectType>
ObjectType* getOperand() {
auto operand = getOperand();
auto ret = NDO_CAST(ObjectType, operand);
ASSERT(ret && "Operand Has Invalid Object Type");
return ret;
}
~OperandStack();
};
};

View file

@ -0,0 +1,46 @@
#pragma once
#include "core/object.h"
#include "Map.hpp"
namespace obj {
struct Scope {
typedef tp::Map<tp::String, obj::Object*> ObjDict;
typedef tp::List<obj::Object*> ObjList;
ObjDict mLocals;
ObjList mTemps;
bool mChildReachable = true;
~Scope();
};
class ScopeStack {
enum : tp::alni {
MAX_STACK_SIZE = 1024 * 4
};
public:
Scope* mBuff;
tp::ualni mIdx;
tp::ualni mIterIdx;
ScopeStack();
void enterScope(bool aChildReachable);
void leaveScope();
void addLocal(obj::Object* local, tp::String id);
void addTemp(obj::Object* tmp);
void popTemp();
void addTempReturn(obj::Object* ret);
obj::Object* getLocal(tp::String& str);
Scope* getCurrentScope();
~ScopeStack();
private:
obj::Object* getLocalUtil(Scope& scope, tp::String* id);
};
};

View file

@ -0,0 +1,12 @@
#pragma once
#include "interpreter/bytecode.h"
namespace obj {
struct Script {
obj::StringObject* mReadable;
ByteCode mBytecode;
void compile();
};
};

View file

@ -0,0 +1,195 @@
#pragma once
#include "NewPlacement.hpp"
#include "compiler/statement.h"
#include "compiler/expression.h"
#include "Tokenizer.hpp"
namespace obj {
class Parser {
struct Token {
tp::String token;
tp::alni integer;
tp::alnf floating;
bool boolean;
tp::String str;
enum TokType : tp::alni {
__START__ = 0,
ID,
CONST_INT,
CONST_FLOAT,
CONST_STRING,
SCOPE_IN,
SCOPE_OUT,
ASSIGN,
DEF_FUNC,
PRINT,
IF,
ELSE,
WHILE,
BRACKET_IN,
BRACKET_OUT,
COMMA,
NEW,
CHILD,
RETURN,
EQUAL,
NOT_EQUAL,
MORE,
LESS,
QE_OR_MORE,
QE_OR_LESS,
BOOL_NOT,
BOOL_AND,
BOOL_OR,
ADD,
MUL,
SUB,
DIV,
QUOTES,
CONST_TRUE,
CONST_FALSE,
STM_END,
SPACE,
VAR,
CLASS_DEF,
SELF,
COMMENT_BLOCK,
__END__,
NO_TOKEN,
FAILED,
SOURCE_END_TOKEN,
} type;
operator TokType() {
return type;
}
bool isAriphm();
bool isBoolean();
};
typedef tp::SimpleTokenizer<char, Token::TokType, Token::NO_TOKEN, Token::FAILED, Token::SOURCE_END_TOKEN> Tokenizer;
Tokenizer mTok;
enum class ExprType {
BOOLEAN_NOT = 0,
BOOLEAN,
Ariphm,
NEW,
LOCAL,
CONST,
Compound
};
enum class StmType {
DefFunc = 0,
DefLocal,
Return,
Print,
If,
While,
Copy,
Call,
CLASS_DEF
};
public:
Parser();
struct Error {
tp::String mDescr = "No Description";
tp::alni mAdvanecedIdx = NULL;
Error() {}
Error(tp::String descr, tp::alni idx) {
mDescr = descr;
mAdvanecedIdx = idx;
}
tp::Pair<tp::alni, tp::alni> get_err_location(const char* stream) {
tp::alni line = 1;
tp::alni colomn = 1;
//assert(mAdvanecedIdx);
for (auto i : tp::Range(mAdvanecedIdx)) {
if (stream[i] == '\n') {
colomn = 0;
line++;
}
colomn++;
}
return { line, colomn };
}
};
struct Resault {
Error* err = NULL;
obj::BCgen::StatementScope* scope = NULL;
} mRes;
Resault parse(const tp::String& stream);
private:
Token tokRead();
Token tokLookup();
void tokSkip();
bool tokInputLeft();
Tokenizer::Cursor tokGetCursor();
void tokSetCursor(Tokenizer::Cursor);
BCgen::Expression* parseExprCompound();
BCgen::Expression* parseExprNEW();
BCgen::Expression* parseExprLOCAL();
BCgen::Expression* parseExprCONST();
BCgen::Expression* parseExprCHILD(BCgen::Expression* prnt);
BCgen::Expression* parseExprCALL(BCgen::Expression* prnt);
BCgen::Expression* parseExprAriphm();
BCgen::Expression* parseExprBOOLEAN();
BCgen::Expression* parseExprBOOLEAN_NOT();
BCgen::Expression* parseExprFUNC();
BCgen::Expression* parseExprChain(BCgen::Expression* prnt);
BCgen::Expression* parseExpr(tp::init_list<ExprType> expressions = {
ExprType::BOOLEAN_NOT,
ExprType::BOOLEAN,
ExprType::Ariphm,
ExprType::NEW,
ExprType::LOCAL,
ExprType::CONST,
});
BCgen::Statement* parseStmCall();
BCgen::Statement* parseStmDefFunc();
BCgen::Statement* parseStmDefLocal();
BCgen::Statement* parseStmReturn();
BCgen::Statement* parseStmPrint();
BCgen::Statement* parseStmIf();
BCgen::Statement* parseStmWhile();
BCgen::Statement* parseStmCopy();
BCgen::Statement* parseStmClassDef();
BCgen::Statement* parseStm(tp::init_list<StmType> stm_types = {
StmType::DefFunc,
StmType::DefLocal,
StmType::Return,
StmType::Print,
StmType::If,
StmType::While,
StmType::Copy,
StmType::Call,
StmType::CLASS_DEF
});
BCgen::StatementScope* parseScope(bool aPushToScopeStack);
};
};

View file

@ -0,0 +1,24 @@
#pragma once
#include "core/object.h"
namespace obj {
struct BoolObject : Object {
tp::alni val;
static ObjectType TypeData;
static void constructor(BoolObject* self);
static void copy(BoolObject* self, const BoolObject* in);
static BoolObject* create(bool in);
static void from_int(BoolObject* self, tp::alni in);
static void from_float(BoolObject* self, tp::alnf in);
static void from_string(BoolObject* self, tp::String in);
static tp::String to_string(BoolObject* self);
static tp::alni to_int(BoolObject* self);
static tp::alnf to_float(BoolObject* self);
};
};

View file

@ -0,0 +1,49 @@
#pragma once
#include "primitives/dictobject.h"
namespace obj {
struct ClassObject : Object {
static ObjectType TypeData;
static void copy(ClassObject* self, const ClassObject* in);
static void destructor(ClassObject* self);
static void constructor(ClassObject* self);
static tp::alni save_size(ClassObject* self);
static void save(ClassObject* self, Archiver& file_self);
static void load(Archiver& file_self, ClassObject* self);
DictObject* members;
void addMember(Object* obj, tp::String id);
void createMember(tp::String type, tp::String id);
template<typename Type>
Type* createMember(tp::String id) {
auto out = NDO->create(Type::TypeData.name);
addMember(out, id);
#ifdef OBJECT_REF_COUNT
NDO->destroy(out);
#endif // OBJECT_REF_COUNT
return (Type*) out;
}
template<typename Type>
Type* getMember(const tp::String& id) {
auto idx = members->presents(id);
if (idx) {
return ((Type*)obj::ndo_cast(members->getSlotVal(idx), &Type::TypeData));
}
return NULL;
}
template<typename Type>
Type* getMemberAssert(const tp::String& id) {
auto out = getMember<Type>(id);
assert(out && "invalid member access");
return out;
}
};
};

View file

@ -0,0 +1,24 @@
#pragma once
#include "core/object.h"
#include "Color.hpp"
namespace obj {
struct ColorObject : Object {
tp::RGBA mCol;
static ObjectType TypeData;
static ObjectTypeAriphmetics TypeAriphm;
static void constructor(Object* self);
static void copy(ColorObject* self, const ColorObject* in);
static void from_int(ColorObject* self, tp::alni in);
static void from_float(ColorObject* self, tp::alnf in);
static tp::String to_string(ColorObject* self);
static ColorObject* create(tp::RGBA in);
};
};

View file

@ -0,0 +1,31 @@
#pragma once
#include "core/object.h"
namespace obj {
struct DictObject : Object {
static ObjectType TypeData;
static void copy(Object* self, const Object* in);
static void destructor(Object* self);
static void constructor(Object* self);
static tp::alni save_size(DictObject* self);
static void save(DictObject* self, Archiver& file_self);
static void load(Archiver& file_self, DictObject* self);
static tp::Buffer<Object*> childs_retrival(DictObject* self);
static tp::alni allocated_size(DictObject* self);
static tp::alni allocated_size_recursive(DictObject* self);
void put(tp::String, Object*);
void remove(tp::String);
Object* get(tp::String);
tp::Map<tp::String, Object*>::Idx presents(tp::String);
Object* getSlotVal(tp::alni);
const tp::Map<tp::String, Object*>& getItems() const;
private:
tp::Map<tp::String, Object*> items;
};
};

View file

@ -0,0 +1,34 @@
#pragma once
#include "core/object.h"
namespace obj {
struct EnumObject : Object {
// one entry is 2 * sizeof(alni) in size
tp::uhalni active;
tp::uhalni nentries;
tp::alni* entries;
static ObjectType TypeData;
static void constructor(EnumObject* self);
static void destructor(EnumObject* self);
static void copy(EnumObject* self, const EnumObject* in);
void init(tp::init_list<const char*> list);
const char* getActiveName();
const char* getItemName(tp::uhalni idx);
static void from_int(EnumObject* self, tp::alni in);
static void from_float(EnumObject* self, tp::alnf in);
static void from_string(EnumObject* self, tp::String in);
static tp::String to_string(EnumObject* self);
static tp::alni to_int(EnumObject* self);
static tp::alnf to_float(EnumObject* self);
static bool compare(EnumObject* first, EnumObject* second);
static EnumObject* create(tp::init_list<const char*> list);
};
};

View file

@ -0,0 +1,26 @@
#pragma once
#include "core/object.h"
namespace obj {
struct FloatObject : Object {
tp::alnf val;
static ObjectType TypeData;
static ObjectTypeAriphmetics TypeAriphm;
static void constructor(FloatObject* self);
static void copy(FloatObject* self, const FloatObject* in);
static FloatObject* create(tp::alnf in);
static void from_int(FloatObject* self, tp::alni in);
static void from_float(FloatObject* self, tp::alnf in);
static void from_string(FloatObject* self, tp::String in);
static tp::String to_string(FloatObject* self);
static tp::alni to_int(FloatObject* self);
static tp::alnf to_float(FloatObject* self);
};
};

View file

@ -0,0 +1,19 @@
#pragma once
#include "interpreter/interpreter.h"
#include "primitives/classobject.h"
namespace obj {
struct InterpreterObject : ClassObject {
static ObjectType TypeData;
Interpreter mInterpreter;
static void destructor(InterpreterObject* self);
static void constructor(InterpreterObject* self);
static void load(Archiver& file_self, InterpreterObject* self);
void exec(obj::ClassObject* self = NULL, tp::init_list<Interpreter::GlobalDef> globals = {});
void debug();
bool running();
};
};

View file

@ -0,0 +1,25 @@
#pragma once
#include "core/object.h"
namespace obj {
struct IntObject : Object {
tp::alni val;
static ObjectType TypeData;
static ObjectTypeAriphmetics TypeAriphm;
static void constructor(Object* self);
static void copy(IntObject* self, const IntObject* in);
static IntObject* create(tp::alni in);
static void from_int(Object* self, tp::alni in);
static void from_float(Object* self, tp::alnf in);
static void from_string(Object* self, tp::String in);
static tp::String to_string(Object* self);
static tp::alni to_int(Object* self);
static tp::alnf to_float(Object* self);
};
};

View file

@ -0,0 +1,29 @@
#pragma once
#include "core/object.h"
namespace obj {
struct LinkObject : Object {
static ObjectType TypeData;
static void constructor(Object* self);
static void destructor(LinkObject* self);
static void copy(Object* self, const Object* in);
static LinkObject* create(Object* in);
static tp::alni save_size(LinkObject* self);
static void save(LinkObject* self, Archiver& file_self);
static void load(Archiver& file_self, LinkObject* self);
static tp::alni allocated_size(LinkObject* self);
static tp::alni allocated_size_recursive(LinkObject* self);
static tp::Buffer<Object*> childs_retrival(LinkObject* self);
Object* getLink();
void setLink(Object* obj);
private:
Object* link;
};
};

View file

@ -0,0 +1,36 @@
#pragma once
#include "core/object.h"
namespace obj {
enum ListMethods {
LISTOBJECT_PUSH_BACK,
LISTOBJECT_GET_LENGTH,
};
struct ListObject : Object {
static ObjectType TypeData;
static void constructor(Object* self);
static void copy(Object* self, const Object* in);
static void destructor(Object* self);
static tp::alni allocated_size_recursive(ListObject* self);
static tp::alni allocated_size(ListObject* self);
static tp::Buffer<Object*> childs_retrival(ListObject* self);
static void load(Archiver& file_self, ListObject* self);
static void save(ListObject* self, Archiver& file_self);
static tp::alni save_size(ListObject* self);
const tp::List<Object*>& getItems() const;
void pushBack(Object* obj);
void pushFront(Object* obj);
void popBack();
void delNode(tp::List<Object*>::Node*);
private:
tp::List<Object*> items;
};
};

View file

@ -0,0 +1,28 @@
#pragma once
#include "primitives/stringobject.h"
#include "interpreter/script.h"
namespace obj {
struct MethodObject : Object {
static ObjectType TypeData;
Script* mScript;
static void constructor(MethodObject* self);
static void copy(MethodObject* self, MethodObject* in);
static void destructor(MethodObject* self);
static tp::alni save_size(MethodObject* self);
static void save(MethodObject* self,Archiver& file_self);
static void load(Archiver& file_self, obj::MethodObject* self);
static void Initialize();
static void UnInitialize();
void compile();
static MethodObject* create(tp::String script);
};
};

View file

@ -0,0 +1,32 @@
#pragma once
#include "core/object.h"
namespace obj {
extern struct NullObject* NdoNull_globalInstance;
struct NullObject : Object {
static void destructor(Object* self);
static ObjectType TypeData;
static void uninit();
static Object* null_return() {
if (!NdoNull_globalInstance) {
NdoNull_globalInstance = (NullObject*) NDO->create("null");
obj::NDO->refinc(NdoNull_globalInstance);
}
return (Object*) NdoNull_globalInstance;
}
static Object* null_return_ref() {
obj::NDO->refinc(null_return());
return NdoNull_globalInstance;
}
};
#define NDO_NULL obj::NullObject::null_return()
#define NDO_NULL_REF obj::NullObject::null_return_ref()
};

View file

@ -0,0 +1,22 @@
#pragma once
#include "primitives/dictobject.h"
#include "primitives/intobject.h"
#include "primitives/linkobject.h"
#include "primitives/listobject.h"
#include "primitives/nullobject.h"
#include "primitives/stringobject.h"
#include "primitives/boolobject.h"
#include "primitives/floatobject.h"
#include "primitives/enumobject.h"
#include "primitives/classobject.h"
#include "primitives/colorobject.h"
#include "primitives/methodobject.h"
#include "primitives/interpreterobject.h"
#include "primitives/typeobject.h"
namespace obj {
void primitives_define_types();
void primitives_uninitialize();
};

View file

@ -0,0 +1,24 @@
#pragma once
#include "core/object.h"
namespace obj {
struct StringObject : Object {
tp::String val;
static ObjectType TypeData;
static void constructor(Object* self);
static void destructor(StringObject* self);
static void copy(Object* self, const Object* in);
static StringObject* create(tp::String in);
static void from_int(StringObject* self, tp::alni in);
static void from_float(StringObject* self, tp::alnf in);
static void from_string(StringObject* self, tp::String in);
static tp::String to_string(StringObject* self);
static tp::alni to_int(StringObject* self);
static tp::alnf to_float(StringObject* self);
};
};

View file

@ -0,0 +1,13 @@
#pragma once
#include "core/object.h"
namespace obj {
struct TypeObject : Object {
static ObjectType TypeData;
const ObjectType* mTypeRef;
static TypeObject* create(const ObjectType* type);
};
};

15
Objects/rsc/script.osc Normal file
View file

@ -0,0 +1,15 @@
class A {
var string = "hello";
def log(name) {
<< self.string;
<< name;
}
}
def main() {
var a = new A();
a.log("user");
}
main();

View file

@ -0,0 +1,90 @@
#include "MethodObject/methodobject.h"
#include "primitives/primitives.h"
#include "Interpreter/Interpreter.h"
#include "log.h"
#include "ByteCodeGen/Function.h"
using namespace osc;
using namespace tp;
using namespace obj;
void TestCompile(ByteCode& bytecode) {
using namespace BCgen;
Genereate(bytecode,
StmScope({
StmDefFunc("main", {}, {
StmDefLocal("i1", ExprConst(1)),
StmDefLocal("i2", ExprConst(2)),
StmDefFunc("add", {"first", "second"}, {
StmReturn(ExprAdd(ExprLocal("first"), ExprLocal("second")))
}),
StmPrint(ExprLocal("i1")),
StmPrint(ExprConst(" + ")),
StmPrint(ExprLocal("i2")),
StmPrint(ExprConst(" = ")),
StmPrint(ExprFunc("add")->ExprCall({ ExprLocal("i1"), ExprLocal("i2") })),
StmPrint(ExprConst("\n")),
}),
StmPrint(ExprBoolNot(ExprConst(0))),
StmWhile(ExprConst(false), StmScope({
StmIgnore(ExprFunc("main")->ExprCall({}))
})
),
StmIf(ExprConst(true),
StmScope({
//StmIgnore(ExprFunc("main")->ExprCall({})),
//StmPrint(ExprConst("true")),
}),
StmScope({
//StmPrint(ExprConst("false")),
})
)
})
);
}
int main(int argc, char* argv[]) {
tp::alloc_init();
string::Initialize();
Logger::init();
objects_init();
primitives_define_types();
MethodObject::Initialize();
{
Interpreter interp;
ByteCode bytecode;
TestCompile(bytecode);
GLog->write(" >> Exec: start \n");
auto start = get_time();
interp.exec(&bytecode);
auto end = get_time();
GLog->write(sfmt("\n >> Exec time %i ms", end - start));
}
MethodObject::UnInitialize();
objects_finalize();
primitives_uninitialize();
Logger::deinit();
string::UnInitialize();
tp::alloc_uninit();
}

75
Objects/tests/test.cpp Normal file
View file

@ -0,0 +1,75 @@
#include "primitives/primitives.h"
#include "compiler/function.h"
#include "interpreter/interpreter.h"
#include "CmdArgParser.h"
void compile(char argc, const char* argv[]) {
tp::CmdArgParser args = {
{ "script", tp::CmdArgParser::Arg::FILE_IN },
{ "out", "out.mo" }
};
if (!args.parse(argc, argv, true)) {
return;
}
auto& script_file = args.getFile("script");
auto outpath = args.getString("out");
tp::string script;
script.loadFile(&script_file);
auto method = obj::MethodObject::create(script);
obj::NDO->save(method, outpath);
}
void execute(char argc, const char* argv[]) {
tp::CmdArgParser args = {
{ "object_path", tp::CmdArgParser::Arg::STR },
{ "debug", false }
};
if (!args.parse(argc, argv, true)) {
return;
}
auto object_path = args.getString("object_path");
auto debug = args.getBool("debug");
auto obj = obj::NDO->load(object_path);
if (!obj) {
printf("Invalid Object File\n");
return;
}
NDO_CASTV(obj::MethodObject, obj, method);
if (!method) {
printf("Object Is Not A Method\n");
return;
}
obj::Interpreter interpreter;
interpreter.execAll(method);
}
int main(char argc, const char* argv[]) {
tp::ModuleManifest* ModuleDependencies[] = { &obj::gModuleObjects, NULL };
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
if (!TestModule.initialize()) {
return 1;
}
#ifdef OBC
compile(argc, argv);
#elif OBVM
execute(argc, argv);
#endif // OBC
TestModule.deinitialize();
}

14
TODO
View file

@ -2,7 +2,19 @@ Testing !
Serialization ! Serialization !
Objects: Objects:
Implement ! Serialization
Alloc Size queries
Compile !!
parser print error
write tests before refactor !!
remove obj_ref_count macro
fix all clang-tidy notices
write archiver
replace all strings with const string ref
replace all type usages with typedefs
remove tp::
rename classes
move functions around
Storage: Storage:
Finish networking Finish networking

View file

@ -111,7 +111,7 @@ namespace tp {
if (!mSource) { if (!mSource) {
return false; return false;
} }
if (mSource[mAdvancedOffset] == nullptr) { if (mSource[mAdvancedOffset] == 0) {
return false; return false;
} }
return true; return true;

View file

@ -87,6 +87,9 @@ namespace tp {
return 0; return 0;
} }
bool memEqual(const void* left, const void* right, uhalni len) {
return memCompare(left, right, len) == 0;
}
int1 memCompareVal(const void* left, uhalni len, uint1 val) { int1 memCompareVal(const void* left, uhalni len, uint1 val) {
MODULE_SANITY_CHECK(gModuleBase) MODULE_SANITY_CHECK(gModuleBase)

View file

@ -12,6 +12,7 @@ namespace tp {
void memSetVal(void* p, uhalni byteSize, uint1 val); void memSetVal(void* p, uhalni byteSize, uint1 val);
void memCopy(void* left, const void* right, uhalni len); void memCopy(void* left, const void* right, uhalni len);
int1 memCompare(const void* left, const void* right, uhalni len); int1 memCompare(const void* left, const void* right, uhalni len);
bool memEqual(const void* left, const void* right, uhalni len);
int1 memCompareVal(const void* left, uhalni len, uint1 val); int1 memCompareVal(const void* left, uhalni len, uint1 val);
} }