Exemple #1
0
 def __init__(self, env):
     self.env = env
     self.writer = CppWriter()
     self.declaration_keys = []
     self.names = {}
     self.ids = set()
     self.included_filenames = set()
Exemple #2
0
class CppBuilder(object):

    def __init__(self, env):
        self.env = env
        self.writer = CppWriter()
        self.declaration_keys = []
        self.names = {}
        self.ids = set()
        self.included_filenames = set()

    def get_name(self, obj):
        name = self.names.get(obj)
        if name is not None:
            return name
        obj_name = obj.name
        name = self.new_id(obj_name)
        self.names[obj] = name
        return name

    def include_filename(self, filename):
        if filename in self.included_filenames:
            return
        self.included_filenames.add(filename)
        self.writer.line("#include \"{}\"", filename)

    def get_used_variables(self, exprs, args):
        variables = frozenset()
        for expr in exprs:
            variables = variables.union(expr.get_variables())
        prev = frozenset()
        while prev != variables:
            prev = variables
            for v in variables:
                a = args.get(v)
                if a is None:
                    raise QitException("Unbound variable '{}'".format(v))
                variables = variables.union(a.get_variables())
        return variables

    def build_collect(self, exprs, args):
        variables = self.get_used_variables(exprs, args)
        validate_variables(variables)
        deps = { v: args[v].get_variables() for v in variables }
        variables = sort_by_deps(deps)

        write_functions = [ expr.type.write_function for expr in exprs ]
        self.write_header()
        for v in variables:
            args[v].declare_all(self)
        for expr in exprs:
            expr.declare_all(self)
        for f in write_functions:
            f.declare_all(self)
        self.main_begin()
        self.init_fifo()
        self.init_variables(variables, args)
        for expr, f in zip(exprs, write_functions):
            self.writer.line(
                 "{}(output, {});", f.build(self), expr.build(self))
        self.writer.line("fclose(output);")
        self.main_end()

    def write_expression_into_variable(self, expr):
        variable = self.new_id()
        self.writer.line("{} {} = {};",
                         expr.type.build(self),
                         variable,
                         expr.build(self))
        return variable

    def build_object(self, type, args):
        args = ",".join(a.build(self) for a in args)
        return "{}({})".format(type.build(self), args)

    def write_iterator_write_method(self):
        self.writer.line("QIT_ITERATOR_WRITE_METHOD")

    def make_sequence_from_iterator(self, iterator):
        result_variable = self.new_id("result")
        self.writer.line("{} {};",
                         iterator.output_type.build(self),
                         result_variable)
        iterator_variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.writer.line("while ({}.next({}))", iterator_variable, element)
        self.writer.block_begin()
        self.writer.line("{}.push_back({});", result_variable, element)
        self.writer.block_end()
        return result_variable

    def make_element_from_iterator(self, iterator):
        iterator_variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.writer.line("assert({}.next({}));", iterator_variable, element)
        return element

    def init_fifo(self):
        self.writer.line("assert(argc > 1);")
        self.writer.line("FILE *output = fopen(argv[1], \"w\");")

    def init_variables(self, variables, args):
        for variable in variables:
            value = args[variable]
            self.writer.line("{} {}({});",
                             variable.type.build(self),
                             variable.build(self),
                             value.build(self))

    def write_header(self):
        self.writer.line("/*")
        self.writer.line("       QIT generated file")
        self.writer.line("*/")
        self.writer.emptyline()
        self.writer.line("#include <vector>")
        self.writer.line("#include <deque>")
        self.writer.line("#include <set>")
        self.writer.line("#include <map>")
        self.writer.line("#include <iostream>")
        self.writer.line("#include <assert.h>")
        self.writer.line("#include <stdlib.h>")
        self.writer.line("#include <time.h>")
        self.writer.line("#include <functional>")
        self.writer.line("#include <algorithm>")
        self.writer.line("#include <random>")
        self.writer.emptyline()
        self.writer.line("std::default_random_engine QIT_GENERATOR(time(nullptr));")
        self.writer.line("typedef int32_t qint;")
        self.writer.emptyline()
        self.writer.emptyline()

    def main_begin(self):
        self.writer.line("int main(int argc, char **argv)")
        self.writer.block_begin()
        self.writer.line("srand(time(NULL));")

    def main_end(self):
        self.writer.line("return 0;")
        self.writer.block_end();

    def new_id(self, name):
        prefix = "q_" + name
        s = ""
        while prefix[-1].isdigit():
            s += prefix[-1]
            prefix = str(prefix[:-1])
        if s:
            suffix = int(s) + 1
        else:
            suffix = 1

        name = prefix + str(suffix)
        while name in self.ids:
            suffix += 1
            name = prefix + str(suffix)
        self.ids.add(name)
        return name

    ## Method for multiple dispatch of base classes

    def check_declaration_key(self, key):
        if key in self.declaration_keys:
            return True
        self.declaration_keys.append(key)
        self.writer.line("/* Declaration: {} */", key)
        return False

    # Struct

    def declare_struct(self, struct):
        if self.check_declaration_key(struct):
            return
        struct_type = struct.build(self)
        self.writer.class_begin(struct_type)
        self.writer.line("public:")

        ## Attributes
        for name, t in zip(struct.names, struct.types):
            self.writer.line("{} {};",
                             t.build(self),
                             name)

        if struct.names:
            params = ",".join(t.build_param(self, name)
                            for t, name in zip(struct.types, struct.names))

            consts = ": " + ",".join("{0}({0})".format(name)
                            for name in struct.names)
            self.writer.line("{}({}) {} {{}}", struct_type, params, consts)
        self.writer.line("{}() {{}}", struct_type)

        # Operator <
        self.writer.line("bool operator <(const {} &other) const", struct_type)
        self.writer.block_begin()
        for name in struct.names:
            self.writer.if_begin("{0} < other.{0}", name)
            self.writer.line("return true;")
            self.writer.block_end()
            self.writer.if_begin("{0} == other.{0}", name)
        for name in struct.names:
            self.writer.block_end()
        self.writer.line("return false;")
        self.writer.block_end()

        # Operator ==
        self.writer.line("bool operator ==(const {} &other) const", struct_type)
        self.writer.block_begin()
        if struct.names:
            self.writer.line("return {};",
                             " && ".join("({0} == other.{0})".format(name)
                                 for name in struct.names))
        else:
            self.writer.line("return true;")
        self.writer.block_end()
        self.writer.class_end()

    # Function

    def build_function_call(self, function_call):
        function = self.build_function(function_call.function)
        args = ",".join(e.build(self) for e in function_call.args)
        return "{}({})".format(function, args)

    def build_function(self, function, prefix=""):
        function_name = self.get_name(function)
        variables = sorted_variables(function.get_variables())
        if variables:
            v = ",".join(prefix + v.build(self) for v in variables)
            return "({}({}))".format(function_name, v)
        else:
            return "{}".format(function_name)

    def declare_function(self, function):
        if self.check_declaration_key(function):
            return

        function_name = self.get_name(function)
        variables = function.get_variables()

        if function.is_external():
            self.include_filename(self.env.get_function_filename(function))

        if not variables:
            decl = function.build_declaration(self, function_name)
            self.writer.line("{}", decl)
            self.writer.block_begin()
            function.write_code(self)
            self.writer.block_end()
            self.writer.emptyline()
            return
        variables = sorted_variables(variables)

        self.writer.class_begin(function_name)
        self.writer.line("public:")
        variables = sorted_variables(variables)
        self.writer.line("{}({}) : {} {{}}",
                         function_name,
                         ",".join("const {} &{}".format(v.type.build(self),
                                                  v.build(self))
                                  for v in variables),
                         ",".join("{0}({0})".format(v.build(self))
                                  for v in variables))
        self.writer.line("{}", function.build_declaration(self, "operator()"))
        self.writer.block_begin()
        function.write_code(self)
        self.writer.block_end()

        for variable in variables:
            self.writer.line("const {} &{};",
                             variable.type.build(self),
                             variable.build(self));

        self.writer.class_end()
        self.writer.emptyline()

    def write_return_expression(self, expression):
        self.writer.line("return {};", expression.build(self))

    def write_code(self, inline_code, inline_code_vars):
        if isinstance(inline_code_vars, dict):
            inline_code_vars = tuple(inline_code_vars.items())
        d = {}
        for name, obj in inline_code_vars:
            if name.startswith("_"):
                d[name] = obj
            else:
                d[name] = obj.build(self)
        template = jinja2.Template(inline_code)
        template.globals.update(b=lambda obj: obj.build(self))
        template.globals["_builder"] = self
        self.writer.text(template.render(d))

    def write_function_external_call(self, function):
        call = ""

        if function.return_type is not None:
            call += "return "

        call += function.name + "("
        call += ", ".join([param.name for param in function.params])  # param names

        self.writer.line(call + ");")

    def get_function_declaration(self, function):
        args = ", ".join(p.type.build_param(self, p.name, p.const)
                         for p in function.params)
        if function.return_type is not None:
            return_type = function.return_type.build(self)
        else:
            return_type = "void"
        return "{} {}({})".format(return_type, function.name, args)
Exemple #3
0
class CppBuilder(object):

    def __init__(self):
        self.writer = CppWriter()
        self.id_counter = 100
        self.declaration_keys = []
        self.autonames = []

    def get_autoname(self, key, prefix):
        for k, name in self.autonames:
            if key == k:
                return name
        name = self.new_id(prefix)
        self.autonames.append((key, name))
        return name

    def build_print_all(self, iterator):
        self.write_header()
        iterator.declare(self)
        self.main_begin()
        variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.writer.line("while ({}.next({}))", variable, element)
        self.writer.block_begin()
        self.writer.line("std::cout << {} << std::endl;", element)
        self.writer.block_end()
        self.main_end()

    def build_collect(self, iterator):
        self.write_header()
        iterator.declare(self)
        self.main_begin()
        variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.init_fifo()
        self.writer.line("while ({}.next({}))", variable, element)
        self.writer.block_begin()
        self.writer.line("qit::write(output, {});", element)
        self.writer.block_end()
        self.main_end()

    def init_fifo(self):
        self.writer.line("assert(argc > 1);")
        self.writer.line("FILE *output = fopen(argv[1], \"w\");")

    def write_header(self):
        self.writer.line("/*")
        self.writer.line("       QIT generated file")
        self.writer.line("*/")
        self.writer.emptyline()
        self.writer.line("#include <assert.h>")
        self.writer.line("#include <iostream>")
        self.writer.line("#include <qit.h>")
        self.writer.line("#include <stdlib.h>")
        self.writer.line("#include <time.h>")
        self.writer.emptyline()

    def main_begin(self):
        self.writer.line("int main(int argc, char **argv)")
        self.writer.block_begin()
        self.writer.line("srand(time(NULL));")

    def main_end(self):
        self.writer.line("return 0;")
        self.writer.block_end();

    def new_id(self, prefix="v"):
        self.id_counter += 1
        return "{}{}".format(prefix, self.id_counter)

    def make_element(self, basic_type):
        variable = self.new_id()
        self.writer.line("{} {};",
                         basic_type.get_element_type(self),
                         variable)
        return variable

    ## Method for multiple dispatch of base classes

    def get_generator_iterator(self, transformation):
        return "qit::GeneratorIterator<{} >" \
                .format(transformation.generator.get_generator_type(self))

    def make_basic_iterator(self, iterator, iterators=(), args=()):
        return self.make_iterator(iterator,
                                  tuple(c.make_iterator(self)
                                     for c in iterators) + args)

    def make_iterator(self, iterator, args):
        variable = self.new_id("i")
        self.writer.line("{} {}({});",
                         iterator.get_iterator_type(self),
                         variable,
                         ",".join(args))
        return variable

    def make_basic_generator(self, iterator, iterators=(), args=()):
        return self.make_generator(iterator,
                                  tuple(c.make_generator(self)
                                     for c in iterators) + args)

    def make_generator(self, iterator, args):
        variable = self.new_id("g");
        self.writer.line("{} {}({});",
                         iterator.get_generator_type(self),
                         variable,
                         ",".join(args))
        return variable


    def check_declaration_key(self, key):
        if key in self.declaration_keys:
            return True
        self.declaration_keys.append(key)
        self.writer.line("/* Declaration: {} */", key)
        return False

    # Int

    def get_int_type(self):
        return "int"

    # Range

    def get_range_iterator(self):
        return "qit::RangeIterator"

    def get_range_generator(self):
        return "qit::RangeGenerator"

    # Take

    def get_take_iterator(self, take):
        return "qit::TakeIterator<{} >" \
                .format(take.parent_iterator.get_iterator_type(self))

    # Map

    def get_map_iterator(self, map):
        return "qit::MapIterator<{}, {}, {} >" \
                .format(map.parent_iterator.get_iterator_type(self),
                        map.function.return_type.get_element_type(self),
                        map.function.name)


    # Product

    def get_product_type(self, product):
        if product.basic_type.name is None:
            return self.get_autoname(product.basic_type, "Product")
        else:
            return product.name

    def get_product_iterator(self, iterator):
        type_name = self.get_product_type(iterator.output_type)
        return self.get_autoname(iterator, type_name + "Iterator")

    def get_product_generator(self, generator):
        type_name = self.get_product_type(generator.output_type)
        return self.get_autoname(generator, type_name + "Generator")

    def declare_product_class(self, product):
        if self.check_declaration_key((product, "class")):
            return
        product_type = self.get_product_type(product)
        self.writer.class_begin(product_type)
        self.writer.line("public:")

        ## Constructor
        for name, t in zip(product.names, product.types):
            self.writer.line("{} {};",
                             t.basic_type.get_element_type(self),
                             name)

        # Write
        self.writer.line("void write(FILE *f)")
        self.writer.block_begin()
        for name in product.names:
            self.writer.line("qit::write(f, {});", name)
        self.writer.block_end()

        self.writer.class_end()

        ## Stream
        self.writer.line("std::ostream& operator<<(std::ostream& os, const {}& v)",
                  product_type)
        self.writer.block_begin()
        self.writer.line("os << \"{{\";")
        for i, name in enumerate(product.names):
            if i != 0:
                self.writer.line("os << \",\";")
            self.writer.line("os << v.{};", name)
        self.writer.line("return os << \"}}\";")
        self.writer.block_end()


    def declare_product_iterator(self, iterator):
        if self.check_declaration_key((iterator, "iterator")):
            return

        product = iterator.output_type
        iterator_type = iterator.get_iterator_type(self)
        element_type = product.get_element_type(self)

        self.writer.class_begin(iterator_type)
        self.writer.line("public:")
        self.writer.line("typedef {} value_type;", element_type)

        names_iterators = list(zip(product.names, iterator.iterators))

        # Attributes
        for name, i in names_iterators:
            self.writer.line("{} {};",
                             i.get_iterator_type(self),
                             name)
        self.writer.line("bool _inited;")

        # Contructor
        args = [ "{} &{}".format(i.get_iterator_type(self), name)
                 for name, i in names_iterators ]
        constructors = [ "{0}({0})".format(name) for name in product.names ]
        constructors.append("_inited(false)")
        self.writer.line("{}({}) {} {}",
                         iterator_type,
                         ",".join(args),
                         ":" if constructors else "",
                         ",".join(constructors))
        self.writer.block_begin()
        self.writer.block_end()

        # Next
        self.writer.line("bool next({} &v)", element_type)
        self.writer.block_begin()
        self.writer.if_begin("_inited")
        for i, name in enumerate(product.names):
            self.writer.if_begin("{0}.next(v.{0})", name)
            self.writer.line("return true;")
            self.writer.block_end()
            if i != len(product.names) - 1:
                self.writer.line("{}.reset();", name)
                self.writer.line("{0}.next(v.{0});", name)
        self.writer.line("return false;")
        self.writer.else_begin()
        for name in product.names:
            self.writer.if_begin("!{0}.next(v.{0})", name)
            self.writer.line("return false;")
            self.writer.block_end()
        self.writer.line("_inited = true;")
        self.writer.line("return true;")
        self.writer.block_end()
        self.writer.block_end()

        # Reset
        self.writer.line("void reset()")
        self.writer.block_begin()
        self.writer.line("_inited = false;")
        for name in product.names:
            self.writer.line("{}.reset();", name)

        self.writer.block_end()

        self.writer.class_end()


    def declare_product_generator(self, generator):
        if self.check_declaration_key((generator, "generator")):
            return

        product = generator.output_type
        generator_type = generator.get_generator_type(self)
        element_type = product.get_element_type(self)
        self.writer.class_begin(generator_type)
        self.writer.line("public:")
        self.writer.line("typedef {} value_type;", element_type)

        # Attributes
        names_generators = list(zip(product.names, generator.generators))
        for name, generator in names_generators:
            self.writer.line("{} {};",
                             generator.get_generator_type(self),
                             name)

        # Contructor
        args = [ "{} &{}".format(generator.get_generator_type(self), name)
                 for name, generator in names_generators ]
        constructors = [ "{0}({0})".format(name) for name in product.names ]
        self.writer.line("{}({}) {} {}",
                         generator_type,
                         ",".join(args),
                         ":" if constructors else "",
                         ",".join(constructors))
        self.writer.block_begin()
        self.writer.block_end()

        # Next
        self.writer.line("void generate({} &v)", element_type)
        self.writer.block_begin()
        for name in product.names:
            self.writer.line("{0}.generate(v.{0});", name)
        self.writer.block_end()

        self.writer.class_end()

    # Sequences

    def get_sequence_iterator(self, iterator):
        return "qit::SequenceIterator<{} >".format(
            iterator.element_iterator.get_iterator_type(self))

    def get_sequence_generator(self, iterator):
        return "qit::SequenceGenerator<{} >".format(
            iterator.element_generator.get_generator_type(self))

    def get_sequence_type(self, sequence):
        return "std::vector<{} >".format(
            sequence.element_type.get_element_type(self))

    # Function

    def declare_function(self, function):
        self.writer.class_begin(function.name)
        self.writer.line("public:")
        params = [ "const {} &{}".format(c.get_element_type(self), name)
                   for c, name in function.params ]
        self.writer.line("{} operator()({})",
                         function.return_type.get_element_type(self),
                         ",".join(params))
        self.writer.block_begin()
        self.writer.text(function.inline_code)
        self.writer.block_end()

        self.writer.class_end()
Exemple #4
0
 def __init__(self):
     self.writer = CppWriter()
     self.id_counter = 100
     self.declaration_keys = []
     self.autonames = []
Exemple #5
0
class CppBuilder(object):

    def __init__(self, env):
        self.env = env
        self.writer = CppWriter()
        self.id_counter = 100
        self.declaration_keys = []
        self.autonames = {}
        self.included_filenames = set()

    def get_autoname(self, obj):
        name = self.autonames.get(obj)
        if name is not None:
            return name
        name = self.new_id(obj.autoname_prefix)
        self.autonames[obj] = name
        return name

    def include_filename(self, filename):
        if filename in self.included_filenames:
            return
        self.included_filenames.add(filename)
        self.writer.line("#include \"{}\"", filename)

    def build_collect(self, obj, args):
        write_function = obj.type.write_function
        self.write_header()
        obj.declare_all(self)
        write_function.declare_all(self)
        self.main_begin()
        self.init_fifo()
        self.init_variables(args)
        self.writer.line(
             "{}(output, {});", write_function.build(self), obj.build(self))
        self.writer.line("fclose(output);")
        self.main_end()

    def write_expression_into_variable(self, expr):
        variable = self.new_id()
        self.writer.line("{} {} = {};",
                         expr.type.build(self),
                         variable,
                         expr.build(self))
        return variable

    def build_object(self, type, args):
        args = ",".join(a.build(self) for a in args)
        return "{}({})".format(type.build(self), args)

    def write_iterator_write_method(self):
        self.writer.line("QIT_ITERATOR_WRITE_METHOD")

    def make_sequence_from_iterator(self, iterator):
        result_variable = self.new_id("result")
        self.writer.line("{} {};",
                         iterator.output_type.build(self),
                         result_variable)
        iterator_variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.writer.line("while ({}.next({}))", iterator_variable, element)
        self.writer.block_begin()
        self.writer.line("{}.push_back({});", result_variable, element)
        self.writer.block_end()
        return result_variable

    def make_element_from_iterator(self, iterator):
        iterator_variable = iterator.make_iterator(self)
        element = self.make_element(iterator.output_type.basic_type)
        self.writer.line("assert({}.next({}));", iterator_variable, element)
        return element

    def init_fifo(self):
        self.writer.line("assert(argc > 1);")
        self.writer.line("FILE *output = fopen(argv[1], \"w\");")

    def init_variables(self, args):
        for variable, value in sorted(args.items(), key=lambda v: v[0].name):
            self.writer.line("{} {}({});",
                             variable.type.build(self),
                             variable.name,
                             value.build(self))

    def write_header(self):
        self.writer.line("/*")
        self.writer.line("       QIT generated file")
        self.writer.line("*/")
        self.writer.emptyline()
        self.writer.line("#include <vector>")
        self.writer.line("#include <set>")
        self.writer.line("#include <map>")
        self.writer.line("#include <iostream>")
        self.writer.line("#include <assert.h>")
        self.writer.line("#include <stdlib.h>")
        self.writer.line("#include <time.h>")
        self.writer.line("#include <algorithm>")
        self.writer.line("#include <random>")
        self.writer.emptyline()
        self.writer.line("std::default_random_engine QIT_GENERATOR(time(nullptr));")
        self.writer.line("typedef int32_t qint;")
        self.writer.emptyline()
        self.writer.emptyline()

    def main_begin(self):
        self.writer.line("int main(int argc, char **argv)")
        self.writer.block_begin()
        self.writer.line("srand(time(NULL));")

    def main_end(self):
        self.writer.line("return 0;")
        self.writer.block_end();

    def new_id(self, prefix="v"):
        self.id_counter += 1
        return "{}{}".format(prefix, self.id_counter)

    ## Method for multiple dispatch of base classes

    def check_declaration_key(self, key):
        if key in self.declaration_keys:
            return True
        self.declaration_keys.append(key)
        self.writer.line("/* Declaration: {} */", key)
        return False

    # Struct

    def declare_struct(self, struct):
        if self.check_declaration_key(struct):
            return
        struct_type = struct.build(self)
        self.writer.class_begin(struct_type)
        self.writer.line("public:")

        ## Attributes
        for name, t in zip(struct.names, struct.types):
            self.writer.line("{} {};",
                             t.build(self),
                             name)

        if struct.names:
            params = ",".join(t.build_param(self, name)
                            for t, name in zip(struct.types, struct.names))

            consts = ": " + ",".join("{0}({0})".format(name)
                            for name in struct.names)
            self.writer.line("{}({}) {} {{}}", struct_type, params, consts)
        self.writer.line("{}() {{}}", struct_type)

        # Operator <
        self.writer.line("bool operator <(const {} &other) const", struct_type)
        self.writer.block_begin()
        for name in struct.names:
            self.writer.if_begin("{0} < other.{0}", name)
            self.writer.line("return true;")
            self.writer.block_end()
            self.writer.if_begin("{0} == other.{0}", name)
        for name in struct.names:
            self.writer.block_end()
        self.writer.line("return false;")
        self.writer.block_end()

        # Operator ==
        self.writer.line("bool operator ==(const {} &other) const", struct_type)
        self.writer.block_begin()
        if struct.names:
            self.writer.line("return {};",
                             " && ".join("({0} == other.{0})".format(name)
                                 for name in struct.names))
        else:
            self.writer.line("return true;")
        self.writer.block_end()
        self.writer.class_end()

    # Function

    def build_function_call(self, function_call):
        functor = self.build_functor(function_call.function)
        args = ",".join(e.build(self) for e in function_call.args)
        return "{}({})".format(functor, args)

    def build_functor(self, function):
        function_name = self.get_autoname(function)
        variables = sorted_variables(function.get_variables())
        if variables:
            v = ",".join(v.build(self) for v in variables)
            return "({}({}))".format(function_name, v)
        else:
            return "{}()".format(function_name)

    def declare_function(self, function):
        if self.check_declaration_key(function):
            return

        if function.is_external():
            self.include_filename(self.env.get_function_filename(function))

        function_name = self.get_autoname(function)
        self.writer.class_begin(function_name)
        self.writer.line("public:")

        variables = function.get_variables()
        if variables:
            variables = sorted_variables(variables)
            self.writer.line("{}({}) : {} {{}}",
                             function_name,
                             ",".join("const {} &{}".format(v.type.build(self),
                                                      v.name)
                                      for v in variables),
                             ",".join("{0}({0})".format(v.name)
                                      for v in variables))

        params = [ p.type.build_param(self, p.name, p.const)
                   for p in function.params ]
        self.writer.line("{} operator()({})",
                         function.return_type.build(self)
                             if function.return_type else "void",
                         ",".join(params))
        self.writer.block_begin()
        function.write_code(self)
        self.writer.block_end()

        for variable in variables:
            self.writer.line("const {} &{};",
                             variable.type.build(self),
                             variable.name);

        self.writer.class_end()

    def write_return_expression(self, expression):
        self.writer.line("return {};", expression.build(self))

    def write_function_inline_code(self, inline_code, inline_code_vars):
        d = {}
        for name, obj in inline_code_vars:
            if name.startswith("_"):
                d[name] = obj
            else:
                d[name] = obj.build(self)
        template = jinja2.Template(inline_code)
        template.globals.update(b=lambda obj: obj.build(self))
        self.writer.text(template.render(d))

    def write_function_external_call(self, function):
        call = ""

        if function.return_type is not None:
            call += "return "

        call += function.name + "("
        call += ", ".join([param.name for param in function.params])  # param names

        self.writer.line(call + ");")

    def get_function_declaration(self, function):
        args = ", ".join(p.type.build_param(self, p.name, p.const)
                         for p in function.params)
        if function.return_type is not None:
            return_type = function.return_type.build(self)
        else:
            return_type = "void"
        return "{} {}({})".format(return_type, function.name, args)