diff --git a/Makefile b/Makefile index 2f7a5e7..005ee72 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ RPYTHON?=../pypy/rpython/bin/rpython RPYTHONFLAGS?=--opt=jit +CXXFLAGS=-std=c++14 -Wall -Os all: aheui-c aheui-py @@ -30,3 +31,6 @@ testpy: pytest if [ -e snippets ]; then cd snippets && git pull; else git clone https://github.com/aheui/snippets; fi cd snippets && AHEUI=../rpaheui.py bash test.sh + +test-template-cc: + $(CXX) $(CXXFLAGS) aheui/template.cc && ./a.out diff --git a/aheui/_argparse.py b/aheui/_argparse.py index 98fd161..ae64c62 100644 --- a/aheui/_argparse.py +++ b/aheui/_argparse.py @@ -144,7 +144,7 @@ def parse_args(self, args): \t- `asm`: See `ahsembly`. \t- usage: `--source=asm`, `-Sbytecode` or `-S text` """) -parser.add_argument('--target', '-T', default='run', choices='run,bytecode,asm', description='Set target filetype.', full_description="""\t- `run`: Run given code. +parser.add_argument('--target', '-T', default='run', choices='run,bytecode,asm,c++', description='Set target filetype.', full_description="""\t- `run`: Run given code. \t- `bytecode`: Aheui bytecode. (Bytecode representation of `ahsembly`. \t- `asm`: See `ahsembly`. \t- usage: `--target=asm`, `-Tbytecode` or `-T run` @@ -157,3 +157,4 @@ def parse_args(self, args): parser.add_argument('--no-c', '--no-c', narg='0', default='no', description='Do not generate `.aheuic` file automatically.', full_description='\tWhat is .aheuic? https://github.com/aheui/snippets/commit/cbb5a12e7cd2db771538ab28dfbc9ad1ada86f35\n') parser.add_argument('--version', '-v', narg='-1', default='no', description='Show program version', message=VERSION) parser.add_argument('--help', '-h', narg='-1', default='no', description='Show this help text') +parser.add_argument('-X', '-X', default='', choices='time', description='Set debug option') diff --git a/aheui/aheui.py b/aheui/aheui.py index 4aa212d..0614849 100644 --- a/aheui/aheui.py +++ b/aheui/aheui.py @@ -504,8 +504,10 @@ def open_r(filename): output += '.aheuis' elif target == 'run': output = '-' + elif target == 'c++': + output = filename + '.cc' else: - os.write(2, b'aheui: error: --target,-t must be one of "bytecode", "asm", "run"\n') + os.write(2, b'aheui: error: --target,-t must be one of "bytecode", "asm", "run" or "c++"\n') raise SystemExit() return cmd, source, contents, opt_level, target, aheuic_output, output @@ -568,6 +570,11 @@ def entry_point(argv): os.write(outfp, bytecode) os.close(outfp) exitcode = 0 + elif target == 'c++': + c_source = compiler.write_cpp().encode('utf-8') + os.write(outfp, c_source) + os.close(outfp) + exitcode = 0 else: assert False return exitcode diff --git a/aheui/compile.py b/aheui/compile.py index 826c578..c614373 100644 --- a/aheui/compile.py +++ b/aheui/compile.py @@ -13,6 +13,11 @@ import aheui.const as c from aheui._compat import unichr, _unicode +fcc = os.open('aheui/template.cc', os.O_RDONLY, 0o777) +template_cc = os.read(fcc, 100000).decode('utf-8') # inlining template +os.close(fcc) +del fcc + OP_NAMES = [None, None, u'DIV', u'ADD', u'MUL', u'MOD', u'POP', u'PUSH', u'DUP', u'SEL', u'MOV', None, u'CMP', None, u'BRZ', None, u'SUB', u'SWAP', u'HALT', u'POPNUM', u'POPCHAR', u'PUSHNUM', u'PUSHCHAR', u'BRPOP2', u'BRPOP1', u'JMP'] @@ -918,3 +923,33 @@ def read_asm(self, text): for key in label_map.keys(): self.label_map[label_map[key]] = label_name_map[key] self.debug = Debug(lines, comments) + + def write_cpp(self): + """Write C code with comments.""" + codes = [] + for i, (op, val) in enumerate(self.lines): + if i in self.label_map.values(): + label_str = u'L%s:' % _unicode(i) + codes.append(padding(label_str, 8)) + else: + codes.append(u' ' * 8) + code = OP_NAMES[op].encode('utf-8').lower().decode('utf-8') # rpython workaround + if op in c.OP_JUMPS: + slabel = _unicode(self.label_map[val]) + if op != c.OP_JMP: + code_val = u'if (r->jump_%s()) goto L%s' % (code, slabel) + else: + code_val = u'goto L%s' % slabel + else: + if OP_USEVAL[op]: + param = _unicode(val) + else: + param = u'' + code_val = u'r->%s(%s)' % (code, param) + comment = self.debug.comment(i) if self.debug else u'' + sline = padding(_unicode(i), 3) + codes.append(u'%s; // L%s %s\n' % (code_val, sline, comment)) + gen_code = u''.join(codes) + splited_cc = template_cc.split(u'\n') + splited_cc[splited_cc.index(u'///GENERATED_CODE///')] = gen_code + return u'\n'.join(splited_cc) diff --git a/aheui/template.cc b/aheui/template.cc new file mode 100644 index 0000000..0572c1f --- /dev/null +++ b/aheui/template.cc @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +namespace aheui { + +typedef int64_t int_t; +typedef std::vector SpaceVector; + +const size_t SPACE_QUEUE_INDEX = 21; +const size_t SPACE_PORT_INDEX = 27; +const size_t SPACE_COUNT = 28; + +struct int_pair { + int_t first; + int_t second; +}; + +void print_unicode(uint32_t codepoint) { + if (codepoint <= 0x7f) { + putchar(codepoint); + } + else if (codepoint <= 0x7ff) { + putchar(0xc0 | ((codepoint >> 6) & 0x1f)); + putchar(0x80 | (codepoint & 0x3f)); + } + else if (codepoint <= 0xffff) { + putchar(0xe0 | ((codepoint >> 12) & 0x0f)); + putchar(0x80 | ((codepoint >> 6) & 0x3f)); + putchar(0x80 | (codepoint & 0x3f)); + } + else { + putchar(0xf0 | ((codepoint >> 18) & 0x07)); + putchar(0x80 | ((codepoint >> 12) & 0x3f)); + putchar(0x80 | ((codepoint >> 6) & 0x3f)); + putchar(0x80 | (codepoint & 0x3f)); + } +} + +class Space { +protected: + inline virtual void _put_value(int_t v) = 0; + inline virtual int_pair _get_2_values() = 0; +public: + inline virtual size_t size() = 0; + inline virtual void push(int_t v) = 0; + inline virtual int_t pop() = 0; + inline virtual void swap() = 0; + inline virtual void dup() = 0; + inline void add() { + auto values = this->_get_2_values(); + auto r = values.second + values.first; + this->_put_value(r); + } + inline void sub() { + auto values = this->_get_2_values(); + auto r = values.second - values.first; + this->_put_value(r); + } + inline void mul() { + auto values = this->_get_2_values(); + auto r = values.second * values.first; + this->_put_value(r); + } + inline void div() { + auto values = this->_get_2_values(); + auto r = values.second / values.first; + this->_put_value(r); + } + inline void mod() { + auto values = this->_get_2_values(); + auto r = values.second % values.first; + this->_put_value(r); + } + inline void cmp() { + auto values = this->_get_2_values(); + auto r = values.second >= values.first; + this->_put_value((int_t)r); + } +}; + +class Stack: public Space, std::vector { +protected: + inline void _put_value(int_t v) { + this->back() = v; + } + inline int_pair _get_2_values() { + int_pair r; + r.first = this->back(); + this->pop_back(); + r.second = this->back(); + return r; + } +public: + inline size_t size() { + return std::vector::size(); + } + inline virtual void push(int_t v) { + this->push_back(v); + } + inline virtual int_t pop() { + auto v = this->back(); + this->pop_back(); + return v; + } + inline void swap() { + std::iter_swap(this->end() - 1, this->end() - 2); + } + inline void dup() { + auto r = this->back(); + this->push_back(r); + } +}; + +class Queue: public Space, std::deque { +protected: + inline void _put_value(int_t v) { + this->push_back(v); + } + inline int_pair _get_2_values() { + int_pair r; + r.first = this->back(); + this->pop_back(); + r.second = this->back(); + this->pop_back(); + return r; + } +public: + inline size_t size() { + return std::deque::size(); + } + inline virtual void push(int_t v) { + this->push_back(v); + } + inline virtual int_t pop() { + auto v = this->front(); + this->pop_front(); + return v; + } + inline void swap() { + std::iter_swap(this->end() - 1, this->end() - 2); + } + inline void dup() { + auto r = this->back(); + this->push_back(r); + } +}; + +class Runtime { + std::unique_ptr spaces[28]; + Space *space; +public: + int_t exitcode = 0; + Runtime() { + for (auto i = 0; i < SPACE_COUNT; i++) { + if (i == SPACE_QUEUE_INDEX) { + this->spaces[i] = std::make_unique(); + } else { + this->spaces[i] = std::make_unique(); + } + } + this->sel(0); + } + // generation resource + inline void add() { + this->space->add(); + } + inline void sub() { + this->space->sub(); + } + inline void mul() { + this->space->mul(); + } + inline void div() { + this->space->div(); + } + inline void mod() { + this->space->mod(); + } + inline void pop() { + this->space->pop(); + } + inline void push(int_t v) { + this->space->push(v); + } + inline void dup() { + this->space->dup(); + } + inline void swap() { + this->space->swap(); + } + inline void sel(size_t i) { + this->space = spaces[i].get(); + } + inline void mov(size_t i) { + auto r = this->space->pop(); + this->spaces[i]->push(r); + } + inline void cmp() { + this->space->cmp(); + } + inline void popnum() { + auto r = this->space->pop(); + printf("%lld", r); + } + inline void popchar() { + auto r = this->space->pop(); + if (r < 0 || r > 0x10ffff) { + this->exitcode = r; + exit(-1); + } + print_unicode((uint32_t)r); + } + inline void pushnum() { + int_t i; + scanf("%lld", &i); + this->space->push(i); + } + inline void pushchar() { + + } + inline void halt() { + if (this->space->size() > 0) { + this->exitcode = this->space->pop(); + } else { + this->exitcode = 0; + } + exit((int)this->exitcode); + } + inline bool jump_brpop1() { + return this->space->size() < 1; + } + inline bool jump_brpop2() { + return this->space->size() < 2; + } + inline bool jump_brz() { + return this->space->pop() == 0; + } +}; + +void _main_run(Runtime *r); +int _main() { + auto runtime = std::make_unique(); + _main_run(runtime.get()); + return (int)runtime->exitcode; +} + +void _main_run(Runtime *r) { +///GENERATED_CODE/// +} + +} + +int main() { + return aheui::_main(); +} + diff --git a/setup.py b/setup.py index feb43b1..0111a38 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def get_readme(): 'aheui/int', ), package_data={ - 'aheui': ['version.py'] + 'aheui': ['version.py', 'template.cc'] }, install_requires=[ ],