Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions practice/preprocessor/Makefile
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions practice/preprocessor/_gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin
97 changes: 97 additions & 0 deletions practice/preprocessor/src/instructions.h
Original file line number Diff line number Diff line change
@@ -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__
90 changes: 90 additions & 0 deletions practice/preprocessor/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <cstdio>
#include <cassert>
#include <vector>
#include <utility>
#include <cstdlib>
#include <ctime>

#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<unsigned char> gen_rnd_instrs(const size_t instr_cnt)
{
std::vector<unsigned char> buffer;
// TODO
return std::move(buffer);
}

void log_instrs(const std::vector<unsigned char> &instrs)
{
// TODO
(void)instrs;
}

void exec_instrs(const std::vector<unsigned char> &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<unsigned char> 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;
}
22 changes: 22 additions & 0 deletions practice/preprocessor/src/myassert.h
Original file line number Diff line number Diff line change
@@ -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 <iostream>
#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__
24 changes: 24 additions & 0 deletions practice/preprocessor/src/mylog.h
Original file line number Diff line number Diff line change
@@ -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 <cstdio>
#define LOG(level, format, ...) do { \
if (level >= static_cast<LOG_LEVELS>(CONFIG_LOG_LEVEL)) { \
printf("[%s : %d : %s ] " format "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);\
} \
} while(0, 0)

#endif // __MY_LOG_H__