├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── include ├── ast │ ├── expression.h │ ├── statement │ │ ├── block.h │ │ ├── expression_statement.h │ │ ├── for_statement.h │ │ ├── if_statement.h │ │ ├── jump_statement.h │ │ ├── statement.h │ │ └── var_def_statement.h │ └── value │ │ ├── character_value.h │ │ ├── float_value.h │ │ ├── signed_int_value.h │ │ ├── string_value.h │ │ ├── unsigned_int_value.h │ │ └── value.h ├── common │ └── common.h ├── parser_context.h ├── utils │ └── BinaryReader.h └── vm │ ├── builtin_functions.h │ ├── context.h │ ├── data_type_table.h │ ├── function_table.h │ ├── variable_table.h │ └── virtual_machine.h ├── src ├── CMakeLists.txt ├── apus.l ├── apus.y ├── ast │ ├── expression.cpp │ ├── statement │ │ ├── block.cpp │ │ ├── expression_statement.cpp │ │ ├── for_statement.cpp │ │ ├── if_statement.cpp │ │ ├── jump_statement.cpp │ │ └── var_def_statement.cpp │ └── value │ │ ├── character_value.cpp │ │ ├── float_value.cpp │ │ ├── signed_int_value.cpp │ │ ├── string_value.cpp │ │ ├── unsigned_int_value.cpp │ │ └── value.cpp ├── common │ └── common.cpp ├── main.cpp ├── parser_context.cpp ├── utils │ └── BinaryReader.cpp └── vm │ ├── builtin_functions.cpp │ ├── context.cpp │ ├── data_type_table.cpp │ ├── function_table.cpp │ ├── variable_table.cpp │ └── virtual_machine.cpp └── test ├── CMakeLists.txt ├── ast └── ast_test.cpp ├── example ├── factorial.cpp ├── factorial.h └── factorial_unit_test.cpp ├── gtest ├── gtest-all.cc ├── gtest.h └── gtest_main.cc ├── parser ├── array_test.cpp ├── data_decl_test.cpp └── statement_test.cpp ├── utils └── BinaryReader_unit_test.cpp └── vm ├── data_type_table_unit_test.cpp └── variable_table_unit_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 2 | 3 | *.iml 4 | 5 | ## Directory-based project format: 6 | .idea/ 7 | # if you remove the above rule, at least ignore the following: 8 | 9 | # User-specific stuff: 10 | # .idea/workspace.xml 11 | # .idea/tasks.xml 12 | # .idea/dictionaries 13 | 14 | # Sensitive or high-churn files: 15 | # .idea/dataSources.ids 16 | # .idea/dataSources.xml 17 | # .idea/sqlDataSources.xml 18 | # .idea/dynamic.xml 19 | # .idea/uiDesigner.xml 20 | 21 | # Gradle: 22 | # .idea/gradle.xml 23 | # .idea/libraries 24 | 25 | # Mongo Explorer plugin: 26 | # .idea/mongoSettings.xml 27 | 28 | ## File-based project format: 29 | *.ipr 30 | *.iws 31 | 32 | ## Plugin-specific files: 33 | 34 | # IntelliJ 35 | /out/ 36 | 37 | # mpeltonen/sbt-idea plugin 38 | .idea_modules/ 39 | 40 | # JIRA plugin 41 | atlassian-ide-plugin.xml 42 | 43 | # Crashlytics plugin (for Android Studio and IntelliJ) 44 | com_crashlytics_export_strings.xml 45 | crashlytics.properties 46 | crashlytics-build.properties 47 | 48 | # CMake generated files 49 | **CMakeFiles/ 50 | **Makefile 51 | **CMakeCache.txt 52 | **cmake_install.cmake 53 | 54 | # Lex and Yacc files 55 | /src/lex.yy.c 56 | /src/lex.yy.cc 57 | /src/y.output 58 | /src/y.tab.c 59 | /src/y.tab.h 60 | /src/y.tab.cc 61 | /src/y.tab.hh 62 | 63 | **bin/ 64 | **obj/ 65 | 66 | 67 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | sudo: true 4 | 5 | install: 6 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 7 | - sudo apt-get update -qq 8 | - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi 9 | - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi 10 | 11 | script: cmake ./ && make 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(apus) 3 | 4 | # build output settings 5 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) 6 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) 7 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 8 | 9 | # sub directories 10 | set(SRC_DIR src) 11 | set(TEST_DIR test) 12 | 13 | # lex & yacc 14 | set(LEX lex) 15 | set(YACC yacc) 16 | 17 | set(LEX_OUT lex.yy.cc) 18 | set(YACC_OUT y.tab.cc) 19 | 20 | # lex 21 | add_custom_target( 22 | lex 23 | ${LEX} -o ${LEX_OUT} ${CMAKE_SOURCE_DIR}/${SRC_DIR}/apus.l 24 | COMMENT "exec lex" 25 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SRC_DIR} 26 | ) 27 | 28 | # yacc 29 | add_custom_target( 30 | yacc 31 | ${YACC} -dv -o ${YACC_OUT} ${CMAKE_SOURCE_DIR}/${SRC_DIR}/apus.y 32 | COMMENT "exex yacc" 33 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SRC_DIR} 34 | ) 35 | 36 | # source 37 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/${SRC_DIR}") 38 | 39 | # test 40 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/${TEST_DIR}") 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/swmaestro06-apus/apus.svg?branch=master)](https://travis-ci.org/swmaestro06-apus/apus) 2 | 3 | # apus 4 | 5 | 6 | ## Build 7 | 8 | ### Linux or Mac OS X 9 | 10 | ``` 11 | $ cmake ./ 12 | $ make 13 | ``` -------------------------------------------------------------------------------- /include/ast/expression.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSION_H_ 2 | #define EXPRESSION_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace apus { 9 | 10 | class Value; 11 | class Variable; 12 | class Context; 13 | 14 | class Expression { 15 | public: 16 | 17 | enum Type { 18 | EXP_NONE, 19 | 20 | EXP_OR, // '|' 21 | EXP_AND, // '&' 22 | 23 | EXP_EQL, // '==' 24 | EXP_NEQ, // '!=' 25 | EXP_LSS, // '<' 26 | EXP_GTR, // '>' 27 | EXP_LEQ, // '<=' 28 | EXP_GEQ, // '>=' 29 | 30 | EXP_LSHIFT, // '<<' 31 | EXP_RSHIFT, // '>>' 32 | 33 | EXP_ADD, // '+' 34 | EXP_SUB, // '-' 35 | EXP_MUL, // '*' 36 | EXP_DIV, // '/' 37 | EXP_MOD, // '%' 38 | EXP_REVERSE, // '~' 39 | EXP_XOR, // '^' 40 | 41 | EXP_NOT, // '!' 42 | 43 | EXP_ASSIGN, // '=' 44 | EXP_ADDASSIGN, // '+=' 45 | EXP_SUBASSIGN, // '-=' 46 | EXP_MULASSIGN, // '*=' 47 | EXP_DIVASSIGN, // '/=' 48 | EXP_MODASSIGN, // '%=' 49 | EXP_ORASSIGN, // '|=' 50 | EXP_ANDASSIGN, // '&=' 51 | EXP_XORASSIGN, // '^=' 52 | EXP_LSASSIGN, // '<<=' 53 | EXP_RSASSIGN, // '>>=' 54 | 55 | EXP_LOR, // '||' 56 | EXP_LAND, // '&&' 57 | 58 | EXP_UNARY, 59 | EXP_VALUE, 60 | EXP_VARIABLE, 61 | EXP_FUNCTION, 62 | EXP_MEMBER, // '.' 63 | }; 64 | 65 | Expression(Type type = EXP_NONE); 66 | virtual ~Expression(); 67 | 68 | virtual Type getType() { return type_; } 69 | virtual std::shared_ptr Evaluate(Context& context) = 0; 70 | 71 | protected: 72 | Type type_; 73 | }; 74 | 75 | typedef std::shared_ptr ExprPtr; 76 | 77 | class BinaryExpression : public Expression { 78 | public: 79 | BinaryExpression(Type type, 80 | std::shared_ptr leftExpression, 81 | std::shared_ptr rightExpression); 82 | 83 | BinaryExpression(Type type, Expression* leftExpression, 84 | Expression* rightExpression); 85 | 86 | virtual ~BinaryExpression(); 87 | 88 | virtual std::shared_ptr Evaluate(Context& context) override; 89 | 90 | private: 91 | 92 | std::shared_ptr left_expression_; 93 | std::shared_ptr right_expression_; 94 | 95 | }; 96 | 97 | class UnaryExpression : public Expression { 98 | public: 99 | UnaryExpression(Type type, std::shared_ptr expression); 100 | 101 | UnaryExpression(Type type, Expression* expression); 102 | 103 | virtual ~UnaryExpression(); 104 | 105 | virtual std::shared_ptr Evaluate(Context& context); 106 | 107 | private: 108 | 109 | std::shared_ptr expression_; 110 | 111 | }; 112 | 113 | class ValueExpression : public Expression { 114 | public: 115 | ValueExpression(std::shared_ptr value); 116 | ValueExpression(Value* value); 117 | virtual ~ValueExpression(){} 118 | 119 | virtual std::shared_ptr Evaluate(Context& context); 120 | 121 | private: 122 | std::shared_ptr value_; 123 | }; 124 | 125 | class VariableExpression : public Expression { 126 | public: 127 | VariableExpression(std::string name); 128 | VariableExpression(char* name); 129 | virtual ~VariableExpression(); 130 | 131 | virtual std::shared_ptr Evaluate(Context& context); 132 | std::shared_ptr getVariable(Context& context); 133 | 134 | private: 135 | std::string name_; 136 | }; 137 | 138 | class AssignExpression : public Expression { 139 | public: 140 | AssignExpression(Type type, std::shared_ptr var_expr, 141 | std::shared_ptr expression); 142 | AssignExpression(Type type, Expression* var_expr, Expression* expression); 143 | virtual ~AssignExpression(); 144 | 145 | virtual std::shared_ptr Evaluate(Context& context); 146 | 147 | private: 148 | std::shared_ptr var_expr_; 149 | std::shared_ptr expression_; 150 | }; 151 | 152 | class MemberExpression : public Expression { 153 | public: 154 | MemberExpression(std::string parent_name, std::string child_name); 155 | MemberExpression(char* parent_name, char* child_name); 156 | virtual ~MemberExpression(); 157 | 158 | virtual std::shared_ptr Evaluate(Context& context); 159 | 160 | private: 161 | 162 | std::string parent_name_; 163 | std::string child_name_; 164 | }; 165 | 166 | class FunctionExpression : public Expression { 167 | public: 168 | FunctionExpression(std::string func_name, std::list> arg_expr); 169 | FunctionExpression(char* func_name, std::list> arg_expr); 170 | virtual ~FunctionExpression(); 171 | 172 | virtual std::shared_ptr Evaluate(Context& context); 173 | 174 | private: 175 | 176 | std::string func_name_; 177 | std::list> arg_expr_; 178 | 179 | }; 180 | 181 | } 182 | 183 | #endif 184 | -------------------------------------------------------------------------------- /include/ast/statement/block.h: -------------------------------------------------------------------------------- 1 | #ifndef BLOCK_H_ 2 | #define BLOCK_H_ 3 | 4 | #include 5 | #include 6 | #include "ast/statement/statement.h" 7 | 8 | namespace apus { 9 | 10 | class Block : public Statement { 11 | public: 12 | Block(std::list statements); 13 | Block(StmtPtr statement); 14 | virtual ~Block(); 15 | 16 | virtual Type getType() override { return STMT_BLOCK; } 17 | virtual void Execute(Context& context) override; 18 | 19 | private: 20 | 21 | std::list statements_; 22 | 23 | }; 24 | 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/ast/statement/expression_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSION_STATEMENT_H_ 2 | #define EXPRESSION_STATEMENT_H_ 3 | 4 | #include 5 | #include "ast/statement/statement.h" 6 | 7 | namespace apus { 8 | 9 | class Expression; 10 | class Context; 11 | 12 | typedef std::shared_ptr ExprPtr; 13 | 14 | class ExpressionStatement : public Statement { 15 | public: 16 | ExpressionStatement(ExprPtr expression); 17 | ExpressionStatement(Expression* expression); 18 | virtual ~ExpressionStatement(); 19 | 20 | virtual Type getType() override { return STMT_EXPR; } 21 | virtual void Execute(Context& context) override; 22 | 23 | private: 24 | 25 | ExprPtr expression_; 26 | 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/ast/statement/for_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef FOR_STATEMENT_H 2 | #define FOR_STATEMENT_H 3 | 4 | #include 5 | #include 6 | #include "ast/statement/statement.h" 7 | 8 | namespace apus { 9 | 10 | class Expression; 11 | class Block; 12 | 13 | typedef std::shared_ptr ExprPtr; 14 | 15 | class ForStatement : public Statement { 16 | public: 17 | 18 | ForStatement (ExprPtr initialization, 19 | ExprPtr termination, 20 | ExprPtr increment, 21 | StmtPtr body_statement); 22 | 23 | ForStatement (Expression* initialization, 24 | Expression* termination, 25 | Expression* increment, 26 | Statement* body); 27 | 28 | virtual ~ForStatement (); 29 | 30 | virtual Type getType() override { return STMT_FOR; } 31 | virtual void Execute(Context& context) override; 32 | 33 | private: 34 | 35 | ExprPtr initialization_; 36 | ExprPtr termination_; 37 | ExprPtr increment_; 38 | 39 | StmtPtr body_; 40 | }; 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/ast/statement/if_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef IF_STATEMENT_H_ 2 | #define IF_STATEMENT_H_ 3 | 4 | #include 5 | #include "ast/statement/statement.h" 6 | 7 | namespace apus { 8 | 9 | class Expression; 10 | class Block; 11 | 12 | typedef std::shared_ptr ExprPtr; 13 | 14 | class IfStatement : public Statement { 15 | public: 16 | IfStatement(ExprPtr condition, 17 | StmtPtr true_block, 18 | StmtPtr false_block); 19 | 20 | IfStatement(Expression* condition, 21 | Statement* true_block, 22 | Statement* false_block); 23 | 24 | virtual ~IfStatement(); 25 | 26 | virtual Type getType() override { return STMT_IF; } 27 | virtual void Execute(Context& context) override; 28 | 29 | private: 30 | ExprPtr condition_; 31 | 32 | StmtPtr true_block_; 33 | StmtPtr false_block_; 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/ast/statement/jump_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef JUMP_STATEMENT_H_ 2 | #define JUMP_STATEMENT_H_ 3 | 4 | #include 5 | #include 6 | #include "ast/statement/statement.h" 7 | 8 | namespace apus { 9 | 10 | class ForStatement; 11 | class Expression; 12 | 13 | typedef std::shared_ptr ExprPtr; 14 | 15 | class BreakStatement : public Statement { 16 | public: 17 | 18 | BreakStatement() {} 19 | virtual ~BreakStatement() {} 20 | 21 | virtual Type getType() override { return STMT_BREAK; } 22 | virtual void Execute(Context& context) override; 23 | 24 | }; 25 | 26 | class ContinueStatement : public Statement { 27 | public: 28 | 29 | ContinueStatement() {} 30 | virtual ~ContinueStatement() {} 31 | 32 | virtual Type getType() override { return STMT_CONTINUE; } 33 | virtual void Execute(Context& context) override; 34 | 35 | }; 36 | 37 | class ReturnStatement : public Statement { 38 | public: 39 | ReturnStatement(); 40 | ReturnStatement(std::shared_ptr expression); 41 | ReturnStatement(Expression* expression); 42 | 43 | virtual ~ReturnStatement() {} 44 | 45 | virtual Type getType() override { return STMT_RETURN; } 46 | virtual void Execute(Context& context) override; 47 | 48 | private: 49 | 50 | ExprPtr expression_; 51 | 52 | }; 53 | 54 | class ExitStatement : public Statement { 55 | public: 56 | ExitStatement() {} 57 | ExitStatement(std::shared_ptr expression); 58 | ExitStatement(Expression* expression); 59 | virtual ~ExitStatement() {} 60 | 61 | virtual Type getType() override { return STMT_EXIT; } 62 | virtual void Execute(Context& context) override; 63 | 64 | private: 65 | 66 | ExprPtr expression_; 67 | 68 | }; 69 | 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/ast/statement/statement.h: -------------------------------------------------------------------------------- 1 | #ifndef STATEMENT_H_ 2 | #define STATEMENT_H_ 3 | 4 | #include 5 | 6 | namespace apus { 7 | 8 | class Context; 9 | 10 | class Statement { 11 | public: 12 | 13 | enum Type { 14 | STMT_BLOCK = 0, 15 | STMT_EXPR, 16 | STMT_IF, 17 | STMT_FOR, 18 | STMT_BREAK, 19 | STMT_CONTINUE, 20 | STMT_RETURN, 21 | STMT_EXIT, 22 | STMT_VAR_DEF, 23 | }; 24 | 25 | Statement() {} 26 | virtual ~Statement() {} 27 | 28 | virtual Type getType() = 0; 29 | virtual void Execute(Context& context) = 0; 30 | 31 | private: 32 | }; 33 | 34 | typedef std::shared_ptr StmtPtr; 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/ast/statement/var_def_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef VAR_DEF_STATEMENT_H_ 2 | #define VAR_DEF_STATEMENT_H_ 3 | 4 | #include 5 | 6 | #include "common/common.h" 7 | #include "ast/statement/statement.h" 8 | 9 | namespace apus { 10 | 11 | class Context; 12 | class Expression; 13 | class DataType; 14 | 15 | typedef std::shared_ptr ExprPtr; 16 | typedef std::shared_ptr DataTypePtr; 17 | 18 | class VarDefStatement : public Statement { 19 | public: 20 | 21 | VarDefStatement(TypeSpecifier type, std::string name); 22 | VarDefStatement(TypeSpecifier type, std::string name, Expression* initializer); 23 | VarDefStatement(std::string type_name, std::string name); 24 | VarDefStatement(std::string type_name, std::string name, Expression* initializer); 25 | 26 | virtual ~VarDefStatement(); 27 | 28 | virtual Type getType() override { return STMT_VAR_DEF; } 29 | void Execute(Context& context) override; 30 | 31 | private: 32 | TypeSpecifier type_; 33 | std::string type_name_; 34 | std::string name_; 35 | ExprPtr initializer_; 36 | }; 37 | 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/ast/value/character_value.h: -------------------------------------------------------------------------------- 1 | #ifndef CHARACTER_VALUE_H_ 2 | #define CHARACTER_VALUE_H_ 3 | 4 | #include 5 | #include "value.h" 6 | #include "common/common.h" 7 | 8 | namespace apus { 9 | 10 | class CharacterValue : public Value { 11 | public: 12 | 13 | static std::shared_ptr Create(DataTypePtr data_type , int32_t value); 14 | 15 | virtual ~CharacterValue() {} 16 | 17 | virtual std::shared_ptr Copy() const { 18 | return CharacterValue::Create(data_type_, getCharValue()); 19 | } 20 | 21 | virtual std::shared_ptr Promote( 22 | const std::shared_ptr another) const override; 23 | 24 | virtual std::shared_ptr OperateBinary( 25 | const Expression::Type expression_type, 26 | const std::shared_ptr& right) const override; 27 | 28 | virtual std::shared_ptr OperateUnary( 29 | const Expression::Type expression_type) const override; 30 | 31 | int32_t getCharValue() const { 32 | return *((int32_t *)value_.get()); 33 | } 34 | 35 | protected: 36 | 37 | CharacterValue(DataTypePtr data_type, int32_t value) 38 | : Value(data_type, std::make_shared(value)) { 39 | } 40 | 41 | CharacterValue(DataTypePtr data_type, std::shared_ptr value_ptr) 42 | : Value(data_type, value_ptr) { 43 | } 44 | 45 | }; 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/ast/value/float_value.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOAT_VALUE_H_ 2 | #define FLOAT_VALUE_H_ 3 | 4 | #include 5 | #include "value.h" 6 | #include "common/common.h" 7 | 8 | namespace apus { 9 | 10 | class FloatValue : public Value { 11 | public: 12 | 13 | static std::shared_ptr Create(DataTypePtr data_type, double value); 14 | 15 | virtual ~FloatValue() {} 16 | 17 | virtual ValuePtr Copy() const { 18 | return FloatValue::Create(data_type_, getFloatValue()); 19 | } 20 | virtual ValuePtr Promote(const ValuePtr another) const override; 21 | 22 | virtual ValuePtr OperateBinary( 23 | const Expression::Type expression_type, 24 | const ValuePtr& right) const override; 25 | 26 | virtual ValuePtr OperateUnary( 27 | const Expression::Type expression_type) const override; 28 | 29 | double getFloatValue() const { 30 | return *((double *)value_.get()); 31 | } 32 | 33 | protected: 34 | 35 | double NearlyEqual(double another) const; 36 | 37 | FloatValue(DataTypePtr data_type, double value) 38 | : Value(data_type, std::make_shared(value)) { 39 | } 40 | 41 | FloatValue(DataTypePtr data_type, std::shared_ptr value_ptr) 42 | : Value(data_type, value_ptr) { 43 | } 44 | 45 | }; 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/ast/value/signed_int_value.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNED_INT_VALUE_H_ 2 | #define SIGNED_INT_VALUE_H_ 3 | 4 | #include 5 | #include "value.h" 6 | #include "common/common.h" 7 | 8 | namespace apus { 9 | 10 | class SignedIntValue : public Value { 11 | public: 12 | 13 | static std::shared_ptr Create(DataTypePtr data_type, int64_t value); 14 | 15 | virtual ~SignedIntValue() {} 16 | 17 | virtual ValuePtr Copy() const override { 18 | return SignedIntValue::Create(data_type_, getIntValue()); 19 | } 20 | 21 | virtual ValuePtr Promote(const ValuePtr another) const override; 22 | 23 | virtual ValuePtr OperateBinary( 24 | const Expression::Type expression_type, 25 | const ValuePtr& right) const override; 26 | 27 | virtual ValuePtr OperateUnary( 28 | const Expression::Type expression_type) const override; 29 | 30 | inline int64_t getIntValue() const { 31 | return *((int64_t *)value_.get()); 32 | } 33 | 34 | protected: 35 | 36 | SignedIntValue(DataTypePtr data_type, int64_t value) 37 | : Value(data_type, std::make_shared(value)) { 38 | } 39 | 40 | SignedIntValue(DataTypePtr data_type, std::shared_ptr value_ptr) 41 | : Value(data_type, value_ptr) { 42 | } 43 | 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/ast/value/string_value.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_VALUE_H_ 2 | #define STRING_VALUE_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "value.h" 8 | #include "common/common.h" 9 | 10 | namespace apus { 11 | 12 | class Value; 13 | 14 | class StringValue : public Value { 15 | public: 16 | 17 | static std::shared_ptr Create(DataTypePtr data_type, std::string value); 18 | static std::shared_ptr CreateU16(DataTypePtr data_type, std::u16string value); 19 | static std::shared_ptr CreateU32(DataTypePtr data_type, std::u32string value); 20 | 21 | virtual ~StringValue() {} 22 | 23 | virtual std::shared_ptr Copy() const { 24 | switch (data_type_->GetType()) { 25 | case STR8: 26 | return StringValue::Create(data_type_, getStringValue()); 27 | case STR16: 28 | return StringValue::CreateU16(data_type_, getU16StringValue()); 29 | case STR32: 30 | return StringValue::CreateU32(data_type_, getU32StringValue()); 31 | default: 32 | return nullptr; 33 | } 34 | } 35 | 36 | virtual std::shared_ptr Promote( 37 | const std::shared_ptr another) const override; 38 | 39 | virtual std::shared_ptr OperateBinary( 40 | const Expression::Type expression_type, 41 | const std::shared_ptr& right) const override; 42 | 43 | virtual std::shared_ptr OperateUnary( 44 | const Expression::Type expression_type) const override; 45 | 46 | std::string getStringValue() const { 47 | return *((std::string *)value_.get()); 48 | } 49 | 50 | std::u16string getU16StringValue() const { 51 | return *((std::u16string *)value_.get()); 52 | } 53 | 54 | std::u32string getU32StringValue() const { 55 | return *((std::u32string *)value_.get()); 56 | } 57 | 58 | char* getCharPtr() const { 59 | return (char *)value_.get(); 60 | } 61 | 62 | protected: 63 | 64 | StringValue(DataTypePtr data_type, std::string value) 65 | : Value(data_type, std::make_shared(value)) { 66 | 67 | } 68 | 69 | StringValue(DataTypePtr data_type, std::u16string value) 70 | : Value(data_type, std::make_shared(value)) { 71 | 72 | } 73 | 74 | StringValue(DataTypePtr data_type, std::u32string value) 75 | : Value(data_type, std::make_shared(value)) { 76 | 77 | } 78 | 79 | StringValue(DataTypePtr data_type, std::shared_ptr value_ptr) 80 | : Value(data_type, value_ptr) { 81 | } 82 | 83 | template T StringOperate(Expression::Type expression_type, T left, T right) const; 84 | 85 | std::u16string Utf8To16(std::string string) const; 86 | std::u32string Utf8To32(std::string string) const; 87 | std::u32string Utf16To32(std::u16string string) const; 88 | 89 | }; 90 | 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /include/ast/value/unsigned_int_value.h: -------------------------------------------------------------------------------- 1 | #ifndef UNSIGNED_INT_VALUE_H_ 2 | #define UNSIGNED_INT_VALUE_H_ 3 | 4 | #include 5 | #include "signed_int_value.h" 6 | 7 | namespace apus { 8 | 9 | class UnsignedIntValue : public Value { 10 | public: 11 | 12 | static std::shared_ptr Create(DataTypePtr data_type, uint64_t value); 13 | 14 | virtual ~UnsignedIntValue() {} 15 | 16 | virtual std::shared_ptr Copy() const { 17 | return UnsignedIntValue::Create(data_type_, getUIntValue()); 18 | } 19 | 20 | virtual std::shared_ptr Promote( 21 | const std::shared_ptr another) const override; 22 | 23 | virtual std::shared_ptr OperateBinary( 24 | const Expression::Type expression_type, 25 | const std::shared_ptr& right) const override; 26 | 27 | virtual std::shared_ptr OperateUnary( 28 | const Expression::Type expression_type) const override; 29 | 30 | uint64_t getUIntValue() const { 31 | return *((uint64_t*)value_.get()); 32 | } 33 | 34 | protected: 35 | 36 | UnsignedIntValue(DataTypePtr data_type, uint64_t value) 37 | : UnsignedIntValue(data_type, std::make_shared(value)) {} 38 | 39 | UnsignedIntValue(DataTypePtr data_type, std::shared_ptr value_ptr) 40 | : Value(data_type, value_ptr) { 41 | } 42 | 43 | }; 44 | 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/ast/value/value.h: -------------------------------------------------------------------------------- 1 | #ifndef VALUE_H_ 2 | #define VALUE_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "ast/expression.h" 8 | #include "common/common.h" 9 | 10 | #include "vm/data_type_table.h" 11 | 12 | namespace apus { 13 | 14 | class Value; 15 | typedef std::shared_ptr ValuePtr; 16 | class DataType; 17 | typedef std::shared_ptr DataTypePtr; 18 | 19 | class Value { 20 | public: 21 | 22 | virtual ~Value(){} 23 | 24 | virtual TypeSpecifier getType() const { return data_type_->GetType(); } 25 | 26 | virtual std::shared_ptr getValue() const { return value_; } 27 | 28 | int getSize() const { return TypeLength(getType()); } 29 | 30 | DataTypePtr getDataType() { return data_type_; } 31 | 32 | // Deep Copy function 33 | inline virtual ValuePtr Copy() const { return nullptr; } 34 | 35 | virtual ValuePtr Promote( 36 | const ValuePtr another) const = 0; 37 | 38 | virtual ValuePtr OperateBinary( 39 | const Expression::Type expression_type, 40 | const ValuePtr& right) const = 0; 41 | 42 | virtual ValuePtr OperateUnary( 43 | const Expression::Type expression_type) const = 0; 44 | 45 | static bool IsTrue(std::shared_ptr value); 46 | 47 | protected: 48 | 49 | Value(DataTypePtr data_type, std::shared_ptr value) 50 | : data_type_(data_type), value_(value) {} 51 | 52 | DataTypePtr data_type_; 53 | std::shared_ptr value_; 54 | 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/common/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace apus { 10 | 11 | #define ERROR_MSG true 12 | 13 | typedef char byte; 14 | 15 | typedef enum { 16 | NOT_SET, 17 | LITTLE = 0x04030201ul, 18 | BIG = 0x01020304ul, 19 | } Endian; 20 | 21 | typedef enum { 22 | U8, U16, U32, U64, // Unsigned Integer 23 | S8, S16, S32, S64, // Signed Integer 24 | F32, F64, // Floating Point Real Number 25 | C8, C16, C32, // Character Type 26 | STR8, STR16, STR32, // String Type 27 | STRUCT, UNION, // Struct and Union 28 | ARRAY, // Array 29 | STRUCT_ARRAY, // Struct Array 30 | USER_DEFINED, // User-defined type 31 | NOT_DEFINED, // Not-defined type 32 | } TypeSpecifier; 33 | 34 | const std::string type_to_string[NOT_DEFINED+1] = { 35 | "U8", "U16", "U32", "U64", 36 | "S8", "S16", "S32", "S64", 37 | "F32", "F64", 38 | "C8", "C16", "C32", 39 | "STR8", "STR16", "STR32", 40 | "STRUCT", "UNION", 41 | "ARRAY", 42 | "STRUCT_ARRAY", 43 | "USER_DEFINED", 44 | "NOT_DEFINED", 45 | }; 46 | 47 | int TypeLength (TypeSpecifier type); 48 | 49 | inline int HostEndian() { 50 | 51 | union { 52 | char bytes[4]; 53 | int value; 54 | } HostOrder = {{1, 2, 3, 4}}; 55 | 56 | return HostOrder.value; 57 | } 58 | 59 | inline void DispErr(std::string err) { 60 | if (ERROR_MSG) { 61 | std::cout << err << std::endl; 62 | } 63 | } 64 | } 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /include/parser_context.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_CONTEXT_H_ 2 | #define PARSER_CONTEXT_H_ 3 | 4 | #include 5 | #include 6 | #include "common/common.h" 7 | #include "vm/virtual_machine.h" 8 | #include "vm/data_type_table.h" 9 | #include "vm/context.h" 10 | 11 | namespace apus { 12 | 13 | class DataType; 14 | class DataTypeTable; 15 | class Statement; 16 | class VirtualMachine; 17 | 18 | typedef std::shared_ptr DataTypePtr; 19 | typedef std::shared_ptr DataTypeTablePtr; 20 | typedef std::shared_ptr StmtPtr; 21 | 22 | class ParserContext { 23 | public: 24 | ParserContext(); 25 | ParserContext(std::shared_ptr vm); 26 | ~ParserContext(); 27 | 28 | std::shared_ptr getVM() { return vm_; } 29 | void setVM(std::shared_ptr vm); 30 | 31 | // send data type table to virtual machine 32 | void SendDataTypeTableToVM(); 33 | 34 | DataTypeTablePtr getDataTypeTable(); 35 | 36 | // get/set method for name of current data type 37 | void setCurrentName(const std::string& name); 38 | std::string getCurrentName(); 39 | 40 | // get/set method for shared ptr of current data type 41 | void setCurrentDataType(DataTypePtr type); 42 | DataTypePtr getCurrentDataType(); 43 | 44 | // Add a data type into current data type(struct or union) 45 | void AddToCurrentDataType(const std::string& name, 46 | const std::string& type_name); 47 | void AddToCurrentDataType(const std::string& name, TypeSpecifier type); 48 | void AddToCurrentDataType(const std::string& name, DataTypePtr type); 49 | void AddToCurrentDataType(const std::string& name, DataType* type); 50 | 51 | void ChangeCurrentDataType(); 52 | 53 | private: 54 | std::shared_ptr vm_; // virtual machine 55 | // data type table 56 | std::shared_ptr data_type_table_; 57 | DataTypePtr current_data_type_; // current data type 58 | std::string current_name_; // name of current data type 59 | }; 60 | } 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /include/utils/BinaryReader.h: -------------------------------------------------------------------------------- 1 | #ifndef __BINARY_READER_H__ 2 | #define __BINARY_READER_H__ 3 | 4 | #include 5 | #include 6 | #include "common/common.h" 7 | using namespace std; 8 | 9 | namespace apus { 10 | 11 | class BinaryReader { 12 | public: 13 | BinaryReader(); 14 | BinaryReader(string &file_name); 15 | ~BinaryReader(); 16 | 17 | Endian GetFileEndian(); 18 | void SetFileEndian(Endian endian); 19 | 20 | int ReadInt(streampos offset, TypeSpecifier type, uint64_t &out_int); 21 | int ReadInt(TypeSpecifier type, uint64_t &out_int); 22 | 23 | int ReadReal(streampos offset, TypeSpecifier type, double &out_real); 24 | int ReadReal(TypeSpecifier type, double &out_real); 25 | 26 | int ReadChar(streampos offset, TypeSpecifier type, uint32_t &out_char); 27 | int ReadChar(TypeSpecifier type, uint32_t &out_char); 28 | 29 | int ReadString(streampos offset, TypeSpecifier type, string &out_str); 30 | int ReadString(TypeSpecifier type, string &out_str); 31 | 32 | private: 33 | string file_name_; // file name 34 | ifstream file_stream_; // file stream to read 35 | Endian file_endian_; // endian of file 36 | 37 | int ConvertBytes(byte out_array[], int length); 38 | }; 39 | } 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /include/vm/builtin_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef BUILTIN_FUNCTIONS_H_ 2 | #define BUILTIN_FUNCTIONS_H_ 3 | 4 | #include 5 | #include "vm/function_table.h" 6 | 7 | namespace apus { 8 | 9 | class BuiltInFunction : public Function { 10 | public: 11 | virtual ~BuiltInFunction() {} 12 | virtual std::shared_ptr Execute(Context& context) final; 13 | virtual std::shared_ptr BlockBody(Context& context) = 0; 14 | }; 15 | 16 | class PrintS64 : public BuiltInFunction { 17 | public: 18 | PrintS64(Context& context); 19 | virtual ~PrintS64(){} 20 | virtual std::shared_ptr BlockBody(Context& context) override; 21 | }; 22 | 23 | class PrintSTR8 : public BuiltInFunction { 24 | public: 25 | PrintSTR8(Context& context); 26 | virtual ~PrintSTR8(){} 27 | virtual std::shared_ptr BlockBody(Context& context) override; 28 | }; 29 | 30 | // READ signed int number 31 | 32 | class ReadS8 : public BuiltInFunction { 33 | public: 34 | ReadS8(Context& context); 35 | virtual ~ReadS8(){} 36 | virtual std::shared_ptr BlockBody(Context& context) override; 37 | }; 38 | 39 | class ReadS16 : public BuiltInFunction { 40 | public: 41 | ReadS16(Context& context); 42 | virtual ~ReadS16(){} 43 | virtual std::shared_ptr BlockBody(Context& context) override; 44 | }; 45 | 46 | class ReadS32 : public BuiltInFunction { 47 | public: 48 | ReadS32(Context& context); 49 | virtual ~ReadS32(){} 50 | virtual std::shared_ptr BlockBody(Context& context) override; 51 | }; 52 | 53 | class ReadS64 : public BuiltInFunction { 54 | public: 55 | ReadS64(Context& context); 56 | virtual ~ReadS64(){} 57 | virtual std::shared_ptr BlockBody(Context& context) override; 58 | }; 59 | 60 | // READ unsigned int value 61 | 62 | class ReadU8 : public BuiltInFunction { 63 | public: 64 | ReadU8(Context& context); 65 | virtual ~ReadU8(){} 66 | virtual std::shared_ptr BlockBody(Context& context) override; 67 | }; 68 | 69 | class ReadU16 : public BuiltInFunction { 70 | public: 71 | ReadU16(Context& context); 72 | virtual ~ReadU16(){} 73 | virtual std::shared_ptr BlockBody(Context& context) override; 74 | }; 75 | 76 | class ReadU32 : public BuiltInFunction { 77 | public: 78 | ReadU32(Context& context); 79 | virtual ~ReadU32(){} 80 | virtual std::shared_ptr BlockBody(Context& context) override; 81 | }; 82 | 83 | class ReadU64 : public BuiltInFunction { 84 | public: 85 | ReadU64(Context& context); 86 | virtual ~ReadU64(){} 87 | virtual std::shared_ptr BlockBody(Context& context) override; 88 | }; 89 | 90 | // READ character value 91 | 92 | class ReadC8 : public BuiltInFunction { 93 | public: 94 | ReadC8(Context& context); 95 | virtual ~ReadC8(){} 96 | virtual std::shared_ptr BlockBody(Context& context) override; 97 | }; 98 | 99 | class ReadC16 : public BuiltInFunction { 100 | public: 101 | ReadC16(Context& context); 102 | virtual ~ReadC16(){} 103 | virtual std::shared_ptr BlockBody(Context& context) override; 104 | }; 105 | 106 | class ReadC32 : public BuiltInFunction { 107 | public: 108 | ReadC32(Context& context); 109 | virtual ~ReadC32(){} 110 | virtual std::shared_ptr BlockBody(Context& context) override; 111 | }; 112 | 113 | 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /include/vm/context.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTEXT_H_ 2 | #define CONTEXT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "ast/value/value.h" 8 | 9 | using namespace std; 10 | 11 | namespace apus { 12 | 13 | class Value; 14 | 15 | class DataType; 16 | class DataTypeTable; 17 | 18 | class Variable; 19 | class VariableTable; 20 | 21 | class Function; 22 | class FunctionTable; 23 | 24 | class BinaryReader; 25 | 26 | class Context { 27 | public: 28 | 29 | Context(shared_ptr data_type_table, std::string binary_file_path); 30 | Context(Context* context); 31 | virtual ~Context(); 32 | 33 | Context BlockBegin(); 34 | shared_ptr BlockEnd(); 35 | 36 | // Find 37 | shared_ptr FindDataType(TypeSpecifier type); 38 | shared_ptr FindDataType(string name); 39 | shared_ptr FindVariable(string name); 40 | shared_ptr FindFunction(string name); 41 | 42 | // Insert 43 | void InsertVariable(shared_ptr variable); 44 | void InsertFunction(shared_ptr function); 45 | 46 | inline bool GetBreak() { return *break_; } 47 | inline bool GetContinue() { return *continue_; } 48 | inline bool GetReturn() { return *return_; } 49 | std::shared_ptr GetReturnValue() { return return_value_; } 50 | shared_ptr GetDataTypeTable() { return data_type_table_; } 51 | shared_ptr GetBinaryReader() { return binary_reader_; } 52 | 53 | inline void SetBreak(bool _break) { *break_ = _break;} 54 | inline void SetContinue(bool _continue) { *continue_ = _continue;} 55 | inline void SetReturn(bool _return) { *return_ = _return; } 56 | void SetReturnValue(std::shared_ptr value) { return_value_ = value; } 57 | void SetParamList(list> param_list) { param_list_ = param_list; } 58 | 59 | private: 60 | 61 | Context* parent_; // I'm not having it 62 | 63 | shared_ptr binary_reader_; 64 | 65 | shared_ptr data_type_table_; 66 | shared_ptr variable_table_; 67 | shared_ptr function_table_; 68 | 69 | list> param_list_; 70 | shared_ptr return_value_; 71 | 72 | shared_ptr break_; 73 | shared_ptr continue_; 74 | shared_ptr return_; 75 | 76 | }; 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/vm/data_type_table.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_TYPE_TABLE_H_ 2 | #define DATA_TYPE_TABLE_H_ 3 | 4 | #include "common/common.h" 5 | #include "ast/expression.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | namespace apus { 15 | 16 | class DataType; 17 | class Expression; 18 | 19 | typedef std::shared_ptr DataTypePtr; 20 | typedef std::shared_ptr ExprPtr; 21 | typedef std::map< std::string, DataTypePtr > DataTypeMap; 22 | 23 | class DataType { 24 | 25 | public: 26 | DataType(); 27 | DataType(TypeSpecifier type); 28 | ~DataType(); 29 | 30 | void Insert(const std::string& name, DataType* elem); 31 | void Insert(const std::string& name, DataTypePtr elem); 32 | DataTypePtr Find(const std::string& name); 33 | 34 | DataTypeMap GetMap(); 35 | 36 | void SetByteSize(int byte_size); 37 | virtual int GetByteSize(); 38 | 39 | DataTypePtr GetChildDataType(int index); 40 | 41 | void SetInitExpr(Expression* expr); 42 | ExprPtr GetInitExpr(); 43 | 44 | void SetType(TypeSpecifier type); 45 | TypeSpecifier GetType(); 46 | 47 | bool HasChild(); 48 | 49 | protected: 50 | TypeSpecifier type_; // type of the data type 51 | DataTypeMap map_; // list of child data types 52 | int current_index_; // current offset 53 | // index of child data types 54 | std::map index_; 55 | int byte_size_; // size of bytes to be assigned 56 | ExprPtr init_expr_; // expression to be initialized 57 | }; 58 | 59 | class ArrayDataType : public DataType { 60 | public: 61 | ArrayDataType(); 62 | ArrayDataType(TypeSpecifier type); 63 | ~ArrayDataType(); 64 | 65 | bool IsArray(); 66 | int GetByteSize() override; 67 | 68 | void AddDimension(int dim); 69 | std::list GetDimensionList(); 70 | 71 | void SetArraySize(int array_size); 72 | int GetArraySize(); 73 | 74 | void SetElement(DataTypePtr elem); 75 | void SetElement(DataType* elem); 76 | DataTypePtr GetElement() const; 77 | 78 | private: 79 | int array_size_; // product of dimension sizes 80 | std::list dimension_list_; // size of each dimension 81 | DataTypePtr elem_data_type_; // element data type 82 | }; 83 | 84 | class DataTypeTable { 85 | 86 | public: 87 | DataTypeTable(); 88 | ~DataTypeTable(); 89 | 90 | void SetPrimitiveTypes(); 91 | 92 | void Insert(const std::string& name, DataType* elem); 93 | void Insert(const std::string& name, DataTypePtr elem); 94 | 95 | DataTypePtr Find(const std::string& name); 96 | DataTypePtr Find(TypeSpecifier type); 97 | 98 | 99 | private: 100 | DataTypeMap map_; 101 | }; 102 | 103 | typedef std::shared_ptr DataTypeTablePtr; 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /include/vm/function_table.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTION_TABLE_H_ 2 | #define FUNCTION_TABLE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "vm/data_type_table.h" 9 | #include "vm/context.h" 10 | 11 | namespace apus { 12 | 13 | class DataType; 14 | class Variable; 15 | class Function; 16 | 17 | typedef std::shared_ptr FunctionPtr; 18 | typedef std::shared_ptr DataTypePtr; 19 | typedef std::shared_ptr VariablePtr; 20 | typedef std::map FunctionMap; 21 | 22 | class Function { 23 | public: 24 | Function(); 25 | Function(const std::string& name); 26 | Function(const std::string& name, DataTypePtr return_type); 27 | Function(const std::string& name, DataTypePtr return_type, list arg_list); 28 | virtual ~Function(); 29 | 30 | virtual std::shared_ptr Execute(Context& context) = 0; 31 | 32 | std::string getName() { return name_; } 33 | DataTypePtr getReturnType() { return return_type_; } 34 | list getArgList() { return arg_list_; } 35 | 36 | protected: 37 | std::string name_; 38 | DataTypePtr return_type_; 39 | list arg_list_; 40 | }; 41 | 42 | class FunctionTable { 43 | public: 44 | FunctionTable(); 45 | 46 | void Insert(std::string name, FunctionPtr function); 47 | FunctionPtr Find(std::string& name); 48 | 49 | private: 50 | FunctionMap map_; 51 | }; 52 | 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /include/vm/variable_table.h: -------------------------------------------------------------------------------- 1 | #ifndef VARIABLE_TABLE_H_ 2 | #define VARIABLE_TABLE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "common/common.h" 10 | #include "ast/value/value.h" 11 | #include "vm/data_type_table.h" 12 | 13 | namespace apus { 14 | 15 | class Value; 16 | class DataType; 17 | class Variable; 18 | 19 | typedef std::shared_ptr ValuePtr; 20 | typedef std::shared_ptr DataTypePtr; 21 | typedef std::shared_ptr VarPtr; 22 | typedef std::map< std::string, VarPtr > VariableMap; 23 | 24 | class Variable { 25 | public: 26 | Variable(const std::string& name, DataTypePtr type); 27 | ~Variable(); 28 | 29 | TypeSpecifier getType(); 30 | 31 | std::string getName(); 32 | void setName(const std::string& name); 33 | 34 | DataTypePtr getDataType(); 35 | void setDataType(DataTypePtr type); 36 | 37 | VarPtr getChildVariable(const std::string& name); 38 | void InsertChildVariable(const std::string& name, VarPtr var); 39 | 40 | ValuePtr getValue(); 41 | void setValue(ValuePtr value); 42 | 43 | bool IsStructVariable(); 44 | 45 | void CreateChildVariables(); 46 | 47 | protected: 48 | std::string name_; // name of variable 49 | DataTypePtr data_type_; // data type 50 | VariableMap map_; // list of child variables 51 | ValuePtr value_; // value 52 | }; 53 | 54 | class VariableTable { 55 | public: 56 | VariableTable(); 57 | ~VariableTable(); 58 | 59 | void Insert(const std::string name, std::shared_ptr variable); 60 | std::shared_ptr Find(const std::string& name); 61 | 62 | private: 63 | VariableMap map_; 64 | }; 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/vm/virtual_machine.h: -------------------------------------------------------------------------------- 1 | #ifndef VIRTUALMACHINE_H 2 | #define VIRTUALMACHINE_H 3 | 4 | #include "vm/context.h" 5 | #include "ast/statement/statement.h" 6 | #include "vm/data_type_table.h" 7 | #include 8 | #include 9 | 10 | namespace apus { 11 | 12 | class DataType; 13 | class DataTypeTable; 14 | class Statement; 15 | 16 | typedef std::shared_ptr DataTypePtr; 17 | typedef std::shared_ptr DataTypeTablePtr; 18 | typedef std::shared_ptr StmtPtr; 19 | typedef std::list StmtPtrList; 20 | 21 | class VirtualMachine { 22 | public: 23 | VirtualMachine(); 24 | virtual ~VirtualMachine(); 25 | 26 | StmtPtrList getStmtList(); 27 | void setStmtList(StmtPtrList stmt_list); 28 | 29 | DataTypeTablePtr getDataTypeTable(); 30 | void setDataTypeTable(DataTypeTablePtr data_type_table); 31 | 32 | void Run(std::string binary_file_path = ""); 33 | 34 | private: 35 | StmtPtrList stmt_list_; 36 | std::shared_ptr data_type_table_; 37 | }; 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Append compile option 3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 4 | 5 | # Add include directory 6 | set(INCLUDE_DIR ../include) 7 | include_directories("${INCLUDE_DIR}") 8 | 9 | # Scan whole files under 'src' and 'include' folders, recursively. 10 | file(GLOB_RECURSE SOURCE_FILES "*.cpp" "*.cc" "*.c") 11 | file(GLOB_RECURSE HEADER_FILES "${INCLUDE_DIR}/*.hpp" "${INCLUDE_DIR}/*.hh" "${INCLUDE_DIR}/*.h") 12 | 13 | set_source_files_properties(${LEX_OUT} GENERATED) 14 | set_source_files_properties(${YACC_OUT} GENERATED) 15 | 16 | # Build executable 17 | add_executable( 18 | apus 19 | ${SOURCE_FILES} ${HEADER_FILES} 20 | ${CMAKE_SOURCE_DIR}/${SRC_DIR}/${LEX_OUT} 21 | ${CMAKE_SOURCE_DIR}/${SRC_DIR}/${YACC_OUT} 22 | ) 23 | 24 | add_dependencies(apus lex;yacc) 25 | -------------------------------------------------------------------------------- /src/apus.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | 4 | #include "parser_context.h" 5 | #include "y.tab.hh" 6 | 7 | %} 8 | 9 | %option noyywrap 10 | %option yylineno 11 | 12 | %% 13 | "u8" { return UINT8; } 14 | "u16" { return UINT16; } 15 | "u32" { return UINT32; } 16 | "u64" { return UINT64; } 17 | "s8" { return SINT8; } 18 | "s16" { return SINT16; } 19 | "s32" { return SINT32; } 20 | "s64" { return SINT64; } 21 | "f32" { return FLOAT32; } 22 | "f64" { return FLOAT64; } 23 | "c8" { return CHAR8; } 24 | "c16" { return CHAR16; } 25 | "c32" { return CHAR32; } 26 | "str" { return STRING; } 27 | "str8" { return STRING8; } 28 | "str16" { return STRING16; } 29 | "str32" { return STRING32; } 30 | "var" { return VAR; } 31 | 32 | "include" { return INCLUDE; } 33 | "union" { return UNION_TYPE; } 34 | "struct" { return STRUCT_TYPE; } 35 | "const" { return CONST_TYPE; } 36 | "if" { return IF; } 37 | "else" { return ELSE; } 38 | "for" { return FOR; } 39 | "continue" { return CONTINUE; } 40 | "break" { return BREAK; } 41 | "return" { return RETURN; } 42 | "exit" { return EXIT; } 43 | "true" { return TRUE; } 44 | "false" { return FALSE; } 45 | 46 | "+=" { return ADDASSIGN; } 47 | "-=" { return SUBASSIGN; } 48 | "*=" { return MULASSIGN; } 49 | "/=" { return DIVASSIGN; } 50 | "%=" { return MODASSIGN; } 51 | "|=" { return ORASSIGN; } 52 | "&=" { return ANDASSIGN; } 53 | "^=" { return XORASSIGN; } 54 | "<<=" { return LSASSIGN; } 55 | ">>=" { return RSASSIGN; } 56 | "<<" { return LSHIFT; } 57 | ">>" { return RSHIFT; } 58 | "||" { return LOR; } 59 | "&&" { return LAND; } 60 | 61 | "+" { return ADD; } 62 | "-" { return SUB; } 63 | "*" { return MUL; } 64 | "/" { return DIV; } 65 | "=" { return ASSIGN; } 66 | "|" { return OR; } 67 | "&" { return AND; } 68 | "%" { return MOD; } 69 | "~" { return REVERSE; } 70 | "^" { return XOR; } 71 | 72 | "==" { return EQL; } 73 | "<" { return LSS; } 74 | ">" { return GTR; } 75 | "<=" { return LEQ; } 76 | ">=" { return GEQ; } 77 | "!=" { return NEQ; } 78 | "!" { return NOT; } 79 | "." { return DOT; } 80 | ";" { return SEMI; } 81 | "," { return COMMA; } 82 | 83 | "{" { return L_BRACE; } 84 | "}" { return R_BRACE; } 85 | "[" { return L_CASE; } 86 | "]" { return R_CASE; } 87 | "(" { return OPEN; } 88 | ")" { return CLOSE; } 89 | "\n" { return CR; } 90 | 91 | ([1-9][0-9]*|[0]) { 92 | int temp; 93 | sscanf(yytext, "%d", &temp); 94 | yylval.int_val = temp; 95 | return INT_LITERAL; 96 | } 97 | [0-9]*\.[0-9]* { 98 | double temp; 99 | sscanf(yytext, "%lf", &temp); 100 | yylval.double_val = temp; 101 | return DOUBLE_LITERAL; 102 | } 103 | 104 | [a-zA-Z_][0-9a-zA-Z_]* { 105 | yylval.str_val = (char*)malloc(yyleng); 106 | sprintf(yylval.str_val, "%s", yytext); 107 | // Sting control : yytext[NUM] 108 | return ID; 109 | } 110 | 111 | '([^'\n|\\'])' { 112 | yylval.char_val = yytext[1]; 113 | return CHAR_LITERAL; 114 | } 115 | 116 | \"([^"\n]|\\\")*\" { 117 | yylval.str_val = (char*)malloc(yyleng-1); 118 | memcpy(yylval.str_val, yytext+1, yyleng-2); 119 | yylval.str_val[yyleng-2] = '\0'; 120 | return STRING_LITERAL; 121 | } 122 | 123 | 0b[0-1]* { 124 | uint64_t num_tmp; 125 | char* tmp = (char*)malloc(yyleng); 126 | sscanf(yytext, "0b%s", tmp); 127 | num_tmp = strtoul(tmp, NULL, 2); 128 | yylval.int_val = num_tmp; 129 | free(tmp); 130 | return BINARY_LITERAL; 131 | } 132 | 133 | 0[0-7]* { 134 | uint64_t num_tmp; 135 | char* tmp = (char*)malloc(yyleng); 136 | sscanf(yytext, "0%s", tmp); 137 | num_tmp = strtoul(tmp, NULL, 8); 138 | yylval.int_val = num_tmp; 139 | free(tmp); 140 | return OCTA_LITERAL; 141 | } 142 | 143 | 0x[0-9a-fA-F]* { 144 | uint64_t num_tmp; 145 | char* tmp = (char*)malloc(yyleng); 146 | sscanf(yytext, "0x%s", tmp); 147 | num_tmp = strtoul(tmp, NULL, 16); 148 | yylval.int_val = num_tmp; 149 | free(tmp); 150 | return HEXA_LITERAL; 151 | } 152 | 153 | [#]+.*[\n] ; 154 | [\t ]+ ; 155 | %% 156 | -------------------------------------------------------------------------------- /src/apus.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | 5 | #include "parser_context.h" 6 | 7 | extern int yylex(); 8 | extern int yyerror(apus::ParserContext* pctx, char const *str); 9 | 10 | %} 11 | 12 | %parse-param { 13 | apus::ParserContext* pctx 14 | } 15 | 16 | %code requires { 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "common/common.h" 24 | 25 | #include "ast/statement/statement.h" 26 | #include "ast/statement/block.h" 27 | #include "ast/statement/for_statement.h" 28 | #include "ast/statement/if_statement.h" 29 | #include "ast/statement/jump_statement.h" 30 | #include "ast/statement/expression_statement.h" 31 | #include "ast/statement/var_def_statement.h" 32 | 33 | #include "vm/virtual_machine.h" 34 | 35 | #include "ast/expression.h" 36 | 37 | #include "ast/value/value.h" 38 | #include "ast/value/signed_int_value.h" 39 | #include "ast/value/unsigned_int_value.h" 40 | #include "ast/value/float_value.h" 41 | #include "ast/value/character_value.h" 42 | #include "ast/value/string_value.h" 43 | 44 | using namespace std; 45 | using namespace apus; 46 | 47 | typedef shared_ptr StmtPtr; 48 | typedef list ListStmt; 49 | typedef shared_ptr ListStmtPtr; 50 | } 51 | 52 | %union { 53 | int64_t int_val; 54 | uint64_t uint_val; 55 | double double_val; 56 | int char_val; 57 | char* str_val; 58 | 59 | TypeSpecifier type_specifier; 60 | 61 | list>* list_stmt; 62 | list>* list_expr; 63 | 64 | Statement* stmt; 65 | 66 | Expression* expr; 67 | Expression::Type expr_type; 68 | 69 | Value* value; 70 | } 71 | 72 | %token INT_LITERAL 73 | %token DOUBLE_LITERAL 74 | %token CHAR_LITERAL 75 | %token STRING_LITERAL 76 | %token ID 77 | %token BINARY_LITERAL OCTA_LITERAL HEXA_LITERAL 78 | 79 | %token UINT8 UINT16 UINT32 UINT64 80 | %token SINT8 SINT16 SINT32 SINT64 81 | %token FLOAT32 FLOAT64 82 | %token CHAR8 CHAR16 CHAR32 83 | %token STRING STRING8 STRING16 STRING32 84 | %token STRUCT_TYPE CONST_TYPE UNION_TYPE 85 | 86 | %token L_BRACE R_BRACE L_CASE R_CASE OPEN CLOSE 87 | %token COMMENT CR DOT VAR SEMI COMMA 88 | %token INCLUDE IF ELSE FOR EXIT TRUE FALSE CONTINUE BREAK RETURN 89 | 90 | %right ASSIGN ADDASSIGN SUBASSIGN MULASSIGN DIVASSIGN MODASSIGN ORASSIGN ANDASSIGN XORASSIGN LSASSIGN RSASSIGN 91 | %left LOR 92 | %left LAND 93 | %left OR 94 | %left XOR 95 | %left AND 96 | %left EQL NEQ 97 | %left LSS GTR LEQ GEQ 98 | %left LSHIFT RSHIFT 99 | %left ADD SUB 100 | %left MUL DIV MOD 101 | %right NOT REVERSE 102 | 103 | %type action_declaration_list action_declaration_opt 104 | %type arg_expression_list arg_expression_opt 105 | %type action_declaration for_statement if_statement else_if jump_statement expression_statement var_def_statement variable_definition block_statement 106 | 107 | %type expression expression_opt unary_expression primary_expression variable_expression init_expression const_expression function_expression 108 | %type assign_operator 109 | %type type_specifier struct_union_type 110 | 111 | %% 112 | program : 113 | line_opt data_declaration_opt action_declaration_opt { 114 | pctx->SendDataTypeTableToVM(); 115 | pctx->getVM()->setStmtList(*$3); 116 | } 117 | ; 118 | data_declaration_opt : 119 | /* empty */ 120 | | data_declaration_list 121 | ; 122 | action_declaration_opt : 123 | /* empty */ { $$ = new list>(); } 124 | | action_declaration_list 125 | ; 126 | line_opt : 127 | /* empty */ 128 | | line_list 129 | ; 130 | line_list : 131 | CR 132 | | CR line_list 133 | ; 134 | data_declaration_list : 135 | data_declaration 136 | | data_declaration_list data_declaration 137 | | line_list data_declaration_list 138 | ; 139 | action_declaration_list : 140 | action_declaration { 141 | $$ = new list>(); 142 | $$->push_back(shared_ptr($1)); 143 | } 144 | | action_declaration action_declaration_list { 145 | $2->push_front(shared_ptr($1)); 146 | $$ = $2; 147 | } 148 | ; 149 | data_declaration : 150 | struct_union_type ID { 151 | pctx->setCurrentDataType(std::make_shared($1)); 152 | pctx->setCurrentName(string($2)); 153 | } block_start member_definition_list R_BRACE line_list { 154 | pctx->ChangeCurrentDataType(); 155 | } 156 | ; 157 | struct_union_type : 158 | STRUCT_TYPE { $$ = TypeSpecifier::STRUCT; } 159 | | UNION_TYPE { $$ = TypeSpecifier::UNION; } 160 | ; 161 | member_definition_list : 162 | member_definition line_opt 163 | | member_definition line_list member_definition_list 164 | ; 165 | member_definition : 166 | type_specifier ID { 167 | pctx->AddToCurrentDataType(string($2), $1); 168 | } 169 | | struct_union_type ID ID { 170 | pctx->AddToCurrentDataType(string($3), string($2)); 171 | } 172 | | type_specifier ID ASSIGN const_expression 173 | | struct_union_type ID ID ASSIGN const_expression 174 | | type_specifier dimension_array ID 175 | | type_specifier dimension_array ID ASSIGN const_expression 176 | | struct_union_type ID dimension_array ID 177 | | struct_union_type ID dimension_array ID ASSIGN const_expression 178 | ; 179 | const_expression_list : 180 | const_expression 181 | | const_expression comma_line_opt const_expression_list 182 | ; 183 | const_expression : 184 | INT_LITERAL { $$ = new ValueExpression(SignedIntValue::Create(pctx->getDataTypeTable()->Find(S64), $1)); } 185 | | DOUBLE_LITERAL { $$ = new ValueExpression(FloatValue::Create(pctx->getDataTypeTable()->Find(F64), $1)); } 186 | | CHAR_LITERAL { $$ = new ValueExpression(CharacterValue::Create(pctx->getDataTypeTable()->Find(C8), $1)); } 187 | | STRING_LITERAL { $$ = new ValueExpression(StringValue::Create(pctx->getDataTypeTable()->Find(STR8), $1)); } 188 | | BINARY_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 189 | | OCTA_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 190 | | HEXA_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 191 | | const_struct_init 192 | | const_array_init 193 | ; 194 | const_struct_init : 195 | block_start const_expression_list block_end 196 | ; 197 | const_array_init : 198 | L_CASE const_expression_list R_CASE 199 | ; 200 | dimension_array : 201 | L_CASE expression R_CASE 202 | | L_CASE expression R_CASE dimension_array 203 | ; 204 | expression_opt : 205 | /* empty */ { $$ = nullptr; } 206 | | expression 207 | ; 208 | expression : 209 | variable_expression assign_operator expression { $$ = new AssignExpression($2, $1, $3);} 210 | | expression LOR expression { $$ = new BinaryExpression(Expression::EXP_LOR, $1, $3); } 211 | | expression LAND expression { $$ = new BinaryExpression(Expression::EXP_LAND, $1, $3); } 212 | | expression OR expression { $$ = new BinaryExpression(Expression::EXP_OR, $1, $3); } 213 | | expression XOR expression { $$ = new BinaryExpression(Expression::EXP_XOR, $1, $3); } 214 | | expression AND expression { $$ = new BinaryExpression(Expression::EXP_AND, $1, $3); } 215 | | expression EQL expression { $$ = new BinaryExpression(Expression::EXP_EQL, $1, $3); } 216 | | expression NEQ expression { $$ = new BinaryExpression(Expression::EXP_NEQ, $1, $3); } 217 | | expression LSS expression { $$ = new BinaryExpression(Expression::EXP_LSS, $1, $3); } 218 | | expression GTR expression { $$ = new BinaryExpression(Expression::EXP_GTR, $1, $3); } 219 | | expression LEQ expression { $$ = new BinaryExpression(Expression::EXP_LEQ, $1, $3); } 220 | | expression GEQ expression { $$ = new BinaryExpression(Expression::EXP_GEQ, $1, $3); } 221 | | expression LSHIFT expression { $$ = new BinaryExpression(Expression::EXP_LSHIFT, $1, $3); } 222 | | expression RSHIFT expression { $$ = new BinaryExpression(Expression::EXP_RSHIFT, $1, $3); } 223 | | expression ADD expression { $$ = new BinaryExpression(Expression::EXP_ADD, $1, $3); } 224 | | expression SUB expression { $$ = new BinaryExpression(Expression::EXP_SUB, $1, $3); } 225 | | expression MUL expression { $$ = new BinaryExpression(Expression::EXP_MUL, $1, $3); } 226 | | expression DIV expression { $$ = new BinaryExpression(Expression::EXP_DIV, $1, $3); } 227 | | expression MOD expression { $$ = new BinaryExpression(Expression::EXP_MOD, $1, $3); } 228 | | unary_expression 229 | ; 230 | unary_expression : 231 | primary_expression 232 | | NOT unary_expression { $$ = new UnaryExpression(Expression::EXP_NOT, $2); } 233 | | REVERSE unary_expression { $$ = new UnaryExpression(Expression::EXP_REVERSE, $2); } 234 | | SUB primary_expression { $$ = new UnaryExpression(Expression::EXP_SUB, $2); } 235 | | ADD primary_expression { $$ = new UnaryExpression(Expression::EXP_ADD, $2); } 236 | ; 237 | primary_expression : 238 | OPEN expression CLOSE { $$ = $2; } 239 | | INT_LITERAL { $$ = new ValueExpression(SignedIntValue::Create(pctx->getDataTypeTable()->Find(S64), $1)); } 240 | | DOUBLE_LITERAL { $$ = new ValueExpression(FloatValue::Create(pctx->getDataTypeTable()->Find(F64), $1)); } 241 | | CHAR_LITERAL { $$ = new ValueExpression(CharacterValue::Create(pctx->getDataTypeTable()->Find(C8), $1)); } 242 | | STRING_LITERAL { $$ = new ValueExpression(StringValue::Create(pctx->getDataTypeTable()->Find(STR8), $1)); } 243 | | BINARY_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 244 | | OCTA_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 245 | | HEXA_LITERAL { $$ = new ValueExpression(UnsignedIntValue::Create(pctx->getDataTypeTable()->Find(U64), $1)); } 246 | | variable_expression 247 | | function_expression 248 | ; 249 | variable_expression : 250 | ID { $$ = new VariableExpression(std::string($1)); } 251 | | ID dimension_array 252 | | variable_expression DOT ID 253 | | variable_expression DOT ID dimension_array 254 | ; 255 | function_expression : 256 | ID OPEN arg_expression_opt CLOSE { $$ = new FunctionExpression(string($1), *$3); } 257 | ; 258 | arg_expression_opt : 259 | /* empty */ { $$ = new list>(); } 260 | | arg_expression_list 261 | ; 262 | arg_expression_list : 263 | expression { 264 | $$ = new list>(); 265 | $$->push_back(shared_ptr($1)); 266 | } 267 | | expression comma_line_opt arg_expression_list { 268 | $3->push_front(shared_ptr($1)); 269 | $$ = $3; 270 | } 271 | ; 272 | comma_line_opt : 273 | COMMA line_opt 274 | ; 275 | block_start : 276 | line_opt L_BRACE line_opt 277 | ; 278 | block_end : 279 | R_BRACE line_opt 280 | ; 281 | paren_start : 282 | line_opt OPEN line_opt 283 | ; 284 | paren_end : 285 | line_opt CLOSE 286 | ; 287 | semi_start : 288 | line_opt SEMI line_opt 289 | ; 290 | type_specifier : 291 | UINT8 { $$ = TypeSpecifier::U8; } 292 | | UINT16 { $$ = TypeSpecifier::U16; } 293 | | UINT32 { $$ = TypeSpecifier::U32; } 294 | | UINT64 { $$ = TypeSpecifier::U64; } 295 | | SINT8 { $$ = TypeSpecifier::S8; } 296 | | SINT16 { $$ = TypeSpecifier::S16; } 297 | | SINT32 { $$ = TypeSpecifier::S32; } 298 | | SINT64 { $$ = TypeSpecifier::S64; } 299 | | FLOAT32 { $$ = TypeSpecifier::F32; } 300 | | FLOAT64 { $$ = TypeSpecifier::F64; } 301 | | CHAR8 { $$ = TypeSpecifier::C8; } 302 | | CHAR16 { $$ = TypeSpecifier::C16; } 303 | | CHAR32 { $$ = TypeSpecifier::C32; } 304 | | STRING { $$ = TypeSpecifier::STR8; } 305 | | STRING8 { $$ = TypeSpecifier::STR8; } 306 | | STRING16 { $$ = TypeSpecifier::STR16; } 307 | | STRING32 { $$ = TypeSpecifier::STR32; } 308 | ; 309 | assign_operator : 310 | ASSIGN { $$ = Expression::EXP_ASSIGN; } 311 | | ADDASSIGN { $$ = Expression::EXP_ADDASSIGN; } 312 | | SUBASSIGN { $$ = Expression::EXP_SUBASSIGN; } 313 | | MULASSIGN { $$ = Expression::EXP_MULASSIGN; } 314 | | DIVASSIGN { $$ = Expression::EXP_DIVASSIGN; } 315 | | MODASSIGN { $$ = Expression::EXP_MODASSIGN; } 316 | | ORASSIGN { $$ = Expression::EXP_ORASSIGN; } 317 | | ANDASSIGN { $$ = Expression::EXP_ANDASSIGN; } 318 | | XORASSIGN { $$ = Expression::EXP_XORASSIGN; } 319 | | LSASSIGN { $$ = Expression::EXP_LSASSIGN; } 320 | | RSASSIGN { $$ = Expression::EXP_RSASSIGN; } 321 | ; 322 | action_declaration : 323 | block_statement 324 | | if_statement 325 | | for_statement 326 | | jump_statement 327 | | expression_statement 328 | | var_def_statement 329 | ; 330 | block_statement : 331 | block_start action_declaration_opt block_end { $$ = new Block(*$2); } 332 | ; 333 | if_statement : 334 | IF paren_start expression paren_end block_statement else_if { $$ = new IfStatement($3, $5, $6); } 335 | ; 336 | else_if : 337 | /* empty */ { $$ = nullptr; } 338 | | ELSE if_statement { $$ = $2; } 339 | | ELSE block_statement { $$ = $2; } 340 | ; 341 | for_statement : 342 | FOR paren_start expression_opt semi_start expression_opt semi_start expression_opt paren_end block_statement { $$ = new ForStatement($3, $5, $7, $9); } 343 | ; 344 | jump_statement : 345 | BREAK line_list { $$ = new BreakStatement(); } 346 | | CONTINUE line_list { $$ = new ContinueStatement(); } 347 | | RETURN expression_opt line_list { $$ = new ReturnStatement($2); } 348 | | EXIT expression_opt line_list { $$ = new ExitStatement($2); } 349 | ; 350 | expression_statement : 351 | expression line_list { $$ = new ExpressionStatement($1); } 352 | ; 353 | var_def_statement : 354 | VAR variable_definition line_list { $$ = $2; } 355 | ; 356 | variable_definition : 357 | type_specifier ID { 358 | $$ = new VarDefStatement($1, string($2)); 359 | } 360 | | struct_union_type ID ID { 361 | $$ = new VarDefStatement(string($2), string($3)); 362 | } 363 | | type_specifier ID ASSIGN init_expression { 364 | $$ = new VarDefStatement($1, string($2), $4); 365 | } 366 | | struct_union_type ID ID ASSIGN init_expression { 367 | $$ = new VarDefStatement(string($2), string($3), $5); 368 | } 369 | | type_specifier dimension_array ID 370 | | type_specifier dimension_array ID ASSIGN init_expression 371 | | struct_union_type ID dimension_array ID 372 | | struct_union_type ID dimension_array ID ASSIGN init_expression 373 | ; 374 | init_expression_list : 375 | init_expression 376 | | init_expression comma_line_opt init_expression_list 377 | ; 378 | init_expression : 379 | expression { $$ = $1; } 380 | | struct_init 381 | | array_init 382 | ; 383 | struct_init : 384 | block_start init_expression_list block_end 385 | ; 386 | array_init : 387 | L_CASE init_expression_list R_CASE 388 | ; 389 | %% 390 | int yyerror(apus::ParserContext* pctx, char const *str) { 391 | extern char yylineno; 392 | extern char *yytext; 393 | fprintf(stderr, "parser error near %s, line is %d\n", yytext, yylineno); 394 | return 0; 395 | } 396 | -------------------------------------------------------------------------------- /src/ast/expression.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/expression.h" 2 | #include "ast/value/value.h" 3 | 4 | #include "vm/variable_table.h" 5 | #include "vm/context.h" 6 | 7 | #include "vm/function_table.h" 8 | 9 | namespace apus { 10 | 11 | // Expression:: 12 | 13 | Expression::Expression(Type type) 14 | : type_(type){ 15 | } 16 | 17 | Expression::~Expression() { 18 | 19 | } 20 | 21 | // BinaryExpression:: 22 | 23 | BinaryExpression::BinaryExpression(Type type, 24 | std::shared_ptr leftExpression, 25 | std::shared_ptr rightExpression) 26 | : Expression(type), 27 | left_expression_(leftExpression), 28 | right_expression_(rightExpression) { 29 | } 30 | 31 | 32 | BinaryExpression::BinaryExpression(Type type, Expression* leftExpression, 33 | Expression* rightExpression) 34 | 35 | : BinaryExpression(type, 36 | std::shared_ptr(leftExpression), 37 | std::shared_ptr(rightExpression)) { 38 | 39 | } 40 | 41 | BinaryExpression::~BinaryExpression() { 42 | 43 | } 44 | 45 | std::shared_ptr BinaryExpression::Evaluate(Context& context) { 46 | 47 | std::shared_ptr result = nullptr; 48 | 49 | // 1. check expression 50 | if (left_expression_ != nullptr && right_expression_ != nullptr) { 51 | 52 | std::shared_ptr left_value = left_expression_->Evaluate(context); 53 | std::shared_ptr right_value = right_expression_->Evaluate(context); 54 | 55 | // 2. check lvalue, rvalue 56 | if (left_value != nullptr && right_value != nullptr) { 57 | 58 | std::shared_ptr left_promoted = left_value->Promote(right_value); 59 | std::shared_ptr right_promoted = right_value->Promote(left_value); 60 | 61 | // 3. check promoted values 62 | if (left_promoted != nullptr && right_promoted != nullptr) { 63 | 64 | result = left_promoted->OperateBinary(this->getType(), 65 | right_promoted); 66 | } 67 | 68 | } 69 | 70 | } 71 | 72 | return result; 73 | } 74 | 75 | // UnaryExpression:: 76 | 77 | UnaryExpression::UnaryExpression(Type type, std::shared_ptr expression) 78 | : Expression(type), expression_(expression) { 79 | 80 | } 81 | 82 | UnaryExpression::UnaryExpression(Type type, Expression* expression) 83 | 84 | : UnaryExpression(type, std::shared_ptr(expression)) { 85 | } 86 | 87 | UnaryExpression::~UnaryExpression() { 88 | 89 | } 90 | 91 | std::shared_ptr UnaryExpression::Evaluate(Context& context) { 92 | 93 | std::shared_ptr result = nullptr; 94 | result = expression_->Evaluate(context); 95 | result = result->OperateUnary(this->getType()); 96 | 97 | return result; 98 | } 99 | 100 | // ValueExpression:: 101 | 102 | ValueExpression::ValueExpression(std::shared_ptr value) 103 | : Expression(EXP_VALUE), value_(value) { 104 | 105 | } 106 | 107 | ValueExpression::ValueExpression(Value *value) 108 | : ValueExpression(std::shared_ptr(value)) { 109 | } 110 | 111 | std::shared_ptr ValueExpression::Evaluate(Context &context) { 112 | return value_; 113 | } 114 | 115 | // VariableExpression 116 | 117 | VariableExpression::VariableExpression(std::string name) 118 | : Expression(EXP_VARIABLE), name_(name) { 119 | } 120 | 121 | VariableExpression::VariableExpression(char *name) 122 | : VariableExpression(std::string(name)) { 123 | } 124 | 125 | VariableExpression::~VariableExpression() { 126 | 127 | } 128 | 129 | std::shared_ptr VariableExpression::Evaluate(Context &context) { 130 | return context.FindVariable(name_)->getValue(); 131 | } 132 | 133 | 134 | std::shared_ptr VariableExpression::getVariable(Context& context) { 135 | return context.FindVariable(name_); 136 | } 137 | 138 | // AssignExpression:: 139 | 140 | AssignExpression::AssignExpression(Type type, 141 | std::shared_ptr var_expr, 142 | std::shared_ptr expression) 143 | : Expression(type), var_expr_(var_expr), expression_(expression) { 144 | 145 | } 146 | 147 | AssignExpression::AssignExpression(Type type, 148 | Expression* var_expr, 149 | Expression* expression) 150 | : AssignExpression(type, std::shared_ptr(var_expr), 151 | std::shared_ptr(expression)) { 152 | } 153 | 154 | AssignExpression::~AssignExpression() { 155 | 156 | } 157 | 158 | std::shared_ptr AssignExpression::Evaluate(Context &context) { 159 | 160 | if (expression_ != nullptr) { 161 | 162 | // Find left value from the variable table 163 | std::shared_ptr left = var_expr_->Evaluate(context); 164 | std::shared_ptr right = expression_->Evaluate(context); 165 | 166 | if (left != nullptr && right != nullptr) { 167 | 168 | std::shared_ptr right_promoted = right->Promote(left); 169 | 170 | if (right_promoted != nullptr) { 171 | 172 | std::shared_ptr result = 173 | left->OperateBinary(this->getType(), right_promoted); 174 | 175 | // TODO : and, put 'result' value into the variable 176 | std::shared_ptr var = std::dynamic_pointer_cast(var_expr_)->getVariable(context); 177 | var->setValue(result); 178 | 179 | return result; 180 | } 181 | } 182 | } 183 | return nullptr; 184 | } 185 | 186 | // MemberExpression:: 187 | 188 | MemberExpression::MemberExpression(std::string parent_name, 189 | std::string child_name) 190 | : Expression(EXP_MEMBER), parent_name_(parent_name), child_name_(child_name) { 191 | 192 | } 193 | 194 | MemberExpression::MemberExpression(char* parent_name, char* child_name) 195 | : MemberExpression(std::string(parent_name), std::string(child_name)) { 196 | } 197 | 198 | MemberExpression::~MemberExpression() { 199 | 200 | } 201 | 202 | std::shared_ptr MemberExpression::Evaluate(Context &context) { 203 | 204 | std::shared_ptr result = nullptr; 205 | 206 | // find variable member 207 | 208 | return result; 209 | } 210 | 211 | // FunctionExpression:: 212 | 213 | FunctionExpression::FunctionExpression(std::string func_name, std::list> arg_expr) 214 | : Expression(EXP_FUNCTION), func_name_(func_name), arg_expr_(arg_expr) { 215 | 216 | } 217 | 218 | FunctionExpression::FunctionExpression(char* func_name, std::list> arg_expr) 219 | : FunctionExpression(std::string(func_name), arg_expr) { 220 | } 221 | 222 | FunctionExpression::~FunctionExpression() { 223 | 224 | } 225 | 226 | std::shared_ptr FunctionExpression::Evaluate(Context &context) { 227 | 228 | std::shared_ptr function = context.FindFunction(func_name_); 229 | std::shared_ptr result = nullptr; 230 | 231 | // use '>=' ? 232 | if (function != nullptr && 233 | arg_expr_.size() == function->getArgList().size()) { 234 | 235 | // exprs -> values 236 | list> param_list; 237 | list>::iterator it = arg_expr_.begin(); 238 | 239 | for (VariablePtr variablePtr : function->getArgList()) { 240 | // TODO : put nth arg_expr's value if datatype match 241 | ValuePtr val = (*it)->Evaluate(context); 242 | variablePtr->setValue(val); 243 | 244 | ++it; 245 | } 246 | 247 | context.SetParamList(function->getArgList()); 248 | 249 | function->Execute(context); 250 | result = context.GetReturnValue(); 251 | } 252 | 253 | return result; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/ast/statement/block.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/statement/block.h" 2 | #include "vm/context.h" 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | namespace apus { 9 | 10 | Block::Block(std::list statements) 11 | : statements_(statements) { 12 | } 13 | 14 | Block::Block(StmtPtr statement) { 15 | statements_.push_back(statement); 16 | } 17 | 18 | Block::~Block() { 19 | 20 | } 21 | 22 | void Block::Execute(Context& context) { 23 | 24 | Context child = context.BlockBegin(); 25 | 26 | for (StmtPtr stmt : statements_) { 27 | 28 | stmt->Execute(child); 29 | 30 | if (child.GetBreak() || child.GetContinue() || child.GetReturn()) { 31 | break; 32 | } 33 | } 34 | 35 | child.BlockEnd(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/ast/statement/expression_statement.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/statement/expression_statement.h" 2 | #include "ast/expression.h" 3 | 4 | #include "vm/context.h" 5 | 6 | namespace apus { 7 | 8 | ExpressionStatement::ExpressionStatement( 9 | ExprPtr expression) 10 | : expression_(expression) { 11 | 12 | } 13 | 14 | ExpressionStatement::ExpressionStatement(Expression* expression) 15 | : ExpressionStatement(ExprPtr(expression)) { 16 | } 17 | 18 | ExpressionStatement::~ExpressionStatement() { 19 | 20 | } 21 | 22 | void ExpressionStatement::Execute(Context& context) { 23 | if (expression_) { 24 | expression_->Evaluate(context); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ast/statement/for_statement.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/statement/for_statement.h" 2 | #include "ast/statement/block.h" 3 | #include "ast/value/value.h" 4 | #include "vm/context.h" 5 | 6 | namespace apus { 7 | 8 | ForStatement::ForStatement(ExprPtr initialization, 9 | ExprPtr termination, 10 | ExprPtr increment, 11 | StmtPtr body) 12 | 13 | : initialization_(initialization), termination_(termination), 14 | increment_(increment), body_(body) { 15 | } 16 | 17 | ForStatement::ForStatement(Expression* initialization, 18 | Expression* termination, 19 | Expression* increment, 20 | Statement* body) { 21 | 22 | initialization_ = ExprPtr(initialization); 23 | termination_ = ExprPtr(termination); 24 | increment_ = ExprPtr(increment); 25 | body_ = StmtPtr(body); 26 | } 27 | 28 | ForStatement::~ForStatement() { 29 | 30 | } 31 | 32 | void ForStatement::Execute(Context& context) { 33 | 34 | if (initialization_) { 35 | initialization_->Evaluate(context); 36 | } 37 | 38 | while (true) { 39 | 40 | bool terminate = false; 41 | 42 | if (termination_) { 43 | terminate = !Value::IsTrue(termination_->Evaluate(context)); 44 | } 45 | 46 | if (!terminate) { 47 | if (body_) { 48 | body_->Execute(context); 49 | } 50 | 51 | if (context.GetBreak()) { 52 | context.SetBreak(false); 53 | break; 54 | } 55 | 56 | if (context.GetContinue()) { 57 | context.SetContinue(false); 58 | } 59 | 60 | if (increment_) { 61 | increment_->Evaluate(context); 62 | } 63 | } 64 | else { 65 | break; 66 | } 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/ast/statement/if_statement.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/statement/if_statement.h" 2 | #include "ast/statement/block.h" 3 | #include "ast/expression.h" 4 | 5 | #include "ast/value/value.h" 6 | 7 | #include "vm/context.h" 8 | 9 | namespace apus { 10 | 11 | IfStatement::IfStatement(ExprPtr condition, 12 | StmtPtr true_block, 13 | StmtPtr false_block) 14 | : condition_(condition), true_block_(true_block), 15 | false_block_(false_block) { 16 | } 17 | 18 | IfStatement::IfStatement(Expression *condition, 19 | Statement *true_block, 20 | Statement *false_block) { 21 | condition_ = ExprPtr(condition); 22 | true_block_ = StmtPtr(true_block); 23 | false_block_ = StmtPtr(false_block); 24 | } 25 | 26 | IfStatement::~IfStatement() { 27 | 28 | } 29 | 30 | void IfStatement::Execute(Context& context) { 31 | 32 | if (condition_) { 33 | 34 | if (Value::IsTrue(condition_->Evaluate(context))) { 35 | 36 | if (true_block_) { 37 | true_block_->Execute(context); 38 | } 39 | } 40 | 41 | else { 42 | 43 | if (false_block_) { 44 | false_block_->Execute(context); 45 | } 46 | } 47 | 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/ast/statement/jump_statement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ast/statement/jump_statement.h" 4 | #include "ast/statement/for_statement.h" 5 | 6 | #include "ast/value/signed_int_value.h" 7 | #include "ast/value/unsigned_int_value.h" 8 | 9 | #include "vm/context.h" 10 | 11 | namespace apus { 12 | 13 | void BreakStatement::Execute(Context& context) { 14 | context.SetBreak(true); 15 | } 16 | 17 | void ContinueStatement::Execute(Context& context) { 18 | context.SetContinue(true); 19 | } 20 | 21 | ReturnStatement::ReturnStatement() 22 | : expression_(nullptr) { 23 | 24 | } 25 | 26 | ReturnStatement::ReturnStatement(ExprPtr expression) 27 | : expression_(expression) { 28 | 29 | } 30 | 31 | ReturnStatement::ReturnStatement(Expression *expression) 32 | : ReturnStatement( ExprPtr(expression) ) { 33 | } 34 | 35 | void ReturnStatement::Execute(Context& context) { 36 | 37 | if (expression_) { 38 | expression_->Evaluate(context); 39 | } 40 | 41 | context.SetReturn(true); 42 | } 43 | 44 | ExitStatement::ExitStatement(ExprPtr expression) 45 | : expression_(expression) { 46 | 47 | } 48 | 49 | ExitStatement::ExitStatement(Expression *expression) 50 | : ExitStatement( ExprPtr(expression) ) { 51 | } 52 | 53 | void ExitStatement::Execute(Context &context) { 54 | 55 | int int_val = 0; 56 | 57 | if (expression_) { 58 | ValuePtr val = expression_->Evaluate(context); 59 | TypeSpecifier val_type = val->getType(); 60 | 61 | if (S8 <= val_type && val_type <= S64) { 62 | int_val = std::dynamic_pointer_cast(val)->getIntValue(); 63 | } 64 | else if (U8 <= val_type && val_type <= U64) { 65 | int_val = std::dynamic_pointer_cast(val)->getUIntValue(); 66 | } 67 | 68 | } 69 | 70 | exit(int_val); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/ast/statement/var_def_statement.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/statement/var_def_statement.h" 2 | 3 | #include "ast/value/value.h" 4 | 5 | #include "vm/variable_table.h" 6 | #include "vm/context.h" 7 | 8 | namespace apus { 9 | 10 | VarDefStatement::VarDefStatement(TypeSpecifier type, std::string name) { 11 | type_ = type; 12 | type_name_ = ""; 13 | name_ = name; 14 | initializer_ = nullptr; 15 | } 16 | 17 | VarDefStatement::VarDefStatement(TypeSpecifier type, std::string name, Expression* initializer) { 18 | type_ = type; 19 | type_name_ = ""; 20 | name_ = name; 21 | initializer_ = ExprPtr(initializer); 22 | } 23 | 24 | VarDefStatement::VarDefStatement(std::string type_name, 25 | std::string name) { 26 | type_ = NOT_DEFINED; 27 | type_name_ = type_name; 28 | name_ = name; 29 | initializer_ = nullptr; 30 | } 31 | 32 | VarDefStatement::VarDefStatement(std::string type_name, std::string name, 33 | Expression *initializer) { 34 | type_ = NOT_DEFINED; 35 | type_name_ = type_name; 36 | name_ = name; 37 | initializer_ = ExprPtr(initializer); 38 | } 39 | 40 | VarDefStatement::~VarDefStatement() { 41 | 42 | } 43 | 44 | void VarDefStatement::Execute(Context& context) { 45 | 46 | std::shared_ptr var = nullptr; 47 | 48 | if (type_ != NOT_DEFINED) { 49 | var = std::make_shared(name_, context.FindDataType(type_)); 50 | } 51 | else { 52 | var = std::make_shared(name_, context.FindDataType(type_name_)); 53 | } 54 | 55 | if (initializer_) { 56 | var->setValue(initializer_->Evaluate(context)); 57 | } 58 | 59 | else { 60 | var->setValue(nullptr); 61 | } 62 | 63 | context.InsertVariable(var); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/ast/value/character_value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/value/character_value.h" 2 | #include "ast/value/float_value.h" 3 | #include "ast/value/string_value.h" 4 | #include "vm/data_type_table.h" 5 | 6 | namespace apus { 7 | 8 | std::shared_ptr CharacterValue::Create(DataTypePtr data_type, int32_t value) { 9 | 10 | TypeSpecifier type = data_type->GetType(); 11 | 12 | if (type == C8 || type == C16 || type == C32) { 13 | return std::shared_ptr(new CharacterValue(data_type, value)); 14 | } 15 | 16 | return nullptr; 17 | } 18 | 19 | std::shared_ptr CharacterValue::Promote( 20 | const std::shared_ptr another) const { 21 | 22 | const TypeSpecifier another_type = another->getType(); 23 | 24 | if (getType() == another_type) { 25 | return this->Copy(); 26 | } 27 | 28 | switch (another_type) { 29 | 30 | case C8: 31 | case C16: 32 | case C32: { 33 | DataTypePtr return_type = getSize() > another->getSize() 34 | ? data_type_ 35 | : another->getDataType() ; 36 | 37 | return CharacterValue::Create(return_type, this->getCharValue()); 38 | } 39 | 40 | case STR8: { 41 | std::string val; 42 | val += (char)this->getCharValue(); 43 | return StringValue::Create(another->getDataType(), val); 44 | } 45 | case STR16: { 46 | std::u16string val; 47 | val += (char16_t)this->getCharValue(); 48 | return StringValue::CreateU16(another->getDataType(), val); 49 | } 50 | case STR32: { 51 | std::u32string val; 52 | val += (char32_t)this->getCharValue(); 53 | return StringValue::CreateU32(another->getDataType(), val); 54 | } 55 | 56 | default: 57 | return nullptr; 58 | 59 | } 60 | 61 | } 62 | 63 | std::shared_ptr CharacterValue::OperateBinary( 64 | const Expression::Type expression_type, 65 | const std::shared_ptr &right_promoted) const { 66 | 67 | std::shared_ptr result = nullptr; 68 | 69 | if (right_promoted->getType() == this->getType()) { 70 | 71 | std::shared_ptr right_dynamic = std::dynamic_pointer_cast(right_promoted); 72 | 73 | int32_t left_value = this->getCharValue(); 74 | int32_t right_value = right_dynamic->getCharValue(); 75 | 76 | int32_t result_value = 0; 77 | 78 | switch (expression_type) { 79 | 80 | case Expression::Type::EXP_ASSIGN : 81 | result_value = right_value; 82 | break; 83 | 84 | case Expression::Type::EXP_EQL : 85 | result_value = left_value == right_value; 86 | break; 87 | case Expression::Type::EXP_NEQ : 88 | result_value = left_value != right_value; 89 | break; 90 | case Expression::Type::EXP_LSS : 91 | result_value = left_value < right_value; 92 | break; 93 | case Expression::Type::EXP_GTR : 94 | result_value = left_value > right_value; 95 | break; 96 | case Expression::Type::EXP_LEQ : 97 | result_value = left_value <= right_value; 98 | break; 99 | case Expression::Type::EXP_GEQ : 100 | result_value = left_value >= right_value; 101 | break; 102 | 103 | default: 104 | return nullptr; 105 | } 106 | 107 | result = CharacterValue::Create(data_type_, result_value); 108 | } 109 | 110 | return result; 111 | } 112 | 113 | std::shared_ptr CharacterValue::OperateUnary( 114 | const Expression::Type expression_type) const { 115 | 116 | return nullptr; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/ast/value/float_value.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ast/value/float_value.h" 5 | #include "ast/value/signed_int_value.h" 6 | #include "ast/value/string_value.h" 7 | 8 | namespace apus { 9 | 10 | std::shared_ptr FloatValue::Create(DataTypePtr data_type, 11 | double value) { 12 | TypeSpecifier type = data_type->GetType(); 13 | if (type == F32 || type == F64) { 14 | return std::shared_ptr(new FloatValue(data_type, value)); 15 | } 16 | 17 | return nullptr; 18 | } 19 | 20 | ValuePtr FloatValue::Promote(const ValuePtr another) const { 21 | 22 | const TypeSpecifier another_type = another->getType(); 23 | 24 | // case 1. Exactly same type 25 | if (getType() == another_type) { 26 | return this->Copy(); 27 | } 28 | 29 | switch (another_type) { 30 | 31 | case F32: 32 | case F64: { 33 | DataTypePtr return_type = getSize() > another->getSize() 34 | ? data_type_ 35 | : another->getDataType(); 36 | 37 | return FloatValue::Create(return_type, this->getFloatValue()); 38 | } 39 | 40 | case S8: 41 | case S16: 42 | case S32: 43 | case S64: 44 | case U8: 45 | case U16: 46 | case U32: 47 | case U64: { 48 | 49 | return this->Copy(); 50 | 51 | } 52 | 53 | case STR8: { 54 | std::string val = std::to_string(this->getFloatValue()); 55 | return StringValue::Create(another->getDataType(), val); 56 | } 57 | case STR16: { 58 | std::u16string val; 59 | val += this->getFloatValue(); 60 | return StringValue::CreateU16(another->getDataType(), val); 61 | } 62 | case STR32: { 63 | std::u32string val; 64 | val += this->getFloatValue(); 65 | return StringValue::CreateU32(another->getDataType(), val); 66 | } 67 | 68 | default: 69 | return nullptr; 70 | } 71 | 72 | } 73 | 74 | ValuePtr FloatValue::OperateBinary( 75 | const Expression::Type expression_type, 76 | const ValuePtr &right_promoted) const { 77 | 78 | ValuePtr result = nullptr; 79 | 80 | // 'right' value MUST be same type with this's type; 81 | if (right_promoted->getType() == this->getType()) { 82 | 83 | double epsilon = std::numeric_limits::epsilon(); 84 | 85 | std::shared_ptr right_dynamic = std::dynamic_pointer_cast(right_promoted); 86 | 87 | double left_value = this->getFloatValue(); 88 | double right_value = right_dynamic->getFloatValue(); 89 | 90 | double result_value = 0; 91 | 92 | switch (expression_type) { 93 | 94 | case Expression::Type::EXP_OR : 95 | return nullptr; 96 | case Expression::Type::EXP_AND : 97 | return nullptr; 98 | 99 | case Expression::Type::EXP_EQL : 100 | result_value = this->NearlyEqual(right_value); 101 | break; 102 | case Expression::Type::EXP_NEQ : 103 | result_value = !this->NearlyEqual(right_value); 104 | break; 105 | case Expression::Type::EXP_LSS : 106 | result_value = left_value < right_value; 107 | break; 108 | case Expression::Type::EXP_GTR : 109 | result_value = left_value > right_value; 110 | break; 111 | case Expression::Type::EXP_LEQ : 112 | result_value = (left_value < right_value) || this->NearlyEqual(right_value); 113 | break; 114 | case Expression::Type::EXP_GEQ : 115 | result_value = (left_value > right_value) || this->NearlyEqual(right_value); 116 | break; 117 | 118 | case Expression::Type::EXP_ASSIGN : 119 | result_value = right_value; 120 | break; 121 | 122 | case Expression::Type::EXP_LSHIFT : 123 | case Expression::Type::EXP_LSASSIGN : 124 | return nullptr; 125 | case Expression::Type::EXP_RSHIFT : 126 | case Expression::Type::EXP_RSASSIGN : 127 | return nullptr; 128 | 129 | case Expression::Type::EXP_ADD : 130 | case Expression::Type::EXP_ADDASSIGN : 131 | result_value = left_value + right_value; 132 | break; 133 | case Expression::Type::EXP_SUB : 134 | case Expression::Type::EXP_SUBASSIGN : 135 | result_value = left_value - right_value; 136 | break; 137 | case Expression::Type::EXP_MUL : 138 | case Expression::Type::EXP_MULASSIGN : 139 | result_value = left_value * right_value; 140 | break; 141 | case Expression::Type::EXP_DIV : 142 | case Expression::Type::EXP_DIVASSIGN : 143 | result_value = left_value / right_value; 144 | break; 145 | case Expression::Type::EXP_MOD : 146 | case Expression::Type::EXP_MODASSIGN : 147 | result_value = fmod(left_value, right_value); 148 | break; 149 | case Expression::Type::EXP_XOR : 150 | case Expression::Type::EXP_XORASSIGN : 151 | return nullptr; 152 | 153 | case Expression::Type::EXP_LOR : 154 | result_value = left_value || right_value; 155 | break; 156 | case Expression::Type::EXP_LAND : 157 | result_value = left_value && right_value; 158 | break; 159 | 160 | default: 161 | return nullptr; 162 | } 163 | 164 | result = FloatValue::Create(data_type_, result_value); 165 | } 166 | 167 | return result; 168 | } 169 | 170 | ValuePtr FloatValue::OperateUnary( 171 | const Expression::Type expression_type) const { 172 | 173 | ValuePtr result = nullptr; 174 | double result_value = 0; 175 | 176 | switch (expression_type) { 177 | case Expression::Type::EXP_NOT : 178 | result_value = !(this->getFloatValue()); 179 | break; 180 | case Expression::Type::EXP_REVERSE : 181 | // reverse operation not supported 182 | return nullptr; 183 | case Expression::Type::EXP_SUB : 184 | result_value = -(this->getFloatValue()); 185 | break; 186 | case Expression::Type::EXP_ADD : 187 | result_value = +(this->getFloatValue()); 188 | break; 189 | 190 | default: 191 | return nullptr; 192 | } 193 | 194 | result = FloatValue::Create(data_type_, result_value); 195 | 196 | return result; 197 | } 198 | 199 | double FloatValue::NearlyEqual(double another) const { 200 | 201 | const double a = getFloatValue(); 202 | const double b = another; 203 | 204 | const double absA = std::abs(a); 205 | const double absB = std::abs(b); 206 | const double diff = std::abs(a - b); 207 | 208 | const double epsilon = std::numeric_limits::epsilon(); 209 | 210 | if (a == b) { 211 | // shortcut, handles infinities 212 | return true; 213 | } 214 | else if (a == 0 || b == 0 || diff < std::numeric_limits::min()) { 215 | // a or b is zero or both are extremely close to it 216 | // relative error is less meaningful here 217 | return diff < (epsilon * std::numeric_limits::min()); 218 | } 219 | else { // use relative error 220 | return diff / std::min((absA + absB), std::numeric_limits::max()) < epsilon; 221 | } 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /src/ast/value/signed_int_value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/value/signed_int_value.h" 2 | #include "ast/value/unsigned_int_value.h" 3 | #include "ast/value/float_value.h" 4 | #include "ast/value/character_value.h" 5 | #include "ast/value/string_value.h" 6 | 7 | #include "ast/expression.h" 8 | #include "common/common.h" 9 | 10 | namespace apus { 11 | 12 | std::shared_ptr SignedIntValue::Create(DataTypePtr data_type, 13 | int64_t value) { 14 | TypeSpecifier type = data_type->GetType(); 15 | if (type == S8 || type == S16 || type == S32 || type == S64) { 16 | return std::shared_ptr(new SignedIntValue(data_type, value)); 17 | } 18 | 19 | return nullptr; 20 | } 21 | 22 | ValuePtr SignedIntValue::Promote(const ValuePtr another) const { 23 | 24 | // PROMOTE THIS, NOT another 25 | 26 | const TypeSpecifier another_type = another->getType(); 27 | 28 | // case 1. Exactly same type 29 | if (getType() == another_type) { 30 | return this->Copy(); 31 | } 32 | 33 | switch (another_type) { 34 | 35 | case S8: 36 | case S16: 37 | case S32: 38 | case S64: { 39 | DataTypePtr return_type = getSize() > another->getSize() ? data_type_ : another->getDataType(); 40 | TypeSpecifier type = return_type->GetType(); 41 | return SignedIntValue::Create(return_type, this->getIntValue()); 42 | } 43 | case U8: 44 | case U16: 45 | case U32: 46 | case U64: { 47 | 48 | if (getSize() > another->getSize()) { 49 | return SignedIntValue::Create(data_type_, this->getIntValue()); 50 | } 51 | else { 52 | return UnsignedIntValue::Create(another->getDataType(), this->getIntValue()); 53 | } 54 | } 55 | 56 | case F32: 57 | case F64: { 58 | double double_value = static_cast(this->getIntValue()); 59 | return FloatValue::Create(another->getDataType(), double_value); 60 | } 61 | 62 | case STR8: { 63 | std::string val = std::to_string(this->getIntValue()); 64 | return StringValue::Create(another->getDataType(), val); 65 | } 66 | case STR16: { 67 | std::u16string val; 68 | val += this->getIntValue(); 69 | return StringValue::CreateU16(another->getDataType(), val); 70 | } 71 | case STR32: { 72 | std::u32string val; 73 | val += this->getIntValue(); 74 | return StringValue::CreateU32(another->getDataType(), val); 75 | } 76 | 77 | default: 78 | return nullptr; 79 | } 80 | } 81 | 82 | ValuePtr SignedIntValue::OperateBinary( 83 | const Expression::Type expression_type, 84 | const ValuePtr &right_promoted) const { 85 | 86 | ValuePtr result = nullptr; 87 | 88 | // 'right' value MUST be same type with this's type; 89 | if (right_promoted->getType() == this->getType()) { 90 | 91 | std::shared_ptr right_dynamic = std::dynamic_pointer_cast(right_promoted); 92 | 93 | int64_t left_value = this->getIntValue(); 94 | int64_t right_value = right_dynamic->getIntValue(); 95 | 96 | int64_t result_value = 0; 97 | 98 | switch (expression_type) { 99 | 100 | case Expression::Type::EXP_OR : 101 | result_value = left_value | right_value; 102 | break; 103 | case Expression::Type::EXP_AND : 104 | result_value = left_value & right_value; 105 | break; 106 | 107 | case Expression::Type::EXP_EQL : 108 | result_value = left_value == right_value; 109 | break; 110 | case Expression::Type::EXP_NEQ : 111 | result_value = left_value != right_value; 112 | break; 113 | case Expression::Type::EXP_LSS : 114 | result_value = left_value < right_value; 115 | break; 116 | case Expression::Type::EXP_GTR : 117 | result_value = left_value > right_value; 118 | break; 119 | case Expression::Type::EXP_LEQ : 120 | result_value = left_value <= right_value; 121 | break; 122 | case Expression::Type::EXP_GEQ : 123 | result_value = left_value >= right_value; 124 | break; 125 | 126 | case Expression::Type::EXP_ASSIGN : 127 | result_value = right_value; 128 | break; 129 | 130 | case Expression::Type::EXP_LSHIFT : 131 | case Expression::Type::EXP_LSASSIGN : 132 | result_value = left_value << right_value; 133 | break; 134 | case Expression::Type::EXP_RSHIFT : 135 | case Expression::Type::EXP_RSASSIGN : 136 | result_value = left_value >> right_value; 137 | break; 138 | 139 | case Expression::Type::EXP_ADD : 140 | case Expression::Type::EXP_ADDASSIGN : 141 | result_value = left_value + right_value; 142 | break; 143 | case Expression::Type::EXP_SUB : 144 | case Expression::Type::EXP_SUBASSIGN : 145 | result_value = left_value - right_value; 146 | break; 147 | case Expression::Type::EXP_MUL : 148 | case Expression::Type::EXP_MULASSIGN : 149 | result_value = left_value * right_value; 150 | break; 151 | case Expression::Type::EXP_DIV : 152 | case Expression::Type::EXP_DIVASSIGN : 153 | result_value = left_value / right_value; 154 | break; 155 | case Expression::Type::EXP_MOD : 156 | case Expression::Type::EXP_MODASSIGN : 157 | result_value = left_value % right_value; 158 | break; 159 | case Expression::Type::EXP_XOR : 160 | case Expression::Type::EXP_XORASSIGN : 161 | result_value = left_value ^ right_value; 162 | break; 163 | 164 | case Expression::Type::EXP_LOR : 165 | result_value = left_value || right_value; 166 | break; 167 | case Expression::Type::EXP_LAND : 168 | result_value = left_value && right_value; 169 | break; 170 | 171 | default: 172 | return nullptr; 173 | } 174 | 175 | result = SignedIntValue::Create(data_type_, result_value); 176 | } 177 | 178 | return result; 179 | } 180 | 181 | ValuePtr SignedIntValue::OperateUnary( 182 | const Expression::Type expression_type) const { 183 | 184 | ValuePtr result = nullptr; 185 | int64_t result_value = 0; 186 | 187 | switch (expression_type) { 188 | case Expression::Type::EXP_NOT : 189 | result_value = !(this->getIntValue()); 190 | break; 191 | case Expression::Type::EXP_REVERSE : 192 | result_value = ~(this->getIntValue()); 193 | break; 194 | case Expression::Type::EXP_SUB : 195 | result_value = -(this->getIntValue()); 196 | break; 197 | case Expression::Type::EXP_ADD : 198 | result_value = +(this->getIntValue()); 199 | break; 200 | 201 | default: 202 | return nullptr; 203 | } 204 | 205 | result = SignedIntValue::Create(data_type_, result_value); 206 | 207 | return result; 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /src/ast/value/string_value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/value/string_value.h" 2 | #include "ast/value/float_value.h" 3 | #include "ast/value/character_value.h" 4 | #include "ast/value/signed_int_value.h" 5 | 6 | namespace apus { 7 | 8 | std::shared_ptr StringValue::Create(DataTypePtr data_type, std::string value) { 9 | 10 | TypeSpecifier type = data_type->GetType(); 11 | if (type == STR8) { 12 | return std::shared_ptr(new StringValue(data_type, value)); 13 | } 14 | return nullptr; 15 | } 16 | 17 | std::shared_ptr StringValue::CreateU16(DataTypePtr data_type, std::u16string value) { 18 | 19 | TypeSpecifier type = data_type->GetType(); 20 | if (type == STR16) { 21 | return std::shared_ptr(new StringValue(data_type, value)); 22 | } 23 | return nullptr; 24 | } 25 | 26 | std::shared_ptr StringValue::CreateU32(DataTypePtr data_type, std::u32string value) { 27 | 28 | TypeSpecifier type = data_type->GetType(); 29 | if (type == STR32) { 30 | return std::shared_ptr(new StringValue(data_type, value)); 31 | } 32 | return nullptr; 33 | } 34 | 35 | std::shared_ptr StringValue::Promote( 36 | const std::shared_ptr another) const { 37 | 38 | const TypeSpecifier another_type = another->getType(); 39 | 40 | if (getType() == another_type) { 41 | return this->Copy(); 42 | } 43 | 44 | switch (another_type) { 45 | 46 | case STR8 : { 47 | return this->Copy(); 48 | } 49 | case STR16: { 50 | 51 | switch (getType()) { 52 | case STR8: 53 | return StringValue::CreateU16(another->getDataType(), Utf8To16(getStringValue())); 54 | case STR32: 55 | return this->Copy(); 56 | default: 57 | return nullptr; 58 | } 59 | } 60 | case STR32: { 61 | 62 | switch (getType()) { 63 | case STR8: 64 | return StringValue::CreateU32(another->getDataType(), Utf8To32(getStringValue())); 65 | case STR16: 66 | return StringValue::CreateU32(another->getDataType(), Utf16To32(getU16StringValue())); 67 | default: 68 | return nullptr; 69 | } 70 | } 71 | 72 | case F32: 73 | case F64: 74 | case C8: 75 | case C16: 76 | case C32: 77 | case S8: 78 | case S16: 79 | case S32: 80 | case S64: 81 | case U8: 82 | case U16: 83 | case U32: 84 | case U64: { 85 | return this->Copy(); 86 | } 87 | 88 | default: 89 | return nullptr; 90 | } 91 | 92 | } 93 | 94 | std::shared_ptr StringValue::OperateBinary( 95 | const Expression::Type expression_type, 96 | const std::shared_ptr &right_promoted) const { 97 | 98 | std::shared_ptr result = nullptr; 99 | 100 | if (right_promoted->getType() == this->getType()) { 101 | 102 | std::shared_ptr right_dynamic = std::dynamic_pointer_cast(right_promoted); 103 | 104 | switch (data_type_->GetType()) { 105 | case STR8:{ 106 | std::string left_value = this->getStringValue(); 107 | std::string right_value = right_dynamic->getStringValue(); 108 | std::string result_value = StringOperate(expression_type, left_value, right_value); 109 | result = StringValue::Create(data_type_, result_value); 110 | break; 111 | } 112 | case STR16:{ 113 | std::u16string left_value = this->getU16StringValue(); 114 | std::u16string right_value = right_dynamic->getU16StringValue(); 115 | std::u16string result_value = StringOperate(expression_type, left_value, right_value); 116 | result = StringValue::CreateU16(data_type_, result_value); 117 | break; 118 | } 119 | case STR32:{ 120 | std::u32string left_value = this->getU32StringValue(); 121 | std::u32string right_value = right_dynamic->getU32StringValue(); 122 | std::u32string result_value = StringOperate(expression_type, left_value, right_value); 123 | result = StringValue::CreateU32(data_type_, result_value); 124 | break; 125 | } 126 | 127 | default: 128 | return nullptr; 129 | } 130 | 131 | } 132 | 133 | return result; 134 | } 135 | 136 | template 137 | T StringValue::StringOperate(Expression::Type expression_type, 138 | T left_value, 139 | T right_value) const { 140 | T result_value; 141 | 142 | switch (expression_type) { 143 | 144 | case Expression::Type::EXP_EQL : 145 | result_value = left_value == right_value; 146 | break; 147 | case Expression::Type::EXP_NEQ : 148 | result_value = left_value != right_value; 149 | break; 150 | case Expression::Type::EXP_LSS : 151 | result_value = left_value < right_value; 152 | break; 153 | case Expression::Type::EXP_GTR : 154 | result_value = left_value > right_value; 155 | break; 156 | case Expression::Type::EXP_LEQ : 157 | result_value = left_value <= right_value; 158 | break; 159 | case Expression::Type::EXP_GEQ : 160 | result_value = left_value >= right_value; 161 | break; 162 | 163 | case Expression::Type::EXP_ADD : 164 | case Expression::Type::EXP_ADDASSIGN : 165 | result_value = left_value + right_value; 166 | break; 167 | 168 | default: 169 | return nullptr; 170 | } 171 | 172 | return result_value; 173 | } 174 | 175 | std::shared_ptr StringValue::OperateUnary( 176 | const Expression::Type expression_type) const { 177 | 178 | std::shared_ptr result = nullptr; 179 | 180 | return result; 181 | } 182 | 183 | std::u16string StringValue::Utf8To16(std::string string) const { 184 | const char* str_data = string.data(); 185 | std::u16string result = u""; 186 | 187 | while (*str_data) { 188 | char16_t c = static_cast(*str_data); 189 | result += c; 190 | str_data++; 191 | } 192 | return result; 193 | } 194 | 195 | std::u32string StringValue::Utf8To32(std::string string) const { 196 | const char* str_data = string.data(); 197 | std::u32string result = U""; 198 | 199 | while (*str_data) { 200 | char32_t c = static_cast(*str_data); 201 | result += c; 202 | str_data++; 203 | } 204 | return result; 205 | } 206 | 207 | std::u32string StringValue::Utf16To32(std::u16string string) const { 208 | const char16_t* str_data = string.data(); 209 | std::u32string result = U""; 210 | 211 | while (*str_data) { 212 | char32_t c = static_cast(*str_data); 213 | result += c; 214 | str_data++; 215 | } 216 | return result; 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /src/ast/value/unsigned_int_value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/value/unsigned_int_value.h" 2 | #include "ast/value/signed_int_value.h" 3 | #include "ast/value/character_value.h" 4 | #include "ast/value/float_value.h" 5 | #include "ast/value/string_value.h" 6 | 7 | #include "common/common.h" 8 | 9 | namespace apus { 10 | 11 | std::shared_ptr UnsignedIntValue::Create(DataTypePtr data_type, uint64_t value) { 12 | 13 | TypeSpecifier type = data_type->GetType(); 14 | if (type == U8 || type == U16 || type == U32 || type == U64) { 15 | return std::shared_ptr(new UnsignedIntValue(data_type, value)); 16 | } 17 | 18 | return nullptr; 19 | 20 | } 21 | 22 | std::shared_ptr UnsignedIntValue::Promote( 23 | const std::shared_ptr another) const { 24 | 25 | const TypeSpecifier another_type = another->getType(); 26 | 27 | // case 1. Exactly same type 28 | if (getType() == another_type) { 29 | return this->Copy(); 30 | } 31 | 32 | switch (another_type) { 33 | 34 | case U8: 35 | case U16: 36 | case U32: 37 | case U64: { 38 | DataTypePtr return_type = getSize() > another->getSize() ? data_type_ : another->getDataType(); 39 | TypeSpecifier type = return_type->GetType(); 40 | return UnsignedIntValue::Create(return_type, this->getUIntValue()); 41 | } 42 | 43 | case S8: 44 | case S16: 45 | case S32: 46 | case S64: { 47 | 48 | if (getSize() >= another->getSize()) { 49 | return UnsignedIntValue::Create(data_type_, this->getUIntValue()); 50 | } 51 | else { 52 | return SignedIntValue::Create(another->getDataType(), this->getUIntValue()); 53 | } 54 | } 55 | 56 | case F32: 57 | case F64: { 58 | double double_value = static_cast(this->getUIntValue()); 59 | return FloatValue::Create(another->getDataType(), double_value); 60 | } 61 | 62 | case STR8: { 63 | std::string val = std::to_string(this->getUIntValue()); 64 | return StringValue::Create(another->getDataType(), val); 65 | } 66 | case STR16: { 67 | std::u16string val; 68 | val += this->getUIntValue(); 69 | return StringValue::CreateU16(another->getDataType(), val); 70 | } 71 | case STR32: { 72 | std::u32string val; 73 | val += this->getUIntValue(); 74 | return StringValue::CreateU32(another->getDataType(), val); 75 | } 76 | 77 | default: 78 | return nullptr; 79 | } 80 | 81 | } 82 | 83 | std::shared_ptr UnsignedIntValue::OperateBinary( 84 | const Expression::Type expression_type, 85 | const std::shared_ptr &right_promoted) const { 86 | 87 | std::shared_ptr result = nullptr; 88 | 89 | // 'right' value MUST be same type with this's type; 90 | if (right_promoted->getType() == this->getType()) { 91 | 92 | std::shared_ptr right_dynamic = std::dynamic_pointer_cast(right_promoted); 93 | 94 | uint64_t left_value = this->getUIntValue(); 95 | uint64_t right_value = right_dynamic->getUIntValue(); 96 | 97 | uint64_t result_value = 0; 98 | 99 | switch (expression_type) { 100 | 101 | case Expression::Type::EXP_OR : 102 | result_value = left_value | right_value; 103 | break; 104 | case Expression::Type::EXP_AND : 105 | result_value = left_value & right_value; 106 | break; 107 | 108 | case Expression::Type::EXP_EQL : 109 | result_value = left_value == right_value; 110 | break; 111 | case Expression::Type::EXP_NEQ : 112 | result_value = left_value != right_value; 113 | break; 114 | case Expression::Type::EXP_LSS : 115 | result_value = left_value < right_value; 116 | break; 117 | case Expression::Type::EXP_GTR : 118 | result_value = left_value > right_value; 119 | break; 120 | case Expression::Type::EXP_LEQ : 121 | result_value = left_value <= right_value; 122 | break; 123 | case Expression::Type::EXP_GEQ : 124 | result_value = left_value >= right_value; 125 | break; 126 | 127 | case Expression::Type::EXP_LSHIFT : 128 | case Expression::Type::EXP_LSASSIGN : 129 | result_value = left_value << right_value; 130 | break; 131 | case Expression::Type::EXP_RSHIFT : 132 | case Expression::Type::EXP_RSASSIGN : 133 | result_value = left_value >> right_value; 134 | break; 135 | 136 | case Expression::Type::EXP_ADD : 137 | case Expression::Type::EXP_ADDASSIGN : 138 | result_value = left_value + right_value; 139 | break; 140 | case Expression::Type::EXP_SUB : 141 | case Expression::Type::EXP_SUBASSIGN : 142 | result_value = left_value - right_value; 143 | break; 144 | case Expression::Type::EXP_MUL : 145 | case Expression::Type::EXP_MULASSIGN : 146 | result_value = left_value * right_value; 147 | break; 148 | case Expression::Type::EXP_DIV : 149 | case Expression::Type::EXP_DIVASSIGN : 150 | result_value = left_value / right_value; 151 | break; 152 | case Expression::Type::EXP_MOD : 153 | case Expression::Type::EXP_MODASSIGN : 154 | result_value = left_value % right_value; 155 | break; 156 | case Expression::Type::EXP_XOR : 157 | case Expression::Type::EXP_XORASSIGN : 158 | result_value = left_value ^ right_value; 159 | break; 160 | 161 | case Expression::Type::EXP_LOR : 162 | result_value = left_value || right_value; 163 | break; 164 | case Expression::Type::EXP_LAND : 165 | result_value = left_value && right_value; 166 | break; 167 | 168 | default: 169 | return nullptr; 170 | } 171 | 172 | result = UnsignedIntValue::Create(data_type_, result_value); 173 | } 174 | 175 | return result; 176 | } 177 | 178 | std::shared_ptr UnsignedIntValue::OperateUnary( 179 | const Expression::Type expression_type) const { 180 | 181 | std::shared_ptr result = nullptr; 182 | uint64_t result_value = 0; 183 | 184 | switch (expression_type) { 185 | case Expression::Type::EXP_NOT : 186 | result_value = !(this->getUIntValue()); 187 | break; 188 | case Expression::Type::EXP_REVERSE : 189 | result_value = ~(this->getUIntValue()); 190 | break; 191 | case Expression::Type::EXP_SUB : 192 | result_value = -(this->getUIntValue()); 193 | break; 194 | case Expression::Type::EXP_ADD : 195 | result_value = +(this->getUIntValue()); 196 | break; 197 | 198 | default: 199 | return nullptr; 200 | } 201 | 202 | result = UnsignedIntValue::Create(data_type_, result_value); 203 | 204 | return result; 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /src/ast/value/value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/value/value.h" 2 | 3 | #include "ast/value/signed_int_value.h" 4 | #include "ast/value/float_value.h" 5 | #include "ast/value/unsigned_int_value.h" 6 | #include "ast/value/character_value.h" 7 | #include "ast/value/string_value.h" 8 | 9 | namespace apus { 10 | 11 | bool Value::IsTrue(std::shared_ptr value) { 12 | 13 | switch (value->getType()) { 14 | case S8: 15 | case S16: 16 | case S32: 17 | case S64: 18 | return (std::dynamic_pointer_cast(value)->getIntValue() != 0); 19 | 20 | case U8: 21 | case U16: 22 | case U32: 23 | case U64: 24 | return (std::dynamic_pointer_cast(value)->getUIntValue() != 0); 25 | 26 | case C8: 27 | case C16: 28 | case C32: 29 | return (std::dynamic_pointer_cast(value)->getCharValue() != 0); 30 | 31 | case F32: 32 | case F64: 33 | return (std::dynamic_pointer_cast(value)->getFloatValue() != 0); 34 | 35 | case STR8:{ 36 | char val = std::dynamic_pointer_cast(value)->getStringValue()[0]; 37 | return val; 38 | } 39 | case STR16: { 40 | char16_t val = std::dynamic_pointer_cast(value)->getU16StringValue()[0]; 41 | return val; 42 | } 43 | case STR32: { 44 | char32_t val = std::dynamic_pointer_cast(value)->getU32StringValue()[0]; 45 | return val; 46 | } 47 | 48 | default: 49 | return false; 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/common/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common/common.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace apus { 6 | 7 | int TypeLength(TypeSpecifier type) { 8 | int length = 0; 9 | switch (type) { 10 | case U8: 11 | case S8: 12 | case C8: 13 | length = 1; // 1 byte 14 | break; 15 | 16 | case U16: 17 | case S16: 18 | case C16: 19 | length = 2; // 2 bytes 20 | break; 21 | 22 | case U32: 23 | case S32: 24 | case C32: 25 | case F32: 26 | length = 4; // 4 bytes 27 | break; 28 | 29 | case U64: 30 | case S64: 31 | case F64: 32 | length = 8; // 8 bytes 33 | break; 34 | 35 | case STR8: 36 | case STR16: 37 | case STR32: 38 | length = 0; // not fixed. variable-length 39 | break; 40 | 41 | // exception 42 | default: 43 | DispErr("There's no matched variable type."); 44 | length = -1; 45 | break; 46 | } 47 | return length; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "parser_context.h" 5 | #include "vm/virtual_machine.h" 6 | 7 | extern int yyparse(apus::ParserContext* pctx); 8 | extern FILE* yyin; 9 | 10 | void PrintUsage() { 11 | 12 | std::cerr << "Usage: apus [options] " << std::endl; 13 | std::cerr << "-f, --file=FILE Use FILE as apus script"< vm = std::make_shared(); 57 | apus::ParserContext pctx(vm); 58 | 59 | int result = yyparse(&pctx); 60 | 61 | if (result == 0) { 62 | vm->Run(binary_file_name); 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /src/parser_context.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_context.h" 2 | 3 | namespace apus { 4 | 5 | ParserContext::ParserContext() { 6 | // make current data type instance 7 | current_data_type_ = std::make_shared(); 8 | 9 | // make DataTypeTable instance and add primitive data types 10 | data_type_table_ = std::make_shared(); 11 | data_type_table_->SetPrimitiveTypes(); 12 | } 13 | 14 | ParserContext::ParserContext(std::shared_ptr vm) 15 | : ParserContext() { 16 | vm_ = vm; 17 | } 18 | 19 | ParserContext::~ParserContext() { 20 | } 21 | 22 | void ParserContext::setVM(std::shared_ptr vm) { 23 | vm_ = vm; 24 | } 25 | 26 | void ParserContext::SendDataTypeTableToVM() { 27 | vm_->setDataTypeTable(data_type_table_); 28 | } 29 | 30 | DataTypeTablePtr ParserContext::getDataTypeTable() { 31 | return data_type_table_; 32 | } 33 | 34 | void ParserContext::setCurrentName(const std::string& name) { 35 | current_name_ = name; 36 | } 37 | 38 | std::string ParserContext::getCurrentName() { 39 | return current_name_; 40 | } 41 | 42 | void ParserContext::setCurrentDataType(std::shared_ptr type) { 43 | current_data_type_ = type; 44 | } 45 | 46 | DataTypePtr ParserContext::getCurrentDataType() { 47 | return current_data_type_; 48 | } 49 | 50 | // name = name of data type to be inserted 51 | // type_name = name of data type representing 'type' 52 | // e.g. struct A B (B = name, A = type_name) 53 | void ParserContext::AddToCurrentDataType 54 | (const std::string& name, const std::string& type_name) { 55 | current_data_type_->Insert(name, data_type_table_->Find(type_name)); 56 | } 57 | 58 | // Add a primitive data type to current data type 59 | void ParserContext::AddToCurrentDataType 60 | (const std::string& name, TypeSpecifier type) { 61 | current_data_type_->Insert(name, data_type_table_->Find(type)); 62 | } 63 | 64 | // Add a data type reference(shared_ptr) to current data type 65 | void ParserContext::AddToCurrentDataType 66 | (const std::string& name, DataTypePtr type) { 67 | current_data_type_->Insert(name, type); 68 | } 69 | 70 | // Add a data type reference(raw pointer) to current data type 71 | void ParserContext::AddToCurrentDataType 72 | (const std::string& name, DataType* type) { 73 | current_data_type_->Insert(name, type); 74 | } 75 | 76 | void ParserContext::ChangeCurrentDataType() { 77 | // Add current data type into data type table 78 | data_type_table_->Insert(current_name_, current_data_type_); 79 | 80 | // clear current name and reference to old current data type 81 | current_name_.clear(); 82 | current_data_type_.reset(); 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/utils/BinaryReader.cpp: -------------------------------------------------------------------------------- 1 | #include "common/common.h" 2 | #include "utils/BinaryReader.h" 3 | using namespace std; 4 | 5 | namespace apus { 6 | 7 | int BinaryReader::ConvertBytes(byte out_array[], int length) { 8 | 9 | byte temp; 10 | try { 11 | for (int i = 0; i < (length / 2); i++) { 12 | temp = out_array[i]; 13 | out_array[i] = out_array[(length - 1) - i]; 14 | out_array[(length - 1) - i] = temp; 15 | } 16 | } catch (std::exception &e) { 17 | DispErr("Out of Range error"); 18 | return -1; 19 | } 20 | return 0; 21 | } 22 | 23 | BinaryReader::BinaryReader() { 24 | 25 | file_endian_ = NOT_SET; 26 | } 27 | 28 | BinaryReader::BinaryReader(string &file_name) { 29 | 30 | file_endian_ = NOT_SET; 31 | file_name_.assign(file_name); 32 | 33 | // open the file in binary instream manner 34 | file_stream_.open(file_name_, ios::in | ios::binary); 35 | if (!file_stream_.is_open()) { 36 | DispErr("There's no file with name: " + file_name); 37 | DispErr("Program will exit."); 38 | exit(-1); 39 | } 40 | } 41 | 42 | BinaryReader::~BinaryReader() { 43 | 44 | // close file stream 45 | file_stream_.close(); 46 | } 47 | 48 | Endian BinaryReader::GetFileEndian() { 49 | 50 | return file_endian_; 51 | } 52 | 53 | void BinaryReader::SetFileEndian(Endian endian) { 54 | 55 | if (endian != NOT_SET) { 56 | file_endian_ = endian; 57 | } 58 | } 59 | 60 | int BinaryReader::ReadInt(streampos pos, TypeSpecifier type, uint64_t &out_int) { 61 | 62 | // If it's not proper type, return -1 63 | if (type != U8 && type != U16 && type != U32 && type != U64 && 64 | type != S8 && type != S16 && type != S32 && type != S64) { 65 | return -1; 66 | } 67 | 68 | int length = TypeLength(type); 69 | union { 70 | char bytes[8]; 71 | uint64_t value; 72 | } Integer = {{0,}}; 73 | 74 | // move to the offset POS and read bytes 75 | file_stream_.seekg(pos, ios::beg); 76 | file_stream_.read(Integer.bytes, length); 77 | 78 | // If endian of this file is set and different from host endian, 79 | // revert order of bytes in INTEGER union. 80 | if ((file_endian_ != NOT_SET) && 81 | (file_endian_ != HostEndian())) { 82 | ConvertBytes(Integer.bytes, length); 83 | } 84 | 85 | out_int = Integer.value; 86 | return 0; 87 | } 88 | 89 | int BinaryReader::ReadInt(TypeSpecifier type, uint64_t &out_int) { 90 | 91 | return ReadInt(file_stream_.tellg(), type, out_int); 92 | } 93 | 94 | int BinaryReader::ReadReal(streampos pos, TypeSpecifier type, double &out_real) { 95 | 96 | // If it's not proper type, return -1 97 | if (type != F32 && type != F64) { 98 | return -1; 99 | } 100 | 101 | int length = TypeLength(type); 102 | union { 103 | char bytes[8]; 104 | float single_value; 105 | double double_value; 106 | } Real = {{0,}}; 107 | 108 | // move to the offset POS and read bytes 109 | file_stream_.seekg(pos, ios::beg); 110 | file_stream_.read(Real.bytes, length); 111 | 112 | // If endian of this file is set and different from host endian, 113 | // revert order of bytes in REAL union. 114 | if ((file_endian_ != NOT_SET) && 115 | (file_endian_ != HostEndian())) { 116 | ConvertBytes(Real.bytes, length); 117 | } 118 | 119 | if (type == F32) { 120 | out_real = (double) Real.single_value; 121 | } else if (type == F64) { 122 | out_real = Real.double_value; 123 | } 124 | return 0; 125 | } 126 | 127 | int BinaryReader::ReadReal(TypeSpecifier type, double &out_real) { 128 | 129 | return ReadReal(file_stream_.tellg(), type, out_real); 130 | } 131 | 132 | int BinaryReader::ReadChar(streampos pos, TypeSpecifier type, 133 | uint32_t &out_char) { 134 | 135 | // If it's not proper type, return -1 136 | if (type != C8 && type != C16 && type != C32) { 137 | return -1; 138 | } 139 | 140 | int length = TypeLength(type); 141 | union { 142 | char bytes[4]; 143 | uint8_t c8; 144 | uint16_t c16; 145 | uint32_t c32; 146 | } Character = {{0,}}; 147 | 148 | // move to the offset POS and read bytes 149 | file_stream_.seekg(pos, ios::beg); 150 | file_stream_.read(Character.bytes, length); 151 | 152 | if (type == C8) { 153 | out_char = (uint32_t) Character.c8; 154 | } else if (type == C16) { 155 | out_char = (uint32_t) Character.c16; 156 | } else if (type == C32) { 157 | out_char = Character.c32; 158 | } 159 | return 0; 160 | } 161 | 162 | int BinaryReader::ReadChar(TypeSpecifier type, uint32_t &out_char) { 163 | 164 | return ReadChar(file_stream_.tellg(), type, out_char); 165 | } 166 | 167 | int BinaryReader::ReadString(streampos pos, TypeSpecifier type, string &out_str) { 168 | 169 | uint32_t read = 0; // read character 170 | TypeSpecifier char_type; // type of a character 171 | 172 | // assign type of a character 173 | if (type == STR8) { 174 | char_type = C8; 175 | } else if (type == STR16) { 176 | char_type = C16; 177 | } else if (type == STR32) { 178 | char_type = C32; 179 | } else { 180 | // If it's not proper type, return -1 181 | return -1; 182 | } 183 | 184 | // move to the offset POS 185 | file_stream_.seekg(pos, ios::beg); 186 | do { 187 | if (ReadChar(char_type, read) != 0) { 188 | // If reading character fails, return -1 189 | return -1; 190 | } else { 191 | // If reading character succeeds, concatenate it to the string 192 | union { 193 | char bytes[4]; 194 | uint32_t read; 195 | } Character; 196 | Character.read = read; 197 | out_str.append(Character.bytes); 198 | } 199 | } while (read != 0); 200 | 201 | return 0; 202 | } 203 | 204 | int BinaryReader::ReadString(TypeSpecifier type, string &out_char) { 205 | 206 | return ReadString(file_stream_.tellg(), type, out_char); 207 | } 208 | } 209 | 210 | -------------------------------------------------------------------------------- /src/vm/builtin_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "vm/builtin_functions.h" 3 | #include "vm/variable_table.h" 4 | 5 | #include "utils/BinaryReader.h" 6 | 7 | #include "ast/value/signed_int_value.h" 8 | #include "ast/value/unsigned_int_value.h" 9 | #include "ast/value/string_value.h" 10 | 11 | namespace apus { 12 | 13 | // Built-in Functions 14 | 15 | std::shared_ptr BuiltInFunction::Execute(Context &context) { 16 | 17 | Context child = context.BlockBegin(); 18 | 19 | this->BlockBody(child); 20 | 21 | child.BlockEnd(); 22 | return context.GetReturnValue(); 23 | } 24 | 25 | PrintS64::PrintS64(Context& context) { 26 | name_ = "printS64"; 27 | return_type_ = context.GetDataTypeTable()->Find(std::string("S64")); 28 | 29 | VariablePtr arg = 30 | std::make_shared( 31 | std::string("val"), 32 | context.GetDataTypeTable()->Find(S64) 33 | ); 34 | 35 | arg_list_.push_back(arg); 36 | } 37 | 38 | std::shared_ptr PrintS64::BlockBody(Context & context) { 39 | 40 | ValuePtr value = nullptr; 41 | VariablePtr var = context.FindVariable("val"); 42 | 43 | if (var) { 44 | value = var->getValue(); 45 | 46 | int64_t int_val = std::dynamic_pointer_cast(value)->getIntValue(); 47 | cout << int_val << endl; 48 | 49 | context.SetReturnValue(value); 50 | } 51 | return value; 52 | } 53 | 54 | 55 | PrintSTR8::PrintSTR8(Context& context) { 56 | name_ = "printSTR8"; 57 | return_type_ = context.GetDataTypeTable()->Find(STR8); 58 | 59 | VariablePtr arg = 60 | std::make_shared( 61 | std::string("val"), 62 | context.GetDataTypeTable()->Find(STR8) 63 | ); 64 | 65 | arg_list_.push_back(arg); 66 | } 67 | 68 | std::shared_ptr PrintSTR8::BlockBody(Context & context) { 69 | 70 | ValuePtr value = nullptr; 71 | VariablePtr var = context.FindVariable("val"); 72 | 73 | if (var) { 74 | value = var->getValue(); 75 | 76 | std::string str_val = std::dynamic_pointer_cast(value)->getStringValue(); 77 | cout << str_val << endl; 78 | 79 | context.SetReturnValue(value); 80 | } 81 | 82 | return value; 83 | } 84 | 85 | // READ signed int number 86 | 87 | ReadS8::ReadS8(Context& context) { 88 | name_ = "readS8"; 89 | return_type_ = context.GetDataTypeTable()->Find(std::string("S8")); 90 | } 91 | 92 | std::shared_ptr ReadS8::BlockBody(Context & context) { 93 | 94 | shared_ptr value = nullptr; 95 | shared_ptr bin_reader = context.GetBinaryReader(); 96 | 97 | if (bin_reader) { 98 | 99 | uint64_t int_val; 100 | context.GetBinaryReader()->ReadInt(S8, int_val); 101 | value = SignedIntValue::Create(context.GetDataTypeTable()->Find(S8), int_val); 102 | 103 | } 104 | 105 | context.SetReturnValue(value); 106 | return value; 107 | } 108 | 109 | ReadS16::ReadS16(Context& context) { 110 | name_ = "readS16"; 111 | return_type_ = context.GetDataTypeTable()->Find(std::string("S16")); 112 | } 113 | 114 | std::shared_ptr ReadS16::BlockBody(Context & context) { 115 | 116 | shared_ptr value = nullptr; 117 | shared_ptr bin_reader = context.GetBinaryReader(); 118 | 119 | if (bin_reader) { 120 | 121 | uint64_t int_val; 122 | context.GetBinaryReader()->ReadInt(S16, int_val); 123 | value = SignedIntValue::Create(context.GetDataTypeTable()->Find(S16), int_val); 124 | 125 | } 126 | 127 | context.SetReturnValue(value); 128 | return value; 129 | } 130 | 131 | ReadS32::ReadS32(Context& context) { 132 | name_ = "readS32"; 133 | return_type_ = context.GetDataTypeTable()->Find(std::string("S32")); 134 | } 135 | 136 | std::shared_ptr ReadS32::BlockBody(Context & context) { 137 | 138 | shared_ptr value = nullptr; 139 | shared_ptr bin_reader = context.GetBinaryReader(); 140 | 141 | if (bin_reader) { 142 | 143 | uint64_t int_val; 144 | context.GetBinaryReader()->ReadInt(S32, int_val); 145 | value = SignedIntValue::Create(context.GetDataTypeTable()->Find(S32), int_val); 146 | 147 | } 148 | 149 | context.SetReturnValue(value); 150 | return value; 151 | } 152 | 153 | ReadS64::ReadS64(Context& context) { 154 | name_ = "readS64"; 155 | return_type_ = context.GetDataTypeTable()->Find(std::string("S64")); 156 | } 157 | 158 | std::shared_ptr ReadS64::BlockBody(Context & context) { 159 | 160 | shared_ptr value = nullptr; 161 | shared_ptr bin_reader = context.GetBinaryReader(); 162 | 163 | if (bin_reader) { 164 | 165 | uint64_t int_val; 166 | context.GetBinaryReader()->ReadInt(S64, int_val); 167 | value = SignedIntValue::Create(context.GetDataTypeTable()->Find(S64), int_val); 168 | 169 | } 170 | 171 | context.SetReturnValue(value); 172 | return value; 173 | } 174 | 175 | // READ unsigned int value 176 | 177 | ReadU8::ReadU8(Context& context) { 178 | name_ = "readU8"; 179 | return_type_ = context.GetDataTypeTable()->Find(std::string("U8")); 180 | } 181 | 182 | std::shared_ptr ReadU8::BlockBody(Context & context) { 183 | 184 | shared_ptr value = nullptr; 185 | shared_ptr bin_reader = context.GetBinaryReader(); 186 | 187 | if (bin_reader) { 188 | 189 | uint64_t int_val; 190 | context.GetBinaryReader()->ReadInt(U8, int_val); 191 | value = UnsignedIntValue::Create(context.GetDataTypeTable()->Find(U8), int_val); 192 | 193 | } 194 | 195 | context.SetReturnValue(value); 196 | return value; 197 | } 198 | 199 | ReadU16::ReadU16(Context& context) { 200 | name_ = "readU16"; 201 | return_type_ = context.GetDataTypeTable()->Find(std::string("U16")); 202 | } 203 | 204 | std::shared_ptr ReadU16::BlockBody(Context & context) { 205 | 206 | shared_ptr value = nullptr; 207 | shared_ptr bin_reader = context.GetBinaryReader(); 208 | 209 | if (bin_reader) { 210 | 211 | uint64_t int_val; 212 | context.GetBinaryReader()->ReadInt(U16, int_val); 213 | value = UnsignedIntValue::Create(context.GetDataTypeTable()->Find(U16), int_val); 214 | 215 | } 216 | 217 | context.SetReturnValue(value); 218 | return value; 219 | } 220 | 221 | ReadU32::ReadU32(Context& context) { 222 | name_ = "readU32"; 223 | return_type_ = context.GetDataTypeTable()->Find(std::string("U32")); 224 | } 225 | 226 | std::shared_ptr ReadU32::BlockBody(Context & context) { 227 | 228 | shared_ptr value = nullptr; 229 | shared_ptr bin_reader = context.GetBinaryReader(); 230 | 231 | if (bin_reader) { 232 | 233 | uint64_t int_val; 234 | context.GetBinaryReader()->ReadInt(U32, int_val); 235 | value = UnsignedIntValue::Create(context.GetDataTypeTable()->Find(U32), int_val); 236 | 237 | } 238 | 239 | context.SetReturnValue(value); 240 | return value; 241 | } 242 | 243 | ReadU64::ReadU64(Context& context) { 244 | name_ = "readU64"; 245 | return_type_ = context.GetDataTypeTable()->Find(std::string("U64")); 246 | } 247 | 248 | std::shared_ptr ReadU64::BlockBody(Context & context) { 249 | 250 | shared_ptr value = nullptr; 251 | shared_ptr bin_reader = context.GetBinaryReader(); 252 | 253 | if (bin_reader) { 254 | 255 | uint64_t int_val; 256 | context.GetBinaryReader()->ReadInt(U64, int_val); 257 | value = UnsignedIntValue::Create(context.GetDataTypeTable()->Find(U64), int_val); 258 | 259 | } 260 | 261 | context.SetReturnValue(value); 262 | return value; 263 | } 264 | 265 | // READ character value 266 | 267 | ReadC8::ReadC8(Context& context) { 268 | name_ = "readC8"; 269 | return_type_ = context.GetDataTypeTable()->Find(std::string("C8")); 270 | } 271 | 272 | std::shared_ptr ReadC8::BlockBody(Context & context) { 273 | 274 | shared_ptr value = nullptr; 275 | shared_ptr bin_reader = context.GetBinaryReader(); 276 | 277 | if (bin_reader) { 278 | 279 | uint32_t int_val; 280 | context.GetBinaryReader()->ReadChar(C8, int_val); 281 | value = CharacterValue::Create(context.GetDataTypeTable()->Find(C8), int_val); 282 | 283 | } 284 | 285 | context.SetReturnValue(value); 286 | return value; 287 | } 288 | 289 | ReadC16::ReadC16(Context& context) { 290 | name_ = "readC16"; 291 | return_type_ = context.GetDataTypeTable()->Find(std::string("C16")); 292 | } 293 | 294 | std::shared_ptr ReadC16::BlockBody(Context & context) { 295 | 296 | shared_ptr value = nullptr; 297 | shared_ptr bin_reader = context.GetBinaryReader(); 298 | 299 | if (bin_reader) { 300 | 301 | uint32_t int_val; 302 | context.GetBinaryReader()->ReadChar(C16, int_val); 303 | value = CharacterValue::Create(context.GetDataTypeTable()->Find(C16), int_val); 304 | 305 | } 306 | 307 | context.SetReturnValue(value); 308 | return value; 309 | } 310 | 311 | ReadC32::ReadC32(Context& context) { 312 | name_ = "readC32"; 313 | return_type_ = context.GetDataTypeTable()->Find(std::string("C32")); 314 | } 315 | 316 | std::shared_ptr ReadC32::BlockBody(Context & context) { 317 | 318 | shared_ptr value = nullptr; 319 | shared_ptr bin_reader = context.GetBinaryReader(); 320 | 321 | if (bin_reader) { 322 | 323 | uint32_t int_val; 324 | context.GetBinaryReader()->ReadChar(C32, int_val); 325 | value = CharacterValue::Create(context.GetDataTypeTable()->Find(C32), int_val); 326 | 327 | } 328 | 329 | context.SetReturnValue(value); 330 | return value; 331 | } 332 | 333 | } 334 | -------------------------------------------------------------------------------- /src/vm/context.cpp: -------------------------------------------------------------------------------- 1 | #include "vm/context.h" 2 | 3 | #include "ast/value/value.h" 4 | #include "vm/data_type_table.h" 5 | #include "vm/variable_table.h" 6 | #include "vm/function_table.h" 7 | 8 | #include "utils/BinaryReader.h" 9 | 10 | namespace apus { 11 | 12 | Context::Context(shared_ptr data_type_table, std::string binary_file_path) 13 | : parent_(nullptr), data_type_table_(data_type_table) { 14 | 15 | if (binary_file_path.empty() == false) { 16 | binary_reader_ = std::make_shared(binary_file_path); 17 | } 18 | 19 | break_ = std::make_shared(false); 20 | continue_ = std::make_shared(false); 21 | return_ = std::make_shared(false); 22 | 23 | variable_table_ = make_shared(); 24 | function_table_ = make_shared(); 25 | } 26 | 27 | Context::Context(Context* context) { 28 | parent_ = context; 29 | 30 | break_ = parent_->break_; 31 | continue_ = parent_->continue_; 32 | return_ = parent_->return_; 33 | 34 | data_type_table_ = parent_->data_type_table_; 35 | binary_reader_ = context->binary_reader_; 36 | 37 | variable_table_ = make_shared(); 38 | function_table_ = make_shared(); 39 | } 40 | 41 | Context::~Context() { 42 | } 43 | 44 | Context Context::BlockBegin() { 45 | 46 | Context child(this); 47 | 48 | for (VariablePtr varPtr : param_list_) { 49 | child.InsertVariable(varPtr); 50 | } 51 | 52 | param_list_.clear(); 53 | 54 | return child; 55 | } 56 | 57 | std::shared_ptr Context::BlockEnd() { 58 | 59 | param_list_.clear(); 60 | 61 | if (return_value_) { 62 | parent_->return_value_ = return_value_; 63 | return parent_->return_value_; 64 | } 65 | 66 | return nullptr; 67 | } 68 | 69 | shared_ptr Context::FindDataType(TypeSpecifier name) { 70 | return data_type_table_->Find(name); 71 | } 72 | 73 | shared_ptr Context::FindDataType(string name) { 74 | return data_type_table_->Find(name); 75 | } 76 | 77 | shared_ptr Context::FindVariable(string name) { 78 | 79 | shared_ptr var = nullptr; 80 | 81 | Context* ctx_ptr = this; 82 | 83 | while (ctx_ptr) { 84 | 85 | if ( (var = ctx_ptr->variable_table_->Find(name)) ) { 86 | return var; 87 | } 88 | 89 | ctx_ptr = ctx_ptr->parent_; 90 | } 91 | 92 | return nullptr; 93 | } 94 | 95 | shared_ptr Context::FindFunction(string name) { 96 | 97 | shared_ptr func = nullptr; 98 | 99 | Context* ctx_ptr = this; 100 | 101 | while (ctx_ptr) { 102 | 103 | if ( (func = ctx_ptr->function_table_->Find(name)) ) { 104 | return func; 105 | } 106 | 107 | ctx_ptr = ctx_ptr->parent_; 108 | } 109 | return nullptr; 110 | } 111 | 112 | void Context::InsertVariable(shared_ptr variable) { 113 | variable_table_->Insert(variable->getName(), variable); 114 | } 115 | 116 | void Context::InsertFunction(shared_ptr function) { 117 | function_table_->Insert(function->getName(), function); 118 | } 119 | 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/vm/data_type_table.cpp: -------------------------------------------------------------------------------- 1 | #include "vm/data_type_table.h" 2 | #include 3 | 4 | namespace apus { 5 | 6 | // DataType class 7 | 8 | DataType::DataType() { 9 | byte_size_ = 0; 10 | current_index_ = 0; 11 | } 12 | 13 | DataType::DataType(TypeSpecifier type): DataType() { 14 | type_ = type; 15 | } 16 | 17 | DataType::~DataType() { 18 | } 19 | 20 | void DataType::Insert(const std::string& name, DataType* elem) { 21 | DataTypePtr elem_ptr(elem); // pointer to shared_ptr 22 | map_[name] = elem_ptr; 23 | index_[current_index_++] = elem_ptr; 24 | } 25 | 26 | void DataType::Insert(const std::string& name, DataTypePtr elem) { 27 | map_[name] = elem; 28 | index_[current_index_++] = elem; 29 | } 30 | 31 | DataTypePtr DataType::Find(const std::string& name) { 32 | DataTypeMap::iterator it = map_.find(name); 33 | if (it != map_.end()) { 34 | return it->second; 35 | } 36 | return nullptr; 37 | } 38 | 39 | DataTypeMap DataType::GetMap() { 40 | return map_; 41 | } 42 | 43 | void DataType::SetByteSize(int byte_size) { 44 | byte_size_ = byte_size; 45 | } 46 | 47 | int DataType::GetByteSize() { 48 | int type_length = apus::TypeLength(type_); 49 | // If byte_size_ is not set 50 | if (byte_size_ == 0) { 51 | // If primitive types, get TypeLength() value 52 | if (type_length > 0) { 53 | byte_size_ = type_length; 54 | // If not primitive types (e.g. struct) 55 | } else { 56 | int byte_size = 0; 57 | // get sum of byte size of child data types 58 | for (DataTypeMap::iterator it = map_.begin(); 59 | it != map_.end(); it++) { 60 | byte_size += it->second->GetByteSize(); 61 | } 62 | byte_size_ = byte_size; 63 | } 64 | } 65 | // If byte_size_ is set, just return it 66 | return byte_size_; 67 | } 68 | 69 | DataTypePtr DataType::GetChildDataType(int index) { 70 | if (index < index_.size()) { 71 | return index_[index]; 72 | } else { 73 | return nullptr; 74 | } 75 | } 76 | 77 | void DataType::SetInitExpr(Expression* expr_ptr) { 78 | // pointer to shared_ptr 79 | init_expr_ = ExprPtr (expr_ptr); 80 | } 81 | 82 | ExprPtr DataType::GetInitExpr() { 83 | return init_expr_; 84 | } 85 | 86 | void DataType::SetType(TypeSpecifier type) { 87 | type_ = type; 88 | } 89 | 90 | TypeSpecifier DataType::GetType() { 91 | return type_; 92 | } 93 | 94 | bool DataType::HasChild() { 95 | if (map_.size() != 0) { 96 | return true; 97 | } else { 98 | return false; 99 | } 100 | } 101 | 102 | // ArrayDataType class 103 | 104 | ArrayDataType::ArrayDataType() : DataType() { 105 | array_size_ = 0; 106 | } 107 | 108 | ArrayDataType::ArrayDataType(TypeSpecifier type) 109 | : DataType(type) { 110 | array_size_ = 0; 111 | } 112 | 113 | ArrayDataType::~ArrayDataType() { 114 | } 115 | 116 | 117 | bool ArrayDataType::IsArray() { 118 | if (dimension_list_.size() > 0) { 119 | if (array_size_ <= 1) { 120 | GetArraySize(); 121 | } 122 | return true; 123 | } else { 124 | return false; 125 | } 126 | } 127 | 128 | int ArrayDataType::GetByteSize() { 129 | int byte_size = elem_data_type_->GetByteSize(); 130 | // If byte_size is not set 131 | if (byte_size > 0) { 132 | // If array_size_ is set 133 | if (array_size_ > 1) { 134 | byte_size_ = byte_size * array_size_; 135 | // If array_size_ is not set 136 | } else if (dimension_list_.size() > 0) { 137 | byte_size_ = byte_size * GetArraySize(); 138 | } 139 | } 140 | // If byte_size is set, just return it 141 | return byte_size_; 142 | } 143 | 144 | void ArrayDataType::AddDimension(int dim) { 145 | dimension_list_.push_front (dim); 146 | } 147 | 148 | std::list ArrayDataType::GetDimensionList() { 149 | return dimension_list_; 150 | } 151 | 152 | void ArrayDataType::SetArraySize(int array_size) { 153 | array_size_ = array_size; 154 | } 155 | 156 | int ArrayDataType::GetArraySize() { 157 | // If array_size_ is not set 158 | if (array_size_ <= 1 && dimension_list_.size() > 0) { 159 | int array_size = 1; 160 | // multiply all dimension 161 | for (std::list::iterator it = dimension_list_.begin(); 162 | it != dimension_list_.end(); it++) { 163 | array_size *= *it; 164 | } 165 | if (array_size <= 1) { 166 | DispErr("array size cannot be less than or 1 "); 167 | DispErr("in DataType::SetArraySize()"); 168 | } else { 169 | array_size_ = array_size; 170 | } 171 | } 172 | return array_size_; 173 | } 174 | 175 | void ArrayDataType::SetElement(DataTypePtr elem) { 176 | elem_data_type_ = elem; 177 | } 178 | 179 | void ArrayDataType::SetElement(DataType* elem) { 180 | // pointer to shared_ptr 181 | elem_data_type_ = std::make_shared(*elem); 182 | } 183 | 184 | DataTypePtr ArrayDataType::GetElement() const { 185 | return elem_data_type_; 186 | } 187 | 188 | // DataTypeTable class 189 | 190 | DataTypeTable::DataTypeTable() { 191 | } 192 | 193 | DataTypeTable::~DataTypeTable() { 194 | } 195 | 196 | void DataTypeTable::SetPrimitiveTypes() { 197 | // Add primitive types into data type table's map 198 | for (int i = U8; i <= STR32; i++) { 199 | TypeSpecifier type = (TypeSpecifier) i; 200 | map_[apus::type_to_string[type]] = std::make_shared(type); 201 | } 202 | } 203 | 204 | void DataTypeTable::Insert(const std::string& name, DataType* elem) { 205 | DataTypePtr elem_ptr = std::make_shared(*elem); 206 | map_[name] = elem_ptr; 207 | } 208 | 209 | void DataTypeTable::Insert(const std::string& name, DataTypePtr elem) { 210 | map_[name] = elem; 211 | } 212 | 213 | DataTypePtr DataTypeTable::Find(const std::string& name) { 214 | DataTypeMap::iterator it = map_.find(name); 215 | if (it != map_.end()) { 216 | return it->second; 217 | } 218 | return nullptr; 219 | } 220 | 221 | DataTypePtr DataTypeTable::Find(TypeSpecifier type) { 222 | DataTypeMap::iterator it = map_.find(apus::type_to_string[type]); 223 | if (it != map_.end()) { 224 | return it->second; 225 | } 226 | return nullptr; 227 | } 228 | } 229 | 230 | -------------------------------------------------------------------------------- /src/vm/function_table.cpp: -------------------------------------------------------------------------------- 1 | #include "vm/function_table.h" 2 | #include "vm/variable_table.h" 3 | 4 | #include "ast/value/signed_int_value.h" 5 | #include "ast/value/string_value.h" 6 | 7 | #include "utils/BinaryReader.h" 8 | 9 | #include "vm/function_table.h" 10 | 11 | namespace apus { 12 | 13 | // Function class 14 | 15 | Function::Function() { 16 | } 17 | 18 | Function::Function(const std::string& name) { 19 | name_ = name; 20 | return_type_ = nullptr; 21 | } 22 | 23 | Function::Function(const std::string& name, DataTypePtr return_type) { 24 | name_ = name; 25 | return_type_ = return_type; 26 | } 27 | 28 | Function::Function(const std::string& name, DataTypePtr return_type, list arg_list) { 29 | name_ = name; 30 | return_type_ = return_type; 31 | arg_list_ = arg_list; 32 | } 33 | 34 | Function::~Function() { 35 | } 36 | 37 | // FunctionTable class 38 | 39 | FunctionTable::FunctionTable() { 40 | 41 | } 42 | void FunctionTable::Insert(std::string name, 43 | std::shared_ptr function) { 44 | map_[name] = function; 45 | } 46 | 47 | std::shared_ptr FunctionTable::Find(std::string& name) { 48 | FunctionMap::iterator it = map_.find(name); 49 | 50 | if(it != map_.end()) { 51 | return it->second; 52 | } 53 | return nullptr; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/vm/variable_table.cpp: -------------------------------------------------------------------------------- 1 | #include "vm/variable_table.h" 2 | 3 | namespace apus { 4 | 5 | // Variable class 6 | 7 | Variable::Variable(const std::string& name, DataTypePtr type) { 8 | name_ = name; 9 | data_type_ = type; 10 | 11 | CreateChildVariables(); 12 | } 13 | 14 | Variable::~Variable() { 15 | } 16 | 17 | TypeSpecifier Variable::getType() { 18 | return data_type_->GetType(); 19 | } 20 | 21 | std::string Variable::getName() { 22 | return name_; 23 | } 24 | 25 | void Variable::setName(const std::string& name) { 26 | name_ = name; 27 | } 28 | 29 | DataTypePtr Variable::getDataType() { 30 | return data_type_; 31 | } 32 | 33 | void Variable::setDataType(DataTypePtr type) { 34 | data_type_ = type; 35 | } 36 | 37 | VarPtr Variable::getChildVariable(const std::string& name) { 38 | VariableMap::iterator it = map_.find(name); 39 | if (it != map_.end()) { 40 | return it->second; 41 | } 42 | return nullptr; 43 | } 44 | 45 | void Variable::InsertChildVariable(const std::string& name, VarPtr var) { 46 | map_[name] = var; 47 | } 48 | 49 | bool Variable::IsStructVariable() { 50 | if (map_.size() != 0) { 51 | return true; 52 | } else { 53 | return false; 54 | } 55 | } 56 | 57 | void Variable::CreateChildVariables() { 58 | if (data_type_ != NULL && data_type_->GetType() == STRUCT) { 59 | // key = string, value = shared pointer to DataType 60 | DataTypeMap map = data_type_->GetMap(); 61 | for (DataTypeMap::iterator it = map.begin(); 62 | it != map.end(); it++) { 63 | VarPtr var = std::make_shared(it->first, it->second); 64 | map_[it->first] = var; 65 | } 66 | } 67 | } 68 | 69 | ValuePtr Variable::getValue() { 70 | return value_; 71 | } 72 | 73 | void Variable::setValue(ValuePtr value) { 74 | value_ = value; 75 | } 76 | 77 | // VariableTable class 78 | 79 | VariableTable::VariableTable() { 80 | } 81 | 82 | VariableTable::~VariableTable() { 83 | } 84 | 85 | void VariableTable::Insert(const std::string name, 86 | std::shared_ptr variable) { 87 | map_[name] = variable; 88 | } 89 | 90 | std::shared_ptr VariableTable::Find(const std::string& name) { 91 | VariableMap::iterator it = map_.find(name); 92 | 93 | if (it != map_.end()) { 94 | return it->second; 95 | } 96 | return nullptr; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/vm/virtual_machine.cpp: -------------------------------------------------------------------------------- 1 | #include "vm/virtual_machine.h" 2 | #include "vm/context.h" 3 | #include "vm/function_table.h" 4 | 5 | #include "vm/builtin_functions.h" 6 | 7 | namespace apus { 8 | 9 | VirtualMachine::VirtualMachine() { 10 | 11 | } 12 | 13 | VirtualMachine::~VirtualMachine() { 14 | 15 | } 16 | 17 | StmtPtrList VirtualMachine::getStmtList() { 18 | return stmt_list_; 19 | } 20 | 21 | void VirtualMachine::setStmtList(StmtPtrList stmt_list) { 22 | stmt_list_ = stmt_list; 23 | } 24 | 25 | DataTypeTablePtr VirtualMachine::getDataTypeTable() { 26 | return data_type_table_; 27 | } 28 | 29 | void VirtualMachine::setDataTypeTable(DataTypeTablePtr data_type_table) { 30 | data_type_table_ = data_type_table; 31 | } 32 | 33 | void VirtualMachine::Run(std::string binary_file_path) { 34 | 35 | Context context(data_type_table_, binary_file_path); 36 | 37 | // Insert Built-in function 38 | context.InsertFunction(std::make_shared(context)); 39 | context.InsertFunction(std::make_shared(context)); 40 | 41 | context.InsertFunction(std::make_shared(context)); 42 | context.InsertFunction(std::make_shared(context)); 43 | context.InsertFunction(std::make_shared(context)); 44 | context.InsertFunction(std::make_shared(context)); 45 | 46 | context.InsertFunction(std::make_shared(context)); 47 | context.InsertFunction(std::make_shared(context)); 48 | context.InsertFunction(std::make_shared(context)); 49 | context.InsertFunction(std::make_shared(context)); 50 | 51 | context.InsertFunction(std::make_shared(context)); 52 | context.InsertFunction(std::make_shared(context)); 53 | context.InsertFunction(std::make_shared(context)); 54 | 55 | for(std::shared_ptr stmt : stmt_list_) { 56 | stmt->Execute(context); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # set google test directory 3 | set(GTEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/gtest) 4 | 5 | set(TEST_EXE unit_test) 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -g -std=c++0x") 7 | 8 | # build libgtest_main.a 9 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 10 | add_library( 11 | gtest_main 12 | STATIC 13 | ${GTEST_DIR}/gtest-all.cc 14 | ${GTEST_DIR}/gtest_main.cc 15 | ${GTEST_DIR}/gtest.h) 16 | 17 | # scan every ".cpp" test files 18 | file(GLOB_RECURSE TEST_SRC "*.cpp") 19 | 20 | # scan src files 21 | file(GLOB_RECURSE SOURCE 22 | ${CMAKE_SOURCE_DIR}/src/*.c 23 | ${CMAKE_SOURCE_DIR}/src/*.cc 24 | ${CMAKE_SOURCE_DIR}/src/*.cpp) 25 | 26 | ## but the main.cpp 27 | list(REMOVE_ITEM SOURCE 28 | ${CMAKE_SOURCE_DIR}/src/main.cpp) 29 | 30 | # scan header files 31 | file(GLOB_RECURSE HEADER 32 | ${CMAKE_SOURCE_DIR}/include/*.h 33 | ${CMAKE_SOURCE_DIR}/include/*.hh 34 | ${CMAKE_SOURCE_DIR}/include/*.hpp) 35 | 36 | #include header directory 37 | include_directories("${CMAKE_SOURCE_DIR}/include") 38 | 39 | # set lex yacc files 'GENERATED' 40 | set_source_files_properties(${CMAKE_SOURCE_DIR}/${SRC_DIR}/${LEX_OUT} GENERATED) 41 | set_source_files_properties(${CMAKE_SOURCE_DIR}/${SRC_DIR}/${YACC_OUT} GENERATED) 42 | 43 | # test executable 44 | add_executable(${TEST_EXE} 45 | ${TEST_SRC} ${SOURCE} ${HEADER} 46 | ${CMAKE_SOURCE_DIR}/${SRC_DIR}/${LEX_OUT} 47 | ${CMAKE_SOURCE_DIR}/${SRC_DIR}/${YACC_OUT}) 48 | 49 | # find and link google test library 50 | find_library(gtest_main ${CMAKE_CURRENT_DIR}/../lib) 51 | target_link_libraries(${TEST_EXE} gtest_main) 52 | 53 | add_dependencies(${TEST_EXE} lex;yacc) 54 | 55 | add_custom_command( 56 | OUTPUT exec 57 | COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_EXE} 58 | DEPENDS ${TEST_EXE} 59 | COMMENT "executing '${TEST_EXE}'" 60 | VERBATIM 61 | ) 62 | 63 | add_custom_target(run_${TEST_EXE} DEPENDS exec) 64 | 65 | -------------------------------------------------------------------------------- /test/ast/ast_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gtest/gtest.h" 5 | 6 | #include "ast/expression.h" 7 | #include "ast/statement/statement.h" 8 | 9 | #include "ast/value/signed_int_value.h" 10 | #include "ast/value/unsigned_int_value.h" 11 | #include "ast/value/float_value.h" 12 | #include "ast/value/character_value.h" 13 | #include "ast/value/string_value.h" 14 | 15 | #include "vm/context.h" 16 | #include "vm/data_type_table.h" 17 | 18 | using namespace apus; 19 | 20 | 21 | TEST (ASTTest, Expression_nullptr) { 22 | 23 | DataTypeTablePtr dtt = std::make_shared(); 24 | dtt->SetPrimitiveTypes(); 25 | apus::Context ctx(dtt, ""); 26 | 27 | // nullptr input 28 | { 29 | std::shared_ptr left_expr = nullptr; 30 | std::shared_ptr right_expr = nullptr; 31 | Expression *expr = nullptr; 32 | 33 | expr = new BinaryExpression(Expression::EXP_ADD, left_expr, 34 | right_expr); 35 | 36 | EXPECT_EQ(nullptr, expr->Evaluate(ctx)); 37 | } 38 | } 39 | 40 | // add, sub, mul, div and modulo 41 | TEST (ASTTest, Expression_ASMD) { 42 | 43 | DataTypeTablePtr dtt = std::make_shared(); 44 | dtt->SetPrimitiveTypes(); 45 | apus::Context ctx(dtt, ""); 46 | 47 | // 1 + 2 == 3 48 | { 49 | std::shared_ptr left_value = SignedIntValue::Create(dtt->Find("S32"), 1); 50 | std::shared_ptr left_expr = std::make_shared(left_value); 51 | 52 | std::shared_ptr right_value = SignedIntValue::Create(dtt->Find("S32"), 2); 53 | std::shared_ptr right_expr = std::make_shared(right_value); 54 | std::shared_ptr expr = std::make_shared(Expression::EXP_ADD, left_expr, right_expr); 55 | 56 | std::shared_ptr result = std::dynamic_pointer_cast(expr->Evaluate(ctx)); 57 | 58 | EXPECT_EQ(3, result->getIntValue()); 59 | } 60 | 61 | // 1 + 2 * 3 == 7 62 | { 63 | std::shared_ptr _1 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 1)); 64 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 2)); 65 | std::shared_ptr _3 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 3)); 66 | 67 | std::shared_ptr mul_expr = std::make_shared(Expression::EXP_MUL, _2, _3); 68 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _1, mul_expr); 69 | 70 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 71 | 72 | EXPECT_EQ(7, result->getIntValue()); 73 | } 74 | 75 | // ( 1 + 2 * 3 ) % 5 == 2 76 | { 77 | std::shared_ptr _1 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 1)); 78 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 2)); 79 | std::shared_ptr _3 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 3)); 80 | std::shared_ptr _5 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 5)); 81 | 82 | std::shared_ptr mul_expr = std::make_shared(Expression::EXP_MUL, _2, _3); 83 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _1, mul_expr); 84 | 85 | std::shared_ptr mod_expr = std::make_shared(Expression::EXP_MOD, add_expr, _5); 86 | 87 | std::shared_ptr result = std::dynamic_pointer_cast(mod_expr->Evaluate(ctx)); 88 | 89 | EXPECT_EQ(2, result->getIntValue()); 90 | } 91 | 92 | // 2 * 3.5 / 3 93 | { 94 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S64"), 2)); 95 | std::shared_ptr _3_5 = std::make_shared(FloatValue::Create(dtt->Find("F64"), 3.5)); 96 | std::shared_ptr _3 = std::make_shared(SignedIntValue::Create(dtt->Find("S64"), 3)); 97 | 98 | std::shared_ptr mul_expr = std::make_shared(Expression::EXP_MUL, _2, _3_5); 99 | std::shared_ptr div_expr = std::make_shared(Expression::EXP_DIV, mul_expr, _3); 100 | 101 | std::shared_ptr result = std::dynamic_pointer_cast(div_expr->Evaluate(ctx)); 102 | 103 | EXPECT_EQ( (2 * 3.5 / 3) , result->getFloatValue()); 104 | } 105 | 106 | } 107 | 108 | TEST (ASTTest, Expression_Int_Compare) { 109 | 110 | DataTypeTablePtr dtt = std::make_shared(); 111 | dtt->SetPrimitiveTypes(); 112 | apus::Context ctx(dtt, ""); 113 | 114 | { 115 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 2)); 116 | std::shared_ptr _3 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 3)); 117 | 118 | std::shared_ptr eql_expr = std::make_shared(Expression::EXP_EQL, _2, _3); 119 | std::shared_ptr neq_expr = std::make_shared(Expression::EXP_NEQ, _2, _3); 120 | std::shared_ptr lss_expr = std::make_shared(Expression::EXP_LSS, _2, _3); 121 | std::shared_ptr gtr_expr = std::make_shared(Expression::EXP_GTR, _2, _3); 122 | std::shared_ptr leq_expr = std::make_shared(Expression::EXP_LEQ, _2, _3); 123 | std::shared_ptr geq_expr = std::make_shared(Expression::EXP_GEQ, _2, _3); 124 | 125 | std::shared_ptr result = std::dynamic_pointer_cast(eql_expr->Evaluate(ctx)); 126 | EXPECT_FALSE(result->getIntValue()); 127 | result = std::dynamic_pointer_cast(neq_expr->Evaluate(ctx)); 128 | EXPECT_TRUE(result->getIntValue()); 129 | result = std::dynamic_pointer_cast(lss_expr->Evaluate(ctx)); 130 | EXPECT_TRUE(result->getIntValue()); 131 | result = std::dynamic_pointer_cast(gtr_expr->Evaluate(ctx)); 132 | EXPECT_FALSE(result->getIntValue()); 133 | result = std::dynamic_pointer_cast(leq_expr->Evaluate(ctx)); 134 | EXPECT_TRUE(result->getIntValue()); 135 | result = std::dynamic_pointer_cast(geq_expr->Evaluate(ctx)); 136 | EXPECT_FALSE(result->getIntValue()); 137 | 138 | } 139 | } 140 | 141 | TEST (ASTTest, Expression_Float_Compare) { 142 | 143 | DataTypeTablePtr dtt = std::make_shared(); 144 | dtt->SetPrimitiveTypes(); 145 | apus::Context ctx(dtt, ""); 146 | 147 | const double __2_5 = 2.000000000005; 148 | const double __2_7 = 2.000000000007; 149 | 150 | { 151 | std::shared_ptr _2_5 = std::make_shared(FloatValue::Create(dtt->Find("F32"), __2_5)); 152 | std::shared_ptr _2_7 = std::make_shared(FloatValue::Create(dtt->Find("F32"), __2_7)); 153 | 154 | std::shared_ptr eql_expr = std::make_shared(Expression::EXP_EQL, _2_5, _2_7); 155 | std::shared_ptr neq_expr = std::make_shared(Expression::EXP_NEQ, _2_5, _2_7); 156 | std::shared_ptr lss_expr = std::make_shared(Expression::EXP_LSS, _2_5, _2_7); 157 | std::shared_ptr gtr_expr = std::make_shared(Expression::EXP_GTR, _2_5, _2_7); 158 | std::shared_ptr leq_expr = std::make_shared(Expression::EXP_LEQ, _2_5, _2_7); 159 | std::shared_ptr geq_expr = std::make_shared(Expression::EXP_GEQ, _2_5, _2_7); 160 | 161 | std::shared_ptr result = std::dynamic_pointer_cast(eql_expr->Evaluate(ctx)); 162 | EXPECT_FALSE(result->getFloatValue()); 163 | result = std::dynamic_pointer_cast(neq_expr->Evaluate(ctx)); 164 | EXPECT_TRUE(result->getFloatValue()); 165 | result = std::dynamic_pointer_cast(lss_expr->Evaluate(ctx)); 166 | EXPECT_TRUE(result->getFloatValue()); 167 | result = std::dynamic_pointer_cast(gtr_expr->Evaluate(ctx)); 168 | EXPECT_FALSE(result->getFloatValue()); 169 | result = std::dynamic_pointer_cast(leq_expr->Evaluate(ctx)); 170 | EXPECT_TRUE(result->getFloatValue()); 171 | result = std::dynamic_pointer_cast(geq_expr->Evaluate(ctx)); 172 | EXPECT_FALSE(result->getFloatValue()); 173 | 174 | } 175 | } 176 | 177 | TEST (ASTTest, Expression_Float_EQL_Compare) { 178 | 179 | DataTypeTablePtr dtt = std::make_shared(); 180 | dtt->SetPrimitiveTypes(); 181 | apus::Context ctx(dtt, ""); 182 | 183 | const double a = 0.15 + 0.15; 184 | const double b = 0.1 + 0.2; 185 | 186 | std::shared_ptr a_ = std::make_shared(FloatValue::Create(dtt->Find("F64"), a)); 187 | std::shared_ptr b_ = std::make_shared(FloatValue::Create(dtt->Find("F64"), b)); 188 | 189 | std::shared_ptr eql_expr = std::make_shared(Expression::EXP_EQL, a_, b_); 190 | std::shared_ptr neq_expr = std::make_shared(Expression::EXP_NEQ, a_, b_); 191 | std::shared_ptr leq_expr = std::make_shared(Expression::EXP_LEQ, a_, b_); 192 | 193 | // a == b 194 | std::shared_ptr result = std::dynamic_pointer_cast(eql_expr->Evaluate(ctx)); 195 | EXPECT_TRUE(result->getFloatValue()); 196 | 197 | // a != b 198 | result = std::dynamic_pointer_cast(neq_expr->Evaluate(ctx)); 199 | EXPECT_FALSE(result->getFloatValue()); 200 | 201 | // a <= b 202 | result = std::dynamic_pointer_cast(leq_expr->Evaluate(ctx)); 203 | EXPECT_TRUE(result->getFloatValue()); 204 | 205 | } 206 | 207 | TEST (ASTTest, Expression_Promote) { 208 | 209 | DataTypeTablePtr dtt = std::make_shared(); 210 | dtt->SetPrimitiveTypes(); 211 | apus::Context ctx(dtt, ""); 212 | 213 | // 2 * 3.5 (S16 * F32) 214 | { 215 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S16"), 2)); 216 | std::shared_ptr _3_5 = std::make_shared(FloatValue::Create(dtt->Find("F32"), 3.5)); 217 | 218 | std::shared_ptr mul_expr = std::make_shared(Expression::EXP_MUL, _2, _3_5); 219 | 220 | std::shared_ptr result = std::dynamic_pointer_cast(mul_expr->Evaluate(ctx)); 221 | 222 | EXPECT_EQ( (2 * 3.5) , result->getFloatValue()); 223 | EXPECT_EQ(F32 , result->getType()); 224 | } 225 | 226 | // 2 * 3.5 (S64 * F32) 227 | { 228 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S64"), 2)); 229 | std::shared_ptr _3_5 = std::make_shared(FloatValue::Create(dtt->Find("F32"), 3.5)); 230 | 231 | std::shared_ptr mul_expr = std::make_shared(Expression::EXP_MUL, _2, _3_5); 232 | 233 | std::shared_ptr result = std::dynamic_pointer_cast(mul_expr->Evaluate(ctx)); 234 | 235 | EXPECT_EQ( (2 * 3.5) , result->getFloatValue()); 236 | EXPECT_EQ(F32 , result->getType()); 237 | } 238 | 239 | // 'A' < 'B' (C8 + C16) 240 | { 241 | std::shared_ptr _a = std::make_shared(CharacterValue::Create(dtt->Find("C8"), 'A')); 242 | std::shared_ptr _b = std::make_shared(CharacterValue::Create(dtt->Find("C16"), 'B')); 243 | 244 | std::shared_ptr lss_expr = std::make_shared(Expression::EXP_LSS, _a, _b); 245 | 246 | std::shared_ptr result = std::dynamic_pointer_cast(lss_expr->Evaluate(ctx)); 247 | 248 | EXPECT_TRUE(result->getCharValue()); 249 | EXPECT_EQ(C16 , result->getType()); 250 | } 251 | // 2 + 3 (S16 * U32) 252 | { 253 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S16"), 2)); 254 | std::shared_ptr _3 = std::make_shared(UnsignedIntValue::Create(dtt->Find("U32"), 3)); 255 | 256 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _2, _3); 257 | 258 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 259 | 260 | EXPECT_EQ( 2 + 3, result->getUIntValue()); 261 | EXPECT_EQ(U32 , result->getType()); 262 | } 263 | 264 | // 2 + 3 (S32 * U16) 265 | { 266 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 2)); 267 | std::shared_ptr _3 = std::make_shared(UnsignedIntValue::Create(dtt->Find("U16"), 3)); 268 | 269 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _2, _3); 270 | 271 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 272 | 273 | EXPECT_EQ( 2 + 3, result->getIntValue()); 274 | EXPECT_EQ(S32 , result->getType()); 275 | } 276 | 277 | // 2 + 3 (S32 * U32) 278 | { 279 | std::shared_ptr _2 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 2)); 280 | std::shared_ptr _3 = std::make_shared(UnsignedIntValue::Create(dtt->Find("U32"), 3)); 281 | 282 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _2, _3); 283 | 284 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 285 | 286 | EXPECT_EQ( 2 + 3, result->getUIntValue()); 287 | EXPECT_EQ(U32 , result->getType()); 288 | } 289 | 290 | // "Hello" + 3 (STR8 + U32) 291 | { 292 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("hello"))); 293 | std::shared_ptr _3 = std::make_shared(UnsignedIntValue::Create(dtt->Find("U32"), 3)); 294 | 295 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _hello, _3); 296 | 297 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 298 | 299 | EXPECT_EQ(std::string("hello3"), result->getStringValue()); 300 | EXPECT_EQ(STR8 , result->getType()); 301 | } 302 | 303 | // "Hello" + 3 (STR8 + S32) 304 | { 305 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("hello"))); 306 | std::shared_ptr _3 = std::make_shared(SignedIntValue::Create(dtt->Find("S32"), 3)); 307 | 308 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _hello, _3); 309 | 310 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 311 | 312 | EXPECT_EQ(std::string("hello3"), result->getStringValue()); 313 | EXPECT_EQ(STR8 , result->getType()); 314 | } 315 | 316 | // "Hello" + 3.5 (STR8 + F64) 317 | { 318 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("hello"))); 319 | std::shared_ptr _3 = std::make_shared(FloatValue::Create(dtt->Find("F64"), 3.141592)); 320 | 321 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _hello, _3); 322 | 323 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 324 | 325 | EXPECT_EQ(std::string("hello3.141592"), result->getStringValue()); 326 | EXPECT_EQ(STR8 , result->getType()); 327 | } 328 | 329 | // "Hello" + 'o' (STR8 + C8) 330 | { 331 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("hello"))); 332 | std::shared_ptr _3 = std::make_shared(CharacterValue::Create(dtt->Find("C8"), 'o')); 333 | 334 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _hello, _3); 335 | 336 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 337 | 338 | EXPECT_EQ(std::string("helloo"), result->getStringValue()); 339 | EXPECT_EQ(STR8 , result->getType()); 340 | } 341 | 342 | } 343 | TEST (ASTTest, IsTrue) { 344 | 345 | DataTypeTablePtr dtt = std::make_shared(); 346 | dtt->SetPrimitiveTypes(); 347 | apus::Context ctx(dtt, ""); 348 | 349 | bool result = false; 350 | 351 | result = Value::IsTrue(SignedIntValue::Create(dtt->Find("S32"), 123)); 352 | EXPECT_TRUE(result); 353 | 354 | result = Value::IsTrue(SignedIntValue::Create(dtt->Find("S32"), 0)); 355 | EXPECT_FALSE(result); 356 | 357 | result = Value::IsTrue(FloatValue::Create(dtt->Find("F32"), 123.4)); 358 | EXPECT_TRUE(result); 359 | 360 | result = Value::IsTrue(FloatValue::Create(dtt->Find("F32"), 0)); 361 | EXPECT_FALSE(result); 362 | 363 | { 364 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("Hello ") ) ); 365 | std::shared_ptr _world = std::make_shared(StringValue::CreateU16(dtt->Find("STR16"), std::u16string(u"world") ) ); 366 | 367 | std::shared_ptr neq_expr = std::make_shared(Expression::EXP_NEQ, _hello, _world); 368 | std::shared_ptr result = std::dynamic_pointer_cast(neq_expr->Evaluate(ctx)); 369 | 370 | EXPECT_TRUE(Value::IsTrue(result)); 371 | //EXPECT_EQ(u16string(u"what"),result->getU16StringValue()); 372 | 373 | std::shared_ptr eql_expr = std::make_shared(Expression::EXP_EQL, _hello, _world); 374 | result = std::dynamic_pointer_cast(eql_expr->Evaluate(ctx)); 375 | 376 | EXPECT_FALSE(Value::IsTrue(result)); 377 | EXPECT_EQ(STR16 , result->getType()); 378 | } 379 | } 380 | 381 | TEST (ASTTest, Expression_String_Add) { 382 | 383 | DataTypeTablePtr dtt = std::make_shared(); 384 | dtt->SetPrimitiveTypes(); 385 | apus::Context ctx(dtt, ""); 386 | 387 | { 388 | std::shared_ptr _hello = std::make_shared(StringValue::Create(dtt->Find("STR8"), std::string("Hello ") ) ); 389 | std::shared_ptr _world = std::make_shared(StringValue::CreateU16(dtt->Find("STR16"), std::u16string(u"world") ) ); 390 | 391 | std::shared_ptr add_expr = std::make_shared(Expression::EXP_ADD, _hello, _world); 392 | std::shared_ptr result = std::dynamic_pointer_cast(add_expr->Evaluate(ctx)); 393 | 394 | EXPECT_EQ(std::u16string(u"Hello world"), result->getU16StringValue()); 395 | EXPECT_EQ(STR16 , result->getType()); 396 | 397 | } 398 | 399 | } 400 | 401 | -------------------------------------------------------------------------------- /test/example/factorial.cpp: -------------------------------------------------------------------------------- 1 | #include "factorial.h" 2 | 3 | int factorial(int n) { 4 | int result = 1; 5 | for (int i = 1; i <= n; i++) { 6 | result *= i; 7 | } 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /test/example/factorial.h: -------------------------------------------------------------------------------- 1 | #ifndef FACTORIAL_H_ 2 | #define FACTORIAL_H_ 3 | 4 | int factorial(int n); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/example/factorial_unit_test.cpp: -------------------------------------------------------------------------------- 1 | # include "gtest/gtest.h" 2 | # include "factorial.h" 3 | 4 | TEST(IntegerFunctionTest, negative) { 5 | EXPECT_EQ(1, factorial(-5)); 6 | EXPECT_EQ(1, factorial(-1)); 7 | } 8 | 9 | TEST(IntegerFunctionTest, zero) { 10 | EXPECT_EQ(1, factorial(0)); 11 | } 12 | 13 | TEST(IntegerFunctionTest, postive) { 14 | EXPECT_EQ(1, factorial(1)); 15 | EXPECT_EQ(2, factorial(2)); 16 | EXPECT_EQ(6, factorial(3)); 17 | EXPECT_EQ(40320, factorial(8)); 18 | } 19 | -------------------------------------------------------------------------------- /test/gtest/gtest_main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gtest/gtest.h" 3 | 4 | GTEST_API_ int main(int argc, char **argv) { 5 | printf("Running main() from gtest_main.cc\n"); 6 | testing::InitGoogleTest(&argc, argv); 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/parser/array_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "parser_context.h" 3 | 4 | extern int yyparse(apus::ParserContext* pctx); 5 | extern int yy_scan_string(const char *); 6 | 7 | // test_x x number is defined sub test 8 | // 1 : corrected test 9 | // 2 : uncorrected test 10 | // 3 : CR test 11 | 12 | static char one_dimension_test_1[] = "\ 13 | var u8[1] aa\n\ 14 | var u8[2] bb = [1, 2]\n\ 15 | var struct id2[2] cc = [{1, 2}, {3, 4}]\n\ 16 | "; 17 | 18 | static char two_dimension_test_1[] = "\ 19 | var u8[1][2] dd\n\ 20 | var u8[2][2] ee = [[1, 2], [3, 4]]\n\ 21 | var struct id2[2][2] ff = [[{1, 2}, {3, 4}], [{5, 6}, {7, 8}]]\n\ 22 | "; 23 | 24 | static char three_dimension_test_1[] = "\ 25 | var u8[1][2][3] gg\n\ 26 | var u8[2][2][2] hh = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]\n\ 27 | var struct id2[2][2][2] ii = [[[{1, 2}, {3, 4}], [{5, 6}, {7, 8}]], [[{1, 2}, {3, 4}], [{5, 6}, {7, 8}]]]\n\ 28 | "; 29 | 30 | static char used_array_test_1[] = "\ 31 | aa = aa[1][2] + bb\n\ 32 | a[1][2] = aa[1][2][3] + bb\n\ 33 | "; 34 | 35 | static char three_dimension_test_3[] = "\ 36 | var u8[2] jj = [1,\n\ 37 | 2]\n\ 38 | var u8[2][2] kk = [[1, 2],\n\ 39 | [3, 4]]\n\ 40 | var struct id2[2][2][2] ll = [[[{1, 2}, {3, 4}], [{5, 6}, {7, 8}]],\n\ 41 | [[{9, 0}, {1, 2}], [{3, 4}, {5, 6}]]]\n\ 42 | "; 43 | 44 | TEST (ParserTest, ArrayCorrectTest) { 45 | int result; 46 | apus::ParserContext pctx(std::make_shared()); 47 | 48 | yy_scan_string(one_dimension_test_1); 49 | result = yyparse(&pctx); 50 | EXPECT_EQ (result, 0); 51 | 52 | yy_scan_string(two_dimension_test_1); 53 | result = yyparse(&pctx); 54 | EXPECT_EQ (result, 0); 55 | 56 | yy_scan_string(three_dimension_test_1); 57 | result = yyparse(&pctx); 58 | EXPECT_EQ (result, 0); 59 | 60 | yy_scan_string(used_array_test_1); 61 | result = yyparse(&pctx); 62 | EXPECT_EQ (result, 0); 63 | } 64 | 65 | TEST (ParserTest, ArrayCRTest) { 66 | int result; 67 | apus::ParserContext pctx(std::make_shared()); 68 | 69 | yy_scan_string(three_dimension_test_3); 70 | result = yyparse(&pctx); 71 | EXPECT_EQ (result, 0); 72 | } 73 | -------------------------------------------------------------------------------- /test/parser/data_decl_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "parser_context.h" 3 | 4 | extern int yyparse(apus::ParserContext* pctx); 5 | extern int yy_scan_string(const char *); 6 | 7 | static char data_decl_test[] = "\ 8 | struct id {\n\ 9 | u8 aa\n\ 10 | f32 bb = 8\n\ 11 | }\n\ 12 | \n\ 13 | struct id2\n\ 14 | {\n\ 15 | s8 aa = 0\n\ 16 | str bb = \"string string\"\n\ 17 | }\n\ 18 | \n\ 19 | struct id3 { c8 aa = 'a' }\n\ 20 | \n\ 21 | union id4 {\n\ 22 | u8 aa\n\ 23 | f32 bb = 3.8\n\ 24 | }\n\ 25 | \n\ 26 | union id5\n\ 27 | {\n\ 28 | u8 aa\n\ 29 | struct id bb\n\ 30 | }\n\ 31 | \n\ 32 | \n\ 33 | union id6 { u32 aa }\n\ 34 | "; 35 | 36 | TEST (ParserTest, DataDeclTest) { 37 | int result; 38 | apus::ParserContext pctx(std::make_shared()); 39 | 40 | yy_scan_string(data_decl_test); 41 | result = yyparse(&pctx); 42 | 43 | EXPECT_EQ (result, 0); 44 | } 45 | -------------------------------------------------------------------------------- /test/parser/statement_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "parser_context.h" 3 | 4 | extern int yyparse(apus::ParserContext* pctx); 5 | extern int yy_scan_string(const char *); 6 | 7 | // test_x x number is defined sub test 8 | // 1 : corrected test 9 | // 2 : uncorrected test 10 | // 3 : CR test 11 | 12 | static char var_def_test_1[] = "\ 13 | var u8 a \n\ 14 | var u8 b = 10 \n\ 15 | var c8 c = 'a' \n\ 16 | var str d = \"sss\" \n\ 17 | var f32 e = 3.4 + 3.7 \n\ 18 | "; 19 | static char jump_stmt_test_1[] = "\ 20 | continue \n\ 21 | break \n\ 22 | return \n\ 23 | return 10+10 \n\ 24 | exit \n\ 25 | exit -1 \n\ 26 | "; 27 | static char for_stmt_test_1[] = "\ 28 | for(i = (32+8)*3/4<<2; i < 10; i += 1) { } \n\ 29 | for(i=10; ; ) { } \n\ 30 | for( ; i < 10; ) { } \n\ 31 | for( ; ; i += 1) { } \n\ 32 | for( ; ; ) { } \n\ 33 | "; 34 | static char if_stmt_test_1[] = "\ 35 | if(i < 10) { } \n\ 36 | if(i == 10) { \n\ 37 | a = 10 \n\ 38 | } \n\ 39 | else { \n\ 40 | a = 0 \n\ 41 | } \n\ 42 | if(i != 10) { \n\ 43 | a = 10 \n\ 44 | } \n\ 45 | else if(i == 10) { \n\ 46 | a = 0 \n\ 47 | } \n\ 48 | else { \n\ 49 | a = 1 \n\ 50 | } \n\ 51 | "; 52 | static char expr_stmt_test_1[] = "\ 53 | 3 + 4 \n\ 54 | 3 << 4 \n\ 55 | 3 ^ 4 \n\ 56 | !4 \n\ 57 | ~4 \n\ 58 | 0xff02ff\n\ 59 | 0b1011 \n\ 60 | 076041 \n\ 61 | a.b.c \n\ 62 | a = a.b + 0xff \n\ 63 | b = 'a' + \"ss\" \n\ 64 | "; 65 | static char block_stmt_test_1[] = "\ 66 | { var u8 a = 7 \n\ 67 | if(a=1) { } \n\ 68 | else if(b=1) { } \n\ 69 | else { } \n\ 70 | for( ; ; ) { } \n\ 71 | 3 * 9 \n\ 72 | return 9 \n\ 73 | exit \n\ 74 | } \n\ 75 | "; 76 | static char if_stmt_test_3[] = "\ 77 | if \n\ 78 | ( i == 10 ) \n\ 79 | { \n\ 80 | var u8 a = 10 \n\ 81 | } else if ( j == 10 ) { \n\ 82 | a = 10 \n\ 83 | } \n\ 84 | \n\ 85 | else { } \n\ 86 | "; 87 | 88 | static char for_test[] = 89 | "var s64 i = 0 \n\ 90 | for (i = 0;i < 3; i += 1) { \ 91 | var s64 a= 7 \n\ 92 | a+3 \n\ 93 | var s64 b = 3 \n\ 94 | b = a + 2 + i\n \ 95 | printS64(b)\n \ 96 | if (b%2 == 1) { printSTR8(\"b is odd_number!\")\n } \n } \n "; 97 | 98 | TEST (ParserTest, StmtCorrectTest) { 99 | int result; 100 | apus::ParserContext pctx(std::make_shared()); 101 | 102 | yy_scan_string(var_def_test_1); 103 | result = yyparse(&pctx); 104 | EXPECT_EQ (result, 0); 105 | 106 | yy_scan_string(jump_stmt_test_1); 107 | result = yyparse(&pctx); 108 | EXPECT_EQ (result, 0); 109 | 110 | yy_scan_string(for_stmt_test_1); 111 | result = yyparse(&pctx); 112 | EXPECT_EQ (result, 0); 113 | 114 | yy_scan_string(if_stmt_test_1); 115 | result = yyparse(&pctx); 116 | EXPECT_EQ (result, 0); 117 | 118 | yy_scan_string(expr_stmt_test_1); 119 | result = yyparse(&pctx); 120 | EXPECT_EQ (result, 0); 121 | 122 | yy_scan_string(block_stmt_test_1); 123 | result = yyparse(&pctx); 124 | EXPECT_EQ (result, 0); 125 | } 126 | 127 | TEST (ParserTest, StmtLineTest) { 128 | int result; 129 | apus::ParserContext pctx(std::make_shared()); 130 | 131 | yy_scan_string(if_stmt_test_3); 132 | result = yyparse(&pctx); 133 | EXPECT_EQ (result, 0); 134 | } 135 | 136 | TEST (ParserTest, StmtForTest) { 137 | int result; 138 | apus::ParserContext pctx(std::make_shared()); 139 | 140 | yy_scan_string(for_test); 141 | result = yyparse(&pctx); 142 | EXPECT_EQ (result, 0); 143 | pctx.getVM()->Run(""); 144 | } 145 | -------------------------------------------------------------------------------- /test/utils/BinaryReader_unit_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "utils/BinaryReader.h" 3 | #include 4 | 5 | using namespace apus; 6 | 7 | TEST (BinaryReaderTest, ReadIntUnsignedIntegerTest) { 8 | 9 | string filename = "./test_unsigned_integer.bin"; 10 | unsigned char ff = 0xff; 11 | FILE *fp = fopen(filename.c_str(), "wb"); 12 | for (int i = 0; i < 15; i++) { 13 | fwrite (&ff, sizeof(unsigned char), 1, fp); 14 | } 15 | fclose (fp); 16 | 17 | uint64_t temp = 0; 18 | BinaryReader br(filename); 19 | 20 | // Read 8-bit unsigned integer 21 | uint8_t expected_uint8 = UCHAR_MAX; 22 | if (br.ReadInt (0, U8, temp) == 0) { 23 | uint8_t read_uint8 = (uint8_t)temp; 24 | EXPECT_EQ (read_uint8, expected_uint8); 25 | } 26 | // Read 16-bit unsigned integer 27 | uint16_t expected_uint16 = USHRT_MAX; 28 | if (br.ReadInt (U16, temp) == 0) { 29 | uint16_t read_uint16 = (uint16_t)temp; 30 | EXPECT_EQ (read_uint16, expected_uint16); 31 | } 32 | // Read 32-bit unsigned integer 33 | uint32_t expected_uint32 = UINT_MAX; 34 | if (br.ReadInt (U32, temp) == 0) { 35 | uint32_t read_uint32 = (uint32_t)temp; 36 | EXPECT_EQ (read_uint32, expected_uint32); 37 | } 38 | // Read 64-bit unsigned integer 39 | uint64_t expected_uint64 = ULONG_MAX; 40 | if (br.ReadInt (U64, temp) == 0) { 41 | uint64_t read_uint64 = (uint64_t)temp; 42 | EXPECT_EQ (read_uint64, expected_uint64); 43 | } 44 | 45 | remove (filename.c_str()); 46 | } 47 | 48 | TEST (BinaryReaderTest, ReadIntSignedIntegerTest) { 49 | 50 | string filename = "./test_signed_integer.bin"; 51 | unsigned char ff = 0xff; 52 | FILE *fp = fopen(filename.c_str(), "wb"); 53 | for (int i = 0; i < 15; i++) { 54 | fwrite (&ff, sizeof(unsigned char), 1, fp); 55 | } 56 | fclose (fp); 57 | 58 | uint64_t temp = 0; 59 | BinaryReader br(filename); 60 | 61 | // Read 8-bit signed integer 62 | int8_t expected_int8 = -1; 63 | if (br.ReadInt (0, U8, temp) == 0) { 64 | int8_t read_int8 = (int8_t)temp; 65 | EXPECT_EQ (read_int8, expected_int8); 66 | } 67 | // Read 16-bit signed integer 68 | int16_t expected_int16 = -1; 69 | if (br.ReadInt (U16, temp) == 0) { 70 | int16_t read_int16 = (int16_t)temp; 71 | EXPECT_EQ (read_int16, expected_int16); 72 | } 73 | // Read 32-bit signed integer 74 | int32_t expected_int32 = -1; 75 | if (br.ReadInt (U32, temp) == 0) { 76 | int32_t read_int32 = (int32_t)temp; 77 | EXPECT_EQ (read_int32, expected_int32); 78 | } 79 | // Read 64-bit signed integer 80 | int64_t expected_int64 = -1; 81 | if (br.ReadInt (U64, temp) == 0) { 82 | int64_t read_int64 = (int64_t)temp; 83 | EXPECT_EQ (read_int64, expected_int64); 84 | } 85 | remove (filename.c_str()); 86 | } 87 | 88 | TEST (BinaryReaderTest, ReadRealTest) { 89 | 90 | string filename = "./test_real.bin"; 91 | float expected_single = 10; 92 | double expected_double = 15; 93 | 94 | FILE *fp = fopen(filename.c_str(), "wb"); 95 | fwrite (&expected_single, sizeof(float), 1, fp); 96 | fwrite (&expected_double, sizeof(double), 1, fp); 97 | fclose (fp); 98 | 99 | double temp; 100 | BinaryReader br(filename); 101 | 102 | // Read 32-bit single-precision floating-point number 103 | if (br.ReadReal (0, F32, temp) == 0) { 104 | float read_single = (float)temp; 105 | EXPECT_EQ (read_single, expected_single); 106 | } 107 | // Read 64-bit double-precision floating-point number 108 | if (br.ReadReal (F64, temp) == 0) { 109 | double read_double = temp; 110 | EXPECT_EQ (read_double, expected_double); 111 | } 112 | remove (filename.c_str()); 113 | } 114 | 115 | TEST (BinaryReaderTest, ReadCharTest) { 116 | 117 | string filename = "./test_char.bin"; 118 | union { 119 | char bytes[4]; 120 | uint8_t c8; 121 | uint16_t c16; 122 | uint32_t c32; 123 | } ExpectedChar = {{'a','b','c','d'}}; 124 | 125 | FILE *fp = fopen(filename.c_str(), "wb"); 126 | fwrite (&ExpectedChar, sizeof(ExpectedChar), 1, fp); 127 | fclose(fp); 128 | 129 | uint32_t temp; 130 | BinaryReader br(filename); 131 | 132 | // Read 8-bit Character 133 | if (br.ReadChar (0, C8, temp) == 0) { 134 | char read_char8 = (char) temp; 135 | EXPECT_EQ (read_char8, ExpectedChar.c8); 136 | } 137 | // Read 16-bit Character 138 | if (br.ReadChar (0, C16, temp) == 0) { 139 | uint16_t read_char16 = (uint16_t) temp; 140 | EXPECT_EQ (read_char16, ExpectedChar.c16); 141 | } 142 | // Read 32-bit Character 143 | if (br.ReadChar (0, C32, temp) == 0) { 144 | uint32_t read_char32 = (uint32_t) temp; 145 | EXPECT_EQ (read_char32, ExpectedChar.c32); 146 | } 147 | remove(filename.c_str()); 148 | } 149 | 150 | TEST (BinaryReaderTest, ReadStringTest) { 151 | 152 | string filename = "./test_string.bin"; 153 | 154 | char nul = 0x0; 155 | char *str = "Test Code"; 156 | FILE *fp = fopen(filename.c_str(), "wb"); 157 | fwrite (str, strlen(str), 1, fp); 158 | fwrite (&nul, sizeof(char), 1, fp); 159 | fwrite (str, strlen(str), 1, fp); 160 | fclose (fp); 161 | 162 | string read_str; 163 | BinaryReader br(filename); 164 | if (br.ReadString (0, STR8, read_str) == 0) { 165 | EXPECT_STREQ (str, read_str.c_str()); 166 | } 167 | 168 | remove(filename.c_str()); 169 | } 170 | 171 | TEST (BinaryReaderTest, EndianTest) { 172 | 173 | string filename = "./test_endian.bin"; 174 | union { 175 | char bytes[4]; 176 | int integer; 177 | } Integer = {{1,2,3,4}}; 178 | 179 | FILE *fp = fopen(filename.c_str(), "wb"); 180 | fwrite (&Integer, sizeof(Integer), 1, fp); 181 | fclose (fp); 182 | 183 | int expected_big = 0x01020304ul; 184 | int expected_little = 0x04030201ul; 185 | 186 | BinaryReader br (filename); 187 | uint64_t read = 0; 188 | // Set the reverse endian of host system to the file endian 189 | if (HostEndian() == LITTLE) { 190 | 191 | br.SetFileEndian (BIG); 192 | if (br.ReadInt(0, S32, read) == 0) { 193 | EXPECT_EQ ((int)read, expected_big); 194 | } 195 | } else if (HostEndian() == BIG) { 196 | 197 | br.SetFileEndian (LITTLE); 198 | if (br.ReadInt (0, S32, read) == 0) { 199 | EXPECT_EQ ((int)read, expected_little); 200 | } 201 | } 202 | 203 | remove(filename.c_str()); 204 | } 205 | 206 | -------------------------------------------------------------------------------- /test/vm/data_type_table_unit_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "common/common.h" 3 | #include "vm/data_type_table.h" 4 | using namespace apus; 5 | 6 | std::shared_ptr g_dtt = std::make_shared(); 7 | 8 | TEST(data_type_test, initialization) { 9 | ASSERT_TRUE(g_dtt != NULL); 10 | g_dtt->SetPrimitiveTypes(); 11 | 12 | // Check primitive types to be in data type table 13 | for (int i = U8; i <= STR32; i++) { 14 | ASSERT_TRUE(g_dtt->Find((TypeSpecifier)i) != NULL); 15 | } 16 | } 17 | 18 | // struct struct1 { 19 | // S32 integer1 20 | // S16 integer2 21 | // F32 float1 22 | // } 23 | TEST(data_type_test, simple_struct_test) { 24 | 25 | DataType* struct1 = new DataType(STRUCT); 26 | struct1->Insert("integer1", g_dtt->Find(U8)); 27 | struct1->Insert("integer2", g_dtt->Find(S16)); 28 | struct1->Insert("float1", g_dtt->Find(F32)); 29 | EXPECT_TRUE(struct1->HasChild()); 30 | 31 | g_dtt->Insert("struct1", struct1); 32 | } 33 | 34 | // struct child_struct { 35 | // U64 unsigned1 36 | // U32 unsigned2 37 | // C16 char1 38 | // } 39 | // 40 | // struct parent_struct { 41 | // C8 char2 42 | // struct child_struct child1 43 | // } 44 | TEST(data_type_test, struct_in_struct_test) { 45 | 46 | DataType* childStruct = new DataType(STRUCT); 47 | childStruct->Insert("unsigned1", g_dtt->Find(U64)); 48 | childStruct->Insert("unsigned2", g_dtt->Find(U32)); 49 | childStruct->Insert("char1", g_dtt->Find(C16)); 50 | EXPECT_TRUE(childStruct->HasChild()); 51 | 52 | DataType* parentStruct = new DataType(STRUCT); 53 | parentStruct->Insert("char2", g_dtt->Find(C8)); 54 | parentStruct->Insert("child_struct", childStruct); 55 | EXPECT_TRUE(parentStruct->HasChild()); 56 | 57 | g_dtt->Insert("parent_struct", parentStruct); 58 | } 59 | 60 | // struct struct2 { 61 | // U64 unsigned1 62 | // U32 unsigned2 63 | // C16 char1 64 | // } 65 | TEST(data_type_test, Find_test) { 66 | 67 | DataType* struct2 = new DataType(STRUCT); 68 | struct2->Insert("unsigned1", g_dtt->Find(U64)); 69 | struct2->Insert("unsigned2", g_dtt->Find(U32)); 70 | struct2->Insert("char1", g_dtt->Find(C16)); 71 | EXPECT_TRUE(struct2->HasChild()); 72 | 73 | // things which can be found in this data type 74 | EXPECT_TRUE(struct2->Find("unsigned1") != NULL); 75 | EXPECT_TRUE(struct2->Find("unsigned2") != NULL); 76 | EXPECT_TRUE(struct2->Find("char1") != NULL); 77 | // things which cannot be found in this data type 78 | EXPECT_TRUE(struct2->Find("not_exist") == NULL); 79 | 80 | g_dtt->Insert("struct2", struct2); 81 | } 82 | 83 | // struct struct_with_array { 84 | // U16[3][4] array1 85 | // } 86 | TEST(data_type_test, array_test) { 87 | 88 | ArrayDataType* array = new ArrayDataType(ARRAY); 89 | array->AddDimension(4); 90 | array->AddDimension(3); 91 | array->SetElement(g_dtt->Find(U16)); 92 | EXPECT_EQ(array->GetArraySize(), 3*4); 93 | EXPECT_EQ(array->GetByteSize(), 3*4*2); 94 | 95 | DataType* struct_with_array = new DataType(STRUCT); 96 | struct_with_array->Insert("array1", array); 97 | 98 | g_dtt->Insert("struct_with_array", struct_with_array); 99 | } 100 | 101 | // struct struct_with_struct_array { 102 | // struct struct1[2] struct_array 103 | // } 104 | TEST(data_type_test, struct_array_test) { 105 | 106 | // copy "struct1" structure from data type table 107 | ArrayDataType* childStruct = new ArrayDataType(STRUCT_ARRAY); 108 | childStruct->AddDimension(2); 109 | childStruct->SetElement(g_dtt->Find("struct1")); 110 | 111 | DataType* struct_with_struct_array = new DataType(STRUCT); 112 | struct_with_struct_array->Insert("struct_array", childStruct); 113 | EXPECT_TRUE(struct_with_struct_array->HasChild()); 114 | 115 | g_dtt->Insert("struct_with_struct_array", struct_with_struct_array); 116 | } 117 | 118 | TEST(data_type_table_test, Find_test) { 119 | 120 | std::shared_ptr struct1 = g_dtt->Find("struct1"); 121 | std::shared_ptr parent_struct = g_dtt->Find("parent_struct"); 122 | std::shared_ptr struct_with_array 123 | = g_dtt->Find("struct_with_array"); 124 | std::shared_ptr struct_with_struct_array 125 | = g_dtt->Find("struct_with_struct_array"); 126 | 127 | ASSERT_TRUE(struct1 != NULL); 128 | EXPECT_TRUE(struct1->Find("integer1") != NULL); 129 | EXPECT_TRUE(struct1->Find("integer2") != NULL); 130 | EXPECT_TRUE(struct1->Find("float1") != NULL); 131 | 132 | ASSERT_TRUE(parent_struct != NULL); 133 | EXPECT_TRUE(parent_struct->Find("char2") != NULL); 134 | std::shared_ptr child_struct 135 | = parent_struct->Find("child_struct"); 136 | ASSERT_TRUE(child_struct != NULL); 137 | EXPECT_TRUE(child_struct->Find("unsigned1") != NULL); 138 | EXPECT_TRUE(child_struct->Find("unsigned2") != NULL); 139 | EXPECT_TRUE(child_struct->Find("char1") != NULL); 140 | 141 | ASSERT_TRUE(struct_with_array != NULL); 142 | ArrayDataType* array1 = dynamic_cast 143 | (struct_with_array->Find("array1").get()); 144 | ASSERT_TRUE(array1 != NULL); 145 | EXPECT_TRUE(array1->IsArray() == true); 146 | 147 | ASSERT_TRUE(struct_with_struct_array != NULL); 148 | EXPECT_TRUE(struct_with_struct_array->Find("struct_array") != NULL); 149 | ArrayDataType* struct_array = dynamic_cast 150 | (struct_with_struct_array->Find("struct_array").get()); 151 | EXPECT_TRUE(struct_array->IsArray()); 152 | } 153 | -------------------------------------------------------------------------------- /test/vm/variable_table_unit_test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "vm/data_type_table.h" 3 | #include "vm/variable_table.h" 4 | #include "ast/value/value.h" 5 | #include "ast/value/signed_int_value.h" 6 | #include "ast/value/string_value.h" 7 | using namespace apus; 8 | 9 | static std::shared_ptr dtt = std::make_shared(); 10 | static std::shared_ptr vt = std::make_shared(); 11 | 12 | TEST(variable_test, initialization) { 13 | ASSERT_TRUE(dtt != NULL); 14 | dtt->SetPrimitiveTypes(); 15 | 16 | // Check primitive types to be in data type table 17 | for (int i = U8; i <= STR32; i++) { 18 | ASSERT_TRUE(dtt->Find((TypeSpecifier)i) != NULL); 19 | } 20 | } 21 | 22 | // var U8 a 23 | TEST(variable_test, only_declaration_test) { 24 | VarPtr var = std::make_shared("a", dtt->Find(U8)); 25 | ASSERT_TRUE(var != NULL); 26 | EXPECT_TRUE(var->getType() == U8); 27 | 28 | vt->Insert(var->getName(), var); 29 | } 30 | 31 | // var S16 b = 5 32 | TEST(variable_test, init_value_test) { 33 | VarPtr var = std::make_shared("b", dtt->Find(S16)); 34 | std::shared_ptr signed_int_5 35 | = SignedIntValue::Create(dtt->Find(S16), 5); 36 | var->setValue(signed_int_5); 37 | 38 | ASSERT_TRUE(var != NULL); 39 | EXPECT_TRUE(var->getValue()->IsTrue(signed_int_5)); 40 | 41 | vt->Insert(var->getName(), var); 42 | } 43 | 44 | // var STR8 c = "Hello" 45 | TEST(variable_test, string_init_test) { 46 | VarPtr var = std::make_shared("c", dtt->Find(STR8)); 47 | std::shared_ptr string_hello 48 | = StringValue::Create(dtt->Find(STR8), "Hello"); 49 | var->setValue(string_hello); 50 | 51 | ASSERT_TRUE(var != NULL); 52 | EXPECT_TRUE(var->getValue()->IsTrue(string_hello)); 53 | 54 | vt->Insert(var->getName(), var); 55 | } 56 | 57 | // struct A { 58 | // S32 aa 59 | // C8 bb 60 | // } 61 | // 62 | // var struct A d 63 | TEST(variable_test, struct_variable_test) { 64 | 65 | std::shared_ptr struct_A = std::make_shared(STRUCT); 66 | struct_A->Insert("aa", dtt->Find(S32)); 67 | struct_A->Insert("bb", dtt->Find(C8)); 68 | EXPECT_TRUE(struct_A->HasChild()); 69 | 70 | VarPtr var = std::make_shared("d", struct_A); 71 | ASSERT_TRUE(var->IsStructVariable()); 72 | 73 | ASSERT_TRUE(var->getChildVariable("aa") != NULL); 74 | EXPECT_EQ(var->getChildVariable("aa")->getType(), S32); 75 | 76 | ASSERT_TRUE(var->getChildVariable("bb") != NULL); 77 | EXPECT_EQ(var->getChildVariable("bb")->getType(), C8); 78 | 79 | vt->Insert(var->getName(), var); 80 | } 81 | 82 | TEST(variable_table_test, find_test) { 83 | std::shared_ptr var_a = vt->Find("a"); 84 | std::shared_ptr var_b = vt->Find("b"); 85 | std::shared_ptr var_c = vt->Find("c"); 86 | std::shared_ptr var_d = vt->Find("d"); 87 | 88 | ASSERT_TRUE(var_a != NULL); 89 | ASSERT_TRUE(var_b != NULL); 90 | ASSERT_TRUE(var_c != NULL); 91 | ASSERT_TRUE(var_d != NULL); 92 | } 93 | --------------------------------------------------------------------------------