diff --git a/practice/preprocessor/Makefile b/practice/preprocessor/Makefile new file mode 100644 index 0000000..b710333 --- /dev/null +++ b/practice/preprocessor/Makefile @@ -0,0 +1,9 @@ +DEFINES=-DCONFIG_DEBUG=1 -DCONFIG_LOG_LEVEL=0 + +bin/test: src/main.cpp src/myassert.h src/mylog.h src/instructions.h + g++ -Wall -Werror -ggdb $(DEFINES) -std=c++11 $< -o $@ + +clean: + rm -rf bin/* + +.PHONY: clean diff --git a/practice/preprocessor/_gitignore b/practice/preprocessor/_gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/practice/preprocessor/_gitignore @@ -0,0 +1 @@ +bin diff --git a/practice/preprocessor/src/instructions.h b/practice/preprocessor/src/instructions.h new file mode 100644 index 0000000..04cc881 --- /dev/null +++ b/practice/preprocessor/src/instructions.h @@ -0,0 +1,97 @@ +#ifndef __INSTRUCTIONS_H__ +#define __INSTRUCTIONS_H__ + +#define FOR_INSTRUCTIONS(DO) \ + DO(INVALID, "Invalid instruction.", 1) \ + DO(DLOAD, "Load double on TOS, inlined into insn stream.", 9) \ + DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9) \ + DO(SLOAD, "Load string reference on TOS, next two bytes - constant id.", 3) \ + DO(DLOAD0, "Load double 0 on TOS.", 1) \ + DO(ILOAD0, "Load int 0 on TOS.", 1) \ + DO(SLOAD0, "Load empty string on TOS.", 1) \ + DO(DLOAD1, "Load double 1 on TOS.", 1) \ + DO(ILOAD1, "Load int 1 on TOS.", 1) \ + DO(DLOADM1, "Load double -1 on TOS.", 1) \ + DO(ILOADM1, "Load int -1 on TOS.", 1) \ + DO(DADD, "Add 2 doubles on TOS, push value back.", 1) \ + DO(IADD, "Add 2 ints on TOS, push value back.", 1) \ + DO(DSUB, "Subtract 2 doubles on TOS (lower from upper), push value back.", 1) \ + DO(ISUB, "Subtract 2 ints on TOS (lower from upper), push value back.", 1) \ + DO(DMUL, "Multiply 2 doubles on TOS, push value back.", 1) \ + DO(IMUL, "Multiply 2 ints on TOS, push value back.", 1) \ + DO(DDIV, "Divide 2 doubles on TOS (upper to lower), push value back.", 1) \ + DO(IDIV, "Divide 2 ints on TOS (upper to lower), push value back.", 1) \ + DO(IMOD, "Modulo operation on 2 ints on TOS (upper to lower), push value back.", 1) \ + DO(DNEG, "Negate double on TOS.", 1) \ + DO(INEG, "Negate int on TOS.", 1) \ + DO(IAOR, "Arithmetic OR of 2 ints on TOS, push value back.", 1) \ + DO(IAAND, "Arithmetic AND of 2 ints on TOS, push value back.", 1) \ + DO(IAXOR, "Arithmetic XOR of 2 ints on TOS, push value back.", 1) \ + DO(IPRINT, "Pop and print integer TOS.", 1) \ + DO(DPRINT, "Pop and print double TOS.", 1) \ + DO(SPRINT, "Pop and print string TOS.", 1) \ + DO(I2D, "Convert int on TOS to double.", 1) \ + DO(D2I, "Convert double on TOS to int.", 1) \ + DO(S2I, "Convert string on TOS to int.", 1) \ + DO(SWAP, "Swap 2 topmost values.", 1) \ + DO(POP, "Remove topmost value.", 1) \ + DO(LOADDVAR0, "Load double from variable 0, push on TOS.", 1) \ + DO(LOADDVAR1, "Load double from variable 1, push on TOS.", 1) \ + DO(LOADDVAR2, "Load double from variable 2, push on TOS.", 1) \ + DO(LOADDVAR3, "Load double from variable 3, push on TOS.", 1) \ + DO(LOADIVAR0, "Load int from variable 0, push on TOS.", 1) \ + DO(LOADIVAR1, "Load int from variable 1, push on TOS.", 1) \ + DO(LOADIVAR2, "Load int from variable 2, push on TOS.", 1) \ + DO(LOADIVAR3, "Load int from variable 3, push on TOS.", 1) \ + DO(LOADSVAR0, "Load string from variable 0, push on TOS.", 1) \ + DO(LOADSVAR1, "Load string from variable 1, push on TOS.", 1) \ + DO(LOADSVAR2, "Load string from variable 2, push on TOS.", 1) \ + DO(LOADSVAR3, "Load string from variable 3, push on TOS.", 1) \ + DO(STOREDVAR0, "Pop TOS and store to double variable 0.", 1) \ + DO(STOREDVAR1, "Pop TOS and store to double variable 1.", 1) \ + DO(STOREDVAR2, "Pop TOS and store to double variable 0.", 1) \ + DO(STOREDVAR3, "Pop TOS and store to double variable 3.", 1) \ + DO(STOREIVAR0, "Pop TOS and store to int variable 0.", 1) \ + DO(STOREIVAR1, "Pop TOS and store to int variable 1.", 1) \ + DO(STOREIVAR2, "Pop TOS and store to int variable 0.", 1) \ + DO(STOREIVAR3, "Pop TOS and store to int variable 3.", 1) \ + DO(STORESVAR0, "Pop TOS and store to string variable 0.", 1) \ + DO(STORESVAR1, "Pop TOS and store to string variable 1.", 1) \ + DO(STORESVAR2, "Pop TOS and store to string variable 0.", 1) \ + DO(STORESVAR3, "Pop TOS and store to string variable 3.", 1) \ + DO(LOADDVAR, "Load double from variable, whose 2-byte is id inlined to insn stream, push on TOS.", 3) \ + DO(LOADIVAR, "Load int from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \ + DO(LOADSVAR, "Load string from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \ + DO(STOREDVAR, "Pop TOS and store to double variable, whose 2-byte id is inlined to insn stream.", 3) \ + DO(STOREIVAR, "Pop TOS and store to int variable, whose 2-byte id is inlined to insn stream.", 3) \ + DO(STORESVAR, "Pop TOS and store to string variable, whose 2-byte id is inlined to insn stream.", 3) \ + DO(LOADCTXDVAR, "Load double from variable, whose 2-byte context and 2-byte id inlined to insn stream, push on TOS.", 5) \ + DO(LOADCTXIVAR, "Load int from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \ + DO(LOADCTXSVAR, "Load string from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \ + DO(STORECTXDVAR, "Pop TOS and store to double variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ + DO(STORECTXIVAR, "Pop TOS and store to int variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ + DO(STORECTXSVAR, "Pop TOS and store to string variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ + DO(DCMP, "Compare 2 topmost doubles, pushing libc-stryle comparator value cmp(upper, lower) as integer.", 1) \ + DO(ICMP, "Compare 2 topmost ints, pushing libc-style comparator value cmp(upper, lower) as integer.", 1) \ + DO(JA, "Jump always, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPNE, "Compare two topmost integers and jump if upper != lower, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPE, "Compare two topmost integers and jump if upper == lower, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPG, "Compare two topmost integers and jump if upper > lower, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPGE, "Compare two topmost integers and jump if upper >= lower, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPL, "Compare two topmost integers and jump if upper < lower, next two bytes - signed offset of jump destination.", 3) \ + DO(IFICMPLE, "Compare two topmost integers and jump if upper <= lower, next two bytes - signed offset of jump destination.", 3) \ + DO(DUMP, "Dump value on TOS, without removing it.", 1) \ + DO(STOP, "Stop execution.", 1) \ + DO(CALL, "Call function, next two bytes - unsigned function id.", 3) \ + DO(CALLNATIVE, "Call native function, next two bytes - id of the native function.", 3) \ + DO(RETURN, "Return to call location", 1) \ + DO(BREAK, "Breakpoint for the debugger.", 1) + +enum InstructionCode { +#define ENUM_ELEM(b, d, l) INST_##b, + FOR_INSTRUCTIONS(ENUM_ELEM) +#undef ENUM_ELEM + INST_LAST +}; + +#endif //__INSTRUCTIONS_H__ diff --git a/practice/preprocessor/src/main.cpp b/practice/preprocessor/src/main.cpp new file mode 100644 index 0000000..a4666e9 --- /dev/null +++ b/practice/preprocessor/src/main.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +#include "myassert.h" +#include "mylog.h" +#include "instructions.h" + +const char* instruction_name(InstructionCode code) +{ + (void)code; + // TODO + return "I don't know"; +} + +const char* instruction_description(InstructionCode code) +{ + (void)code; + // TODO + return "I don't know"; +} + +std::vector gen_rnd_instrs(const size_t instr_cnt) +{ + std::vector buffer; + // TODO + return std::move(buffer); +} + +void log_instrs(const std::vector &instrs) +{ + // TODO + (void)instrs; +} + +void exec_instrs(const std::vector &instrs) +{ + (void)instrs; + // TODO this function should interpret instrs stream. + // instrs stream parsing is similar to the one done in log_instrs +} + +int main() +{ + std::srand(std::time(0)); + using ::LOG_LEVELS; + // Part 1 + bool assertion1_evaluated = false; + myassert(assertion1_evaluated = true); + assert((CONFIG_DEBUG && assertion1_evaluated) + || (!CONFIG_DEBUG && !assertion1_evaluated)); + + //myassert(1 == 4); + + // Part 2 + LOG(LOG_LEVELS::INFO, "=============================="); + LOG(LOG_LEVELS::DEBUG, "%d %d %d %s", 1, 2, 3, "debug"); + LOG(LOG_LEVELS::INFO, "%d %d %s", 1, 2, "info"); + LOG(LOG_LEVELS::WARN, "%d %s", 1, "warning"); + LOG(LOG_LEVELS::ERROR, "%s", "error!"); + + // Part 3 + LOG(LOG_LEVELS::INFO, "=============================="); + LOG(LOG_LEVELS::INFO, "%s %s", instruction_name(INST_DADD), + instruction_description(INST_DADD)); + LOG(LOG_LEVELS::INFO, "%s %s", instruction_name(INST_IPRINT), + instruction_description(INST_IPRINT)); + + // Part 4 + auto inst_stream = gen_rnd_instrs(20); + log_instrs(inst_stream); + + // Part 5 + LOG(LOG_LEVELS::INFO, "=============================="); + std::vector super_code = { + INST_ILOAD, 0xff, 0, 0, 0, 0, 0, 0, 0, + INST_ILOAD, 0, 0, 0xdd, 0, 0, 0, 0, 0, + INST_IADD, + INST_ILOAD, 0xff, 0, 0, 0, 0, 0, 0, 0, + INST_IADD, + INST_IPRINT + }; // 0xff + 0xdd0000 + 0xff = 0xdd01fe + log_instrs(super_code); + exec_instrs(super_code); + + return 0; +} diff --git a/practice/preprocessor/src/myassert.h b/practice/preprocessor/src/myassert.h new file mode 100644 index 0000000..28e2c36 --- /dev/null +++ b/practice/preprocessor/src/myassert.h @@ -0,0 +1,22 @@ +#ifndef __MY_ASSERT_H__ +#define __MY_ASSERT_H__ + +#ifndef CONFIG_DEBUG +#define CONFIG_DEBUG 0 +#endif + +// TODO +#if CONFIG_DEBUG != 0 +#include +#define myassert(expr) do {\ + if (!(expr)) { \ + std::cerr << "assertion failed in " << __FILE__ << " function name: " << __func__ << std::endl << \ + "On line = " << __LINE__ << ". In expression " << #expr << std::endl; \ + abort(); \ + }\ +} while(0, 0) +#else +#define myassert(...) do {} while(0, 0) +#endif + +#endif //__MY_ASSERT_H__ diff --git a/practice/preprocessor/src/mylog.h b/practice/preprocessor/src/mylog.h new file mode 100644 index 0000000..abcd1f1 --- /dev/null +++ b/practice/preprocessor/src/mylog.h @@ -0,0 +1,24 @@ +#ifndef __MY_LOG_H__ +#define __MY_LOG_H__ + +#ifndef CONFIG_LOG_LEVEL +#define CONFIG_LOG_LEVEL 0 +#endif + +enum class LOG_LEVELS { + DEBUG = 1, + INFO = 2, + WARN = 3, + ERROR = 4, + NO_LOG = 5 +}; + +// TODO +#include +#define LOG(level, format, ...) do { \ + if (level >= static_cast(CONFIG_LOG_LEVEL)) { \ + printf("[%s : %d : %s ] " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);\ + } \ +} while(0, 0) + +#endif // __MY_LOG_H__