Cleaned up root directory
authorBenedikt Tutzer <e1225461@student.tuwien.ac.at>
Tue, 30 Apr 2019 11:19:04 +0000 (13:19 +0200)
committerBenedikt Tutzer <e1225461@student.tuwien.ac.at>
Tue, 30 Apr 2019 11:19:04 +0000 (13:19 +0200)
Makefile
__init__.py [deleted file]
misc/__init__.py [new file with mode: 0644]
misc/py_wrap_generator.py [new file with mode: 0644]
py_wrap_generator.py [deleted file]

index 993cbb7e5437d44b29dd55a0929d75820246522d..4f078197e7a04ceb08260d444e7aa2d5ed30cf83 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -294,7 +294,7 @@ endif
 PY_WRAPPER_FILE = kernel/python_wrappers
 OBJS += $(PY_WRAPPER_FILE).o
 PY_GEN_SCRIPT= py_wrap_generator
-PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
+PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
 endif
 
 ifeq ($(ENABLE_READLINE),1)
@@ -550,9 +550,9 @@ libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
        $(Q) mkdir -p $(dir $@)
        $(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P -
 
-$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
+$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
        $(Q) mkdir -p $(dir $@)
-       $(P) python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
+       $(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
 
 %.o: %.cpp
        $(Q) mkdir -p $(dir $@)
@@ -685,7 +685,7 @@ ifeq ($(ENABLE_LIBYOSYS),1)
 ifeq ($(ENABLE_PYOSYS),1)
        $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys
        $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys
-       $(INSTALL_SUDO) cp __init__.py $(PYTHON_DESTDIR)/pyosys
+       $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys
 endif
 endif
 
diff --git a/__init__.py b/__init__.py
deleted file mode 100644 (file)
index 330fd6d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-import os
-import sys
-sys.setdlopenflags(os.RTLD_NOW | os.RTLD_GLOBAL)
-
-__all__ = ["libyosys"]
diff --git a/misc/__init__.py b/misc/__init__.py
new file mode 100644 (file)
index 0000000..330fd6d
--- /dev/null
@@ -0,0 +1,5 @@
+import os
+import sys
+sys.setdlopenflags(os.RTLD_NOW | os.RTLD_GLOBAL)
+
+__all__ = ["libyosys"]
diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py
new file mode 100644 (file)
index 0000000..09f9340
--- /dev/null
@@ -0,0 +1,2096 @@
+#
+#  yosys -- Yosys Open SYnthesis Suite
+#
+#  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+#
+#  Permission to use, copy, modify, and/or distribute this software for any
+#  purpose with or without fee is hereby granted, provided that the above
+#  copyright notice and this permission notice appear in all copies.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+#  Author Benedikt Tutzer
+#
+
+import copy
+
+#Map c++ operator Syntax to Python functions
+wrappable_operators = {
+               "<" : "__lt__",
+               "==": "__eq__",
+               "!=": "__ne__",
+               "+" : "__add__",
+               "-" : "__sub__",
+               "*" : "__mul__",
+               "/" : "__div__",
+               "()": "__call__"
+       }
+
+#Restrict certain strings from being function names in Python
+keyword_aliases = {
+               "in" : "in_",
+               "False" : "False_",
+               "None" : "None_",
+               "True" : "True_",
+               "and" : "and_",
+               "as" : "as_",
+               "assert" : "assert_",
+               "break" : "break_",
+               "class" : "class_",
+               "continue" : "continue_",
+               "def" : "def_",
+               "del" : "del_",
+               "elif" : "elif_",
+               "else" : "else_",
+               "except" : "except_",
+               "for" : "for_",
+               "from" : "from_",
+               "global" : "global_",
+               "if" : "if_",
+               "import" : "import_",
+               "in" : "in_",
+               "is" : "is_",
+               "lambda" : "lambda_",
+               "nonlocal" : "nonlocal_",
+               "not" : "not_",
+               "or" : "or_",
+               "pass" : "pass_",
+               "raise" : "raise_",
+               "return" : "return_",
+               "try" : "try_",
+               "while" : "while_",
+               "with" : "with_",
+               "yield" : "yield_"
+       }
+
+#These can be used without any explicit conversion
+primitive_types = ["void", "bool", "int", "double", "size_t", "std::string",
+               "string", "State", "char_p"]
+
+from enum import Enum
+
+#Ways to link between Python- and C++ Objects
+class link_types(Enum):
+       global_list = 1         #Manage a global list of objects in C++, the Python
+                                               #object contains a key to find the corresponding C++
+                                               #object and a Pointer to the object to verify it is
+                                               #still the same, making collisions unlikely to happen
+       ref_copy = 2            #The Python object contains a copy of the C++ object.
+                                               #The C++ object is deleted when the Python object gets
+                                               #deleted
+       pointer = 3                     #The Python Object contains a pointer to it's C++
+                                               #counterpart
+       derive = 4                      #The Python-Wrapper is derived from the C++ object.
+
+class attr_types(Enum):
+       star = "*"
+       amp = "&"
+       ampamp = "&&"
+       default = ""
+
+#For source-files
+class Source:
+       name = ""
+       classes = []
+
+       def __init__(self, name, classes):
+               self.name = name
+               self.classes = classes
+
+#Splits a list by the given delimiter, without splitting strings inside
+#pointy-brackets (< and >)
+def split_list(str_def, delim):
+       str_def = str_def.strip()
+       if len(str_def) == 0:
+               return []
+       if str_def.count(delim) == 0:
+               return [str_def]
+       if str_def.count("<") == 0:
+               return str_def.split(delim)
+       if str_def.find("<") < str_def.find(" "):
+               closing = find_closing(str_def[str_def.find("<")+1:], "<", ">") + str_def.find("<")
+               comma = str_def[closing:].find(delim)
+               if comma == -1:
+                       return [str_def]
+               comma = closing  + comma
+       else:
+               comma = str_def.find(delim)
+       rest = split_list(str_def[comma+1:], delim)
+       ret = [str_def[:comma]]
+       if rest != None and len(rest) != 0:
+               ret.extend(rest)
+       return ret
+
+#Represents a Type
+class WType:
+       name = ""
+       cont = None
+       attr_type = attr_types.default
+
+       def __init__(self, name = "", cont = None, attr_type = attr_types.default):
+               self.name = name
+               self.cont = cont
+               self.attr_type = attr_type
+
+       #Python type-string
+       def gen_text(self):
+               text = self.name
+               if self.name in enum_names:
+                       text = enum_by_name(self.name).namespace + "::" + self.name
+               if self.cont != None:
+                       return known_containers[self.name].typename
+               return text
+
+       #C++ type-string
+       def gen_text_cpp(self):
+               postfix = ""
+               if self.attr_type == attr_types.star:
+                       postfix = "*"
+               if self.name in primitive_types:
+                       return self.name + postfix
+               if self.name in enum_names:
+                       return enum_by_name(self.name).namespace + "::" + self.name + postfix
+               if self.name in classnames:
+                       return class_by_name(self.name).namespace + "::" + self.name + postfix
+               text = self.name
+               if self.cont != None:
+                       text += "<"
+                       for a in self.cont.args:
+                               text += a.gen_text_cpp() + ", "
+                       text = text[:-2]
+                       text += ">"
+               return text
+
+       @staticmethod
+       def from_string(str_def, containing_file, line_number):
+               str_def = str_def.strip()
+               if len(str_def) == 0:
+                       return None
+               str_def = str_def.replace("RTLIL::SigSig", "std::pair<SigSpec, SigSpec>").replace("SigSig", "std::pair<SigSpec, SigSpec>")
+               t = WType()
+               t.name = ""
+               t.cont = None
+               t.attr_type = attr_types.default
+               if str_def.find("<") != -1:# and str_def.find("<") < str_def.find(" "):
+                       candidate = WContainer.from_string(str_def, containing_file, line_number)
+                       if candidate == None:
+                               return None
+                       t.name = str_def[:str_def.find("<")]
+
+                       if t.name.count("*") + t.name.count("&") > 1:
+                               return None
+
+                       if t.name.count("*") == 1 or str_def[0] == '*' or str_def[-1] == '*':
+                               t.attr_type = attr_types.star
+                               t.name = t.name.replace("*","")
+                       elif t.name.count("&&") == 1:
+                               t.attr_type = attr_types.ampamp
+                               t.name = t.name.replace("&&","")
+                       elif t.name.count("&") == 1 or str_def[0] == '&' or str_def[-1] == '&':
+                               t.attr_type = attr_types.amp
+                               t.name = t.name.replace("&","")
+
+                       t.cont = candidate
+                       if(t.name not in known_containers):
+                               return None     
+                       return t
+
+               prefix = ""
+
+               if str.startswith(str_def, "unsigned "):
+                       prefix = "unsigned "
+                       str_def = str_def[9:]
+               while str.startswith(str_def, "long "):
+                       prefix= "long " + prefix
+                       str_def = str_def[5:]
+               while str.startswith(str_def, "short "):
+                       prefix = "short " + prefix
+                       str_def = str_def[6:]
+
+               str_def = str_def.split("::")[-1]
+
+               if str_def.count("*") + str_def.count("&") >= 2:
+                       return None
+
+               if str_def.count("*") == 1:
+                       t.attr_type = attr_types.star
+                       str_def = str_def.replace("*","")
+               elif str_def.count("&&") == 1:
+                       t.attr_type = attr_types.ampamp
+                       str_def = str_def.replace("&&","")
+               elif str_def.count("&") == 1:
+                       t.attr_type = attr_types.amp
+                       str_def = str_def.replace("&","")
+
+               if len(str_def) > 0 and str_def.split("::")[-1] not in primitive_types and str_def.split("::")[-1] not in classnames and str_def.split("::")[-1] not in enum_names:
+                       return None
+
+               if str_def.count(" ") == 0:
+                       t.name = (prefix + str_def).replace("char_p", "char *")
+                       t.cont = None
+                       return t
+               return None
+
+#Represents a container-type
+class WContainer:
+       name = ""
+       args = []
+
+       def from_string(str_def, containing_file, line_number):
+               if str_def == None or len(str_def) < 4:
+                       return None
+               cont = WContainer()
+               cont.name = str_def[:str_def.find("<")]
+               str_def = str_def[str_def.find("<")+1:find_closing(str_def, "<", ">")]
+               cont.args = []
+               for arg in split_list(str_def, ","):
+                       candidate = WType.from_string(arg.strip(), containing_file, line_number)
+                       if candidate == None:
+                               return None
+                       cont.args.append(candidate)
+               return cont
+
+#Translators between Python and C++ containers
+#Base Type
+class Translator:
+       tmp_cntr = 0
+       typename = "DefaultType"
+       orig_name = "DefaultCpp"
+
+       @classmethod
+       def gen_type(c, types):
+               return "\nImplement a function that outputs the c++ type of this container here\n"
+
+       @classmethod
+       def translate(c, varname, types, prefix):
+               return "\nImplement a function translating a python container to a c++ container here\n"
+
+       @classmethod
+       def translate_cpp(c, varname, types, prefix, ref):
+               return "\nImplement a function translating a c++ container to a python container here\n"
+
+#Translates list-types (vector, pool, set), that only differ in their name and
+#the name of the insertion function
+class PythonListTranslator(Translator):
+       typename = "boost::python::list"
+       insert_name = "Default"
+
+       #generate the c++ type string
+       @classmethod
+       def gen_type(c, types):
+               text = c.orig_name + "<"
+               if types[0].name in primitive_types:
+                       text += types[0].name
+               elif types[0].name in known_containers:
+                       text += known_containers[types[0].name].gen_type(types[0].cont.args)
+               else:
+                       text += class_by_name(types[0].name).namespace + "::" + types[0].name
+                       if types[0].attr_type == attr_types.star:
+                               text += "*"
+               text += ">"
+               return text
+
+       #Generate C++ code to translate from a boost::python::list
+       @classmethod
+       def translate(c, varname, types, prefix):
+               text  = prefix + c.gen_type(types) + " " + varname + "___tmp;"
+               cntr_name = "cntr_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               text += prefix + "for(int " + cntr_name + " = 0; " + cntr_name + " < len(" + varname + "); " + cntr_name + "++)"
+               text += prefix + "{"
+               tmp_name = "tmp_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               if types[0].name in known_containers:
+                       text += prefix + "\t" + known_containers[types[0].name].typename + " " + tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "[" + cntr_name + "]);"
+                       text += known_containers[types[0].name].translate(tmp_name, types[0].cont.args, prefix+"\t")
+                       tmp_name = tmp_name + "___tmp"
+                       text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");"
+               elif types[0].name in classnames:
+                       text += prefix + "\t" + types[0].name + "* " + tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "[" + cntr_name + "]);"
+                       if types[0].attr_type == attr_types.star:
+                               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + "->get_cpp_obj());"
+                       else:
+                               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());"
+               else:
+                       text += prefix + "\t" + types[0].name + " " + tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "[" + cntr_name + "]);"
+                       text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");"
+               text += prefix + "}"
+               return text
+
+       #Generate C++ code to translate to a boost::python::list
+       @classmethod
+       def translate_cpp(c, varname, types, prefix, ref):
+               text  = prefix + c.typename + " " + varname + "___tmp;"
+               tmp_name = "tmp_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               if ref:
+                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
+               else:
+                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
+               text += prefix + "{"
+               if types[0].name in classnames:
+                       if types[0].attr_type == attr_types.star:
+                               text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
+                       else:
+                               text += prefix + "\t" + varname + "___tmp.append(*" + types[0].name + "::get_py_obj(&" + tmp_name + "));"
+               elif types[0].name in known_containers:
+                       text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[0].attr_type == attr_types.star)
+                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + "___tmp);"
+               else:
+                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");"
+               text += prefix + "}"
+               return text
+
+#Sub-type for std::set
+class SetTranslator(PythonListTranslator):
+       insert_name = "insert"
+       orig_name = "std::set"
+
+#Sub-type for std::vector
+class VectorTranslator(PythonListTranslator):
+       insert_name = "push_back"
+       orig_name = "std::vector"
+
+#Sub-type for pool
+class PoolTranslator(PythonListTranslator):
+       insert_name = "insert"
+       orig_name = "pool"
+
+#Translates dict-types (dict, std::map), that only differ in their name and
+#the name of the insertion function
+class PythonDictTranslator(Translator):
+       typename = "boost::python::dict"
+       insert_name = "Default"
+
+       @classmethod
+       def gen_type(c, types):
+               text = c.orig_name + "<"
+               if types[0].name in primitive_types:
+                       text += types[0].name
+               elif types[0].name in known_containers:
+                       text += known_containers[types[0].name].gen_type(types[0].cont.args)
+               else:
+                       text += class_by_name(types[0].name).namespace + "::" + types[0].name
+                       if types[0].attr_type == attr_types.star:
+                               text += "*"
+               text += ", "
+               if types[1].name in primitive_types:
+                       text += types[1].name
+               elif types[1].name in known_containers:
+                       text += known_containers[types[1].name].gen_type(types[1].cont.args)
+               else:
+                       text += class_by_name(types[1].name).namespace + "::" + types[1].name
+                       if types[1].attr_type == attr_types.star:
+                               text += "*"
+               text += ">"
+               return text
+
+       #Generate c++ code to translate from a boost::python::dict
+       @classmethod
+       def translate(c, varname, types, prefix):
+               text  = prefix + c.gen_type(types) + " " + varname + "___tmp;"
+               text += prefix + "boost::python::list " + varname + "_keylist = " + varname + ".keys();"
+               cntr_name = "cntr_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               text += prefix + "for(int " + cntr_name + " = 0; " + cntr_name + " < len(" + varname + "_keylist); " + cntr_name + "++)"
+               text += prefix + "{"
+               key_tmp_name = "key_tmp_" + str(Translator.tmp_cntr)
+               val_tmp_name = "val_tmp_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+
+               if types[0].name in known_containers:
+                       text += prefix + "\t" + known_containers[types[0].name].typename + " " + key_tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "_keylist[ " + cntr_name + " ]);"
+                       text += known_containers[types[0].name].translate(key_tmp_name, types[0].cont.args, prefix+"\t")
+                       key_tmp_name = key_tmp_name + "___tmp"
+               elif types[0].name in classnames:
+                       text += prefix + "\t" + types[0].name + "* " + key_tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "_keylist[ " + cntr_name + " ]);"
+               else:
+                       text += prefix + "\t" + types[0].name + " " + key_tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "_keylist[ " + cntr_name + " ]);"
+
+               if types[1].name in known_containers:
+                       text += prefix + "\t" + known_containers[types[1].name].typename + " " + val_tmp_name + " = boost::python::extract<" + known_containers[types[1].name].typename + ">(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
+                       text += known_containers[types[1].name].translate(val_tmp_name, types[1].cont.args, prefix+"\t")
+                       val_tmp_name = val_tmp_name + "___tmp"
+               elif types[1].name in classnames:
+                       text += prefix + "\t" + types[1].name + "* " + val_tmp_name + " = boost::python::extract<" + types[1].name + "*>(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
+               else:
+                       text += prefix + "\t" + types[1].name + " " + val_tmp_name + " = boost::python::extract<" + types[1].name + ">(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
+
+               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(std::pair<" + types[0].gen_text_cpp() + ", " + types[1].gen_text_cpp() + ">("
+
+               if types[0].name not in classnames:
+                       text += key_tmp_name
+               else:
+                       if types[0].attr_type != attr_types.star:
+                               text += "*"
+                       text += key_tmp_name + "->get_cpp_obj()"
+               
+               text += ", "
+               if types[1].name not in classnames:
+                       text += val_tmp_name
+               else:
+                       if types[1].attr_type != attr_types.star:
+                               text += "*"
+                       text += val_tmp_name + "->get_cpp_obj()"
+               text += "));\n" + prefix + "}"
+               return text
+       
+       #Generate c++ code to translate to a boost::python::dict
+       @classmethod
+       def translate_cpp(c, varname, types, prefix, ref):
+               text  = prefix + c.typename + " " + varname + "___tmp;"
+               tmp_name = "tmp_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               if ref:
+                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
+               else:
+                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
+               text += prefix + "{"
+               if types[1].name in known_containers:
+                       text += prefix + "\tauto " + tmp_name + "_second = " + tmp_name + ".second;"
+                       text += known_containers[types[1].name].translate_cpp(tmp_name + "_second", types[1].cont.args, prefix + "\t", types[1].attr_type == attr_types.star)
+
+               if types[0].name in classnames:
+                       text += prefix + "\t" + varname + "___tmp[" + types[0].name + "::get_py_obj(" + tmp_name + ".first)] = "
+               elif types[0].name not in known_containers:
+                       text += prefix + "\t" + varname + "___tmp[" + tmp_name + ".first] = "
+
+               if types[1].name in classnames:
+                       if types[1].attr_type == attr_types.star:
+                               text += types[1].name + "::get_py_obj(" + tmp_name + ".second);"
+                       else:
+                               text += "*" + types[1].name + "::get_py_obj(&" + tmp_name + ".second);"
+               elif types[1].name in known_containers:
+                       text += tmp_name + "_second___tmp;"
+               else:
+                       text += tmp_name + ".second;"
+               text += prefix + "}"
+               return text
+
+#Sub-type for dict
+class DictTranslator(PythonDictTranslator):
+       insert_name = "insert"
+       orig_name = "dict"
+
+#Sub_type for std::map
+class MapTranslator(PythonDictTranslator):
+       insert_name = "insert"
+       orig_name = "std::map"  
+
+#Translator for std::pair. Derived from PythonDictTranslator because the
+#gen_type function is the same (because both have two template parameters)
+class TupleTranslator(PythonDictTranslator):
+       typename = "boost::python::tuple"
+       orig_name = "std::pair"
+
+       #Generate c++ code to translate from a boost::python::tuple
+       @classmethod
+       def translate(c, varname, types, prefix):
+               text  = prefix + types[0].name + " " + varname + "___tmp_0 = boost::python::extract<" + types[0].name + ">(" + varname + "[0]);"
+               text += prefix + types[1].name + " " + varname + "___tmp_1 = boost::python::extract<" + types[1].name + ">(" + varname + "[1]);"
+               text += prefix + TupleTranslator.gen_type(types) + " " + varname + "___tmp("
+               if types[0].name.split(" ")[-1] in primitive_types:
+                       text += varname + "___tmp_0, "
+               else:
+                       text += varname + "___tmp_0.get_cpp_obj(), "
+               if types[1].name.split(" ")[-1] in primitive_types:
+                       text += varname + "___tmp_1);"
+               else:
+                       text += varname + "___tmp_1.get_cpp_obj());"
+               return text
+
+       #Generate c++ code to translate to a boost::python::tuple
+       @classmethod
+       def translate_cpp(c, varname, types, prefix, ref):
+               text  = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + varname + ".first, " + varname + ".second);"
+               return text
+               tmp_name = "tmp_" + str(Translator.tmp_cntr)
+               Translator.tmp_cntr = Translator.tmp_cntr + 1
+               if ref:
+                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
+               else:
+                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
+               text += prefix + "{"
+               if types[0].name.split(" ")[-1] in primitive_types or types[0].name in enum_names:
+                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");"
+               elif types[0].name in known_containers:
+                       text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[1].attr_type == attr_types.star)
+                       text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "___tmp);"
+               elif types[0].name in classnames:
+                       text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
+               text += prefix + "}"
+               return text
+
+#Associate the Translators with their c++ type
+known_containers = {
+       "std::set"              :       SetTranslator,
+       "std::vector"   :       VectorTranslator,
+       "pool"                  :       PoolTranslator,
+       "dict"                  :       DictTranslator,
+       "std::pair"             :       TupleTranslator,
+       "std::map"              :       MapTranslator
+}
+
+class Attribute:
+       wtype = None
+       varname = None
+       is_const = False
+       default_value = None
+       pos = None
+       pos_counter = 0
+
+       def __init__(self, wtype, varname, is_const = False, default_value = None):
+               self.wtype = wtype
+               self.varname = varname
+               self.is_const = is_const
+               self.default_value = None
+               self.container = None
+
+       @staticmethod
+       def from_string(str_def, containing_file, line_number):
+               if len(str_def) < 3:
+                       return None
+               orig = str_def
+               arg = Attribute(None, None)
+               prefix = ""
+               arg.wtype = None
+               arg.varname = None
+               arg.is_const = False
+               arg.default_value = None
+               arg.container = None
+               if str.startswith(str_def, "const "):
+                       arg.is_const = True
+                       str_def = str_def[6:]
+               if str.startswith(str_def, "unsigned "):
+                       prefix = "unsigned "
+                       str_def = str_def[9:]
+               while str.startswith(str_def, "long "):
+                       prefix= "long " + prefix
+                       str_def = str_def[5:]
+               while str.startswith(str_def, "short "):
+                       prefix = "short " + prefix
+                       str_def = str_def[6:]
+
+               if str_def.find("<") != -1 and str_def.find("<") < str_def.find(" "):
+                       closing = find_closing(str_def[str_def.find("<"):], "<", ">") + str_def.find("<") + 1
+                       arg.wtype = WType.from_string(str_def[:closing].strip(), containing_file, line_number)
+                       str_def = str_def[closing+1:]
+               else:
+                       if str_def.count(" ") > 0:
+                               arg.wtype = WType.from_string(prefix + str_def[:str_def.find(" ")].strip(), containing_file, line_number)
+                               str_def = str_def[str_def.find(" ")+1:]
+                       else:
+                               arg.wtype = WType.from_string(prefix + str_def.strip(), containing_file, line_number)
+                               str_def = ""
+                               arg.varname = ""
+
+               if arg.wtype == None:
+                       return None
+               if str_def.count("=") == 0:
+                       arg.varname = str_def.strip()
+                       if arg.varname.find(" ") > 0:
+                               return None
+               else:
+                       arg.varname = str_def[:str_def.find("=")].strip()
+                       if arg.varname.find(" ") > 0:
+                               return None
+                       str_def = str_def[str_def.find("=")+1:].strip()
+                       arg.default_value = str_def[arg.varname.find("=")+1:].strip()
+               if len(arg.varname) == 0:
+                       arg.varname = None
+                       return arg
+               if arg.varname[0] == '*':
+                       arg.wtype.attr_type = attr_types.star
+                       arg.varname = arg.varname[1:]
+               elif arg.varname[0] == '&':
+                       if arg.wtype.attr_type != attr_types.default:
+                               return None
+                       if arg.varname[1] == '&':
+                               arg.wtype.attr_type = attr_types.ampamp
+                               arg.varname = arg.varname[2:]
+                       else:
+                               arg.wtype.attr_type = attr_types.amp
+                               arg.varname = arg.varname[1:]
+               return arg
+
+       #Generates the varname. If the attribute has no name in the header file,
+       #a name is generated
+       def gen_varname(self):
+               if self.varname != None:
+                       return self.varname
+               if self.wtype.name == "void":
+                       return ""
+               if self.pos == None:
+                       self.pos = Attribute.pos_counter
+                       Attribute.pos_counter = Attribute.pos_counter + 1
+               return "gen_varname_" + str(self.pos)
+
+       #Generates the text for the function headers with wrapper types
+       def gen_listitem(self):
+               prefix = ""
+               if self.is_const:
+                       prefix = "const "
+               if self.wtype.name in classnames:
+                       return prefix + self.wtype.name + "* " + self.gen_varname()
+               if self.wtype.name in known_containers:
+                       return prefix + known_containers[self.wtype.name].typename + " " + self.gen_varname()
+               return prefix + self.wtype.name + " " + self.gen_varname()
+
+       #Generates the test for the function headers with c++ types
+       def gen_listitem_cpp(self):
+               prefix = ""
+               if self.is_const:
+                       prefix = "const "
+               infix = ""
+               if self.wtype.attr_type == attr_types.star:
+                       infix = "*"
+               elif self.wtype.attr_type == attr_types.amp:
+                       infix = "&"
+               elif self.wtype.attr_type == attr_types.ampamp:
+                       infix = "&&"
+               if self.wtype.name in known_containers:
+                       return prefix + known_containers[self.wtype.name].gen_type(self.wtype.cont.args) + " " + infix + self.gen_varname()
+               if self.wtype.name in classnames:
+                       return prefix + class_by_name(self.wtype.name).namespace + "::" + self.wtype.name + " " + infix + self.gen_varname()
+               return prefix + self.wtype.name + " " + infix + self.gen_varname()
+
+       #Generates the listitem withtout the varname, so the signature can be
+       #compared
+       def gen_listitem_hash(self):
+               prefix = ""
+               if self.is_const:
+                       prefix = "const "
+               if self.wtype.name in classnames:
+                       return prefix + self.wtype.name + "* "
+               if self.wtype.name in known_containers:
+                       return known_containers[self.wtype.name].typename
+               return prefix + self.wtype.name
+               
+       #Generate Translation code for the attribute
+       def gen_translation(self):
+               if self.wtype.name in known_containers:
+                       return known_containers[self.wtype.name].translate(self.gen_varname(), self.wtype.cont.args, "\n\t\t")
+               return ""
+
+       #Generate Translation code from c++ for the attribute
+       def gen_translation_cpp(self):
+               if self.wtype.name in known_containers:
+                       return known_containers[self.wtype.name].translate_cpp(self.gen_varname(), self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star)
+               return ""
+
+       #Generate Text for the call
+       def gen_call(self):
+               ret = self.gen_varname()
+               if self.wtype.name in known_containers:
+                       if self.wtype.attr_type == attr_types.star:
+                               return "&" + ret + "___tmp"
+                       return ret + "___tmp"
+               if self.wtype.name in classnames:
+                       if self.wtype.attr_type != attr_types.star:
+                               ret = "*" + ret
+                       return ret + "->get_cpp_obj()"
+               if self.wtype.name == "char *" and self.gen_varname() in ["format", "fmt"]:
+                       return "\"%s\", " + self.gen_varname()
+               if self.wtype.attr_type == attr_types.star:
+                       return "&" + ret
+               return ret
+
+       def gen_call_cpp(self):
+               ret = self.gen_varname()
+               if self.wtype.name.split(" ")[-1] in primitive_types or self.wtype.name in enum_names:
+                       if self.wtype.attr_type == attr_types.star:
+                               return "&" + ret
+                       return ret
+               if self.wtype.name not in classnames:
+                       if self.wtype.attr_type == attr_types.star:
+                               return "&" + ret + "___tmp"
+                       return ret + "___tmp"
+               if self.wtype.attr_type != attr_types.star:
+                       ret = "*" + ret
+               return self.wtype.name + "::get_py_obj(" + self.gen_varname()  + ")"
+
+       #Generate cleanup code
+       def gen_cleanup(self):
+               if self.wtype.name in primitive_types or self.wtype.name in classnames or self.wtype.name in enum_names or not self.wtype.attr_type == attr_types.star or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star):
+                       return ""
+               return "\n\t\tdelete " + self.gen_varname() + "___tmp;"
+
+class WClass:
+       name = None
+       namespace = None
+       link_type = None
+       id_ = None
+       string_id = None
+       hash_id = None
+       needs_clone = False
+       found_funs = []
+       found_vars = []
+       found_constrs = []
+
+       def __init__(self, name, link_type, id_, string_id = None, hash_id = None, needs_clone = False):
+               self.name = name
+               self.namespace = None
+               self.link_type = link_type
+               self.id_ = id_
+               self.string_id = string_id
+               self.hash_id = hash_id
+               self.needs_clone = needs_clone
+               self.found_funs = []
+               self.found_vars = []
+               self.found_constrs = []
+
+       def printable_constrs(self):
+               ret = 0
+               for con in self.found_constrs:
+                       if not con.protected:
+                               ret += 1
+               return ret
+
+       def gen_decl(self, filename):
+               long_name = self.namespace + "::" + self.name
+
+               text = "\n\t// WRAPPED from " + filename
+               text += "\n\tstruct " + self.name
+               if self.link_type == link_types.derive:
+                       text += " : public " + self.namespace + "::" + self.name
+               text += "\n\t{\n"
+
+               if self.link_type != link_types.derive:
+
+                       text += "\t\t" + long_name + "* ref_obj;\n"
+
+                       if self.link_type == link_types.ref_copy or self.link_type == link_types.pointer:
+                               text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{\n\t\t\treturn ref_obj;\n\t\t}\n"
+                       elif self.link_type == link_types.global_list:
+                               text += "\t\t" + self.id_.wtype.name + " " + self.id_.varname + ";\n"
+                               text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{"
+                               text += "\n\t\t\t" + long_name + "* ret = " + long_name + "::get_all_" + self.name.lower() + "s()->at(this->" + self.id_.varname + ");"
+                               text += "\n\t\t\tif(ret != NULL && ret == this->ref_obj)"
+                               text += "\n\t\t\t\treturn ret;"
+                               text += "\n\t\t\tthrow std::runtime_error(\"" + self.name + "'s c++ object does not exist anymore.\");"
+                               text += "\n\t\t\treturn NULL;"
+                               text += "\n\t\t}\n"
+
+                       #if self.link_type != link_types.pointer:
+                       text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{"
+                       text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));"
+                       if self.link_type == link_types.pointer:
+                               text += "\n\t\t\tret->ref_obj = ref;"
+                       if self.link_type == link_types.ref_copy:
+                               if self.needs_clone:
+                                       text += "\n\t\t\tret->ref_obj = ref->clone();"
+                               else:
+                                       text += "\n\t\t\tret->ref_obj = new "+long_name+"(*ref);"
+                       if self.link_type == link_types.global_list:
+                               text += "\n\t\t\tret->ref_obj = ref;"
+                               text += "\n\t\t\tret->" + self.id_.varname + " = ret->ref_obj->" + self.id_.varname + ";"
+                       text += "\n\t\t\treturn ret;"
+                       text += "\n\t\t}\n"
+
+                       if self.link_type == link_types.ref_copy:
+                               text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + " ref)\n\t\t{"
+                               text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));"
+                               if self.needs_clone:
+                                       text += "\n\t\t\tret->ref_obj = ref.clone();"
+                               else:
+                                       text += "\n\t\t\tret->ref_obj = new "+long_name+"(ref);"
+                               text += "\n\t\t\treturn ret;"
+                               text += "\n\t\t}\n"
+
+                       for con in self.found_constrs:
+                               text += con.gen_decl()
+                       for var in self.found_vars:
+                               text += var.gen_decl()
+                       for fun in self.found_funs:
+                               text += fun.gen_decl()
+
+
+               if self.link_type == link_types.derive:
+                       duplicates = {}
+                       for fun in self.found_funs:
+                               if fun.name in duplicates:
+                                       fun.gen_alias()
+                                       duplicates[fun.name].gen_alias()
+                               else:
+                                       duplicates[fun.name] = fun
+
+                       text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{\n\t\t\treturn (" + self.namespace + "::" + self.name +"*)this;\n\t\t}\n"
+                       text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{"
+                       text += "\n\t\t\treturn (" + self.name + "*)ref;"
+                       text += "\n\t\t}\n"
+
+                       for con in self.found_constrs:
+                               text += con.gen_decl_derive()
+                       for var in self.found_vars:
+                               text += var.gen_decl()
+                       for fun in self.found_funs:
+                               text += fun.gen_decl_virtual()
+
+               if self.hash_id != None:
+                       text += "\n\t\tunsigned int get_hash_py()"
+                       text += "\n\t\t{"
+                       text += "\n\t\t\treturn get_cpp_obj()->" + self.hash_id + ";"
+                       text += "\n\t\t}"
+
+               text += "\n\t};\n"
+
+               if self.link_type == link_types.derive:
+                       text += "\n\tstruct " + self.name + "Wrap : " + self.name + ", boost::python::wrapper<" + self.name + ">"
+                       text += "\n\t{"
+
+                       for con in self.found_constrs:
+                               text += con.gen_decl_wrapperclass()
+                       for fun in self.found_funs:
+                               text += fun.gen_default_impl()
+
+                       text += "\n\t};"
+
+               text += "\n\tstd::ostream &operator<<(std::ostream &ostr, const " + self.name + " &ref)"
+               text += "\n\t{"
+               text += "\n\t\tostr << \"" + self.name
+               if self.string_id != None:
+                       text +=" \\\"\""
+                       text += " << ref.get_cpp_obj()->" + self.string_id
+                       text += " << \"\\\"\""
+               else:
+                       text += " at \" << ref.get_cpp_obj()"
+               text += ";"
+               text += "\n\t\treturn ostr;"
+               text += "\n\t}"
+               text += "\n"
+
+               return text
+
+       def gen_funs(self, filename):
+               text = ""
+               if self.link_type != link_types.derive:
+                       for con in self.found_constrs:
+                               text += con.gen_def()
+                       for var in self.found_vars:
+                               text += var.gen_def()
+                       for fun in self.found_funs:
+                               text += fun.gen_def()
+               else:
+                       for var in self.found_vars:
+                               text += var.gen_def()
+                       for fun in self.found_funs:
+                               text += fun.gen_def_virtual()
+               return text
+
+       def gen_boost_py(self):
+               text = "\n\t\tclass_<" + self.name
+               if self.link_type == link_types.derive:
+                       text += "Wrap, boost::noncopyable"
+               text += ">(\"" + self.name + "\""
+               if self.printable_constrs() == 0 or not self.contains_default_constr():
+                       text += ", no_init"
+               text += ")"
+               text += "\n\t\t\t.def(boost::python::self_ns::str(boost::python::self_ns::self))"
+               text += "\n\t\t\t.def(boost::python::self_ns::repr(boost::python::self_ns::self))"
+               for con in self.found_constrs:
+                       text += con.gen_boost_py()
+               for var in self.found_vars:
+                       text += var.gen_boost_py()
+               static_funs = []
+               for fun in self.found_funs:
+                       text += fun.gen_boost_py()
+                       if fun.is_static and fun.alias not in static_funs:
+                               static_funs.append(fun.alias)
+               for fun in static_funs:
+                       text += "\n\t\t\t.staticmethod(\"" + fun + "\")"
+
+               if self.hash_id != None:
+                       text += "\n\t\t\t.def(\"__hash__\", &" + self.name + "::get_hash_py)"
+               text += "\n\t\t\t;\n"
+               return text
+
+       def contains_default_constr(self):
+               for c in self.found_constrs:
+                       if len(c.args) == 0:
+                               return True
+               return False
+
+#CONFIGURE HEADER-FILES TO BE PARSED AND CLASSES EXPECTED IN THEM HERE
+
+sources = [
+       Source("kernel/celltypes",[
+               WClass("CellType", link_types.pointer, None, None, "type.hash()", True),
+               WClass("CellTypes", link_types.pointer, None, None, None, True)
+               ]
+               ),
+       Source("kernel/consteval",[
+               WClass("ConstEval", link_types.pointer, None, None, None, True)
+               ]
+               ),
+       Source("kernel/log",[]),
+       Source("kernel/register",[
+               WClass("Pass", link_types.derive, None, None, None, True),
+               ]
+               ),
+       Source("kernel/rtlil",[
+               WClass("IdString", link_types.ref_copy, None, "str()", "hash()"),
+               WClass("Const", link_types.ref_copy, None, "as_string()", "hash()"),
+               WClass("AttrObject", link_types.ref_copy, None, None, None),
+               WClass("Selection", link_types.ref_copy, None, None, None),
+               WClass("Monitor", link_types.derive, None, None, None),
+               WClass("CaseRule",link_types.ref_copy, None, None, None, True),
+               WClass("SwitchRule",link_types.ref_copy, None, None, None, True),
+               WClass("SyncRule", link_types.ref_copy, None, None, None, True),
+               WClass("Process",  link_types.ref_copy, None, "name.c_str()", "name.hash()"),
+               WClass("SigChunk", link_types.ref_copy, None, None, None),
+               WClass("SigBit", link_types.ref_copy, None, None, "hash()"),
+               WClass("SigSpec", link_types.ref_copy, None, None, "hash()"),
+               WClass("Cell", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
+               WClass("Wire", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
+               WClass("Memory", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
+               WClass("Module", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
+               WClass("Design", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "hashidx_", "hash()")
+               ]
+               ),
+       #Source("kernel/satgen",[
+       #       ]
+       #       ),
+       #Source("libs/ezsat/ezsat",[
+       #       ]
+       #       ),
+       #Source("libs/ezsat/ezminisat",[
+       #       ]
+       #       ),
+       Source("kernel/sigtools",[
+               WClass("SigMap", link_types.pointer, None, None, None, True)
+               ]
+               ),
+       Source("kernel/yosys",[
+               ]
+               ),
+       Source("kernel/cost",[])
+       ]
+
+blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Module::Pow", "YOSYS_NAMESPACE::Module::Bu0", "YOSYS_NAMESPACE::CaseRule::optimize"]
+
+enum_names = ["State","SyncType","ConstFlags"]
+
+enums = [] #Do not edit
+
+unowned_functions = []
+
+classnames = []
+for source in sources:
+       for wclass in source.classes:
+               classnames.append(wclass.name)
+
+def class_by_name(name):
+       for source in sources:
+               for wclass in source.classes:
+                       if wclass.name == name:
+                               return wclass
+       return None
+
+def enum_by_name(name):
+       for e in enums:
+               if e.name == name:
+                       return e
+       return None
+
+def find_closing(text, open_tok, close_tok):
+       if text.find(open_tok) == -1 or text.find(close_tok) <= text.find(open_tok):
+               return text.find(close_tok)
+       return text.find(close_tok) + find_closing(text[text.find(close_tok)+1:], open_tok, close_tok) + 1
+
+def unpretty_string(s):
+       s = s.strip()
+       while s.find("  ") != -1:
+               s = s.replace("  "," ")
+       while s.find("\t") != -1:
+               s = s.replace("\t"," ")
+       s = s.replace(" (","(")
+       return s
+
+class WEnum:
+       name = None
+       namespace = None
+       values = []
+
+       def from_string(str_def, namespace, line_number):
+               str_def = str_def.strip()
+               if not str.startswith(str_def, "enum "):
+                       return None
+               if str_def.count(";") != 1:
+                       return None
+               str_def = str_def[5:]
+               enum = WEnum()
+               split = str_def.split(":")
+               if(len(split) != 2):
+                       return None
+               enum.name = split[0].strip()
+               if enum.name not in enum_names:
+                       return None
+               str_def = split[1]
+               if str_def.count("{") != str_def.count("}") != 1:
+                       return None
+               if len(str_def) < str_def.find("}")+2 or str_def[str_def.find("}")+1] != ';':
+                       return None
+               str_def = str_def.split("{")[-1].split("}")[0]
+               enum.values = []
+               for val in str_def.split(','):
+                       enum.values.append(val.strip().split('=')[0].strip())
+               enum.namespace = namespace
+               return enum
+
+       def gen_boost_py(self):
+               text = "\n\t\tenum_<" + self.namespace + "::" + self.name + ">(\"" + self.name + "\")\n"
+               for value in self.values:
+                       text += "\t\t\t.value(\"" + value + "\"," + self.namespace + "::" + value + ")\n"
+               text += "\t\t\t;\n"
+               return text
+
+       def __str__(self):
+               ret = "Enum " + self.namespace + "::" + self.name + "(\n"
+               for val in self.values:
+                       ret = ret + "\t" + val + "\n"
+               return ret + ")"
+
+       def __repr__(self):
+               return __str__(self)
+
+class WConstructor:
+       orig_text = None
+       args = []
+       containing_file = None
+       member_of = None
+       duplicate = False
+       protected = False
+
+       def __init__(self, containing_file, class_):
+               self.orig_text = "Auto generated default constructor"
+               self.args = []
+               self.containing_file = containing_file
+               self.member_of = class_
+               self.protected = False
+
+       def from_string(str_def, containing_file, class_, line_number, protected = False):
+               if class_ == None:
+                       return None
+               if str_def.count("delete;") > 0:
+                       return None
+               con = WConstructor(containing_file, class_)
+               con.orig_text = str_def
+               con.args = []
+               con.duplicate = False
+               con.protected = protected
+               if not str.startswith(str_def, class_.name + "("):
+                       return None
+               str_def = str_def[len(class_.name)+1:]
+               found = find_closing(str_def, "(", ")")
+               if found == -1:
+                       return None
+               str_def = str_def[0:found].strip()
+               if len(str_def) == 0:
+                       return con
+               for arg in split_list(str_def, ","):
+                       parsed = Attribute.from_string(arg.strip(), containing_file, line_number)
+                       if parsed == None:
+                               return None
+                       con.args.append(parsed)
+               return con
+
+       def gen_decl(self):
+               if self.duplicate or self.protected:
+                       return ""
+               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t\t" + self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ");\n"
+               return text
+
+       def gen_decl_derive(self):
+               if self.duplicate or self.protected:
+                       return ""
+               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t\t" + self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ")"
+               if len(self.args) == 0:
+                       return text + "{}"
+               text += " : "
+               text += self.member_of.namespace + "::" + self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_call() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += "){}\n"
+               return text
+
+       def gen_decl_wrapperclass(self):
+               if self.duplicate or self.protected:
+                       return ""
+               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t\t" + self.member_of.name + "Wrap("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ")"
+               if len(self.args) == 0:
+                       return text + "{}"
+               text += " : "
+               text += self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_call() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += "){}\n"
+               return text
+
+       def gen_decl_hash_py(self):
+               text = self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem_hash() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ");"
+               return text
+
+       def gen_def(self):
+               if self.duplicate or self.protected:
+                       return ""
+               text = "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t" + self.member_of.name + "::" + self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text +=")\n\t{"
+               for arg in self.args:
+                       text += arg.gen_translation()
+               if self.member_of.link_type != link_types.derive:
+                       text += "\n\t\tthis->ref_obj = new " + self.member_of.namespace + "::" + self.member_of.name + "("
+               for arg in self.args:
+                       text += arg.gen_call() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               if self.member_of.link_type != link_types.derive:
+                       text += ");"
+               if self.member_of.link_type == link_types.global_list:
+                       text += "\n\t\tthis->" + self.member_of.id_.varname + " = this->ref_obj->" + self.member_of.id_.varname + ";"
+               for arg in self.args:
+                       text += arg.gen_cleanup()
+               text += "\n\t}\n"
+               return text
+
+       def gen_boost_py(self):
+               if self.duplicate or self.protected or len(self.args) == 0:
+                       return ""
+               text  = "\n\t\t\t.def(init"
+               text += "<"
+               for a in self.args:
+                       text += a.gen_listitem_hash() + ", "
+               text = text[0:-2] + ">())"
+               return text
+
+class WFunction:
+       orig_text = None
+       is_static = False
+       is_inline = False
+       is_virtual = False
+       ret_attr_type = attr_types.default
+       is_operator = False
+       ret_type = None
+       name = None
+       alias = None
+       args = []
+       containing_file = None
+       member_of = None
+       duplicate = False
+       namespace = ""
+
+       def from_string(str_def, containing_file, class_, line_number, namespace):
+               if str_def.count("delete;") > 0:
+                       return None
+               func = WFunction()
+               func.is_static = False
+               func.is_inline = False
+               func.is_virtual = False
+               func.ret_attr_type = attr_types.default
+               func.is_operator = False
+               func.member_of = None
+               func.orig_text = str_def
+               func.args = []
+               func.containing_file = containing_file
+               func.member_of = class_
+               func.duplicate = False
+               func.namespace = namespace
+               str_def = str_def.replace("operator ","operator")
+               if str.startswith(str_def, "static "):
+                       func.is_static = True
+                       str_def = str_def[7:]
+               else:
+                       func.is_static = False
+               if str.startswith(str_def, "inline "):
+                       func.is_inline = True
+                       str_def = str_def[7:]
+               else:
+                       func.is_inline = False
+               if str.startswith(str_def, "virtual "):
+                       func.is_virtual = True
+                       str_def = str_def[8:]
+               else:
+                       func.is_virtual = False
+
+               if str_def.count(" ") == 0:
+                       return None
+
+               parts = split_list(str_def.strip(), " ")
+
+               prefix = ""
+               i = 0
+               for part in parts:
+                       if part in ["unsigned", "long", "short"]:
+                               prefix += part + " "
+                               i += 1
+                       else:
+                               break
+               parts = parts[i:]
+
+               if len(parts) <= 1:
+                       return None
+
+               func.ret_type = WType.from_string(prefix + parts[0], containing_file, line_number)
+
+               if func.ret_type == None:
+                       return None
+
+               str_def = parts[1]
+               for part in parts[2:]:
+                       str_def = str_def + " " + part
+
+               found = str_def.find("(")
+               if found == -1 or (str_def.find(" ") != -1 and found > str_def.find(" ")):
+                       return None
+               func.name = str_def[:found]
+               str_def = str_def[found:]
+               if func.name.find("operator") != -1 and str.startswith(str_def, "()("):
+                               func.name += "()"
+                               str_def = str_def[2:]
+               str_def = str_def[1:]
+               if func.name.find("operator") != -1:
+                       func.is_operator = True
+               if func.name.find("*") == 0:
+                       func.name = func.name.replace("*", "")
+                       func.ret_type.attr_type = attr_types.star
+               if func.name.find("&&") == 0:
+                       func.name = func.name.replace("&&", "")
+                       func.ret_type.attr_type = attr_types.ampamp
+               if func.name.find("&") == 0:
+                       func.name = func.name.replace("&", "")
+                       func.ret_type.attr_type = attr_types.amp
+
+               found = find_closing(str_def, "(", ")")
+               if found == -1:
+                       return None
+               str_def = str_def[0:found]
+               if func.name in blacklist_methods:
+                       return None
+               if func.namespace != None and func.namespace != "":
+                       if (func.namespace + "::" + func.name) in blacklist_methods:
+                               return None
+                       if func.member_of != None:
+                               if (func.namespace + "::" + func.member_of.name + "::" + func.name) in blacklist_methods:
+                                       return None
+               if func.is_operator and func.name.replace(" ","").replace("operator","").split("::")[-1] not in wrappable_operators:
+                       return None
+
+               testname = func.name
+               if func.is_operator:
+                       testname = testname[:testname.find("operator")]
+               if testname.count(")") != 0 or testname.count("(") != 0 or testname.count("~") != 0 or testname.count(";") != 0 or testname.count(">") != 0 or testname.count("<") != 0 or testname.count("throw") != 0:
+                       return None
+
+               func.alias = func.name
+               if func.name in keyword_aliases:
+                       func.alias = keyword_aliases[func.name]
+               str_def = str_def[:found].strip()
+               if(len(str_def) == 0):
+                       return func
+               for arg in split_list(str_def, ","):
+                       if arg.strip() == "...":
+                               continue
+                       parsed = Attribute.from_string(arg.strip(), containing_file, line_number)
+                       if parsed == None:
+                               return None
+                       func.args.append(parsed)
+               return func
+
+       def gen_alias(self):
+               self.alias = self.name
+               for arg in self.args:
+                       self.alias += "__" + arg.wtype.gen_text_cpp().replace("::", "_").replace("<","_").replace(">","_").replace(" ","").replace("*","").replace(",","")
+
+       def gen_decl(self):
+               if self.duplicate:
+                       return ""
+               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t\t"
+               if self.is_static:
+                       text += "static "
+               text += self.ret_type.gen_text() + " " + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem()
+                       text += ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ");\n"
+               return text
+
+       def gen_decl_virtual(self):
+               if self.duplicate:
+                       return ""
+               if not self.is_virtual:
+                       return self.gen_decl()
+               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t\tvirtual "
+               if self.is_static:
+                       text += "static "
+               text += self.ret_type.gen_text() + " py_" + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem()
+                       text += ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ")"
+               if len(self.args) == 0:
+                       text += "{}"
+               else:
+                       text += "\n\t\t{"
+                       for arg in self.args:
+                               text += "\n\t\t\t(void)" + arg.gen_varname() + ";"
+                       text += "\n\t\t}\n"
+               text += "\n\t\tvirtual "
+               if self.is_static:
+                       text += "static "
+               text += self.ret_type.gen_text() + " " + self.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem_cpp()
+                       text += ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ") YS_OVERRIDE;\n"
+               return text
+
+       def gen_decl_hash_py(self):
+               text = self.ret_type.gen_text() + " " + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem_hash() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ");"
+               return text
+
+       def gen_def(self):
+               if self.duplicate:
+                       return ""
+               text  = "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t" + self.ret_type.gen_text() + " "
+               if self.member_of != None:
+                       text += self.member_of.name + "::"
+               text += self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem()
+                       text += ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text +=")\n\t{"
+               for arg in self.args:
+                       text += arg.gen_translation()
+               text += "\n\t\t"
+               if self.ret_type.name != "void":
+                       if self.ret_type.name in known_containers:
+                               text += self.ret_type.gen_text_cpp()
+                       else:
+                               text += self.ret_type.gen_text()
+                       if self.ret_type.name in classnames or (self.ret_type.name in known_containers and self.ret_type.attr_type == attr_types.star):
+                               text += "*"
+                       text += " ret_ = "
+                       if self.ret_type.name in classnames:
+                               text += self.ret_type.name + "::get_py_obj("
+               if self.member_of == None:
+                       text += "::" + self.namespace + "::" + self.alias + "("
+               elif self.is_static:
+                       text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "("
+               else:
+                       text += "this->get_cpp_obj()->" + self.name + "("
+               for arg in self.args:
+                       text += arg.gen_call() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               if self.ret_type.name in classnames:
+                       text += ")"
+               text += ");"
+               for arg in self.args:
+                       text += arg.gen_cleanup()
+               if self.ret_type.name != "void":
+                       if self.ret_type.name in classnames:
+                               text += "\n\t\treturn *ret_;"
+                       elif self.ret_type.name in known_containers:
+                               text += known_containers[self.ret_type.name].translate_cpp("ret_", self.ret_type.cont.args, "\n\t\t", self.ret_type.attr_type == attr_types.star)
+                               text += "\n\t\treturn ret____tmp;"
+                       else:
+                               text += "\n\t\treturn ret_;"
+               text += "\n\t}\n"
+               return text
+
+       def gen_def_virtual(self):
+               if self.duplicate:
+                       return ""
+               if not self.is_virtual:
+                       return self.gen_def()
+               text =  "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
+               text += "\n\t"
+               if self.is_static:
+                       text += "static "
+               text += self.ret_type.gen_text() + " " + self.member_of.name + "::" + self.name + "("
+               for arg in self.args:
+                       text += arg.gen_listitem_cpp()
+                       text += ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ")\n\t{"
+               for arg in self.args:
+                       text += arg.gen_translation_cpp()
+               text += "\n\t\t"
+               if self.member_of == None:
+                       text += "::" + self.namespace + "::" + self.alias + "("
+               elif self.is_static:
+                       text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "("
+               else:
+                       text += "py_" + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_call_cpp() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               if self.ret_type.name in classnames:
+                       text += ")"
+               text += ");"
+               for arg in self.args:
+                       text += arg.gen_cleanup()
+               text += "\n\t}\n"
+               return text
+
+       def gen_default_impl(self):
+               if self.duplicate:
+                       return ""
+               if not self.is_virtual:
+                       return ""
+               text = "\n\n\t\t" + self.ret_type.gen_text() + " py_" + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+
+               call_string = "py_" + self.alias + "("
+               for arg in self.args:
+                       call_string += arg.gen_varname() + ", "
+               if len(self.args) > 0:
+                       call_string = call_string[0:-2]
+               call_string += ");"
+
+               text += ")\n\t\t{"
+               text += "\n\t\t\tif(boost::python::override py_" + self.alias + " = this->get_override(\"py_" + self.alias + "\"))"
+               text += "\n\t\t\t\t" + call_string
+               text += "\n\t\t\telse"
+               text += "\n\t\t\t\t" + self.member_of.name + "::" + call_string
+               text += "\n\t\t}"
+
+               text += "\n\n\t\t" + self.ret_type.gen_text() + " default_py_" + self.alias + "("
+               for arg in self.args:
+                       text += arg.gen_listitem() + ", "
+               if len(self.args) > 0:
+                       text = text[:-2]
+               text += ")\n\t\t{"
+               text += "\n\t\t\tthis->" + self.member_of.name + "::" + call_string
+               text += "\n\t\t}"
+               return text
+
+
+       def gen_boost_py(self):
+               if self.duplicate:
+                       return ""
+               if self.member_of == None:
+                       text = "\n\t\tdef"
+               else:
+                       text = "\n\t\t\t.def"
+               if len(self.args) > -1:
+                       if self.ret_type.name in known_containers:
+                               text += "<" + known_containers[self.ret_type.name].typename + " "
+                       else:
+                               text += "<" + self.ret_type.name + " "
+                       if self.member_of == None or self.is_static:
+                               text += "(*)("
+                       else:
+                               text += "(" + self.member_of.name + "::*)("
+                       for a in self.args:
+                               text += a.gen_listitem_hash() + ", "
+                       if len(self.args) > 0:
+                               text = text[0:-2] + ")>"
+                       else:
+                               text += "void)>"
+
+               if self.is_operator:
+                       text += "(\"" + wrappable_operators[self.name.replace("operator","")] + "\""
+               else:
+                       if self.member_of != None and self.member_of.link_type == link_types.derive and self.is_virtual:
+                               text += "(\"py_" + self.alias + "\""
+                       else:
+                               text += "(\"" + self.alias + "\""
+               if self.member_of != None:
+                       text += ", &" + self.member_of.name + "::"
+                       if self.member_of.link_type == link_types.derive and self.is_virtual:
+                               text += "py_" + self.alias
+                               text += ", &" + self.member_of.name + "Wrap::default_py_" + self.alias
+                       else:
+                               text += self.alias
+
+                       text += ")"
+               else:
+                       text += ", " + "YOSYS_PYTHON::" + self.alias + ");"
+               return text
+
+class WMember:
+       orig_text = None
+       wtype = attr_types.default
+       name = None
+       containing_file = None
+       member_of = None
+       namespace = ""
+       is_const = False
+
+       def from_string(str_def, containing_file, class_, line_number, namespace):
+               member = WMember()
+               member.orig_text = str_def
+               member.wtype = None
+               member.name = ""
+               member.containing_file = containing_file
+               member.member_of = class_
+               member.namespace = namespace
+               member.is_const = False
+
+               if str.startswith(str_def, "const "):
+                       member.is_const = True
+                       str_def = str_def[6:]
+
+               if str_def.count(" ") == 0:
+                       return None
+
+               parts = split_list(str_def.strip(), " ")
+
+               prefix = ""
+               i = 0
+               for part in parts:
+                       if part in ["unsigned", "long", "short"]:
+                               prefix += part + " "
+                               i += 1
+                       else:
+                               break
+               parts = parts[i:]
+
+               if len(parts) <= 1:
+                       return None
+
+               member.wtype = WType.from_string(prefix + parts[0], containing_file, line_number)
+
+               if member.wtype == None:
+                       return None
+
+               str_def = parts[1]
+               for part in parts[2:]:
+                       str_def = str_def + " " + part
+
+               if str_def.find("(") != -1 or str_def.find(")") != -1 or str_def.find("{") != -1 or str_def.find("}") != -1:
+                       return None
+
+               found = str_def.find(";")
+               if found == -1:
+                       return None
+
+               found_eq = str_def.find("=")
+               if found_eq != -1:
+                       found = found_eq
+
+               member.name = str_def[:found]
+               str_def = str_def[found+1:]
+               if member.name.find("*") == 0:
+                       member.name = member.name.replace("*", "")
+                       member.wtype.attr_type = attr_types.star
+               if member.name.find("&&") == 0:
+                       member.name = member.name.replace("&&", "")
+                       member.wtype.attr_type = attr_types.ampamp
+               if member.name.find("&") == 0:
+                       member.name = member.name.replace("&", "")
+                       member.wtype.attr_type = attr_types.amp
+
+               if(len(str_def.strip()) != 0):
+                       return None
+
+               if len(member.name.split(",")) > 1:
+                       member_list = []
+                       for name in member.name.split(","):
+                               name = name.strip();
+                               member_list.append(WMember())
+                               member_list[-1].orig_text = member.orig_text
+                               member_list[-1].wtype = member.wtype
+                               member_list[-1].name = name
+                               member_list[-1].containing_file = member.containing_file
+                               member_list[-1].member_of = member.member_of
+                               member_list[-1].namespace = member.namespace
+                               member_list[-1].is_const = member.is_const
+                       return member_list
+
+               return member
+
+       def gen_decl(self):
+               text = "\n\t\t" + self.wtype.gen_text() + " get_var_py_" + self.name + "();\n"
+               if self.is_const:
+                       return text
+               if self.wtype.name in classnames:
+                       text += "\n\t\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs);\n"
+               else:
+                       text += "\n\t\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs);\n"
+               return text
+
+       def gen_def(self):
+               text = "\n\t" + self.wtype.gen_text() + " " + self.member_of.name +"::get_var_py_" + self.name + "()"
+               text += "\n\t{\n\t\t"
+               if self.wtype.attr_type == attr_types.star:
+                       text += "if(this->get_cpp_obj()->" + self.name + " == NULL)\n\t\t\t"
+                       text += "throw std::runtime_error(\"Member \\\"" + self.name + "\\\" is NULL\");\n\t\t"
+               if self.wtype.name in known_containers:
+                       text += self.wtype.gen_text_cpp()
+               else:
+                       text += self.wtype.gen_text()
+
+               if self.wtype.name in classnames or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star):
+                       text += "*"
+               text += " ret_ = "
+               if self.wtype.name in classnames:
+                       text += self.wtype.name + "::get_py_obj("
+                       if self.wtype.attr_type != attr_types.star:
+                               text += "&"
+               text += "this->get_cpp_obj()->" + self.name
+               if self.wtype.name in classnames:
+                       text += ")"
+               text += ";"
+               
+               if self.wtype.name in classnames:
+                       text += "\n\t\treturn *ret_;"
+               elif self.wtype.name in known_containers:
+                       text += known_containers[self.wtype.name].translate_cpp("ret_", self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star)
+                       text += "\n\t\treturn ret____tmp;"
+               else:
+                       text += "\n\t\treturn ret_;"
+               text += "\n\t}\n"
+
+               if self.is_const:
+                       return text
+
+               ret = Attribute(self.wtype, "rhs");
+
+               if self.wtype.name in classnames:
+                       text += "\n\tvoid " + self.member_of.name+ "::set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs)"
+               else:
+                       text += "\n\tvoid " + self.member_of.name+ "::set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs)"
+               text += "\n\t{"
+               text += ret.gen_translation()
+               text += "\n\t\tthis->get_cpp_obj()->" + self.name + " = " + ret.gen_call() + ";"
+               text += "\n\t}\n"               
+
+               return text;
+
+       def gen_boost_py(self):
+               text = "\n\t\t\t.add_property(\"" + self.name + "\", &" + self.member_of.name + "::get_var_py_" + self.name 
+               if not self.is_const:
+                       text += ", &" + self.member_of.name + "::set_var_py_" + self.name
+               text += ")"
+               return text
+
+def concat_namespace(tuple_list):
+       if len(tuple_list) == 0:
+               return ""
+       ret = ""
+       for namespace in tuple_list:
+               ret += "::" + namespace[0]
+       return ret[2:]
+
+def calc_ident(text):
+       if len(text) == 0 or text[0] != ' ':
+               return 0
+       return calc_ident(text[1:]) + 1
+
+def assure_length(text, length, left = False):
+       if len(text) > length:
+               return text[:length]
+       if left:
+               return text + " "*(length - len(text))
+       return " "*(length - len(text)) + text
+       
+def parse_header(source):
+       debug("Parsing " + source.name + ".pyh",1)
+       source_file = open(source.name + ".pyh", "r")
+
+       source_text = []
+       in_line = source_file.readline()
+
+       namespaces = []
+
+       while(in_line):
+               if(len(in_line)>1):
+                       source_text.append(in_line.replace("char *", "char_p ").replace("char* ", "char_p "))
+               in_line = source_file.readline()
+
+       i = 0
+
+       namespaces = []
+       class_ = None
+       private_segment = False
+
+       while i < len(source_text):
+               line = source_text[i].replace("YOSYS_NAMESPACE_BEGIN", "                    namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END","                    }")
+               ugly_line = unpretty_string(line)
+
+               if str.startswith(ugly_line, "namespace "):# and ugly_line.find("std") == -1 and ugly_line.find("__") == -1:
+                       namespace_name = ugly_line[10:].replace("{","").strip()
+                       namespaces.append((namespace_name, ugly_line.count("{")))
+                       debug("-----NAMESPACE " + concat_namespace(namespaces) + "-----",3)
+                       i += 1
+                       continue
+
+               if len(namespaces) != 0:
+                       namespaces[-1] = (namespaces[-1][0], namespaces[-1][1] + ugly_line.count("{") - ugly_line.count("}"))
+                       if namespaces[-1][1] == 0:
+                               debug("-----END NAMESPACE " + concat_namespace(namespaces) + "-----",3)
+                               del namespaces[-1]
+                               i += 1
+                               continue
+
+               if class_ == None and (str.startswith(ugly_line, "struct ") or str.startswith(ugly_line, "class")) and ugly_line.count(";") == 0:
+
+                       struct_name = ugly_line.split(" ")[1].split("::")[-1]
+                       impl_namespaces = ugly_line.split(" ")[1].split("::")[:-1]
+                       complete_namespace = concat_namespace(namespaces)
+                       for namespace in impl_namespaces:
+                               complete_namespace += "::" + namespace
+                       debug("\tFound " + struct_name + " in " + complete_namespace,2)
+                       class_ = (class_by_name(struct_name), ugly_line.count("{"))#calc_ident(line))
+                       if struct_name in classnames:
+                               class_[0].namespace = complete_namespace
+                       i += 1
+                       continue
+
+               if class_ != None:
+                       class_ = (class_[0], class_[1] + ugly_line.count("{") - ugly_line.count("}"))
+                       if class_[1] == 0:
+                               if class_[0] == None:
+                                       debug("\tExiting unknown class", 3)
+                               else:
+                                       debug("\tExiting class " + class_[0].name, 3)
+                               class_ = None
+                               private_segment = False
+                               i += 1
+                               continue
+
+               if class_ != None and (line.find("private:") != -1 or line.find("protected:") != -1):
+                       private_segment = True
+                       i += 1
+                       continue
+               if class_ != None and line.find("public:") != -1:
+                       private_segment = False
+                       i += 1
+                       continue
+
+               candidate = None
+
+               if private_segment and class_ != None and class_[0] != None:
+                       candidate = WConstructor.from_string(ugly_line, source.name, class_[0], i, True)
+                       if candidate != None:
+                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
+                               class_[0].found_constrs.append(candidate)
+                               i += 1
+                               continue
+
+               if not private_segment and (class_ == None or class_[0] != None):
+                       if class_ != None:
+                               candidate = WFunction.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
+                       else:
+                               candidate = WFunction.from_string(ugly_line, source.name, None, i, concat_namespace(namespaces))
+                       if candidate != None and candidate.name.find("::") == -1:
+                               if class_ == None:
+                                       debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
+                                       unowned_functions.append(candidate)
+                               else:
+                                       debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
+                                       class_[0].found_funs.append(candidate)
+                       else:
+                               candidate = WEnum.from_string(ugly_line, concat_namespace(namespaces), i)
+                               if candidate != None:
+                                       enums.append(candidate)
+                                       debug("\tFound enum \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
+                               elif class_ != None and class_[1] == 1:
+                                       candidate = WConstructor.from_string(ugly_line, source.name, class_[0], i)
+                                       if candidate != None:
+                                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
+                                               class_[0].found_constrs.append(candidate)
+                                       else:
+                                               candidate = WMember.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
+                                               if candidate != None:
+                                                       if type(candidate) == list:
+                                                               for c in candidate:
+                                                                       debug("\t\tFound member \"" + c.name + "\" of class \"" + class_[0].name + "\" of type \"" + c.wtype.name + "\"", 2)
+                                                               class_[0].found_vars.extend(candidate)
+                                                       else:
+                                                               debug("\t\tFound member \"" + candidate.name + "\" of class \"" + class_[0].name + "\" of type \"" + candidate.wtype.name + "\"", 2)
+                                                               class_[0].found_vars.append(candidate)
+
+                       j = i
+                       line = unpretty_string(line)
+                       while candidate == None and j+1 < len(source_text) and  line.count(';') <= 1 and line.count("(") >= line.count(")"):
+                               j += 1
+                               line = line + "\n" + unpretty_string(source_text[j])
+                               if class_ != None:
+                                       candidate = WFunction.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
+                               else:
+                                       candidate = WFunction.from_string(ugly_line, source.name, None, i, concat_namespace(namespaces))
+                               if candidate != None and candidate.name.find("::") == -1:
+                                       if class_ == None:
+                                               debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
+                                               unowned_functions.append(candidate)
+                                       else:
+                                               debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
+                                               class_[0].found_funs.append(candidate)
+                                       continue
+                               candidate = WEnum.from_string(line, concat_namespace(namespaces), i)
+                               if candidate != None:
+                                       enums.append(candidate)
+                                       debug("\tFound enum \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
+                                       continue
+                               if class_ != None:
+                                       candidate = WConstructor.from_string(line, source.name, class_[0], i)
+                                       if candidate != None:
+                                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
+                                               class_[0].found_constrs.append(candidate)
+                                               continue
+               if candidate != None:
+                       while i < j:
+                               i += 1
+                               line = source_text[i].replace("YOSYS_NAMESPACE_BEGIN", "                    namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END","                    }")
+                               ugly_line = unpretty_string(line)
+                               if len(namespaces) != 0:
+                                       namespaces[-1] = (namespaces[-1][0], namespaces[-1][1] + ugly_line.count("{") - ugly_line.count("}"))
+                                       if namespaces[-1][1] == 0:
+                                               debug("-----END NAMESPACE " + concat_namespace(namespaces) + "-----",3)
+                                               del namespaces[-1]
+                               if class_ != None:
+                                       class_ = (class_[0] , class_[1] + ugly_line.count("{") - ugly_line.count("}"))
+                                       if class_[1] == 0:
+                                               if class_[0] == None:
+                                                       debug("\tExiting unknown class", 3)
+                                               else:
+                                                       debug("\tExiting class " + class_[0].name, 3)
+                                               class_ = None
+                                               private_segment = False
+                       i += 1
+               else:
+                       i += 1
+
+def debug(message, level):
+       if level <= debug.debug_level:
+               print(message)
+
+def expand_function(f):
+       fun_list = []
+       arg_list = []
+       for arg in f.args:
+               if arg.default_value != None and (arg.wtype.name.split(" ")[-1] in primitive_types or arg.wtype.name in enum_names or (arg.wtype.name in classnames and arg.default_value == "nullptr")):
+                       fi = copy.deepcopy(f)
+                       fi.args = copy.deepcopy(arg_list)
+                       fun_list.append(fi)
+               arg_list.append(arg)
+       fun_list.append(f)
+       return fun_list
+
+def expand_functions():
+       global unowned_functions
+       new_funs = []
+       for fun in unowned_functions:
+               new_funs.extend(expand_function(fun))
+       unowned_functions = new_funs
+       for source in sources:
+               for class_ in source.classes:
+                       new_funs = []
+                       for fun in class_.found_funs:
+                               new_funs.extend(expand_function(fun))
+                       class_.found_funs = new_funs
+
+def clean_duplicates():
+       for source in sources:
+               for class_ in source.classes:
+                       known_decls = {}
+                       for fun in class_.found_funs:
+                               if fun.gen_decl_hash_py() in known_decls:
+                                       debug("Multiple declarations of " + fun.gen_decl_hash_py(),3)
+                                       other = known_decls[fun.gen_decl_hash_py()]
+                                       other.gen_alias()
+                                       fun.gen_alias()
+                                       if fun.gen_decl_hash_py() == other.gen_decl_hash_py():
+                                               fun.duplicate = True
+                                               debug("Disabled \"" + fun.gen_decl_hash_py() + "\"", 3)
+                               else:
+                                       known_decls[fun.gen_decl_hash_py()] = fun
+                       known_decls = []
+                       for con in class_.found_constrs:
+                               if con.gen_decl_hash_py() in known_decls:
+                                       debug("Multiple declarations of " + con.gen_decl_hash_py(),3)
+                                       con.duplicate = True
+                               else:
+                                       known_decls.append(con.gen_decl_hash_py())
+       known_decls = []
+       for fun in unowned_functions:
+               if fun.gen_decl_hash_py() in known_decls:
+                       debug("Multiple declarations of " + fun.gen_decl_hash_py(),3)
+                       fun.duplicate = True
+               else:
+                       known_decls.append(fun.gen_decl_hash_py())
+
+def gen_wrappers(filename, debug_level_ = 0):
+       debug.debug_level = debug_level_
+       for source in sources:
+               parse_header(source)
+
+       expand_functions()
+       clean_duplicates()
+
+       import shutil
+       import math
+       col = shutil.get_terminal_size((80,20)).columns
+       debug("-"*col, 1)
+       debug("-"*math.floor((col-7)/2)+"SUMMARY"+"-"*math.ceil((col-7)/2), 1)
+       debug("-"*col, 1)
+       for source in sources:
+               for class_ in source.classes:
+                       debug("Class " + assure_length(class_.name, len(max(classnames, key=len)), True) + " contains " + assure_length(str(len(class_.found_vars)), 3, False) + " member variables, "+ assure_length(str(len(class_.found_funs)), 3, False) + " methods and " + assure_length(str(len(class_.found_constrs)), 2, False) + " constructors", 1)
+                       if len(class_.found_constrs) == 0:
+                               class_.found_constrs.append(WConstructor(source.name, class_))
+       debug(str(len(unowned_functions)) + " functions are unowned", 1)
+       for enum in enums:
+               debug("Enum " + assure_length(enum.name, len(max(enum_names, key=len)), True) + " contains " + assure_length(str(len(enum.values)), 2, False) + " values", 1)
+       debug("-"*col, 1)
+       wrapper_file = open(filename, "w+")
+       wrapper_file.write(
+"""/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *  This is a generated file and can be overwritten by make
+ */
+
+#ifdef WITH_PYTHON
+""")
+       for source in sources:
+               wrapper_file.write("#include \""+source.name+".h\"\n")
+       wrapper_file.write("""
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/wrapper.hpp>
+#include <boost/python/call.hpp>
+#include <boost/python.hpp>
+#include <boost/log/exceptions.hpp>
+
+USING_YOSYS_NAMESPACE
+
+namespace YOSYS_PYTHON {
+""")
+
+       for source in sources:
+               for wclass in source.classes:
+                       wrapper_file.write("\n\tstruct " + wclass.name + ";")
+
+       wrapper_file.write("\n")
+
+       for source in sources:
+               for wclass in source.classes:
+                       wrapper_file.write(wclass.gen_decl(source.name))
+
+       wrapper_file.write("\n")
+
+       for source in sources:
+               for wclass in source.classes:
+                       wrapper_file.write(wclass.gen_funs(source.name))
+
+       for fun in unowned_functions:
+               wrapper_file.write(fun.gen_def())
+
+       wrapper_file.write("""  struct Initializer
+       {
+               Initializer() {
+                       if(!Yosys::yosys_already_setup())
+                       {
+                               Yosys::log_streams.push_back(&std::cout);
+                               Yosys::log_error_stderr = true;
+                               Yosys::yosys_setup();
+                               Yosys::yosys_banner();
+                       }
+               }
+
+               Initializer(Initializer const &) {}
+
+               ~Initializer() {
+                       Yosys::yosys_shutdown();
+               }
+       };
+
+       BOOST_PYTHON_MODULE(libyosys)
+       {
+               using namespace boost::python;
+
+               class_<Initializer>("Initializer");
+               scope().attr("_hidden") = new Initializer();
+""")
+
+       for enum in enums:
+               wrapper_file.write(enum.gen_boost_py())
+
+       for source in sources:
+               for wclass in source.classes:
+                       wrapper_file.write(wclass.gen_boost_py())
+
+       for fun in unowned_functions:
+               wrapper_file.write(fun.gen_boost_py())
+
+       wrapper_file.write("\n\t}\n}\n#endif")
+
+def print_includes():
+       for source in sources:
+               print(source.name + ".pyh")
diff --git a/py_wrap_generator.py b/py_wrap_generator.py
deleted file mode 100644 (file)
index 09f9340..0000000
+++ /dev/null
@@ -1,2096 +0,0 @@
-#
-#  yosys -- Yosys Open SYnthesis Suite
-#
-#  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
-#
-#  Permission to use, copy, modify, and/or distribute this software for any
-#  purpose with or without fee is hereby granted, provided that the above
-#  copyright notice and this permission notice appear in all copies.
-#
-#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-#  Author Benedikt Tutzer
-#
-
-import copy
-
-#Map c++ operator Syntax to Python functions
-wrappable_operators = {
-               "<" : "__lt__",
-               "==": "__eq__",
-               "!=": "__ne__",
-               "+" : "__add__",
-               "-" : "__sub__",
-               "*" : "__mul__",
-               "/" : "__div__",
-               "()": "__call__"
-       }
-
-#Restrict certain strings from being function names in Python
-keyword_aliases = {
-               "in" : "in_",
-               "False" : "False_",
-               "None" : "None_",
-               "True" : "True_",
-               "and" : "and_",
-               "as" : "as_",
-               "assert" : "assert_",
-               "break" : "break_",
-               "class" : "class_",
-               "continue" : "continue_",
-               "def" : "def_",
-               "del" : "del_",
-               "elif" : "elif_",
-               "else" : "else_",
-               "except" : "except_",
-               "for" : "for_",
-               "from" : "from_",
-               "global" : "global_",
-               "if" : "if_",
-               "import" : "import_",
-               "in" : "in_",
-               "is" : "is_",
-               "lambda" : "lambda_",
-               "nonlocal" : "nonlocal_",
-               "not" : "not_",
-               "or" : "or_",
-               "pass" : "pass_",
-               "raise" : "raise_",
-               "return" : "return_",
-               "try" : "try_",
-               "while" : "while_",
-               "with" : "with_",
-               "yield" : "yield_"
-       }
-
-#These can be used without any explicit conversion
-primitive_types = ["void", "bool", "int", "double", "size_t", "std::string",
-               "string", "State", "char_p"]
-
-from enum import Enum
-
-#Ways to link between Python- and C++ Objects
-class link_types(Enum):
-       global_list = 1         #Manage a global list of objects in C++, the Python
-                                               #object contains a key to find the corresponding C++
-                                               #object and a Pointer to the object to verify it is
-                                               #still the same, making collisions unlikely to happen
-       ref_copy = 2            #The Python object contains a copy of the C++ object.
-                                               #The C++ object is deleted when the Python object gets
-                                               #deleted
-       pointer = 3                     #The Python Object contains a pointer to it's C++
-                                               #counterpart
-       derive = 4                      #The Python-Wrapper is derived from the C++ object.
-
-class attr_types(Enum):
-       star = "*"
-       amp = "&"
-       ampamp = "&&"
-       default = ""
-
-#For source-files
-class Source:
-       name = ""
-       classes = []
-
-       def __init__(self, name, classes):
-               self.name = name
-               self.classes = classes
-
-#Splits a list by the given delimiter, without splitting strings inside
-#pointy-brackets (< and >)
-def split_list(str_def, delim):
-       str_def = str_def.strip()
-       if len(str_def) == 0:
-               return []
-       if str_def.count(delim) == 0:
-               return [str_def]
-       if str_def.count("<") == 0:
-               return str_def.split(delim)
-       if str_def.find("<") < str_def.find(" "):
-               closing = find_closing(str_def[str_def.find("<")+1:], "<", ">") + str_def.find("<")
-               comma = str_def[closing:].find(delim)
-               if comma == -1:
-                       return [str_def]
-               comma = closing  + comma
-       else:
-               comma = str_def.find(delim)
-       rest = split_list(str_def[comma+1:], delim)
-       ret = [str_def[:comma]]
-       if rest != None and len(rest) != 0:
-               ret.extend(rest)
-       return ret
-
-#Represents a Type
-class WType:
-       name = ""
-       cont = None
-       attr_type = attr_types.default
-
-       def __init__(self, name = "", cont = None, attr_type = attr_types.default):
-               self.name = name
-               self.cont = cont
-               self.attr_type = attr_type
-
-       #Python type-string
-       def gen_text(self):
-               text = self.name
-               if self.name in enum_names:
-                       text = enum_by_name(self.name).namespace + "::" + self.name
-               if self.cont != None:
-                       return known_containers[self.name].typename
-               return text
-
-       #C++ type-string
-       def gen_text_cpp(self):
-               postfix = ""
-               if self.attr_type == attr_types.star:
-                       postfix = "*"
-               if self.name in primitive_types:
-                       return self.name + postfix
-               if self.name in enum_names:
-                       return enum_by_name(self.name).namespace + "::" + self.name + postfix
-               if self.name in classnames:
-                       return class_by_name(self.name).namespace + "::" + self.name + postfix
-               text = self.name
-               if self.cont != None:
-                       text += "<"
-                       for a in self.cont.args:
-                               text += a.gen_text_cpp() + ", "
-                       text = text[:-2]
-                       text += ">"
-               return text
-
-       @staticmethod
-       def from_string(str_def, containing_file, line_number):
-               str_def = str_def.strip()
-               if len(str_def) == 0:
-                       return None
-               str_def = str_def.replace("RTLIL::SigSig", "std::pair<SigSpec, SigSpec>").replace("SigSig", "std::pair<SigSpec, SigSpec>")
-               t = WType()
-               t.name = ""
-               t.cont = None
-               t.attr_type = attr_types.default
-               if str_def.find("<") != -1:# and str_def.find("<") < str_def.find(" "):
-                       candidate = WContainer.from_string(str_def, containing_file, line_number)
-                       if candidate == None:
-                               return None
-                       t.name = str_def[:str_def.find("<")]
-
-                       if t.name.count("*") + t.name.count("&") > 1:
-                               return None
-
-                       if t.name.count("*") == 1 or str_def[0] == '*' or str_def[-1] == '*':
-                               t.attr_type = attr_types.star
-                               t.name = t.name.replace("*","")
-                       elif t.name.count("&&") == 1:
-                               t.attr_type = attr_types.ampamp
-                               t.name = t.name.replace("&&","")
-                       elif t.name.count("&") == 1 or str_def[0] == '&' or str_def[-1] == '&':
-                               t.attr_type = attr_types.amp
-                               t.name = t.name.replace("&","")
-
-                       t.cont = candidate
-                       if(t.name not in known_containers):
-                               return None     
-                       return t
-
-               prefix = ""
-
-               if str.startswith(str_def, "unsigned "):
-                       prefix = "unsigned "
-                       str_def = str_def[9:]
-               while str.startswith(str_def, "long "):
-                       prefix= "long " + prefix
-                       str_def = str_def[5:]
-               while str.startswith(str_def, "short "):
-                       prefix = "short " + prefix
-                       str_def = str_def[6:]
-
-               str_def = str_def.split("::")[-1]
-
-               if str_def.count("*") + str_def.count("&") >= 2:
-                       return None
-
-               if str_def.count("*") == 1:
-                       t.attr_type = attr_types.star
-                       str_def = str_def.replace("*","")
-               elif str_def.count("&&") == 1:
-                       t.attr_type = attr_types.ampamp
-                       str_def = str_def.replace("&&","")
-               elif str_def.count("&") == 1:
-                       t.attr_type = attr_types.amp
-                       str_def = str_def.replace("&","")
-
-               if len(str_def) > 0 and str_def.split("::")[-1] not in primitive_types and str_def.split("::")[-1] not in classnames and str_def.split("::")[-1] not in enum_names:
-                       return None
-
-               if str_def.count(" ") == 0:
-                       t.name = (prefix + str_def).replace("char_p", "char *")
-                       t.cont = None
-                       return t
-               return None
-
-#Represents a container-type
-class WContainer:
-       name = ""
-       args = []
-
-       def from_string(str_def, containing_file, line_number):
-               if str_def == None or len(str_def) < 4:
-                       return None
-               cont = WContainer()
-               cont.name = str_def[:str_def.find("<")]
-               str_def = str_def[str_def.find("<")+1:find_closing(str_def, "<", ">")]
-               cont.args = []
-               for arg in split_list(str_def, ","):
-                       candidate = WType.from_string(arg.strip(), containing_file, line_number)
-                       if candidate == None:
-                               return None
-                       cont.args.append(candidate)
-               return cont
-
-#Translators between Python and C++ containers
-#Base Type
-class Translator:
-       tmp_cntr = 0
-       typename = "DefaultType"
-       orig_name = "DefaultCpp"
-
-       @classmethod
-       def gen_type(c, types):
-               return "\nImplement a function that outputs the c++ type of this container here\n"
-
-       @classmethod
-       def translate(c, varname, types, prefix):
-               return "\nImplement a function translating a python container to a c++ container here\n"
-
-       @classmethod
-       def translate_cpp(c, varname, types, prefix, ref):
-               return "\nImplement a function translating a c++ container to a python container here\n"
-
-#Translates list-types (vector, pool, set), that only differ in their name and
-#the name of the insertion function
-class PythonListTranslator(Translator):
-       typename = "boost::python::list"
-       insert_name = "Default"
-
-       #generate the c++ type string
-       @classmethod
-       def gen_type(c, types):
-               text = c.orig_name + "<"
-               if types[0].name in primitive_types:
-                       text += types[0].name
-               elif types[0].name in known_containers:
-                       text += known_containers[types[0].name].gen_type(types[0].cont.args)
-               else:
-                       text += class_by_name(types[0].name).namespace + "::" + types[0].name
-                       if types[0].attr_type == attr_types.star:
-                               text += "*"
-               text += ">"
-               return text
-
-       #Generate C++ code to translate from a boost::python::list
-       @classmethod
-       def translate(c, varname, types, prefix):
-               text  = prefix + c.gen_type(types) + " " + varname + "___tmp;"
-               cntr_name = "cntr_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               text += prefix + "for(int " + cntr_name + " = 0; " + cntr_name + " < len(" + varname + "); " + cntr_name + "++)"
-               text += prefix + "{"
-               tmp_name = "tmp_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               if types[0].name in known_containers:
-                       text += prefix + "\t" + known_containers[types[0].name].typename + " " + tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "[" + cntr_name + "]);"
-                       text += known_containers[types[0].name].translate(tmp_name, types[0].cont.args, prefix+"\t")
-                       tmp_name = tmp_name + "___tmp"
-                       text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");"
-               elif types[0].name in classnames:
-                       text += prefix + "\t" + types[0].name + "* " + tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "[" + cntr_name + "]);"
-                       if types[0].attr_type == attr_types.star:
-                               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + "->get_cpp_obj());"
-                       else:
-                               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());"
-               else:
-                       text += prefix + "\t" + types[0].name + " " + tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "[" + cntr_name + "]);"
-                       text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");"
-               text += prefix + "}"
-               return text
-
-       #Generate C++ code to translate to a boost::python::list
-       @classmethod
-       def translate_cpp(c, varname, types, prefix, ref):
-               text  = prefix + c.typename + " " + varname + "___tmp;"
-               tmp_name = "tmp_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               if ref:
-                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
-               else:
-                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
-               text += prefix + "{"
-               if types[0].name in classnames:
-                       if types[0].attr_type == attr_types.star:
-                               text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
-                       else:
-                               text += prefix + "\t" + varname + "___tmp.append(*" + types[0].name + "::get_py_obj(&" + tmp_name + "));"
-               elif types[0].name in known_containers:
-                       text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[0].attr_type == attr_types.star)
-                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + "___tmp);"
-               else:
-                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");"
-               text += prefix + "}"
-               return text
-
-#Sub-type for std::set
-class SetTranslator(PythonListTranslator):
-       insert_name = "insert"
-       orig_name = "std::set"
-
-#Sub-type for std::vector
-class VectorTranslator(PythonListTranslator):
-       insert_name = "push_back"
-       orig_name = "std::vector"
-
-#Sub-type for pool
-class PoolTranslator(PythonListTranslator):
-       insert_name = "insert"
-       orig_name = "pool"
-
-#Translates dict-types (dict, std::map), that only differ in their name and
-#the name of the insertion function
-class PythonDictTranslator(Translator):
-       typename = "boost::python::dict"
-       insert_name = "Default"
-
-       @classmethod
-       def gen_type(c, types):
-               text = c.orig_name + "<"
-               if types[0].name in primitive_types:
-                       text += types[0].name
-               elif types[0].name in known_containers:
-                       text += known_containers[types[0].name].gen_type(types[0].cont.args)
-               else:
-                       text += class_by_name(types[0].name).namespace + "::" + types[0].name
-                       if types[0].attr_type == attr_types.star:
-                               text += "*"
-               text += ", "
-               if types[1].name in primitive_types:
-                       text += types[1].name
-               elif types[1].name in known_containers:
-                       text += known_containers[types[1].name].gen_type(types[1].cont.args)
-               else:
-                       text += class_by_name(types[1].name).namespace + "::" + types[1].name
-                       if types[1].attr_type == attr_types.star:
-                               text += "*"
-               text += ">"
-               return text
-
-       #Generate c++ code to translate from a boost::python::dict
-       @classmethod
-       def translate(c, varname, types, prefix):
-               text  = prefix + c.gen_type(types) + " " + varname + "___tmp;"
-               text += prefix + "boost::python::list " + varname + "_keylist = " + varname + ".keys();"
-               cntr_name = "cntr_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               text += prefix + "for(int " + cntr_name + " = 0; " + cntr_name + " < len(" + varname + "_keylist); " + cntr_name + "++)"
-               text += prefix + "{"
-               key_tmp_name = "key_tmp_" + str(Translator.tmp_cntr)
-               val_tmp_name = "val_tmp_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-
-               if types[0].name in known_containers:
-                       text += prefix + "\t" + known_containers[types[0].name].typename + " " + key_tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "_keylist[ " + cntr_name + " ]);"
-                       text += known_containers[types[0].name].translate(key_tmp_name, types[0].cont.args, prefix+"\t")
-                       key_tmp_name = key_tmp_name + "___tmp"
-               elif types[0].name in classnames:
-                       text += prefix + "\t" + types[0].name + "* " + key_tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "_keylist[ " + cntr_name + " ]);"
-               else:
-                       text += prefix + "\t" + types[0].name + " " + key_tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "_keylist[ " + cntr_name + " ]);"
-
-               if types[1].name in known_containers:
-                       text += prefix + "\t" + known_containers[types[1].name].typename + " " + val_tmp_name + " = boost::python::extract<" + known_containers[types[1].name].typename + ">(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
-                       text += known_containers[types[1].name].translate(val_tmp_name, types[1].cont.args, prefix+"\t")
-                       val_tmp_name = val_tmp_name + "___tmp"
-               elif types[1].name in classnames:
-                       text += prefix + "\t" + types[1].name + "* " + val_tmp_name + " = boost::python::extract<" + types[1].name + "*>(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
-               else:
-                       text += prefix + "\t" + types[1].name + " " + val_tmp_name + " = boost::python::extract<" + types[1].name + ">(" + varname + "[" + varname + "_keylist[ " + cntr_name + " ]]);"
-
-               text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(std::pair<" + types[0].gen_text_cpp() + ", " + types[1].gen_text_cpp() + ">("
-
-               if types[0].name not in classnames:
-                       text += key_tmp_name
-               else:
-                       if types[0].attr_type != attr_types.star:
-                               text += "*"
-                       text += key_tmp_name + "->get_cpp_obj()"
-               
-               text += ", "
-               if types[1].name not in classnames:
-                       text += val_tmp_name
-               else:
-                       if types[1].attr_type != attr_types.star:
-                               text += "*"
-                       text += val_tmp_name + "->get_cpp_obj()"
-               text += "));\n" + prefix + "}"
-               return text
-       
-       #Generate c++ code to translate to a boost::python::dict
-       @classmethod
-       def translate_cpp(c, varname, types, prefix, ref):
-               text  = prefix + c.typename + " " + varname + "___tmp;"
-               tmp_name = "tmp_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               if ref:
-                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
-               else:
-                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
-               text += prefix + "{"
-               if types[1].name in known_containers:
-                       text += prefix + "\tauto " + tmp_name + "_second = " + tmp_name + ".second;"
-                       text += known_containers[types[1].name].translate_cpp(tmp_name + "_second", types[1].cont.args, prefix + "\t", types[1].attr_type == attr_types.star)
-
-               if types[0].name in classnames:
-                       text += prefix + "\t" + varname + "___tmp[" + types[0].name + "::get_py_obj(" + tmp_name + ".first)] = "
-               elif types[0].name not in known_containers:
-                       text += prefix + "\t" + varname + "___tmp[" + tmp_name + ".first] = "
-
-               if types[1].name in classnames:
-                       if types[1].attr_type == attr_types.star:
-                               text += types[1].name + "::get_py_obj(" + tmp_name + ".second);"
-                       else:
-                               text += "*" + types[1].name + "::get_py_obj(&" + tmp_name + ".second);"
-               elif types[1].name in known_containers:
-                       text += tmp_name + "_second___tmp;"
-               else:
-                       text += tmp_name + ".second;"
-               text += prefix + "}"
-               return text
-
-#Sub-type for dict
-class DictTranslator(PythonDictTranslator):
-       insert_name = "insert"
-       orig_name = "dict"
-
-#Sub_type for std::map
-class MapTranslator(PythonDictTranslator):
-       insert_name = "insert"
-       orig_name = "std::map"  
-
-#Translator for std::pair. Derived from PythonDictTranslator because the
-#gen_type function is the same (because both have two template parameters)
-class TupleTranslator(PythonDictTranslator):
-       typename = "boost::python::tuple"
-       orig_name = "std::pair"
-
-       #Generate c++ code to translate from a boost::python::tuple
-       @classmethod
-       def translate(c, varname, types, prefix):
-               text  = prefix + types[0].name + " " + varname + "___tmp_0 = boost::python::extract<" + types[0].name + ">(" + varname + "[0]);"
-               text += prefix + types[1].name + " " + varname + "___tmp_1 = boost::python::extract<" + types[1].name + ">(" + varname + "[1]);"
-               text += prefix + TupleTranslator.gen_type(types) + " " + varname + "___tmp("
-               if types[0].name.split(" ")[-1] in primitive_types:
-                       text += varname + "___tmp_0, "
-               else:
-                       text += varname + "___tmp_0.get_cpp_obj(), "
-               if types[1].name.split(" ")[-1] in primitive_types:
-                       text += varname + "___tmp_1);"
-               else:
-                       text += varname + "___tmp_1.get_cpp_obj());"
-               return text
-
-       #Generate c++ code to translate to a boost::python::tuple
-       @classmethod
-       def translate_cpp(c, varname, types, prefix, ref):
-               text  = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + varname + ".first, " + varname + ".second);"
-               return text
-               tmp_name = "tmp_" + str(Translator.tmp_cntr)
-               Translator.tmp_cntr = Translator.tmp_cntr + 1
-               if ref:
-                       text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
-               else:
-                       text += prefix + "for(auto " + tmp_name + " : " + varname + ")"
-               text += prefix + "{"
-               if types[0].name.split(" ")[-1] in primitive_types or types[0].name in enum_names:
-                       text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");"
-               elif types[0].name in known_containers:
-                       text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[1].attr_type == attr_types.star)
-                       text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "___tmp);"
-               elif types[0].name in classnames:
-                       text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
-               text += prefix + "}"
-               return text
-
-#Associate the Translators with their c++ type
-known_containers = {
-       "std::set"              :       SetTranslator,
-       "std::vector"   :       VectorTranslator,
-       "pool"                  :       PoolTranslator,
-       "dict"                  :       DictTranslator,
-       "std::pair"             :       TupleTranslator,
-       "std::map"              :       MapTranslator
-}
-
-class Attribute:
-       wtype = None
-       varname = None
-       is_const = False
-       default_value = None
-       pos = None
-       pos_counter = 0
-
-       def __init__(self, wtype, varname, is_const = False, default_value = None):
-               self.wtype = wtype
-               self.varname = varname
-               self.is_const = is_const
-               self.default_value = None
-               self.container = None
-
-       @staticmethod
-       def from_string(str_def, containing_file, line_number):
-               if len(str_def) < 3:
-                       return None
-               orig = str_def
-               arg = Attribute(None, None)
-               prefix = ""
-               arg.wtype = None
-               arg.varname = None
-               arg.is_const = False
-               arg.default_value = None
-               arg.container = None
-               if str.startswith(str_def, "const "):
-                       arg.is_const = True
-                       str_def = str_def[6:]
-               if str.startswith(str_def, "unsigned "):
-                       prefix = "unsigned "
-                       str_def = str_def[9:]
-               while str.startswith(str_def, "long "):
-                       prefix= "long " + prefix
-                       str_def = str_def[5:]
-               while str.startswith(str_def, "short "):
-                       prefix = "short " + prefix
-                       str_def = str_def[6:]
-
-               if str_def.find("<") != -1 and str_def.find("<") < str_def.find(" "):
-                       closing = find_closing(str_def[str_def.find("<"):], "<", ">") + str_def.find("<") + 1
-                       arg.wtype = WType.from_string(str_def[:closing].strip(), containing_file, line_number)
-                       str_def = str_def[closing+1:]
-               else:
-                       if str_def.count(" ") > 0:
-                               arg.wtype = WType.from_string(prefix + str_def[:str_def.find(" ")].strip(), containing_file, line_number)
-                               str_def = str_def[str_def.find(" ")+1:]
-                       else:
-                               arg.wtype = WType.from_string(prefix + str_def.strip(), containing_file, line_number)
-                               str_def = ""
-                               arg.varname = ""
-
-               if arg.wtype == None:
-                       return None
-               if str_def.count("=") == 0:
-                       arg.varname = str_def.strip()
-                       if arg.varname.find(" ") > 0:
-                               return None
-               else:
-                       arg.varname = str_def[:str_def.find("=")].strip()
-                       if arg.varname.find(" ") > 0:
-                               return None
-                       str_def = str_def[str_def.find("=")+1:].strip()
-                       arg.default_value = str_def[arg.varname.find("=")+1:].strip()
-               if len(arg.varname) == 0:
-                       arg.varname = None
-                       return arg
-               if arg.varname[0] == '*':
-                       arg.wtype.attr_type = attr_types.star
-                       arg.varname = arg.varname[1:]
-               elif arg.varname[0] == '&':
-                       if arg.wtype.attr_type != attr_types.default:
-                               return None
-                       if arg.varname[1] == '&':
-                               arg.wtype.attr_type = attr_types.ampamp
-                               arg.varname = arg.varname[2:]
-                       else:
-                               arg.wtype.attr_type = attr_types.amp
-                               arg.varname = arg.varname[1:]
-               return arg
-
-       #Generates the varname. If the attribute has no name in the header file,
-       #a name is generated
-       def gen_varname(self):
-               if self.varname != None:
-                       return self.varname
-               if self.wtype.name == "void":
-                       return ""
-               if self.pos == None:
-                       self.pos = Attribute.pos_counter
-                       Attribute.pos_counter = Attribute.pos_counter + 1
-               return "gen_varname_" + str(self.pos)
-
-       #Generates the text for the function headers with wrapper types
-       def gen_listitem(self):
-               prefix = ""
-               if self.is_const:
-                       prefix = "const "
-               if self.wtype.name in classnames:
-                       return prefix + self.wtype.name + "* " + self.gen_varname()
-               if self.wtype.name in known_containers:
-                       return prefix + known_containers[self.wtype.name].typename + " " + self.gen_varname()
-               return prefix + self.wtype.name + " " + self.gen_varname()
-
-       #Generates the test for the function headers with c++ types
-       def gen_listitem_cpp(self):
-               prefix = ""
-               if self.is_const:
-                       prefix = "const "
-               infix = ""
-               if self.wtype.attr_type == attr_types.star:
-                       infix = "*"
-               elif self.wtype.attr_type == attr_types.amp:
-                       infix = "&"
-               elif self.wtype.attr_type == attr_types.ampamp:
-                       infix = "&&"
-               if self.wtype.name in known_containers:
-                       return prefix + known_containers[self.wtype.name].gen_type(self.wtype.cont.args) + " " + infix + self.gen_varname()
-               if self.wtype.name in classnames:
-                       return prefix + class_by_name(self.wtype.name).namespace + "::" + self.wtype.name + " " + infix + self.gen_varname()
-               return prefix + self.wtype.name + " " + infix + self.gen_varname()
-
-       #Generates the listitem withtout the varname, so the signature can be
-       #compared
-       def gen_listitem_hash(self):
-               prefix = ""
-               if self.is_const:
-                       prefix = "const "
-               if self.wtype.name in classnames:
-                       return prefix + self.wtype.name + "* "
-               if self.wtype.name in known_containers:
-                       return known_containers[self.wtype.name].typename
-               return prefix + self.wtype.name
-               
-       #Generate Translation code for the attribute
-       def gen_translation(self):
-               if self.wtype.name in known_containers:
-                       return known_containers[self.wtype.name].translate(self.gen_varname(), self.wtype.cont.args, "\n\t\t")
-               return ""
-
-       #Generate Translation code from c++ for the attribute
-       def gen_translation_cpp(self):
-               if self.wtype.name in known_containers:
-                       return known_containers[self.wtype.name].translate_cpp(self.gen_varname(), self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star)
-               return ""
-
-       #Generate Text for the call
-       def gen_call(self):
-               ret = self.gen_varname()
-               if self.wtype.name in known_containers:
-                       if self.wtype.attr_type == attr_types.star:
-                               return "&" + ret + "___tmp"
-                       return ret + "___tmp"
-               if self.wtype.name in classnames:
-                       if self.wtype.attr_type != attr_types.star:
-                               ret = "*" + ret
-                       return ret + "->get_cpp_obj()"
-               if self.wtype.name == "char *" and self.gen_varname() in ["format", "fmt"]:
-                       return "\"%s\", " + self.gen_varname()
-               if self.wtype.attr_type == attr_types.star:
-                       return "&" + ret
-               return ret
-
-       def gen_call_cpp(self):
-               ret = self.gen_varname()
-               if self.wtype.name.split(" ")[-1] in primitive_types or self.wtype.name in enum_names:
-                       if self.wtype.attr_type == attr_types.star:
-                               return "&" + ret
-                       return ret
-               if self.wtype.name not in classnames:
-                       if self.wtype.attr_type == attr_types.star:
-                               return "&" + ret + "___tmp"
-                       return ret + "___tmp"
-               if self.wtype.attr_type != attr_types.star:
-                       ret = "*" + ret
-               return self.wtype.name + "::get_py_obj(" + self.gen_varname()  + ")"
-
-       #Generate cleanup code
-       def gen_cleanup(self):
-               if self.wtype.name in primitive_types or self.wtype.name in classnames or self.wtype.name in enum_names or not self.wtype.attr_type == attr_types.star or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star):
-                       return ""
-               return "\n\t\tdelete " + self.gen_varname() + "___tmp;"
-
-class WClass:
-       name = None
-       namespace = None
-       link_type = None
-       id_ = None
-       string_id = None
-       hash_id = None
-       needs_clone = False
-       found_funs = []
-       found_vars = []
-       found_constrs = []
-
-       def __init__(self, name, link_type, id_, string_id = None, hash_id = None, needs_clone = False):
-               self.name = name
-               self.namespace = None
-               self.link_type = link_type
-               self.id_ = id_
-               self.string_id = string_id
-               self.hash_id = hash_id
-               self.needs_clone = needs_clone
-               self.found_funs = []
-               self.found_vars = []
-               self.found_constrs = []
-
-       def printable_constrs(self):
-               ret = 0
-               for con in self.found_constrs:
-                       if not con.protected:
-                               ret += 1
-               return ret
-
-       def gen_decl(self, filename):
-               long_name = self.namespace + "::" + self.name
-
-               text = "\n\t// WRAPPED from " + filename
-               text += "\n\tstruct " + self.name
-               if self.link_type == link_types.derive:
-                       text += " : public " + self.namespace + "::" + self.name
-               text += "\n\t{\n"
-
-               if self.link_type != link_types.derive:
-
-                       text += "\t\t" + long_name + "* ref_obj;\n"
-
-                       if self.link_type == link_types.ref_copy or self.link_type == link_types.pointer:
-                               text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{\n\t\t\treturn ref_obj;\n\t\t}\n"
-                       elif self.link_type == link_types.global_list:
-                               text += "\t\t" + self.id_.wtype.name + " " + self.id_.varname + ";\n"
-                               text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{"
-                               text += "\n\t\t\t" + long_name + "* ret = " + long_name + "::get_all_" + self.name.lower() + "s()->at(this->" + self.id_.varname + ");"
-                               text += "\n\t\t\tif(ret != NULL && ret == this->ref_obj)"
-                               text += "\n\t\t\t\treturn ret;"
-                               text += "\n\t\t\tthrow std::runtime_error(\"" + self.name + "'s c++ object does not exist anymore.\");"
-                               text += "\n\t\t\treturn NULL;"
-                               text += "\n\t\t}\n"
-
-                       #if self.link_type != link_types.pointer:
-                       text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{"
-                       text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));"
-                       if self.link_type == link_types.pointer:
-                               text += "\n\t\t\tret->ref_obj = ref;"
-                       if self.link_type == link_types.ref_copy:
-                               if self.needs_clone:
-                                       text += "\n\t\t\tret->ref_obj = ref->clone();"
-                               else:
-                                       text += "\n\t\t\tret->ref_obj = new "+long_name+"(*ref);"
-                       if self.link_type == link_types.global_list:
-                               text += "\n\t\t\tret->ref_obj = ref;"
-                               text += "\n\t\t\tret->" + self.id_.varname + " = ret->ref_obj->" + self.id_.varname + ";"
-                       text += "\n\t\t\treturn ret;"
-                       text += "\n\t\t}\n"
-
-                       if self.link_type == link_types.ref_copy:
-                               text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + " ref)\n\t\t{"
-                               text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));"
-                               if self.needs_clone:
-                                       text += "\n\t\t\tret->ref_obj = ref.clone();"
-                               else:
-                                       text += "\n\t\t\tret->ref_obj = new "+long_name+"(ref);"
-                               text += "\n\t\t\treturn ret;"
-                               text += "\n\t\t}\n"
-
-                       for con in self.found_constrs:
-                               text += con.gen_decl()
-                       for var in self.found_vars:
-                               text += var.gen_decl()
-                       for fun in self.found_funs:
-                               text += fun.gen_decl()
-
-
-               if self.link_type == link_types.derive:
-                       duplicates = {}
-                       for fun in self.found_funs:
-                               if fun.name in duplicates:
-                                       fun.gen_alias()
-                                       duplicates[fun.name].gen_alias()
-                               else:
-                                       duplicates[fun.name] = fun
-
-                       text += "\n\t\t" + long_name + "* get_cpp_obj() const\n\t\t{\n\t\t\treturn (" + self.namespace + "::" + self.name +"*)this;\n\t\t}\n"
-                       text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{"
-                       text += "\n\t\t\treturn (" + self.name + "*)ref;"
-                       text += "\n\t\t}\n"
-
-                       for con in self.found_constrs:
-                               text += con.gen_decl_derive()
-                       for var in self.found_vars:
-                               text += var.gen_decl()
-                       for fun in self.found_funs:
-                               text += fun.gen_decl_virtual()
-
-               if self.hash_id != None:
-                       text += "\n\t\tunsigned int get_hash_py()"
-                       text += "\n\t\t{"
-                       text += "\n\t\t\treturn get_cpp_obj()->" + self.hash_id + ";"
-                       text += "\n\t\t}"
-
-               text += "\n\t};\n"
-
-               if self.link_type == link_types.derive:
-                       text += "\n\tstruct " + self.name + "Wrap : " + self.name + ", boost::python::wrapper<" + self.name + ">"
-                       text += "\n\t{"
-
-                       for con in self.found_constrs:
-                               text += con.gen_decl_wrapperclass()
-                       for fun in self.found_funs:
-                               text += fun.gen_default_impl()
-
-                       text += "\n\t};"
-
-               text += "\n\tstd::ostream &operator<<(std::ostream &ostr, const " + self.name + " &ref)"
-               text += "\n\t{"
-               text += "\n\t\tostr << \"" + self.name
-               if self.string_id != None:
-                       text +=" \\\"\""
-                       text += " << ref.get_cpp_obj()->" + self.string_id
-                       text += " << \"\\\"\""
-               else:
-                       text += " at \" << ref.get_cpp_obj()"
-               text += ";"
-               text += "\n\t\treturn ostr;"
-               text += "\n\t}"
-               text += "\n"
-
-               return text
-
-       def gen_funs(self, filename):
-               text = ""
-               if self.link_type != link_types.derive:
-                       for con in self.found_constrs:
-                               text += con.gen_def()
-                       for var in self.found_vars:
-                               text += var.gen_def()
-                       for fun in self.found_funs:
-                               text += fun.gen_def()
-               else:
-                       for var in self.found_vars:
-                               text += var.gen_def()
-                       for fun in self.found_funs:
-                               text += fun.gen_def_virtual()
-               return text
-
-       def gen_boost_py(self):
-               text = "\n\t\tclass_<" + self.name
-               if self.link_type == link_types.derive:
-                       text += "Wrap, boost::noncopyable"
-               text += ">(\"" + self.name + "\""
-               if self.printable_constrs() == 0 or not self.contains_default_constr():
-                       text += ", no_init"
-               text += ")"
-               text += "\n\t\t\t.def(boost::python::self_ns::str(boost::python::self_ns::self))"
-               text += "\n\t\t\t.def(boost::python::self_ns::repr(boost::python::self_ns::self))"
-               for con in self.found_constrs:
-                       text += con.gen_boost_py()
-               for var in self.found_vars:
-                       text += var.gen_boost_py()
-               static_funs = []
-               for fun in self.found_funs:
-                       text += fun.gen_boost_py()
-                       if fun.is_static and fun.alias not in static_funs:
-                               static_funs.append(fun.alias)
-               for fun in static_funs:
-                       text += "\n\t\t\t.staticmethod(\"" + fun + "\")"
-
-               if self.hash_id != None:
-                       text += "\n\t\t\t.def(\"__hash__\", &" + self.name + "::get_hash_py)"
-               text += "\n\t\t\t;\n"
-               return text
-
-       def contains_default_constr(self):
-               for c in self.found_constrs:
-                       if len(c.args) == 0:
-                               return True
-               return False
-
-#CONFIGURE HEADER-FILES TO BE PARSED AND CLASSES EXPECTED IN THEM HERE
-
-sources = [
-       Source("kernel/celltypes",[
-               WClass("CellType", link_types.pointer, None, None, "type.hash()", True),
-               WClass("CellTypes", link_types.pointer, None, None, None, True)
-               ]
-               ),
-       Source("kernel/consteval",[
-               WClass("ConstEval", link_types.pointer, None, None, None, True)
-               ]
-               ),
-       Source("kernel/log",[]),
-       Source("kernel/register",[
-               WClass("Pass", link_types.derive, None, None, None, True),
-               ]
-               ),
-       Source("kernel/rtlil",[
-               WClass("IdString", link_types.ref_copy, None, "str()", "hash()"),
-               WClass("Const", link_types.ref_copy, None, "as_string()", "hash()"),
-               WClass("AttrObject", link_types.ref_copy, None, None, None),
-               WClass("Selection", link_types.ref_copy, None, None, None),
-               WClass("Monitor", link_types.derive, None, None, None),
-               WClass("CaseRule",link_types.ref_copy, None, None, None, True),
-               WClass("SwitchRule",link_types.ref_copy, None, None, None, True),
-               WClass("SyncRule", link_types.ref_copy, None, None, None, True),
-               WClass("Process",  link_types.ref_copy, None, "name.c_str()", "name.hash()"),
-               WClass("SigChunk", link_types.ref_copy, None, None, None),
-               WClass("SigBit", link_types.ref_copy, None, None, "hash()"),
-               WClass("SigSpec", link_types.ref_copy, None, None, "hash()"),
-               WClass("Cell", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
-               WClass("Wire", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
-               WClass("Memory", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
-               WClass("Module", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
-               WClass("Design", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "hashidx_", "hash()")
-               ]
-               ),
-       #Source("kernel/satgen",[
-       #       ]
-       #       ),
-       #Source("libs/ezsat/ezsat",[
-       #       ]
-       #       ),
-       #Source("libs/ezsat/ezminisat",[
-       #       ]
-       #       ),
-       Source("kernel/sigtools",[
-               WClass("SigMap", link_types.pointer, None, None, None, True)
-               ]
-               ),
-       Source("kernel/yosys",[
-               ]
-               ),
-       Source("kernel/cost",[])
-       ]
-
-blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Module::Pow", "YOSYS_NAMESPACE::Module::Bu0", "YOSYS_NAMESPACE::CaseRule::optimize"]
-
-enum_names = ["State","SyncType","ConstFlags"]
-
-enums = [] #Do not edit
-
-unowned_functions = []
-
-classnames = []
-for source in sources:
-       for wclass in source.classes:
-               classnames.append(wclass.name)
-
-def class_by_name(name):
-       for source in sources:
-               for wclass in source.classes:
-                       if wclass.name == name:
-                               return wclass
-       return None
-
-def enum_by_name(name):
-       for e in enums:
-               if e.name == name:
-                       return e
-       return None
-
-def find_closing(text, open_tok, close_tok):
-       if text.find(open_tok) == -1 or text.find(close_tok) <= text.find(open_tok):
-               return text.find(close_tok)
-       return text.find(close_tok) + find_closing(text[text.find(close_tok)+1:], open_tok, close_tok) + 1
-
-def unpretty_string(s):
-       s = s.strip()
-       while s.find("  ") != -1:
-               s = s.replace("  "," ")
-       while s.find("\t") != -1:
-               s = s.replace("\t"," ")
-       s = s.replace(" (","(")
-       return s
-
-class WEnum:
-       name = None
-       namespace = None
-       values = []
-
-       def from_string(str_def, namespace, line_number):
-               str_def = str_def.strip()
-               if not str.startswith(str_def, "enum "):
-                       return None
-               if str_def.count(";") != 1:
-                       return None
-               str_def = str_def[5:]
-               enum = WEnum()
-               split = str_def.split(":")
-               if(len(split) != 2):
-                       return None
-               enum.name = split[0].strip()
-               if enum.name not in enum_names:
-                       return None
-               str_def = split[1]
-               if str_def.count("{") != str_def.count("}") != 1:
-                       return None
-               if len(str_def) < str_def.find("}")+2 or str_def[str_def.find("}")+1] != ';':
-                       return None
-               str_def = str_def.split("{")[-1].split("}")[0]
-               enum.values = []
-               for val in str_def.split(','):
-                       enum.values.append(val.strip().split('=')[0].strip())
-               enum.namespace = namespace
-               return enum
-
-       def gen_boost_py(self):
-               text = "\n\t\tenum_<" + self.namespace + "::" + self.name + ">(\"" + self.name + "\")\n"
-               for value in self.values:
-                       text += "\t\t\t.value(\"" + value + "\"," + self.namespace + "::" + value + ")\n"
-               text += "\t\t\t;\n"
-               return text
-
-       def __str__(self):
-               ret = "Enum " + self.namespace + "::" + self.name + "(\n"
-               for val in self.values:
-                       ret = ret + "\t" + val + "\n"
-               return ret + ")"
-
-       def __repr__(self):
-               return __str__(self)
-
-class WConstructor:
-       orig_text = None
-       args = []
-       containing_file = None
-       member_of = None
-       duplicate = False
-       protected = False
-
-       def __init__(self, containing_file, class_):
-               self.orig_text = "Auto generated default constructor"
-               self.args = []
-               self.containing_file = containing_file
-               self.member_of = class_
-               self.protected = False
-
-       def from_string(str_def, containing_file, class_, line_number, protected = False):
-               if class_ == None:
-                       return None
-               if str_def.count("delete;") > 0:
-                       return None
-               con = WConstructor(containing_file, class_)
-               con.orig_text = str_def
-               con.args = []
-               con.duplicate = False
-               con.protected = protected
-               if not str.startswith(str_def, class_.name + "("):
-                       return None
-               str_def = str_def[len(class_.name)+1:]
-               found = find_closing(str_def, "(", ")")
-               if found == -1:
-                       return None
-               str_def = str_def[0:found].strip()
-               if len(str_def) == 0:
-                       return con
-               for arg in split_list(str_def, ","):
-                       parsed = Attribute.from_string(arg.strip(), containing_file, line_number)
-                       if parsed == None:
-                               return None
-                       con.args.append(parsed)
-               return con
-
-       def gen_decl(self):
-               if self.duplicate or self.protected:
-                       return ""
-               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t\t" + self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ");\n"
-               return text
-
-       def gen_decl_derive(self):
-               if self.duplicate or self.protected:
-                       return ""
-               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t\t" + self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ")"
-               if len(self.args) == 0:
-                       return text + "{}"
-               text += " : "
-               text += self.member_of.namespace + "::" + self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_call() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += "){}\n"
-               return text
-
-       def gen_decl_wrapperclass(self):
-               if self.duplicate or self.protected:
-                       return ""
-               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t\t" + self.member_of.name + "Wrap("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ")"
-               if len(self.args) == 0:
-                       return text + "{}"
-               text += " : "
-               text += self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_call() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += "){}\n"
-               return text
-
-       def gen_decl_hash_py(self):
-               text = self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem_hash() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ");"
-               return text
-
-       def gen_def(self):
-               if self.duplicate or self.protected:
-                       return ""
-               text = "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t" + self.member_of.name + "::" + self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text +=")\n\t{"
-               for arg in self.args:
-                       text += arg.gen_translation()
-               if self.member_of.link_type != link_types.derive:
-                       text += "\n\t\tthis->ref_obj = new " + self.member_of.namespace + "::" + self.member_of.name + "("
-               for arg in self.args:
-                       text += arg.gen_call() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               if self.member_of.link_type != link_types.derive:
-                       text += ");"
-               if self.member_of.link_type == link_types.global_list:
-                       text += "\n\t\tthis->" + self.member_of.id_.varname + " = this->ref_obj->" + self.member_of.id_.varname + ";"
-               for arg in self.args:
-                       text += arg.gen_cleanup()
-               text += "\n\t}\n"
-               return text
-
-       def gen_boost_py(self):
-               if self.duplicate or self.protected or len(self.args) == 0:
-                       return ""
-               text  = "\n\t\t\t.def(init"
-               text += "<"
-               for a in self.args:
-                       text += a.gen_listitem_hash() + ", "
-               text = text[0:-2] + ">())"
-               return text
-
-class WFunction:
-       orig_text = None
-       is_static = False
-       is_inline = False
-       is_virtual = False
-       ret_attr_type = attr_types.default
-       is_operator = False
-       ret_type = None
-       name = None
-       alias = None
-       args = []
-       containing_file = None
-       member_of = None
-       duplicate = False
-       namespace = ""
-
-       def from_string(str_def, containing_file, class_, line_number, namespace):
-               if str_def.count("delete;") > 0:
-                       return None
-               func = WFunction()
-               func.is_static = False
-               func.is_inline = False
-               func.is_virtual = False
-               func.ret_attr_type = attr_types.default
-               func.is_operator = False
-               func.member_of = None
-               func.orig_text = str_def
-               func.args = []
-               func.containing_file = containing_file
-               func.member_of = class_
-               func.duplicate = False
-               func.namespace = namespace
-               str_def = str_def.replace("operator ","operator")
-               if str.startswith(str_def, "static "):
-                       func.is_static = True
-                       str_def = str_def[7:]
-               else:
-                       func.is_static = False
-               if str.startswith(str_def, "inline "):
-                       func.is_inline = True
-                       str_def = str_def[7:]
-               else:
-                       func.is_inline = False
-               if str.startswith(str_def, "virtual "):
-                       func.is_virtual = True
-                       str_def = str_def[8:]
-               else:
-                       func.is_virtual = False
-
-               if str_def.count(" ") == 0:
-                       return None
-
-               parts = split_list(str_def.strip(), " ")
-
-               prefix = ""
-               i = 0
-               for part in parts:
-                       if part in ["unsigned", "long", "short"]:
-                               prefix += part + " "
-                               i += 1
-                       else:
-                               break
-               parts = parts[i:]
-
-               if len(parts) <= 1:
-                       return None
-
-               func.ret_type = WType.from_string(prefix + parts[0], containing_file, line_number)
-
-               if func.ret_type == None:
-                       return None
-
-               str_def = parts[1]
-               for part in parts[2:]:
-                       str_def = str_def + " " + part
-
-               found = str_def.find("(")
-               if found == -1 or (str_def.find(" ") != -1 and found > str_def.find(" ")):
-                       return None
-               func.name = str_def[:found]
-               str_def = str_def[found:]
-               if func.name.find("operator") != -1 and str.startswith(str_def, "()("):
-                               func.name += "()"
-                               str_def = str_def[2:]
-               str_def = str_def[1:]
-               if func.name.find("operator") != -1:
-                       func.is_operator = True
-               if func.name.find("*") == 0:
-                       func.name = func.name.replace("*", "")
-                       func.ret_type.attr_type = attr_types.star
-               if func.name.find("&&") == 0:
-                       func.name = func.name.replace("&&", "")
-                       func.ret_type.attr_type = attr_types.ampamp
-               if func.name.find("&") == 0:
-                       func.name = func.name.replace("&", "")
-                       func.ret_type.attr_type = attr_types.amp
-
-               found = find_closing(str_def, "(", ")")
-               if found == -1:
-                       return None
-               str_def = str_def[0:found]
-               if func.name in blacklist_methods:
-                       return None
-               if func.namespace != None and func.namespace != "":
-                       if (func.namespace + "::" + func.name) in blacklist_methods:
-                               return None
-                       if func.member_of != None:
-                               if (func.namespace + "::" + func.member_of.name + "::" + func.name) in blacklist_methods:
-                                       return None
-               if func.is_operator and func.name.replace(" ","").replace("operator","").split("::")[-1] not in wrappable_operators:
-                       return None
-
-               testname = func.name
-               if func.is_operator:
-                       testname = testname[:testname.find("operator")]
-               if testname.count(")") != 0 or testname.count("(") != 0 or testname.count("~") != 0 or testname.count(";") != 0 or testname.count(">") != 0 or testname.count("<") != 0 or testname.count("throw") != 0:
-                       return None
-
-               func.alias = func.name
-               if func.name in keyword_aliases:
-                       func.alias = keyword_aliases[func.name]
-               str_def = str_def[:found].strip()
-               if(len(str_def) == 0):
-                       return func
-               for arg in split_list(str_def, ","):
-                       if arg.strip() == "...":
-                               continue
-                       parsed = Attribute.from_string(arg.strip(), containing_file, line_number)
-                       if parsed == None:
-                               return None
-                       func.args.append(parsed)
-               return func
-
-       def gen_alias(self):
-               self.alias = self.name
-               for arg in self.args:
-                       self.alias += "__" + arg.wtype.gen_text_cpp().replace("::", "_").replace("<","_").replace(">","_").replace(" ","").replace("*","").replace(",","")
-
-       def gen_decl(self):
-               if self.duplicate:
-                       return ""
-               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t\t"
-               if self.is_static:
-                       text += "static "
-               text += self.ret_type.gen_text() + " " + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem()
-                       text += ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ");\n"
-               return text
-
-       def gen_decl_virtual(self):
-               if self.duplicate:
-                       return ""
-               if not self.is_virtual:
-                       return self.gen_decl()
-               text =  "\n\t\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t\tvirtual "
-               if self.is_static:
-                       text += "static "
-               text += self.ret_type.gen_text() + " py_" + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem()
-                       text += ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ")"
-               if len(self.args) == 0:
-                       text += "{}"
-               else:
-                       text += "\n\t\t{"
-                       for arg in self.args:
-                               text += "\n\t\t\t(void)" + arg.gen_varname() + ";"
-                       text += "\n\t\t}\n"
-               text += "\n\t\tvirtual "
-               if self.is_static:
-                       text += "static "
-               text += self.ret_type.gen_text() + " " + self.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem_cpp()
-                       text += ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ") YS_OVERRIDE;\n"
-               return text
-
-       def gen_decl_hash_py(self):
-               text = self.ret_type.gen_text() + " " + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem_hash() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ");"
-               return text
-
-       def gen_def(self):
-               if self.duplicate:
-                       return ""
-               text  = "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t" + self.ret_type.gen_text() + " "
-               if self.member_of != None:
-                       text += self.member_of.name + "::"
-               text += self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem()
-                       text += ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text +=")\n\t{"
-               for arg in self.args:
-                       text += arg.gen_translation()
-               text += "\n\t\t"
-               if self.ret_type.name != "void":
-                       if self.ret_type.name in known_containers:
-                               text += self.ret_type.gen_text_cpp()
-                       else:
-                               text += self.ret_type.gen_text()
-                       if self.ret_type.name in classnames or (self.ret_type.name in known_containers and self.ret_type.attr_type == attr_types.star):
-                               text += "*"
-                       text += " ret_ = "
-                       if self.ret_type.name in classnames:
-                               text += self.ret_type.name + "::get_py_obj("
-               if self.member_of == None:
-                       text += "::" + self.namespace + "::" + self.alias + "("
-               elif self.is_static:
-                       text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "("
-               else:
-                       text += "this->get_cpp_obj()->" + self.name + "("
-               for arg in self.args:
-                       text += arg.gen_call() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               if self.ret_type.name in classnames:
-                       text += ")"
-               text += ");"
-               for arg in self.args:
-                       text += arg.gen_cleanup()
-               if self.ret_type.name != "void":
-                       if self.ret_type.name in classnames:
-                               text += "\n\t\treturn *ret_;"
-                       elif self.ret_type.name in known_containers:
-                               text += known_containers[self.ret_type.name].translate_cpp("ret_", self.ret_type.cont.args, "\n\t\t", self.ret_type.attr_type == attr_types.star)
-                               text += "\n\t\treturn ret____tmp;"
-                       else:
-                               text += "\n\t\treturn ret_;"
-               text += "\n\t}\n"
-               return text
-
-       def gen_def_virtual(self):
-               if self.duplicate:
-                       return ""
-               if not self.is_virtual:
-                       return self.gen_def()
-               text =  "\n\t// WRAPPED from \"" + self.orig_text.replace("\n"," ") + "\" in " + self.containing_file
-               text += "\n\t"
-               if self.is_static:
-                       text += "static "
-               text += self.ret_type.gen_text() + " " + self.member_of.name + "::" + self.name + "("
-               for arg in self.args:
-                       text += arg.gen_listitem_cpp()
-                       text += ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ")\n\t{"
-               for arg in self.args:
-                       text += arg.gen_translation_cpp()
-               text += "\n\t\t"
-               if self.member_of == None:
-                       text += "::" + self.namespace + "::" + self.alias + "("
-               elif self.is_static:
-                       text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "("
-               else:
-                       text += "py_" + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_call_cpp() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               if self.ret_type.name in classnames:
-                       text += ")"
-               text += ");"
-               for arg in self.args:
-                       text += arg.gen_cleanup()
-               text += "\n\t}\n"
-               return text
-
-       def gen_default_impl(self):
-               if self.duplicate:
-                       return ""
-               if not self.is_virtual:
-                       return ""
-               text = "\n\n\t\t" + self.ret_type.gen_text() + " py_" + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-
-               call_string = "py_" + self.alias + "("
-               for arg in self.args:
-                       call_string += arg.gen_varname() + ", "
-               if len(self.args) > 0:
-                       call_string = call_string[0:-2]
-               call_string += ");"
-
-               text += ")\n\t\t{"
-               text += "\n\t\t\tif(boost::python::override py_" + self.alias + " = this->get_override(\"py_" + self.alias + "\"))"
-               text += "\n\t\t\t\t" + call_string
-               text += "\n\t\t\telse"
-               text += "\n\t\t\t\t" + self.member_of.name + "::" + call_string
-               text += "\n\t\t}"
-
-               text += "\n\n\t\t" + self.ret_type.gen_text() + " default_py_" + self.alias + "("
-               for arg in self.args:
-                       text += arg.gen_listitem() + ", "
-               if len(self.args) > 0:
-                       text = text[:-2]
-               text += ")\n\t\t{"
-               text += "\n\t\t\tthis->" + self.member_of.name + "::" + call_string
-               text += "\n\t\t}"
-               return text
-
-
-       def gen_boost_py(self):
-               if self.duplicate:
-                       return ""
-               if self.member_of == None:
-                       text = "\n\t\tdef"
-               else:
-                       text = "\n\t\t\t.def"
-               if len(self.args) > -1:
-                       if self.ret_type.name in known_containers:
-                               text += "<" + known_containers[self.ret_type.name].typename + " "
-                       else:
-                               text += "<" + self.ret_type.name + " "
-                       if self.member_of == None or self.is_static:
-                               text += "(*)("
-                       else:
-                               text += "(" + self.member_of.name + "::*)("
-                       for a in self.args:
-                               text += a.gen_listitem_hash() + ", "
-                       if len(self.args) > 0:
-                               text = text[0:-2] + ")>"
-                       else:
-                               text += "void)>"
-
-               if self.is_operator:
-                       text += "(\"" + wrappable_operators[self.name.replace("operator","")] + "\""
-               else:
-                       if self.member_of != None and self.member_of.link_type == link_types.derive and self.is_virtual:
-                               text += "(\"py_" + self.alias + "\""
-                       else:
-                               text += "(\"" + self.alias + "\""
-               if self.member_of != None:
-                       text += ", &" + self.member_of.name + "::"
-                       if self.member_of.link_type == link_types.derive and self.is_virtual:
-                               text += "py_" + self.alias
-                               text += ", &" + self.member_of.name + "Wrap::default_py_" + self.alias
-                       else:
-                               text += self.alias
-
-                       text += ")"
-               else:
-                       text += ", " + "YOSYS_PYTHON::" + self.alias + ");"
-               return text
-
-class WMember:
-       orig_text = None
-       wtype = attr_types.default
-       name = None
-       containing_file = None
-       member_of = None
-       namespace = ""
-       is_const = False
-
-       def from_string(str_def, containing_file, class_, line_number, namespace):
-               member = WMember()
-               member.orig_text = str_def
-               member.wtype = None
-               member.name = ""
-               member.containing_file = containing_file
-               member.member_of = class_
-               member.namespace = namespace
-               member.is_const = False
-
-               if str.startswith(str_def, "const "):
-                       member.is_const = True
-                       str_def = str_def[6:]
-
-               if str_def.count(" ") == 0:
-                       return None
-
-               parts = split_list(str_def.strip(), " ")
-
-               prefix = ""
-               i = 0
-               for part in parts:
-                       if part in ["unsigned", "long", "short"]:
-                               prefix += part + " "
-                               i += 1
-                       else:
-                               break
-               parts = parts[i:]
-
-               if len(parts) <= 1:
-                       return None
-
-               member.wtype = WType.from_string(prefix + parts[0], containing_file, line_number)
-
-               if member.wtype == None:
-                       return None
-
-               str_def = parts[1]
-               for part in parts[2:]:
-                       str_def = str_def + " " + part
-
-               if str_def.find("(") != -1 or str_def.find(")") != -1 or str_def.find("{") != -1 or str_def.find("}") != -1:
-                       return None
-
-               found = str_def.find(";")
-               if found == -1:
-                       return None
-
-               found_eq = str_def.find("=")
-               if found_eq != -1:
-                       found = found_eq
-
-               member.name = str_def[:found]
-               str_def = str_def[found+1:]
-               if member.name.find("*") == 0:
-                       member.name = member.name.replace("*", "")
-                       member.wtype.attr_type = attr_types.star
-               if member.name.find("&&") == 0:
-                       member.name = member.name.replace("&&", "")
-                       member.wtype.attr_type = attr_types.ampamp
-               if member.name.find("&") == 0:
-                       member.name = member.name.replace("&", "")
-                       member.wtype.attr_type = attr_types.amp
-
-               if(len(str_def.strip()) != 0):
-                       return None
-
-               if len(member.name.split(",")) > 1:
-                       member_list = []
-                       for name in member.name.split(","):
-                               name = name.strip();
-                               member_list.append(WMember())
-                               member_list[-1].orig_text = member.orig_text
-                               member_list[-1].wtype = member.wtype
-                               member_list[-1].name = name
-                               member_list[-1].containing_file = member.containing_file
-                               member_list[-1].member_of = member.member_of
-                               member_list[-1].namespace = member.namespace
-                               member_list[-1].is_const = member.is_const
-                       return member_list
-
-               return member
-
-       def gen_decl(self):
-               text = "\n\t\t" + self.wtype.gen_text() + " get_var_py_" + self.name + "();\n"
-               if self.is_const:
-                       return text
-               if self.wtype.name in classnames:
-                       text += "\n\t\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs);\n"
-               else:
-                       text += "\n\t\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs);\n"
-               return text
-
-       def gen_def(self):
-               text = "\n\t" + self.wtype.gen_text() + " " + self.member_of.name +"::get_var_py_" + self.name + "()"
-               text += "\n\t{\n\t\t"
-               if self.wtype.attr_type == attr_types.star:
-                       text += "if(this->get_cpp_obj()->" + self.name + " == NULL)\n\t\t\t"
-                       text += "throw std::runtime_error(\"Member \\\"" + self.name + "\\\" is NULL\");\n\t\t"
-               if self.wtype.name in known_containers:
-                       text += self.wtype.gen_text_cpp()
-               else:
-                       text += self.wtype.gen_text()
-
-               if self.wtype.name in classnames or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star):
-                       text += "*"
-               text += " ret_ = "
-               if self.wtype.name in classnames:
-                       text += self.wtype.name + "::get_py_obj("
-                       if self.wtype.attr_type != attr_types.star:
-                               text += "&"
-               text += "this->get_cpp_obj()->" + self.name
-               if self.wtype.name in classnames:
-                       text += ")"
-               text += ";"
-               
-               if self.wtype.name in classnames:
-                       text += "\n\t\treturn *ret_;"
-               elif self.wtype.name in known_containers:
-                       text += known_containers[self.wtype.name].translate_cpp("ret_", self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star)
-                       text += "\n\t\treturn ret____tmp;"
-               else:
-                       text += "\n\t\treturn ret_;"
-               text += "\n\t}\n"
-
-               if self.is_const:
-                       return text
-
-               ret = Attribute(self.wtype, "rhs");
-
-               if self.wtype.name in classnames:
-                       text += "\n\tvoid " + self.member_of.name+ "::set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs)"
-               else:
-                       text += "\n\tvoid " + self.member_of.name+ "::set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs)"
-               text += "\n\t{"
-               text += ret.gen_translation()
-               text += "\n\t\tthis->get_cpp_obj()->" + self.name + " = " + ret.gen_call() + ";"
-               text += "\n\t}\n"               
-
-               return text;
-
-       def gen_boost_py(self):
-               text = "\n\t\t\t.add_property(\"" + self.name + "\", &" + self.member_of.name + "::get_var_py_" + self.name 
-               if not self.is_const:
-                       text += ", &" + self.member_of.name + "::set_var_py_" + self.name
-               text += ")"
-               return text
-
-def concat_namespace(tuple_list):
-       if len(tuple_list) == 0:
-               return ""
-       ret = ""
-       for namespace in tuple_list:
-               ret += "::" + namespace[0]
-       return ret[2:]
-
-def calc_ident(text):
-       if len(text) == 0 or text[0] != ' ':
-               return 0
-       return calc_ident(text[1:]) + 1
-
-def assure_length(text, length, left = False):
-       if len(text) > length:
-               return text[:length]
-       if left:
-               return text + " "*(length - len(text))
-       return " "*(length - len(text)) + text
-       
-def parse_header(source):
-       debug("Parsing " + source.name + ".pyh",1)
-       source_file = open(source.name + ".pyh", "r")
-
-       source_text = []
-       in_line = source_file.readline()
-
-       namespaces = []
-
-       while(in_line):
-               if(len(in_line)>1):
-                       source_text.append(in_line.replace("char *", "char_p ").replace("char* ", "char_p "))
-               in_line = source_file.readline()
-
-       i = 0
-
-       namespaces = []
-       class_ = None
-       private_segment = False
-
-       while i < len(source_text):
-               line = source_text[i].replace("YOSYS_NAMESPACE_BEGIN", "                    namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END","                    }")
-               ugly_line = unpretty_string(line)
-
-               if str.startswith(ugly_line, "namespace "):# and ugly_line.find("std") == -1 and ugly_line.find("__") == -1:
-                       namespace_name = ugly_line[10:].replace("{","").strip()
-                       namespaces.append((namespace_name, ugly_line.count("{")))
-                       debug("-----NAMESPACE " + concat_namespace(namespaces) + "-----",3)
-                       i += 1
-                       continue
-
-               if len(namespaces) != 0:
-                       namespaces[-1] = (namespaces[-1][0], namespaces[-1][1] + ugly_line.count("{") - ugly_line.count("}"))
-                       if namespaces[-1][1] == 0:
-                               debug("-----END NAMESPACE " + concat_namespace(namespaces) + "-----",3)
-                               del namespaces[-1]
-                               i += 1
-                               continue
-
-               if class_ == None and (str.startswith(ugly_line, "struct ") or str.startswith(ugly_line, "class")) and ugly_line.count(";") == 0:
-
-                       struct_name = ugly_line.split(" ")[1].split("::")[-1]
-                       impl_namespaces = ugly_line.split(" ")[1].split("::")[:-1]
-                       complete_namespace = concat_namespace(namespaces)
-                       for namespace in impl_namespaces:
-                               complete_namespace += "::" + namespace
-                       debug("\tFound " + struct_name + " in " + complete_namespace,2)
-                       class_ = (class_by_name(struct_name), ugly_line.count("{"))#calc_ident(line))
-                       if struct_name in classnames:
-                               class_[0].namespace = complete_namespace
-                       i += 1
-                       continue
-
-               if class_ != None:
-                       class_ = (class_[0], class_[1] + ugly_line.count("{") - ugly_line.count("}"))
-                       if class_[1] == 0:
-                               if class_[0] == None:
-                                       debug("\tExiting unknown class", 3)
-                               else:
-                                       debug("\tExiting class " + class_[0].name, 3)
-                               class_ = None
-                               private_segment = False
-                               i += 1
-                               continue
-
-               if class_ != None and (line.find("private:") != -1 or line.find("protected:") != -1):
-                       private_segment = True
-                       i += 1
-                       continue
-               if class_ != None and line.find("public:") != -1:
-                       private_segment = False
-                       i += 1
-                       continue
-
-               candidate = None
-
-               if private_segment and class_ != None and class_[0] != None:
-                       candidate = WConstructor.from_string(ugly_line, source.name, class_[0], i, True)
-                       if candidate != None:
-                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
-                               class_[0].found_constrs.append(candidate)
-                               i += 1
-                               continue
-
-               if not private_segment and (class_ == None or class_[0] != None):
-                       if class_ != None:
-                               candidate = WFunction.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
-                       else:
-                               candidate = WFunction.from_string(ugly_line, source.name, None, i, concat_namespace(namespaces))
-                       if candidate != None and candidate.name.find("::") == -1:
-                               if class_ == None:
-                                       debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
-                                       unowned_functions.append(candidate)
-                               else:
-                                       debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
-                                       class_[0].found_funs.append(candidate)
-                       else:
-                               candidate = WEnum.from_string(ugly_line, concat_namespace(namespaces), i)
-                               if candidate != None:
-                                       enums.append(candidate)
-                                       debug("\tFound enum \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
-                               elif class_ != None and class_[1] == 1:
-                                       candidate = WConstructor.from_string(ugly_line, source.name, class_[0], i)
-                                       if candidate != None:
-                                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
-                                               class_[0].found_constrs.append(candidate)
-                                       else:
-                                               candidate = WMember.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
-                                               if candidate != None:
-                                                       if type(candidate) == list:
-                                                               for c in candidate:
-                                                                       debug("\t\tFound member \"" + c.name + "\" of class \"" + class_[0].name + "\" of type \"" + c.wtype.name + "\"", 2)
-                                                               class_[0].found_vars.extend(candidate)
-                                                       else:
-                                                               debug("\t\tFound member \"" + candidate.name + "\" of class \"" + class_[0].name + "\" of type \"" + candidate.wtype.name + "\"", 2)
-                                                               class_[0].found_vars.append(candidate)
-
-                       j = i
-                       line = unpretty_string(line)
-                       while candidate == None and j+1 < len(source_text) and  line.count(';') <= 1 and line.count("(") >= line.count(")"):
-                               j += 1
-                               line = line + "\n" + unpretty_string(source_text[j])
-                               if class_ != None:
-                                       candidate = WFunction.from_string(ugly_line, source.name, class_[0], i, concat_namespace(namespaces))
-                               else:
-                                       candidate = WFunction.from_string(ugly_line, source.name, None, i, concat_namespace(namespaces))
-                               if candidate != None and candidate.name.find("::") == -1:
-                                       if class_ == None:
-                                               debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
-                                               unowned_functions.append(candidate)
-                                       else:
-                                               debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
-                                               class_[0].found_funs.append(candidate)
-                                       continue
-                               candidate = WEnum.from_string(line, concat_namespace(namespaces), i)
-                               if candidate != None:
-                                       enums.append(candidate)
-                                       debug("\tFound enum \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
-                                       continue
-                               if class_ != None:
-                                       candidate = WConstructor.from_string(line, source.name, class_[0], i)
-                                       if candidate != None:
-                                               debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
-                                               class_[0].found_constrs.append(candidate)
-                                               continue
-               if candidate != None:
-                       while i < j:
-                               i += 1
-                               line = source_text[i].replace("YOSYS_NAMESPACE_BEGIN", "                    namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END","                    }")
-                               ugly_line = unpretty_string(line)
-                               if len(namespaces) != 0:
-                                       namespaces[-1] = (namespaces[-1][0], namespaces[-1][1] + ugly_line.count("{") - ugly_line.count("}"))
-                                       if namespaces[-1][1] == 0:
-                                               debug("-----END NAMESPACE " + concat_namespace(namespaces) + "-----",3)
-                                               del namespaces[-1]
-                               if class_ != None:
-                                       class_ = (class_[0] , class_[1] + ugly_line.count("{") - ugly_line.count("}"))
-                                       if class_[1] == 0:
-                                               if class_[0] == None:
-                                                       debug("\tExiting unknown class", 3)
-                                               else:
-                                                       debug("\tExiting class " + class_[0].name, 3)
-                                               class_ = None
-                                               private_segment = False
-                       i += 1
-               else:
-                       i += 1
-
-def debug(message, level):
-       if level <= debug.debug_level:
-               print(message)
-
-def expand_function(f):
-       fun_list = []
-       arg_list = []
-       for arg in f.args:
-               if arg.default_value != None and (arg.wtype.name.split(" ")[-1] in primitive_types or arg.wtype.name in enum_names or (arg.wtype.name in classnames and arg.default_value == "nullptr")):
-                       fi = copy.deepcopy(f)
-                       fi.args = copy.deepcopy(arg_list)
-                       fun_list.append(fi)
-               arg_list.append(arg)
-       fun_list.append(f)
-       return fun_list
-
-def expand_functions():
-       global unowned_functions
-       new_funs = []
-       for fun in unowned_functions:
-               new_funs.extend(expand_function(fun))
-       unowned_functions = new_funs
-       for source in sources:
-               for class_ in source.classes:
-                       new_funs = []
-                       for fun in class_.found_funs:
-                               new_funs.extend(expand_function(fun))
-                       class_.found_funs = new_funs
-
-def clean_duplicates():
-       for source in sources:
-               for class_ in source.classes:
-                       known_decls = {}
-                       for fun in class_.found_funs:
-                               if fun.gen_decl_hash_py() in known_decls:
-                                       debug("Multiple declarations of " + fun.gen_decl_hash_py(),3)
-                                       other = known_decls[fun.gen_decl_hash_py()]
-                                       other.gen_alias()
-                                       fun.gen_alias()
-                                       if fun.gen_decl_hash_py() == other.gen_decl_hash_py():
-                                               fun.duplicate = True
-                                               debug("Disabled \"" + fun.gen_decl_hash_py() + "\"", 3)
-                               else:
-                                       known_decls[fun.gen_decl_hash_py()] = fun
-                       known_decls = []
-                       for con in class_.found_constrs:
-                               if con.gen_decl_hash_py() in known_decls:
-                                       debug("Multiple declarations of " + con.gen_decl_hash_py(),3)
-                                       con.duplicate = True
-                               else:
-                                       known_decls.append(con.gen_decl_hash_py())
-       known_decls = []
-       for fun in unowned_functions:
-               if fun.gen_decl_hash_py() in known_decls:
-                       debug("Multiple declarations of " + fun.gen_decl_hash_py(),3)
-                       fun.duplicate = True
-               else:
-                       known_decls.append(fun.gen_decl_hash_py())
-
-def gen_wrappers(filename, debug_level_ = 0):
-       debug.debug_level = debug_level_
-       for source in sources:
-               parse_header(source)
-
-       expand_functions()
-       clean_duplicates()
-
-       import shutil
-       import math
-       col = shutil.get_terminal_size((80,20)).columns
-       debug("-"*col, 1)
-       debug("-"*math.floor((col-7)/2)+"SUMMARY"+"-"*math.ceil((col-7)/2), 1)
-       debug("-"*col, 1)
-       for source in sources:
-               for class_ in source.classes:
-                       debug("Class " + assure_length(class_.name, len(max(classnames, key=len)), True) + " contains " + assure_length(str(len(class_.found_vars)), 3, False) + " member variables, "+ assure_length(str(len(class_.found_funs)), 3, False) + " methods and " + assure_length(str(len(class_.found_constrs)), 2, False) + " constructors", 1)
-                       if len(class_.found_constrs) == 0:
-                               class_.found_constrs.append(WConstructor(source.name, class_))
-       debug(str(len(unowned_functions)) + " functions are unowned", 1)
-       for enum in enums:
-               debug("Enum " + assure_length(enum.name, len(max(enum_names, key=len)), True) + " contains " + assure_length(str(len(enum.values)), 2, False) + " values", 1)
-       debug("-"*col, 1)
-       wrapper_file = open(filename, "w+")
-       wrapper_file.write(
-"""/*
- *  yosys -- Yosys Open SYnthesis Suite
- *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *
- *  Permission to use, copy, modify, and/or distribute this software for any
- *  purpose with or without fee is hereby granted, provided that the above
- *  copyright notice and this permission notice appear in all copies.
- *
- *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- *  This is a generated file and can be overwritten by make
- */
-
-#ifdef WITH_PYTHON
-""")
-       for source in sources:
-               wrapper_file.write("#include \""+source.name+".h\"\n")
-       wrapper_file.write("""
-#include <boost/python/module.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/wrapper.hpp>
-#include <boost/python/call.hpp>
-#include <boost/python.hpp>
-#include <boost/log/exceptions.hpp>
-
-USING_YOSYS_NAMESPACE
-
-namespace YOSYS_PYTHON {
-""")
-
-       for source in sources:
-               for wclass in source.classes:
-                       wrapper_file.write("\n\tstruct " + wclass.name + ";")
-
-       wrapper_file.write("\n")
-
-       for source in sources:
-               for wclass in source.classes:
-                       wrapper_file.write(wclass.gen_decl(source.name))
-
-       wrapper_file.write("\n")
-
-       for source in sources:
-               for wclass in source.classes:
-                       wrapper_file.write(wclass.gen_funs(source.name))
-
-       for fun in unowned_functions:
-               wrapper_file.write(fun.gen_def())
-
-       wrapper_file.write("""  struct Initializer
-       {
-               Initializer() {
-                       if(!Yosys::yosys_already_setup())
-                       {
-                               Yosys::log_streams.push_back(&std::cout);
-                               Yosys::log_error_stderr = true;
-                               Yosys::yosys_setup();
-                               Yosys::yosys_banner();
-                       }
-               }
-
-               Initializer(Initializer const &) {}
-
-               ~Initializer() {
-                       Yosys::yosys_shutdown();
-               }
-       };
-
-       BOOST_PYTHON_MODULE(libyosys)
-       {
-               using namespace boost::python;
-
-               class_<Initializer>("Initializer");
-               scope().attr("_hidden") = new Initializer();
-""")
-
-       for enum in enums:
-               wrapper_file.write(enum.gen_boost_py())
-
-       for source in sources:
-               for wclass in source.classes:
-                       wrapper_file.write(wclass.gen_boost_py())
-
-       for fun in unowned_functions:
-               wrapper_file.write(fun.gen_boost_py())
-
-       wrapper_file.write("\n\t}\n}\n#endif")
-
-def print_includes():
-       for source in sources:
-               print(source.name + ".pyh")