Get code generator plugin to a decently working state.

Still a few outstanding performance issues, and imports inside .capnp
files may not be working
This commit is contained in:
Jason Paryani
2014-10-19 20:06:00 -07:00
parent ece4e36329
commit 64e80e06bf
6 changed files with 278 additions and 95 deletions

View File

@@ -7,13 +7,114 @@
# cython: c_string_type = str
# cython: c_string_encoding = default
# cython: embedsignature = True
# cython: profile=True
{% macro getter(field, type) -%}
{% if 'uint' in field['type'] -%}
uint64_t get{{field.c_name}}() except +reraise_kj_exception
{% elif 'int' in field['type'] -%}
int64_t get{{field.c_name}}() except +reraise_kj_exception
{% elif 'void' == field['type'] -%}
void get{{field.c_name}}() except +reraise_kj_exception
{% elif 'bool' == field['type'] -%}
cbool get{{field.c_name}}() except +reraise_kj_exception
{% elif 'text' == field['type'] -%}
StringPtr get{{field.c_name}}() except +reraise_kj_exception
{% elif 'data' == field['type'] -%}
Data.{{type}} get{{field.c_name}}() except +reraise_kj_exception
{% else -%}
DynamicValue.{{type}} get{{field.c_name}}() except +reraise_kj_exception
{%- endif %}
{%- endmacro %}
# TODO: add struct/enum/list types
{% macro getfield(field, type) -%}
cpdef _get_{{field.name}}(self):
{% if 'int' in field['type'] -%}
return self.thisptr_child.get{{field.c_name}}()
{% elif 'void' == field['type'] -%}
self.thisptr_child.get{{field.c_name}}()
return None
{% elif 'bool' == field['type'] -%}
return self.thisptr_child.get{{field.c_name}}()
{% elif 'text' == field['type'] -%}
temp = self.thisptr_child.get{{field.c_name}}()
return (<char*>temp.begin())[:temp.size()]
{% elif 'data' == field['type'] -%}
temp = self.thisptr_child.get{{field.c_name}}()
return <bytes>((<char*>temp.begin())[:temp.size()])
{% else -%}
cdef DynamicValue.{{type}} temp = self.thisptr_child.get{{field.c_name}}()
return to_python_{{type | lower}}(temp, self._parent)
{% endif -%}
{%- endmacro %}
{% macro setter(field) -%}
{% if 'int' in field['type'] -%}
void set{{field.c_name}}({{field.type}}_t) except +reraise_kj_exception
{% elif 'bool' == field['type'] -%}
void set{{field.c_name}}(cbool) except +reraise_kj_exception
{% elif 'text' == field['type'] -%}
void set{{field.c_name}}(StringPtr) except +reraise_kj_exception
{% elif 'data' == field['type'] -%}
void set{{field.c_name}}(ArrayPtr[byte]) except +reraise_kj_exception
{% else -%}
void set{{field.c_name}}(DynamicValue.Reader) except +reraise_kj_exception
{%- endif %}
{%- endmacro %}
{% macro setfield(field) -%}
{% if 'int' in field['type'] -%}
cpdef _set_{{field.name}}(self, {{field.type}}_t value):
self.thisptr_child.set{{field.c_name}}(value)
{% elif 'void' == field['type'] -%}
cpdef _set_{{field.name}}(self, value=None):
pass
{% elif 'bool' == field['type'] -%}
cpdef _set_{{field.name}}(self, bool value):
self.thisptr_child.set{{field.c_name}}(value)
{% elif 'list' == field['type'] -%}
cpdef _set_{{field.name}}(self, list value):
cdef uint i = 0
self.init("{{field.name}}", len(value))
cdef _DynamicListBuilder temp = self._get_{{field.name}}()
for elem in value:
{% if 'struct' in field['sub_type'] -%}
temp._get(i).from_dict(elem)
{% else -%}
temp[i] = elem
{% endif -%}
i += 1
{% elif 'text' == field['type'] -%}
cpdef _set_{{field.name}}(self, value):
cdef StringPtr temp_string
if type(value) is bytes:
temp_string = StringPtr(<char*>value, len(value))
else:
encoded_value = value.encode()
temp_string = StringPtr(<char*>encoded_value, len(encoded_value))
self.thisptr_child.set{{field.c_name}}(temp_string)
{% elif 'data' == field['type'] -%}
cpdef _set_{{field.name}}(self, value):
cdef StringPtr temp_string
if type(value) is bytes:
temp_string = StringPtr(<char*>value, len(value))
else:
encoded_value = value.encode()
temp_string = StringPtr(<char*>encoded_value, len(encoded_value))
self.thisptr_child.set{{field.c_name}}(ArrayPtr[byte](<byte *>temp_string.begin(), temp_string.size()))
{% else -%}
cpdef _set_{{field.name}}(self, value):
_setDynamicFieldStatic(self.thisptr, "{{field.name}}", value, self._parent)
{% endif -%}
{%- endmacro %}
import capnp
import {{file.filename | replace('.', '_')}}
from libcpp cimport bool as cbool
from capnp.includes.types cimport *
from capnp cimport helpers
from capnp.includes.capnp_cpp cimport DynamicValue, Schema, VOID, StringPtr
from capnp.includes.capnp_cpp cimport DynamicValue, Schema, VOID, StringPtr, ArrayPtr, Data
from capnp.lib.capnp cimport _DynamicStructReader, _DynamicStructBuilder, _DynamicListBuilder, _DynamicEnum, _StructSchemaField, to_python_builder, to_python_reader, _to_dict, _setDynamicFieldStatic, _Schema, _InterfaceSchema
from capnp.helpers.non_circular cimport reraise_kj_exception
@@ -27,16 +128,6 @@ cdef DynamicValue.Reader _extract_dynamic_struct_reader(_DynamicStructReader val
cdef DynamicValue.Reader _extract_dynamic_enum(_DynamicEnum value):
return DynamicValue.Reader(value.thisptr)
cdef _from_dict(_DynamicStructBuilder msg, dict d):
for key, val in d.iteritems():
if key != 'which':
try:
msg._set(key, val)
except Exception as e:
if 'expected isSetInUnion(field)' in str(e):
msg.init(key)
msg._set(key, val)
cdef _from_list(_DynamicListBuilder msg, list d):
cdef size_t count = 0
for val in d:
@@ -85,12 +176,12 @@ cdef extern from "{{file.filename}}.h":
cdef cppclass {{node.module_name}}"{{node.c_module_path}}":
cppclass Reader:
{%- for field in node.struct.fields %}
DynamicValue.Reader get{{field.c_name}}()
{{ getter(field, "Reader")|indent(12)}}
{%- endfor %}
cppclass Builder:
{%- for field in node.struct.fields %}
DynamicValue.Builder get{{field.c_name}}()
set{{field.c_name}}(DynamicValue.Reader)
{{ getter(field, "Builder")|indent(12)}}
{{ setter(field)|indent(12)}}
{%- endfor %}
{%- endfor %}
@@ -115,9 +206,9 @@ cdef class {{node.module_name}}_Reader(_DynamicStructReader):
self._init(struct.thisptr, struct._parent, struct.is_root, False)
self.thisptr_child = (<C_DynamicStruct_Reader>struct.thisptr).as{{node.module_name}}()
{% for field in node.struct.fields %}
cpdef _get_{{field.name}}(self) except +reraise_kj_exception:
cdef DynamicValue.Reader temp = self.thisptr_child.get{{field.c_name}}()
return to_python_reader(temp, self._parent)
{{ getfield(field, "Reader")|indent(4) }}
property {{field.name}}:
def __get__(self):
return self._get_{{field.name}}()
@@ -133,7 +224,7 @@ cdef class {{node.module_name}}_Reader(_DynamicStructReader):
}
{% if node.is_union %}
which = self.which()
which = self._which_str()
ret[which] = getattr(self, which)
{% endif %}
@@ -145,21 +236,8 @@ cdef class {{node.module_name}}_Builder(_DynamicStructBuilder):
self._init(struct.thisptr, struct._parent, struct.is_root, False)
self.thisptr_child = (<C_DynamicStruct_Builder>struct.thisptr).as{{node.module_name}}()
{% for field in node.struct.fields %}
cpdef _get_{{field.name}}(self) except +reraise_kj_exception:
cdef DynamicValue.Builder temp = self.thisptr_child.get{{field.c_name}}()
return to_python_builder(temp, self._parent)
cpdef _set_{{field.name}}(self, value) except +reraise_kj_exception:
_setDynamicFieldStatic(self.thisptr, "{{field.name}}", value, self._parent)
# cdef DynamicValue.Builder temp
# value_type = type(value)
# if value_type is list:
# builder = to_python_builder(self.thisptr_child.get{{field.c_name}}(), self._parent)
# _from_list(builder, value)
# elif value_type is dict:
# builder = to_python_builder(self.thisptr_child.get{{field.c_name}}(), self._parent)
# _from_dict(builder, value)
# else:
# self.thisptr_child.set{{field.c_name}}(to_dynamic_value(value))
{{ getfield(field, "Builder")|indent(4) }}
{{ setfield(field)|indent(4) }}
property {{field.name}}:
def __get__(self):
@@ -178,11 +256,30 @@ cdef class {{node.module_name}}_Builder(_DynamicStructBuilder):
}
{% if node.is_union %}
which = self.which()
which = self._which_str()
ret[which] = getattr(self, which)
{% endif %}
return ret
def from_dict(self, dict d):
cdef str key
for key, val in d.iteritems():
if False: pass
{% for field in node.struct.fields %}
elif key == "{{field.name}}":
try:
self._set_{{field.name}}(val)
except Exception as e:
if 'expected isSetInUnion(field)' in str(e):
self.init(key)
self._set_{{field.name}}(val)
else:
raise
{%- endfor %}
else:
raise ValueError('Key not found in struct: ' + key)
capnp.register_type({{node.id}}, ({{node.module_name}}_Reader, {{node.module_name}}_Builder))
{% endfor %}

View File

@@ -5,14 +5,21 @@ import os
import re
files = [{% for f in code.requestedFiles %}"{{f.filename}}",{% endfor %}]
files = [{% for f in code.requestedFiles %}"{{f.filename}}", {% endfor %}]
for f in files:
cpp_file = f + '.cpp'
if not os.path.exists(cpp_file):
if not os.path.exists(f + '.c++'):
cplus_file = f + '.c++'
cpp_mod = os.path.getmtime(cpp_file)
cplus_mod = 0
try:
cplus_mod = os.path.getmtime(cplus_file)
except:
pass
if not os.path.exists(cpp_file) or cpp_mod < cplus_mod:
if not os.path.exists(cplus_file):
raise RuntimeError("You need to run `capnp compile -oc++` in addition to `-ocython` first.")
os.rename(f + '.c++', cpp_file)
os.rename(cplus_file, cpp_file)
with open(f + '.h', "r") as file:
lines = file.readlines()