Quellcode durchsuchen

refactor: Code封装

SongZihuan vor 3 Jahren
Ursprung
Commit
3ff5ec949f

+ 45 - 37
include/core/code.h

@@ -5,6 +5,30 @@
 
 namespace aFuncore {
     class AFUN_CORE_EXPORT Code {
+    public:
+        class ByteCode;
+
+        inline explicit Code(aFuntool::StringFilePath file_);
+        ~Code();
+        Code &operator=(const Code &)=delete;
+
+        void display() const;
+        [[nodiscard]] std::string getMD5_v1() const;
+        bool writeByteCode(aFuntool::ConstFilePath file_path, bool debug=false) const;  // NOLINT 允许忽略返回值
+        bool readByteCode(aFuntool::ConstFilePath file_path);
+
+        [[nodiscard]] inline aFuntool::ConstFilePath getFilePath() const;
+        [[nodiscard]] inline ByteCode *getByteCode() const;
+    private:
+        ByteCode *code;
+        aFuntool::StringFilePath file;
+
+        bool write_v1(FILE *f, bool debug=false) const;
+        bool read_v1(FILE *f, bool debug=false);
+    };
+    
+    class AFUN_CORE_EXPORT Code::ByteCode {
+        friend class Code;
     public:
         typedef enum CodeType {
             code_start = 0,
@@ -18,66 +42,50 @@ namespace aFuncore {
             block_c = '{',
         } BlockType;
 
-        Code(const Code &)=delete;
-        Code &operator=(const Code &)=delete;
-
-        static Code *create(aFuntool::FileLine line, aFuntool::ConstFilePath file="");
-        static Code *create(const std::string &element,
-                            aFuntool::FileLine line, aFuntool::ConstFilePath file="", char prefix=aFuntool::NUL);
-        static Code *create(BlockType block_type, Code *son,
-                            aFuntool::FileLine line, aFuntool::ConstFilePath file="", char prefix=aFuntool::NUL);
-        static void destruct(Code *code);
+        explicit ByteCode(Code &belong, aFuntool::FileLine line);
+        ByteCode(Code &belong, const std::string &element, aFuntool::FileLine line, char prefix=aFuntool::NUL);
+        ByteCode(Code &belong, BlockType block_type, ByteCode *son, aFuntool::FileLine line, char prefix=aFuntool::NUL);
+        ~ByteCode();
+        ByteCode &operator=(const ByteCode &)=delete;
 
-        Code *connect(Code *code);
+        ByteCode *connect(ByteCode *new_code);
         void display() const;
-        void displayAll() const;
         bool write_v1(FILE *f, bool debug=false) const;
-        bool writeAll_v1(FILE *f, bool debug=false) const;
-        Code *read_v1(FILE *f, bool debug=false, int8_t read_type=code_element, bool to_son=false);
-        bool readAll_v1(FILE *f, bool debug=false);
+        ByteCode *read_v1(FILE *f, bool debug=false, int8_t read_type=code_element, bool to_son=false);
         [[nodiscard]] std::string getMD5_v1() const;
-        [[nodiscard]] std::string getMD5All_v1() const;
-        bool writeByteCode(aFuntool::ConstFilePath file_path, bool debug=false) const;  // NOLINT 允许忽略返回值
-        bool readByteCode(aFuntool::ConstFilePath file_path);
 
         [[nodiscard]] CodeType getType() const;
         [[nodiscard]] char getPrefix() const;
 
         [[nodiscard]] const char *getElement() const;
         [[nodiscard]] BlockType getBlockType() const;
-        [[nodiscard]] Code *getSon() const;
-
-        [[nodiscard]] Code *toNext() const;
-        [[nodiscard]] Code *toPrev() const;
-        [[nodiscard]] Code *toFather() const;
-
+        [[nodiscard]] ByteCode *getSon() const;
         [[nodiscard]] aFuntool::FileLine getFileLine() const;
-        [[nodiscard]] aFuntool::FilePath getFilePath() const;
+        [[nodiscard]] aFuntool::ConstFilePath getFilePath() const;
 
-    protected:
-        explicit Code(aFuntool::FileLine line, aFuntool::ConstFilePath file="");
-        Code(const std::string &element, aFuntool::FileLine line, aFuntool::ConstFilePath file="", char prefix=aFuntool::NUL);
-        Code(BlockType block_type, Code *son, aFuntool::FileLine line, aFuntool::ConstFilePath file="", char prefix=aFuntool::NUL);
-        ~Code();
+        [[nodiscard]] ByteCode *toNext() const;
+        [[nodiscard]] ByteCode *toPrev() const;
+        [[nodiscard]] ByteCode *toFather() const;
 
     private:
         CodeType type;
         char prefix=aFuntool::NUL;
 
-        union {
-            char *element = nullptr;  // union 内不使用 std::string
+        union CodeData {
+            char *element;  // union 内不使用 std::string
             struct {  // NOLINT 不需要初始化
                 BlockType block_type;
-                Code *son;
+                ByteCode *son;
             };
-        };
+            inline CodeData();
+        } data;
 
-        Code *father = nullptr;;
-        Code *next = nullptr;;
-        Code *prev = nullptr;;
+        ByteCode *father = nullptr;
+        ByteCode *next = nullptr;
+        ByteCode *prev = nullptr;
 
+        Code &belong;
         aFuntool::FileLine line;
-        aFuntool::FilePath file;
     };
 }
 

+ 24 - 22
include/core/code.inline.h

@@ -3,64 +3,66 @@
 #include "code.h"
 
 namespace aFuncore {
-    inline Code *Code::create(aFuntool::FileLine line, aFuntool::ConstFilePath file) {
-        return new Code(line, file);
+    inline Code::Code(aFuntool::StringFilePath file_) : code{new ByteCode(*this, 0)}, file{std::move(file_)} {
+
     }
 
-    inline Code *Code::create(const std::string &element,
-                    aFuntool::FileLine line, aFuntool::ConstFilePath file, char prefix) {
-        return new Code(element, line, file, prefix);
+    inline Code::ByteCode *Code::getByteCode() const{
+        return code;
     }
 
-    inline Code *Code::create(BlockType block_type, Code *son,
-                    aFuntool::FileLine line, aFuntool::ConstFilePath file, char prefix) {
-        return new Code(block_type, son, line, file);
+    inline aFuntool::ConstFilePath Code::getFilePath() const{
+        return file;
     }
 
-    inline Code::CodeType Code::getType() const {
+    inline Code::ByteCode::CodeType Code::ByteCode::getType() const {
         return type;
     }
 
-    inline char Code::getPrefix() const {
+    inline char Code::ByteCode::getPrefix() const {
         return prefix;
     }
 
-    inline const char *Code::getElement() const {
+    inline const char *Code::ByteCode::getElement() const {
         if (type != code_element)
             return "";
-        return element;
+        return data.element;
     }
 
-    inline Code::BlockType Code::getBlockType() const {
+    inline Code::ByteCode::BlockType Code::ByteCode::getBlockType() const {
         if (type != code_block)
             return block_p;
-        return block_type;
+        return data.block_type;
     }
 
-    inline Code *Code::getSon() const {
+    inline Code::ByteCode *Code::ByteCode::getSon() const {
         if (type != code_block)
             return nullptr;
-        return son;
+        return data.son;
     }
 
-    inline Code *Code::toNext() const {
+    inline Code::ByteCode *Code::ByteCode::toNext() const {
         return next;
     }
 
-    inline Code *Code::toPrev() const {
+    inline Code::ByteCode *Code::ByteCode::toPrev() const {
         return prev;
     }
 
-    inline Code *Code::toFather() const {
+    inline Code::ByteCode *Code::ByteCode::toFather() const {
         return father;
     }
 
-    inline aFuntool::FileLine Code::getFileLine() const {
+    inline aFuntool::FileLine Code::ByteCode::getFileLine() const {
         return line;
     }
 
-    inline aFuntool::FilePath Code::getFilePath() const {
-        return file;
+    inline aFuntool::ConstFilePath Code::ByteCode::getFilePath() const{
+        return belong.getFilePath();
+    }
+
+    inline Code::ByteCode::CodeData::CodeData() : element{nullptr} {
+
     }
 }
 

+ 20 - 15
include/core/core-activation.h

@@ -27,8 +27,8 @@ namespace aFuncore {
         virtual ~Activation();
         Activation &operator=(const Activation &)=delete;
 
-        virtual ActivationStatus getCode(Code *&code) = 0;
-        virtual void runCode(Code *code);
+        virtual ActivationStatus getCode(Code::ByteCode *&code) = 0;
+        virtual void runCode(Code::ByteCode *code);
         virtual inline void endRun();
 
         [[nodiscard]] inline VarList *getVarlist() const;
@@ -50,35 +50,40 @@ namespace aFuncore {
         aFuntool::StringFilePath path;
         aFuntool::FileLine line;
 
-        virtual void runCodeElement(Code *code);
-        virtual void runCodeBlockP(Code *code);
-        virtual void runCodeBlockC(Code *code);
-        virtual void runCodeBlockB(Code *code);
+        virtual void runCodeElement(Code::ByteCode *code);
+        virtual void runCodeBlockP(Code::ByteCode *code);
+        virtual void runCodeBlockC(Code::ByteCode *code);
+        virtual void runCodeBlockB(Code::ByteCode *code);
     };
 
     class AFUN_CORE_EXPORT ExeActivation : public Activation {
     public:
-        explicit inline  ExeActivation(Code *code, Inter &inter_);
-        ActivationStatus getCode(Code *&code) override;
-        [[nodiscard]] inline  Code *getStart() const;
+        inline  ExeActivation(Code &code, Inter &inter_);
+        inline  ExeActivation(Code::ByteCode *code, Inter &inter_);
+        ActivationStatus getCode(Code::ByteCode *&code) override;
+        [[nodiscard]] inline Code::ByteCode *getStart() const;
 
     private:
-        Code *start;
-        Code *next;
+        Code::ByteCode *start;
+        Code::ByteCode *next;
         bool first=true;
     };
 
     class AFUN_CORE_EXPORT TopActivation : public ExeActivation {
     public:
-        explicit TopActivation(Code *code, Inter &inter_);
+        explicit TopActivation(Code &code, Inter &inter_);
         ~TopActivation() override;
+        [[nodiscard]] inline const Code &getBase() const;
+
+    private:
+        Code &base;
     };
 
     class AFUN_CORE_EXPORT FuncActivation : public Activation {
     public:
-        explicit inline FuncActivation(Code *code, Inter &inter_);
+        explicit inline FuncActivation(Code::ByteCode *code, Inter &inter_);
         ~FuncActivation() override;
-        ActivationStatus getCode(Code *&code) override;
+        ActivationStatus getCode(Code::ByteCode *&code) override;
         void endRun() override;
 
     private:
@@ -89,7 +94,7 @@ namespace aFuncore {
         } status = func_first;
 
         bool on_tail = false;
-        Code *call;
+        Code::ByteCode *call;
 
         Function *func = nullptr;
         Function::CallFunction *call_func = nullptr;

+ 11 - 3
include/core/core-activation.inline.h

@@ -32,15 +32,23 @@ namespace aFuncore {
         return path;
     }
 
-    inline ExeActivation::ExeActivation(Code *code, Inter &inter_) : Activation(inter_), start{code}, next{code}{
+    inline ExeActivation::ExeActivation(Code &code, Inter &inter_) : Activation(inter_), start{code.getByteCode()}, next{code.getByteCode()} {
 
     }
 
-    inline Code *ExeActivation::getStart() const{
+    inline ExeActivation::ExeActivation(Code::ByteCode *code, Inter &inter_) : Activation(inter_), start{code}, next{code} {
+
+    }
+
+    inline Code::ByteCode *ExeActivation::getStart() const{
         return start;
     }
 
-    inline FuncActivation::FuncActivation(Code *code, Inter &inter_) : Activation(inter_), call{code,}{
+    const Code &TopActivation::getBase() const {
+        return base;
+    }
+
+    inline FuncActivation::FuncActivation(Code::ByteCode *code, Inter &inter_) : Activation(inter_), call{code} {
 
     }
 }

+ 1 - 1
include/core/inter.h

@@ -100,7 +100,7 @@ namespace aFuncore {
         bool pushLiteral(const std::string &pattern, const std::string &literaler, bool in_protect);
 
         bool runCode();
-        bool runCode(Code *code);
+        bool runCode(Code &code);
 
     private:
         InterStatus status;

+ 2 - 2
include/core/value.h

@@ -23,7 +23,7 @@ namespace aFuncore {
         class AFUN_CORE_EXPORT CallFunction;
 
         inline Function(const std::string &type_, Inter &inter_);
-        virtual CallFunction *getCallFunction(Code *code, Inter &inter) = 0;
+        virtual CallFunction *getCallFunction(Code::ByteCode *code, Inter &inter) = 0;
         virtual inline bool isInfix();
     };
 
@@ -41,7 +41,7 @@ namespace aFuncore {
     };
 
     struct Function::CallFunction::ArgCodeList {
-        Code *code = nullptr;
+        Code::ByteCode *code = nullptr;
         Object *ret = nullptr;
     };
 

+ 4 - 4
include/tool/byte.h

@@ -10,19 +10,19 @@ namespace aFuntool {
         big_endian
     };
 
-    extern enum EndianType endian;
-    extern enum EndianType save_as;
+    AFUN_TOOL_EXPORT extern enum EndianType endian;
+    AFUN_TOOL_EXPORT extern enum EndianType save_as;
 
     AFUN_TOOL_EXPORT void getEndian();
 
     template <typename T>
-    AFUN_TOOL_EXPORT bool byteWriteInt(FILE *file, T num);;
+    bool byteWriteInt(FILE *file, T num);;
 
     AFUN_TOOL_EXPORT bool byteWriteStr(FILE *file, const char *str);
     AFUN_TOOL_EXPORT bool byteWriteStr(FILE *file, const std::string &str);
 
     template <typename T>
-    AFUN_TOOL_EXPORT bool byteReadInt(FILE *file, T *num);
+    bool byteReadInt(FILE *file, T *num);
 
     AFUN_TOOL_EXPORT bool byteReadStr(FILE *file, std::string &str);
     AFUN_TOOL_EXPORT bool byteReadStr(FILE *file, char *&str);

+ 21 - 24
src/core/activation.cpp

@@ -40,23 +40,23 @@ namespace aFuncore {
      * 运行代码
      * @param code
      */
-    void Activation::runCode(Code *code){
+    void Activation::runCode(Code::ByteCode *code){
         auto code_type = code->getType();
-        if (code_type == Code::code_start) {  // start 不处理 msg
+        if (code_type == Code::ByteCode::code_start) {  // start 不处理 msg
             auto *none = new Object("None", inter);
             down.pushMessage(new NormalMessage(none));
         } else {
-            if (code_type == Code::code_element) {
+            if (code_type == Code::ByteCode::code_element) {
                 runCodeElement(code);
             } else
                 switch (code->getBlockType()) {
-                    case Code::block_p:  // 顺序执行
+                    case Code::ByteCode::block_p:  // 顺序执行
                         runCodeBlockP(code);
                         break;
-                    case Code::block_b:
+                    case Code::ByteCode::block_b:
                         runCodeBlockB(code);
                         break;
-                    case Code::block_c:
+                    case Code::ByteCode::block_c:
                         runCodeBlockC(code);
                         break;
                     default:
@@ -66,7 +66,7 @@ namespace aFuncore {
         }
     }
 
-    void Activation::runCodeElement(Code *code){
+    void Activation::runCodeElement(Code::ByteCode *code){
         std::string literaler_name;
         bool in_protect = false;
         Object *obj = nullptr;
@@ -96,19 +96,19 @@ namespace aFuncore {
         }
     }
 
-    void Activation::runCodeBlockP(Code *code){
+    void Activation::runCodeBlockP(Code::ByteCode *code){
         new ExeActivation(code->getSon(), inter);
     }
 
-    void Activation::runCodeBlockC(Code *code){
+    void Activation::runCodeBlockC(Code::ByteCode *code){
         new FuncActivation(code, inter);
     }
 
-    void Activation::runCodeBlockB(Code *code){
+    void Activation::runCodeBlockB(Code::ByteCode *code){
         new FuncActivation(code, inter);
     }
 
-    Activation::ActivationStatus ExeActivation::getCode(Code *&code){
+    Activation::ActivationStatus ExeActivation::getCode(Code::ByteCode *&code){
         code = next;
         if (code == nullptr)
             return as_end;
@@ -124,13 +124,12 @@ namespace aFuncore {
 
         first = false;
         line = code->getFileLine();
-        if (code->getFilePath() != nullptr)
-            path = code->getFilePath();
+        path = code->getFilePath();
         next = code->toNext();
         return as_run;
     }
 
-    TopActivation::TopActivation(Code *code, Inter &inter_) : ExeActivation(code, inter_){
+    TopActivation::TopActivation(Code &code, Inter &inter_) : ExeActivation(code, inter_), base{code} {
         varlist->connect(inter_.getGlobalVarlist());
     }
 
@@ -148,13 +147,13 @@ namespace aFuncore {
         delete call_func;
     }
 
-    Activation::ActivationStatus FuncActivation::getCode(Code *&code){
+    Activation::ActivationStatus FuncActivation::getCode(Code::ByteCode *&code) {
         if (on_tail)
             return as_end;
 
         if (status == func_first) {
             switch (call->getBlockType()) {
-                case Code::block_c:
+                case Code::ByteCode::block_c:
                     status = func_get_func;
                     code = call->getSon();
                     if (code == nullptr) {
@@ -163,17 +162,17 @@ namespace aFuncore {
                         return as_end;
                     }
                     line = code->getFileLine();
-                    if (code->getFilePath() != nullptr)
+                    if (code->getFilePath() != "")
                         path = code->getFilePath();
                     return as_run;
-                case Code::block_b: {
+                case Code::ByteCode::block_b: {
                     std::string prefix;
                     if (!inter.getEnvVarSpace().findString("sys:prefix", prefix) ||
                         prefix.size() != Inter::PREFIX_COUNT)
                         prefix = "''";
                     char quote = prefix[Inter::prefix_quote];
-                    for (Code *var = call->getSon(); var != nullptr; var = var->toNext()) {
-                        if (var->getType() != Code::code_element || var->getPrefix() == quote ||
+                    for (Code::ByteCode *var = call->getSon(); var != nullptr; var = var->toNext()) {
+                        if (var->getType() != Code::ByteCode::code_element || var->getPrefix() == quote ||
                             inter.checkLiteral(var->getElement()))
                             continue;
                         Object *obj = varlist->findObject(var->getElement());
@@ -225,8 +224,7 @@ namespace aFuncore {
             if (acl_begin != acl_end) {  // 如果有参数需要计算
                 code = acl_begin->code;
                 line = code->getFileLine();
-                if (code->getFilePath() != nullptr)
-                    path = code->getFilePath();
+                path = code->getFilePath();
                 return as_run;
             }
         }
@@ -244,8 +242,7 @@ namespace aFuncore {
             if (acl_begin != acl_end) {
                 code = acl_begin->code;
                 line = code->getFileLine();
-                if (code->getFilePath() != nullptr)
-                    path = code->getFilePath();
+                path = code->getFilePath();
                 return as_run;
             }
         }

+ 280 - 299
src/core/code.cpp

@@ -1,157 +1,42 @@
 #include "code.h"
 #include "init.h"
-namespace aFuncore {
-
-/**
- * 创建 `start` 代码块
- * @param line
- * @param file
- */
-    Code::Code(aFuntool::FileLine line, aFuntool::ConstFilePath file){  // NOLINT 不初始化 element, block_type, son
-        this->type = code_start;
-        if (file.empty()) {
-            errorLog(aFunCoreLogger, "Make `start` code without FilePath");
-            this->file = nullptr;
-        } else
-            this->file = aFuntool::strCopy(file.c_str());
-        this->line = line;
-    }
-
-/**
- * 创建 `element` 代码块
- * @param element
- * @param line
- * @param file
- * @param prefix
- */
-    Code::Code(const std::string &element, aFuntool::FileLine line, aFuntool::ConstFilePath file,
-                         char prefix){  // NOLINT 不初始化 block_type, son
-        this->type = code_element;
-        this->prefix = prefix;
-        if (file.empty())
-            this->file = nullptr;
-        else
-            this->file = aFuntool::strCopy(file.c_str());
-        this->line = line;
-
-        if (!aFuntool::isCharUTF8(element)) {
-            errorLog(aFunCoreLogger, "Element not utf-8");
-            this->element = nullptr;
-        } else
-            this->element = aFuntool::strCopy(element.c_str());
-    }
-
-/**
- * 创建 `block` 代码块
- * @param block_type
- * @param son
- * @param line
- * @param file
- * @param prefix
- */
-    Code::Code(BlockType block_type, Code *son, aFuntool::FileLine line, aFuntool::ConstFilePath file, char prefix){  // NOLINT 不出时候 element
-        this->type = code_block;
-        this->prefix = prefix;
-        if (file.empty())
-            this->file = nullptr;
-        else
-            this->file = aFuntool::strCopy(file.c_str());
-        this->line = line;
-
-        this->block_type = block_type;
-        this->son = son;
-
-        for (Code *tmp = son; tmp != nullptr; tmp = tmp->next)
-            tmp->father = this;
-    }
 
+namespace aFuncore {
     Code::~Code(){
-        if (type == code_element)
-            free(element);
-        free(file);
-    }
-
-/**
- * 连结代码块
- * @param code
- * @return
- */
-    Code *Code::connect(Code *code){
-        Code *tmp = this;
-        while (tmp->next != nullptr)
-            tmp = tmp->next;
-
-        if (code->type == code_start) {
-            errorLog(aFunCoreLogger, "Code connect with `start`");
-            return tmp;
-        }
-
-        Code *father_ = tmp->father;
-        tmp->next = code;
-        code->prev = tmp;
-        while (code->next != nullptr) {
-            code = code->next;
-            code->father = father_;
-        }
-        return code;
-    }
-
-/**
- * 删除自己以及其子、兄代码块
- */
-    void Code::destruct(Code *code){
-        if (code->type != code_start) {
-            errorLog(aFunCoreLogger, "Code delete did not with `start`");
-            return;
-        }
-
-        Code *next_tmp;
+        ByteCode *next_tmp;
         while (code != nullptr) {
-            if (code->type != code_block || code->son == nullptr) {
+            if (code->type != ByteCode::code_block || code->data.son == nullptr) {
                 if (code->next == nullptr) {
                     if (code->father == nullptr)
                         next_tmp = nullptr;
                     else {
                         next_tmp = code->father;
-                        next_tmp->son = nullptr;
+                        next_tmp->data.son = nullptr;
                     }
                 } else
                     next_tmp = code->next;
                 delete code;
                 code = next_tmp;
             } else
-                code = code->son;
+                code = code->data.son;
         }
         delete code;
     }
 
-/**
- * 显式代码块内容
- */
+    /**
+     * 显式自己以及其子、兄代码块
+     */
     void Code::display() const{
-        aFuntool::printf_stdout(0, "%c[father: %p] type=%d %p", prefix == aFuntool::NUL ? '-' : prefix, father, type, this);
-        if (type == code_element)
-            aFuntool::printf_stdout(0, " element: %s\n", element);
-        else if (type == code_block)
-            aFuntool::printf_stdout(0, " block: '%c' son: %p\n", block_type, son);
-        else
-            aFuntool::printf_stdout(0, "\n");
-    }
-
-/**
- * 显式自己以及其子、兄代码块
- */
-    void Code::displayAll() const{
-        if (this->type != code_start) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "Code dsplay all did not with `start`");
             return;
         }
 
-        const Code *tmp = this;
+        const Code::ByteCode *tmp = code;
         while (tmp != nullptr) {
             tmp->display();
-            if (tmp->type == code_block && tmp->son != nullptr) {
-                tmp = tmp->son;
+            if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
+                tmp = tmp->data.son;
                 continue;
             }
 
@@ -168,57 +53,24 @@ namespace aFuncore {
     }
 
 #define Done(write) do{if(!(write)){return false;}}while(0)
-
-/**
- * 将code写入到文件中 (版本: 1)
- * @param f
- * @param debug 是否记录 debug 信息
- * @return
- */
+    /**
+     * 将的子、兄code写入到文件中 (版本: 1)
+     * 注意: 不包括自己(`start`)
+     * @param f
+     * @param debug
+     * @return
+     */
     bool Code::write_v1(FILE *f, bool debug) const{
-        switch (type) {
-            case code_element:
-                Done(aFuntool::byteWriteInt(f, (int8_t) code_element));
-                Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
-                Done(aFuntool::byteWriteStr(f, element));
-                break;
-            case code_block:
-                if (son == nullptr)
-                    Done(aFuntool::byteWriteInt(f, (int8_t) 4));  // 空 block 标注为 4
-                else
-                    Done(aFuntool::byteWriteInt(f, (int8_t) code_block));
-                Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
-                Done(aFuntool::byteWriteInt(f, (int8_t) block_type));
-                break;
-            default:
-                break;
-
-        }
-        if (debug) {
-            Done(aFuntool::byteWriteInt(f, (int16_t) line));
-            Done(aFuntool::byteWriteStr(f, file));
-        }
-        return true;
-    }
-
-/**
- * 将的子、兄code写入到文件中 (版本: 1)
- * 注意: 不包括自己(`start`)
- * @param f
- * @param debug
- * @return
- */
-    bool Code::writeAll_v1(FILE *f, bool debug) const{
-        if (this->type != code_start) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "Code write all did not with `start`");
             return false;
         }
 
-        const Code *tmp = this;
+        const Code::ByteCode *tmp = code;
         while (tmp != nullptr) {
             Done(tmp->write_v1(f, debug));
-            if (tmp->type == code_block && tmp->son != nullptr) {
-                tmp = tmp->son;
+            if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
+                tmp = tmp->data.son;
                 continue;
             }
 
@@ -237,21 +89,21 @@ namespace aFuncore {
         return true;
     }
 
-/**
- * 读取文件中的code (版本: 1)
- * @param f
- * @param debug 文件是否包含 debug 信息
- * @return
- */
-    bool Code::readAll_v1(FILE *f, bool debug){
-        if (this->type != code_start) {
+    /**
+     * 读取文件中的code (版本: 1)
+     * @param f
+     * @param debug 文件是否包含 debug 信息
+     * @return
+     */
+    bool Code::read_v1(FILE *f, bool debug) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "Code read all did not with `start`");
             return false;
         }
 
-        Code *father_ = nullptr;
-        Code *next_ = this;
-        const Code *tmp = this;
+        Code::ByteCode *father_ = nullptr;
+        Code::ByteCode *next_ = code;
+        const Code::ByteCode *tmp = code;
         while (tmp != nullptr) {
             int8_t type_ = aFuntool::NUL;
             Done(aFuntool::byteReadInt(f, &type_));
@@ -266,7 +118,7 @@ namespace aFuncore {
                     next_ = next_->father;
                     break;
                 default: {
-                    Code *ret;
+                    Code::ByteCode *ret = nullptr;
                     if (next_ == nullptr && father_ != nullptr)
                         ret = father_->read_v1(f, debug, type_, true);
                     else if (next_ != nullptr)
@@ -279,7 +131,7 @@ namespace aFuncore {
                     if (ret == nullptr) {
                         errorLog(aFunCoreLogger, "Code read error");
                         return false;
-                    } else if (type_ == code_block) {
+                    } else if (type_ == ByteCode::code_block) {
                         next_ = nullptr;
                         father_ = ret;
                     } else {
@@ -294,104 +146,14 @@ RETURN:
         return true;
     }
 
-#undef Done
-#define Done(write) do{if(!(write)){return nullptr;}}while(0)
-
-/**
- * 读取 code 并拼接到 next 或 son 中 (版本: 1)
- * @param f
- * @param debug 文件是否包含 debug 信息
- * @param read_type 读取类型
- * @param to_son 若位true则拼接到son, 否则拼接到next
- * @return
- */
-    Code *Code::read_v1(FILE *f, bool debug, int8_t read_type, bool to_son){
-        Code *ret;
-        switch (read_type) {
-            case code_element: {
-                int8_t prefix_ = aFuntool::NUL;
-                std::string element_;
-                Done(aFuntool::byteReadInt(f, &prefix_));
-                Done(aFuntool::byteReadStr(f, element_));
-                ret = Code::create(element_, 0, "", char(prefix_));
-                break;
-            }
-            case 4:
-            case code_block: {
-                int8_t prefix_ = aFuntool::NUL;
-                int8_t block_type = aFuntool::NUL;
-                Done(aFuntool::byteReadInt(f, &prefix_));
-                Done(aFuntool::byteReadInt(f, &block_type));
-                ret = Code::create(BlockType(block_type), nullptr, 0, "", char(prefix_));
-                break;
-            }
-            default:
-                errorLog(aFunCoreLogger, "Read code with error type.");
-                return nullptr;
-        }
-
-        if (debug) {
-            int16_t line_ = aFuntool::NUL;
-            char *file_ = nullptr;
-            Done(aFuntool::byteReadInt(f, &line_));
-            Done(aFuntool::byteReadStr(f, file_));
-            ret->line = line;
-            if (strlen(file) != 0)
-                ret->file = aFuntool::strCopy(file);
-        }
-
-        if (to_son) {
-            if (type != code_block || son != nullptr) {
-                errorLog(aFunCoreLogger, "Read son with error type.");
-                delete ret;
-                return nullptr;
-            }
-            ret->father = this;
-            son = ret;
-        } else
-            connect(ret);
-        return ret;
-    }
-
 #undef Done
 
-/**
- * 计算代码的MD5值(版本:1)
- * @return md5
- */
+    /**
+     * 计算代码(子、兄)的MD5值(版本:1)
+     * @return md5
+     */
     std::string Code::getMD5_v1() const{
-        char md5str[aFuntool::MD5_STR_LEN + 1]{};
-        char md5_value[aFuntool::MD5_SIZE];
-        aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
-
-        char head[] = {(char) type, prefix, 'x', 'x', aFuntool::NUL};
-        if (prefix == aFuntool::NUL)
-            head[1] = '-';
-        if (type == code_block) {
-            head[2] = son == nullptr ? 'n' : 's';
-            head[3] = block_type;
-        }
-
-        MD5Update(md5, (unsigned char *) head, strlen((char *) head));
-        if (type == code_element)
-            MD5Update(md5, (unsigned char *) element, strlen((char *) element));
-        else if (type == code_block)
-            MD5Update(md5, (unsigned char *) "block", 5);
-        else
-            MD5Update(md5, (unsigned char *) "start", 5);
-
-        MD5Final(md5, (unsigned char *) md5_value);
-        for (int i = 0; i < aFuntool::MD5_SIZE; i++)
-            snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
-        return md5str;
-    }
-
-/**
- * 计算代码(子、兄)的MD5值(版本:1)
- * @return md5
- */
-    std::string Code::getMD5All_v1() const{
-        if (this->type != code_start) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "Code get md5 all did not with `start`");
             return "";
         }
@@ -400,13 +162,13 @@ RETURN:
         char md5_value[aFuntool::MD5_SIZE];
         aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
 
-        const Code *tmp = this;
+        const Code::ByteCode *tmp = code;
         while (tmp != nullptr) {
             std::string code_md5 = tmp->getMD5_v1();
             MD5Update(md5, (unsigned char *) code_md5.c_str(), code_md5.size());
 
-            if (tmp->type == code_block && tmp->son != nullptr) {
-                tmp = tmp->son;
+            if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
+                tmp = tmp->data.son;
                 continue;
             }
 
@@ -432,14 +194,14 @@ RETURN:
 
 #define Done(write) do{if(!(write)){goto RETURN_FALSE;}}while(0)
 
-/**
- * 生成字节码文件(版本: MaxByteCodeVersion)
- * @param file_path
- * @param debug
- * @return
- */
+    /**
+     * 生成字节码文件(版本: MaxByteCodeVersion)
+     * @param file_path
+     * @param debug
+     * @return
+     */
     bool Code::writeByteCode(aFuntool::ConstFilePath file_path, bool debug) const{
-        if (this->type != code_start) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "ByteCode write all did not with `start`");
             return false;
         }
@@ -452,9 +214,9 @@ RETURN:
 
         Done(aFuntool::byteWriteStr(f, ByteCodeHead));
         Done(aFuntool::byteWriteInt(f, int16_t(MaxByteCodeVersion)));
-        Done(aFuntool::byteWriteStr(f, getMD5All_v1()));
+        Done(aFuntool::byteWriteStr(f, getMD5_v1()));
         Done(aFuntool::byteWriteInt(f, int8_t(debug)));
-        Done(writeAll_v1(f, debug));
+        Done(write_v1(f, debug));
         aFuntool::fileClose(f);
         return true;
 
@@ -463,13 +225,13 @@ RETURN_FALSE:
         return false;
     }
 
-/**
- * 读取字节码文件(版本: 自动识别)
- * @param file_path
- * @return
- */
+    /**
+     * 读取字节码文件(版本: 自动识别)
+     * @param file_path
+     * @return
+     */
     bool Code::readByteCode(aFuntool::ConstFilePath file_path){
-        if (this->type != code_start) {
+        if (code->type != ByteCode::code_start) {
             errorLog(aFunCoreLogger, "ByteCode read all did not with `start`");
             return false;
         }
@@ -494,8 +256,8 @@ RETURN_FALSE:
                 Done(aFuntool::byteReadStr(f, md5));
                 Done(aFuntool::byteReadInt(f, &debug));
 
-                Done(readAll_v1(f, debug));
-                std::string md5_ = getMD5All_v1();
+                Done(read_v1(f, debug));
+                std::string md5_ = getMD5_v1();
                 if (md5_ != md5)
                     goto RETURN_FALSE;
                 return true;
@@ -512,4 +274,223 @@ RETURN_FALSE:
     }
 
 #undef Done
+
+    /**
+     * 创建 `start` 代码块
+     * @param line
+     * @param file
+     */
+    Code::ByteCode::ByteCode(Code &belong_, aFuntool::FileLine line) : belong{belong_} {  // NOLINT 不初始化 element, block_type, son
+        this->type = code_start;
+        this->line = line;
+    }
+
+    /**
+     * 创建 `element` 代码块
+     * @param element
+     * @param line
+     * @param file
+     * @param prefix
+     */
+    Code::ByteCode::ByteCode(Code &belong_, const std::string &element, aFuntool::FileLine line,
+                             char prefix) : belong{belong_}{  // NOLINT 不初始化 block_type, son
+        this->type = code_element;
+        this->prefix = prefix;
+        this->line = line;
+
+        if (!aFuntool::isCharUTF8(element)) {
+            errorLog(aFunCoreLogger, "Element not utf-8");
+            this->data.element = nullptr;
+        } else
+            this->data.element = aFuntool::strCopy(element.c_str());
+    }
+
+    /**
+     * 创建 `block` 代码块
+     * @param block_type
+     * @param son
+     * @param line
+     * @param file
+     * @param prefix
+     */
+    Code::ByteCode::ByteCode(Code &belong_, BlockType block_type, Code::ByteCode *son, aFuntool::FileLine line,
+                             char prefix) : belong{belong_} {  // NOLINT 不出时候 element
+        this->type = code_block;
+        this->prefix = prefix;
+        this->line = line;
+
+        this->data.block_type = block_type;
+        this->data.son = son;
+
+        for (Code::ByteCode *tmp = son; tmp != nullptr; tmp = tmp->next)
+            tmp->father = this;
+    }
+
+    Code::ByteCode::~ByteCode(){
+        if (type == code_element)
+            free(data.element);
+    }
+
+    /**
+     * 连结代码块
+     * @param new_code
+     * @return
+     */
+    Code::ByteCode *Code::ByteCode::connect(Code::ByteCode *new_code){
+        Code::ByteCode *tmp = this;
+        while (tmp->next != nullptr)
+            tmp = tmp->next;
+
+        if (new_code->type == code_start) {
+            errorLog(aFunCoreLogger, "Code connect with `start`");
+            return tmp;
+        }
+
+        if (&new_code->belong != &tmp->belong) {
+            errorLog(aFunCoreLogger, "Code connect with difference belong");
+            return tmp;
+        }
+
+        Code::ByteCode *father_ = tmp->father;
+        tmp->next = new_code;
+        new_code->prev = tmp;
+        while (new_code->next != nullptr) {
+            new_code = new_code->next;
+            new_code->father = father_;
+        }
+        return new_code;
+    }
+
+    /**
+     * 显式代码块内容
+     */
+    void Code::ByteCode::display() const{
+        aFuntool::printf_stdout(0, "%c[father: %p] type=%d %p", prefix == aFuntool::NUL ? '-' : prefix, father, type, this);
+        if (type == code_element)
+            aFuntool::printf_stdout(0, " element: %s\n", data.element);
+        else if (type == code_block)
+            aFuntool::printf_stdout(0, " block: '%c' son: %p\n", data.block_type, data.son);
+        else
+            aFuntool::printf_stdout(0, "\n");
+    }
+
+#define Done(write) do{if(!(write)){return false;}}while(0)
+
+    /**
+     * 将code写入到文件中 (版本: 1)
+     * @param f
+     * @param debug 是否记录 debug 信息
+     * @return
+     */
+    bool Code::ByteCode::write_v1(FILE *f, bool debug) const{
+        switch (type) {
+            case code_element:
+                Done(aFuntool::byteWriteInt(f, (int8_t) code_element));
+                Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
+                Done(aFuntool::byteWriteStr(f, data.element));
+                break;
+            case code_block:
+                if (data.son == nullptr)
+                    Done(aFuntool::byteWriteInt(f, (int8_t) 4));  // 空 block 标注为 4
+                else
+                    Done(aFuntool::byteWriteInt(f, (int8_t) code_block));
+                Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
+                Done(aFuntool::byteWriteInt(f, (int8_t) data.block_type));
+                break;
+            default:
+                break;
+
+        }
+        if (debug)
+            Done(aFuntool::byteWriteInt(f, (int16_t) line));
+        return true;
+    }
+
+#undef Done
+#define Done(write) do{if(!(write)){return nullptr;}}while(0)
+
+    /**
+     * 读取 code 并拼接到 next 或 son 中 (版本: 1)
+     * @param f
+     * @param debug 文件是否包含 debug 信息
+     * @param read_type 读取类型
+     * @param to_son 若位true则拼接到son, 否则拼接到next
+     * @return
+     */
+    Code::ByteCode *Code::ByteCode::read_v1(FILE *f, bool debug, int8_t read_type, bool to_son){
+        Code::ByteCode *ret;
+        switch (read_type) {
+            case code_element: {
+                int8_t prefix_ = aFuntool::NUL;
+                std::string element_;
+                Done(aFuntool::byteReadInt(f, &prefix_));
+                Done(aFuntool::byteReadStr(f, element_));
+                ret = new Code::ByteCode(belong, element_, 0, char(prefix_));
+                break;
+            }
+            case 4:
+            case code_block: {
+                int8_t prefix_ = aFuntool::NUL;
+                int8_t block_type = aFuntool::NUL;
+                Done(aFuntool::byteReadInt(f, &prefix_));
+                Done(aFuntool::byteReadInt(f, &block_type));
+                ret = new Code::ByteCode(belong, BlockType(block_type), nullptr, 0, char(prefix_));
+                break;
+            }
+            default:
+                errorLog(aFunCoreLogger, "Read code with error type.");
+                return nullptr;
+        }
+
+        if (debug) {
+            int16_t line_ = aFuntool::NUL;
+            Done(aFuntool::byteReadInt(f, &line_));
+            ret->line = line;
+        }
+
+        if (to_son) {
+            if (type != code_block || data.son != nullptr) {
+                errorLog(aFunCoreLogger, "Read son with error type.");
+                delete ret;
+                return nullptr;
+            }
+            ret->father = this;
+            data.son = ret;
+        } else
+            connect(ret);
+        return ret;
+    }
+
+#undef Done
+
+    /**
+     * 计算代码的MD5值(版本:1)
+     * @return md5
+     */
+    std::string Code::ByteCode::getMD5_v1() const{
+        char md5str[aFuntool::MD5_STR_LEN + 1]{};
+        char md5_value[aFuntool::MD5_SIZE];
+        aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
+
+        char head[] = {(char) type, prefix, 'x', 'x', aFuntool::NUL};
+        if (prefix == aFuntool::NUL)
+            head[1] = '-';
+        if (type == code_block) {
+            head[2] = data.son == nullptr ? 'n' : 's';
+            head[3] = data.block_type;
+        }
+
+        MD5Update(md5, (unsigned char *) head, strlen((char *) head));
+        if (type == code_element)
+            MD5Update(md5, (unsigned char *) data.element, strlen((char *) data.element));
+        else if (type == code_block)
+            MD5Update(md5, (unsigned char *) "block", 5);
+        else
+            MD5Update(md5, (unsigned char *) "start", 5);
+
+        MD5Final(md5, (unsigned char *) md5_value);
+        for (int i = 0; i < aFuntool::MD5_SIZE; i++)
+            snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
+        return md5str;
+    }
 }

+ 2 - 2
src/core/inter.cpp

@@ -69,7 +69,7 @@ namespace aFuncore {
      */
     bool Inter::runCode(){
         while (activation != nullptr) {
-            Code *code = nullptr;
+            Code::ByteCode *code = nullptr;
             Activation::ActivationStatus as = activation->getCode(code);
             switch (as) {
                 case Activation::as_end: {
@@ -108,7 +108,7 @@ namespace aFuncore {
      * @param code 代码
      * @return
      */
-    bool Inter::runCode(Code *code){
+    bool Inter::runCode(Code &code){
         if (activation != nullptr) {
             errorLog(aFunCoreLogger, "Run code with activation");
             return false;

+ 19 - 14
test/src/core-code.cpp

@@ -3,24 +3,29 @@ using namespace aFuncore;
 using namespace aFuntool;
 
 int main() {
-    Code *start = Code::create(1, "test.aun");
-    start->connect(Code::create("Test", 1))->connect(Code::create(Code::block_p, Code::create(Code::block_p, Code::create("Test3", 2), 2), 2));
-    start->displayAll();
-    std::string md5 = start->getMD5All_v1();
-    printf("md5: %s\n", md5.c_str());
+    {
+        Code start = Code("test.aun");
+        start.getByteCode()->connect(new Code::ByteCode(start, "Test", 1))->connect(
+                new Code::ByteCode(start, Code::ByteCode::block_p, new Code::ByteCode(start, Code::ByteCode::block_p,
+                                                                                      new Code::ByteCode(start, "Test3",
+                                                                                                         2), 2), 2));
+        start.display();
+        std::string md5 = start.getMD5_v1();
+        printf("md5: %s\n", md5.c_str());
 
-    getEndian();
+        getEndian();
 
-    start->writeByteCode("test.aun");
-    Code::destruct(start);
-    start = Code::create(1, "test.aun");
+        start.writeByteCode("test.aun");
+    }
 
-    start->readByteCode("test.aun");
+    {
+        Code start = Code("test.aun");
+        start.readByteCode("test.aun");
 
-    start->displayAll();
-    md5 = start->getMD5All_v1();
-    printf("md5: %s\n", md5.c_str());
-    Code::destruct(start);
+        start.display();
+        std::string md5 = start.getMD5_v1();
+        printf("md5: %s\n", md5.c_str());
+    }
 
     return 0;
 }

+ 44 - 50
test/src/run-code.cpp

@@ -5,12 +5,12 @@ using namespace aFuntool;
 
 class Func1 : public Function {
     class CallFunc1 : public CallFunction {
-        Code *func_code;
-        Code *code;
+        Code &func_code;
+        Code::ByteCode *code;
         Inter &inter;
         std::list<ArgCodeList> *acl;
     public:
-        CallFunc1(Code *func_code_, Code *code_, Inter &inter_) : func_code{func_code_}, code{code_}, inter{inter_} {
+        CallFunc1(Code &func_code_, Code::ByteCode *code_, Inter &inter_) : func_code{func_code_}, code{code_}, inter{inter_} {
             acl = new std::list<ArgCodeList>;
             ArgCodeList agr1 = {code_->getSon()->toNext()};
             acl->push_front(agr1);
@@ -30,18 +30,17 @@ class Func1 : public Function {
         }
     };
 
-    Code *func_code;
+    Code func_code;
 public:
-    explicit Func1(Inter &inter_) : Function("Function", inter_) {
-        func_code = (Code::create(0, "run-code.aun"));
-        func_code->connect(Code::create(Code::block_p, Code::create("test-var", 1), 0));
+    explicit Func1(Inter &inter_) : Function("Function", inter_), func_code {"run-code.aun"} {
+        func_code.getByteCode()->connect(
+                new Code::ByteCode(func_code, Code::ByteCode::block_p,
+                                   new Code::ByteCode(func_code, "test-var", 1), 0));
     }
 
-    ~Func1() override {
-        Code::destruct(func_code);
-    }
+    ~Func1() override = default;
 
-    CallFunction *getCallFunction(Code *code, Inter &inter) override {
+    CallFunction *getCallFunction(Code::ByteCode *code, Inter &inter) override {
         return dynamic_cast<CallFunction *>(new CallFunc1(func_code, code, inter));
     }
 
@@ -49,16 +48,15 @@ public:
 };
 
 class Literaler1 : public Literaler {
-    Code *func_code;
+    Code func_code;
 public:
-    explicit Literaler1(Inter &inter_) : Literaler("Data", inter_) {
-        func_code = (Code::create(0, "run-code.aun"));
-        func_code->connect(Code::create(Code::block_p, Code::create("test-var", 1), 0));
+    explicit Literaler1(Inter &inter_) : Literaler("Data", inter_), func_code{"run-code.aun"} {
+        func_code.getByteCode()->connect(
+                new Code::ByteCode(func_code, Code::ByteCode::block_p,
+                                   new Code::ByteCode(func_code, "test-var", 1), 0));
     }
 
-    ~Literaler1() override {
-        Code::destruct(func_code);
-    }
+    ~Literaler1() override = default;
 
     void getObject(const std::string &literal, char prefix, Inter &inter) override {
         printf_stdout(0, "Literaler1: %s %c\n", literal.c_str(), prefix == NUL ? '-' : prefix);
@@ -67,16 +65,15 @@ public:
 };
 
 class CBV1 : public CallBackVar {
-    Code *func_code;
+    Code func_code;
 public:
-    explicit CBV1(Inter &inter_) : CallBackVar("CBV1", inter_) {
-        func_code = (Code::create(0, "run-code.aun"));
-        func_code->connect(Code::create(Code::block_p, Code::create("test-var", 1), 0));
+    explicit CBV1(Inter &inter_) : CallBackVar("CBV1", inter_), func_code{"run-code.aun"} {
+        func_code.getByteCode()->connect(
+                new Code::ByteCode(func_code, Code::ByteCode::block_p,
+                                   new Code::ByteCode(func_code, "test-var", 1), 0));
     }
 
-    ~CBV1() override {
-        Code::destruct(func_code);
-    }
+    ~CBV1() override = default;
 
     void callBack(Inter &inter) override {
         printf_stdout(0, "CallBackVar callback\n");
@@ -107,66 +104,63 @@ int main() {
     inter.getEnvVarSpace().setNumber("sys:error_std", 1);
 
     {
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create(Code::block_p, Code::create("test-var", 1), 0));
+        auto code = Code("run-code.aun");
+        code.getByteCode()->connect(new Code::ByteCode(code, Code::ByteCode::block_p,
+                                                       new Code::ByteCode(code, "test-var", 1), 0));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
-        auto arg = Code::create("test-func", 1);
-        arg->connect(Code::create("test-var", 1));
+        auto code = Code("run-code.aun");
+
+        auto arg = new Code::ByteCode(code, "test-func", 1);
+        arg->connect(new Code::ByteCode(code, "test-var", 1));
+
+        code.getByteCode()->connect(new Code::ByteCode(code, Code::ByteCode::block_c, arg, 0));
 
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create(Code::block_c, arg, 0));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
-        auto arg = Code::create("test-var", 1);
-        arg->connect(Code::create("test-func", 1));
+        auto code = Code("run-code.aun");
+
+        auto arg = new Code::ByteCode(code, "test-var", 1);
+        arg->connect(new Code::ByteCode(code, "test-func", 1));
 
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create(Code::block_b, arg, 0));
+        code.getByteCode()->connect(new Code::ByteCode(code, Code::ByteCode::block_b, arg, 0));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
         inter.pushLiteral("data[0-9]", "test-literaler", false);
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create("data3", 1));
+        auto code = Code("run-code.aun");
+        code.getByteCode()->connect(new Code::ByteCode(code, "data3", 1));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create("test-cbv", 1));
+        auto code = Code("run-code.aun");
+        code.getByteCode()->connect(new Code::ByteCode(code, "test-cbv", 1));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create("test-not-var", 1));
+        auto code = Code("run-code.aun");
+        code.getByteCode()->connect(new Code::ByteCode(code, "test-not-var", 1));
         inter.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }
 
     {
         Inter son {inter};
-        auto code = (Code::create(0, "run-code.aun"));
-        code->connect(Code::create("test-not-var", 1));
+        auto code = Code("run-code.aun");
+        code.getByteCode()->connect(new Code::ByteCode(code, "test-not-var", 1));
         son.runCode(code);
-        Code::destruct(code);
         fputs_stdout("\n");
     }