Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c++ target #14

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

RPYTHON?=../pypy/rpython/bin/rpython
RPYTHONFLAGS?=--opt=jit
CXXFLAGS=-std=c++14 -Wall -Os


all: aheui-c aheui-py
Expand Down Expand Up @@ -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
3 changes: 2 additions & 1 deletion aheui/_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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')
9 changes: 8 additions & 1 deletion aheui/aheui.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
35 changes: 35 additions & 0 deletions aheui/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down Expand Up @@ -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)
260 changes: 260 additions & 0 deletions aheui/template.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
#include <cstdint>
#include <memory>
#include <vector>
#include <deque>
#include <algorithm>
#include <string>

namespace aheui {

typedef int64_t int_t;
typedef std::vector<int_t> 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<int_t> {
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<int_t>::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<int_t> {
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<int_t>::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<Space> 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<Queue>();
} else {
this->spaces[i] = std::make_unique<Stack>();
}
}
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<aheui::Runtime>();
_main_run(runtime.get());
return (int)runtime->exitcode;
}

void _main_run(Runtime *r) {
///GENERATED_CODE///
}

}

int main() {
return aheui::_main();
}

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def get_readme():
'aheui/int',
),
package_data={
'aheui': ['version.py']
'aheui': ['version.py', 'template.cc']
},
install_requires=[
],
Expand Down