mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			963 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			963 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# This file contains code that is common to
 | 
						|
# both the Python build system and the CMake
 | 
						|
# build system.
 | 
						|
#
 | 
						|
# The code here generally is involved in
 | 
						|
# generating files needed by Z3 at build time.
 | 
						|
#
 | 
						|
# You should **not** import ``mk_util`` here
 | 
						|
# to avoid having this code depend on the
 | 
						|
# of the Python build system.
 | 
						|
import io
 | 
						|
import os
 | 
						|
import pprint
 | 
						|
import logging
 | 
						|
import re
 | 
						|
import sys
 | 
						|
 | 
						|
# Logger for this module
 | 
						|
_logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Utility functions
 | 
						|
###############################################################################
 | 
						|
def check_dir_exists(output_dir):
 | 
						|
    """
 | 
						|
        Returns ``True`` if ``output_dir`` exists, otherwise
 | 
						|
        returns ``False``.
 | 
						|
    """
 | 
						|
    if not os.path.isdir(output_dir):
 | 
						|
        _logger.error('"{}" is not an existing directory'.format(output_dir))
 | 
						|
        return False
 | 
						|
    return True
 | 
						|
 | 
						|
def check_files_exist(files):
 | 
						|
    assert isinstance(files, list)
 | 
						|
    for f in files:
 | 
						|
        if not os.path.exists(f):
 | 
						|
            _logger.error('"{}" does not exist'.format(f))
 | 
						|
            return False
 | 
						|
    return True
 | 
						|
 | 
						|
def sorted_headers_by_component(l):
 | 
						|
    """
 | 
						|
      Take a list of header files and sort them by the
 | 
						|
      path after ``src/``. E.g. for ``src/ast/fpa/fpa2bv_converter.h`` the sorting
 | 
						|
      key is ``ast/fpa/fpa2bv_converter.h``.
 | 
						|
 | 
						|
      The sort is done this way because for the CMake build
 | 
						|
      there are two directories for every component (e.g.
 | 
						|
      ``<src_dir>/src/ast/fpa`` and ``<build_dir>/src/ast/fpa``).
 | 
						|
      We don't want to sort based on different ``<src_dir>``
 | 
						|
      and ``<build_dir>`` prefixes so that we can match the Python build
 | 
						|
      system's behaviour.
 | 
						|
    """
 | 
						|
    assert isinstance(l, list)
 | 
						|
    def get_key(path):
 | 
						|
        _logger.debug("get_key({})".format(path))
 | 
						|
        path_components = []
 | 
						|
        stripped_path = path
 | 
						|
        assert 'src' in stripped_path.split(os.path.sep) or 'src' in stripped_path.split('/')
 | 
						|
        # Keep stripping off directory components until we hit ``src``
 | 
						|
        while os.path.basename(stripped_path) != 'src':
 | 
						|
            path_components.append(os.path.basename(stripped_path))
 | 
						|
            stripped_path = os.path.dirname(stripped_path)
 | 
						|
        assert len(path_components) > 0
 | 
						|
        path_components.reverse()
 | 
						|
        # For consistency across platforms use ``/`` rather than ``os.sep``.
 | 
						|
        # This is a sorting key so it doesn't need to a platform suitable
 | 
						|
        # path
 | 
						|
        r = '/'.join(path_components)
 | 
						|
        _logger.debug("return key:'{}'".format(r))
 | 
						|
        return r
 | 
						|
    sorted_headers = sorted(l, key=get_key)
 | 
						|
    _logger.debug('sorted headers:{}'.format(pprint.pformat(sorted_headers)))
 | 
						|
    return sorted_headers
 | 
						|
 | 
						|
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions for generating constant declarations for language bindings
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def mk_z3consts_py_internal(api_files, output_dir):
 | 
						|
    """
 | 
						|
        Generate ``z3consts.py`` from the list of API header files
 | 
						|
        in ``api_files`` and write the output file into
 | 
						|
        the ``output_dir`` directory
 | 
						|
 | 
						|
        Returns the path to the generated file.
 | 
						|
    """
 | 
						|
    assert os.path.isdir(output_dir)
 | 
						|
    assert isinstance(api_files, list)
 | 
						|
 | 
						|
    blank_pat      = re.compile("^ *\r?$")
 | 
						|
    comment_pat    = re.compile("^ *//.*$")
 | 
						|
    typedef_pat    = re.compile("typedef enum *")
 | 
						|
    typedef2_pat   = re.compile("typedef enum { *")
 | 
						|
    openbrace_pat  = re.compile("{ *")
 | 
						|
    closebrace_pat = re.compile("}.*;")
 | 
						|
 | 
						|
    z3consts  = open(os.path.join(output_dir, 'z3', 'z3consts.py'), 'w')
 | 
						|
    z3consts_output_path = z3consts.name
 | 
						|
    z3consts.write('# Automatically generated file\n\n')
 | 
						|
    for api_file in api_files:
 | 
						|
        api = open(api_file, 'r')
 | 
						|
 | 
						|
        SEARCHING  = 0
 | 
						|
        FOUND_ENUM = 1
 | 
						|
        IN_ENUM    = 2
 | 
						|
 | 
						|
        mode    = SEARCHING
 | 
						|
        decls   = {}
 | 
						|
        idx     = 0
 | 
						|
 | 
						|
        linenum = 1
 | 
						|
        for line in api:
 | 
						|
            m1 = blank_pat.match(line)
 | 
						|
            m2 = comment_pat.match(line)
 | 
						|
            if m1 or m2:
 | 
						|
                # skip blank lines and comments
 | 
						|
                linenum = linenum + 1
 | 
						|
            elif mode == SEARCHING:
 | 
						|
                m = typedef_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = FOUND_ENUM
 | 
						|
                m = typedef2_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
            elif mode == FOUND_ENUM:
 | 
						|
                m = openbrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode  = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
                else:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
            else:
 | 
						|
                assert mode == IN_ENUM
 | 
						|
                words = re.split('[^-a-zA-Z0-9_]+', line)
 | 
						|
                m = closebrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    name = words[1]
 | 
						|
                    z3consts.write('# enum %s\n' % name)
 | 
						|
                    # Iterate over key-value pairs ordered by value
 | 
						|
                    for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
 | 
						|
                        z3consts.write('%s = %s\n' % (k, v))
 | 
						|
                    z3consts.write('\n')
 | 
						|
                    mode = SEARCHING
 | 
						|
                elif len(words) <= 2:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
                else:
 | 
						|
                    if words[2] != '':
 | 
						|
                        if len(words[2]) > 1 and words[2][1] == 'x':
 | 
						|
                            idx = int(words[2], 16)
 | 
						|
                        else:
 | 
						|
                            idx = int(words[2])
 | 
						|
                    decls[words[1]] = idx
 | 
						|
                    idx = idx + 1
 | 
						|
            linenum = linenum + 1
 | 
						|
        api.close()
 | 
						|
    z3consts.close()
 | 
						|
    return z3consts_output_path
 | 
						|
 | 
						|
def mk_z3consts_dotnet_internal(api_files, output_dir):
 | 
						|
    """
 | 
						|
        Generate ``Enumerations.cs`` from the list of API header files
 | 
						|
        in ``api_files`` and write the output file into
 | 
						|
        the ``output_dir`` directory
 | 
						|
 | 
						|
        Returns the path to the generated file.
 | 
						|
    """
 | 
						|
    assert os.path.isdir(output_dir)
 | 
						|
    assert isinstance(api_files, list)
 | 
						|
    blank_pat      = re.compile("^ *\r?$")
 | 
						|
    comment_pat    = re.compile("^ *//.*$")
 | 
						|
    typedef_pat    = re.compile("typedef enum *")
 | 
						|
    typedef2_pat   = re.compile("typedef enum { *")
 | 
						|
    openbrace_pat  = re.compile("{ *")
 | 
						|
    closebrace_pat = re.compile("}.*;")
 | 
						|
 | 
						|
    DeprecatedEnums = [ 'Z3_search_failure' ]
 | 
						|
    z3consts  = open(os.path.join(output_dir, 'Enumerations.cs'), 'w')
 | 
						|
    z3consts_output_path = z3consts.name
 | 
						|
    z3consts.write('// Automatically generated file\n\n')
 | 
						|
    z3consts.write('using System;\n\n'
 | 
						|
                   '#pragma warning disable 1591\n\n'
 | 
						|
                   'namespace Microsoft.Z3\n'
 | 
						|
                   '{\n')
 | 
						|
 | 
						|
    for api_file in api_files:
 | 
						|
        api = open(api_file, 'r')
 | 
						|
 | 
						|
        SEARCHING  = 0
 | 
						|
        FOUND_ENUM = 1
 | 
						|
        IN_ENUM    = 2
 | 
						|
 | 
						|
        mode    = SEARCHING
 | 
						|
        decls   = {}
 | 
						|
        idx     = 0
 | 
						|
 | 
						|
        linenum = 1
 | 
						|
        for line in api:
 | 
						|
            m1 = blank_pat.match(line)
 | 
						|
            m2 = comment_pat.match(line)
 | 
						|
            if m1 or m2:
 | 
						|
                # skip blank lines and comments
 | 
						|
                linenum = linenum + 1
 | 
						|
            elif mode == SEARCHING:
 | 
						|
                m = typedef_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = FOUND_ENUM
 | 
						|
                m = typedef2_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
            elif mode == FOUND_ENUM:
 | 
						|
                m = openbrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode  = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
                else:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
            else:
 | 
						|
                assert mode == IN_ENUM
 | 
						|
                words = re.split('[^-a-zA-Z0-9_]+', line)
 | 
						|
                m = closebrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    name = words[1]
 | 
						|
                    if name not in DeprecatedEnums:
 | 
						|
                        z3consts.write('  /// <summary>%s</summary>\n' % name)
 | 
						|
                        z3consts.write('  public enum %s {\n' % name)
 | 
						|
                        z3consts.write
 | 
						|
                        # Iterate over key-value pairs ordered by value
 | 
						|
                        for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
 | 
						|
                            z3consts.write('  %s = %s,\n' % (k, v))
 | 
						|
                        z3consts.write('  }\n\n')
 | 
						|
                    mode = SEARCHING
 | 
						|
                elif len(words) <= 2:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
                else:
 | 
						|
                    if words[2] != '':
 | 
						|
                        if len(words[2]) > 1 and words[2][1] == 'x':
 | 
						|
                            idx = int(words[2], 16)
 | 
						|
                        else:
 | 
						|
                            idx = int(words[2])
 | 
						|
                    decls[words[1]] = idx
 | 
						|
                    idx = idx + 1
 | 
						|
            linenum = linenum + 1
 | 
						|
        api.close()
 | 
						|
    z3consts.write('}\n');
 | 
						|
    z3consts.close()
 | 
						|
    return z3consts_output_path
 | 
						|
 | 
						|
 | 
						|
def mk_z3consts_java_internal(api_files, package_name, output_dir):
 | 
						|
    """
 | 
						|
        Generate "com.microsoft.z3.enumerations" package from the list of API
 | 
						|
        header files in ``api_files`` and write the package directory into
 | 
						|
        the ``output_dir`` directory
 | 
						|
 | 
						|
        Returns a list of the generated java source files.
 | 
						|
    """
 | 
						|
    blank_pat      = re.compile("^ *$")
 | 
						|
    comment_pat    = re.compile("^ *//.*$")
 | 
						|
    typedef_pat    = re.compile("typedef enum *")
 | 
						|
    typedef2_pat   = re.compile("typedef enum { *")
 | 
						|
    openbrace_pat  = re.compile("{ *")
 | 
						|
    closebrace_pat = re.compile("}.*;")
 | 
						|
 | 
						|
    DeprecatedEnums = [ 'Z3_search_failure' ]
 | 
						|
    gendir = os.path.join(output_dir, "enumerations")
 | 
						|
    if not os.path.exists(gendir):
 | 
						|
        os.mkdir(gendir)
 | 
						|
 | 
						|
    generated_enumeration_files = []
 | 
						|
    for api_file in api_files:
 | 
						|
        api = open(api_file, 'r')
 | 
						|
 | 
						|
        SEARCHING  = 0
 | 
						|
        FOUND_ENUM = 1
 | 
						|
        IN_ENUM    = 2
 | 
						|
 | 
						|
        mode    = SEARCHING
 | 
						|
        decls   = {}
 | 
						|
        idx     = 0
 | 
						|
 | 
						|
        linenum = 1
 | 
						|
        for line in api:
 | 
						|
            m1 = blank_pat.match(line)
 | 
						|
            m2 = comment_pat.match(line)
 | 
						|
            if m1 or m2:
 | 
						|
                # skip blank lines and comments
 | 
						|
                linenum = linenum + 1
 | 
						|
            elif mode == SEARCHING:
 | 
						|
                m = typedef_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = FOUND_ENUM
 | 
						|
                m = typedef2_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
            elif mode == FOUND_ENUM:
 | 
						|
                m = openbrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode  = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
                else:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
            else:
 | 
						|
                assert mode == IN_ENUM
 | 
						|
                words = re.split('[^-a-zA-Z0-9_]+', line)
 | 
						|
                m = closebrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    name = words[1]
 | 
						|
                    if name not in DeprecatedEnums:
 | 
						|
                        efile  = open('%s.java' % os.path.join(gendir, name), 'w')
 | 
						|
                        generated_enumeration_files.append(efile.name)
 | 
						|
                        efile.write('/**\n *  Automatically generated file\n **/\n\n')
 | 
						|
                        efile.write('package %s.enumerations;\n\n' % package_name)
 | 
						|
                        efile.write('import java.util.HashMap;\n')
 | 
						|
                        efile.write('import java.util.Map;\n')
 | 
						|
                        efile.write('\n')
 | 
						|
 | 
						|
                        efile.write('/**\n')
 | 
						|
                        efile.write(' * %s\n' % name)
 | 
						|
                        efile.write(' **/\n')
 | 
						|
                        efile.write('public enum %s {\n' % name)
 | 
						|
                        efile.write
 | 
						|
                        first = True
 | 
						|
                        # Iterate over key-value pairs ordered by value
 | 
						|
                        for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
 | 
						|
                            if first:
 | 
						|
                                first = False
 | 
						|
                            else:
 | 
						|
                                efile.write(',\n')
 | 
						|
                            efile.write('    %s (%s)' % (k, v))
 | 
						|
                        efile.write(";\n")
 | 
						|
                        efile.write('\n    private final int intValue;\n\n')
 | 
						|
                        efile.write('    %s(int v) {\n' % name)
 | 
						|
                        efile.write('        this.intValue = v;\n')
 | 
						|
                        efile.write('    }\n\n')
 | 
						|
                        efile.write('    // Cannot initialize map in constructor, so need to do it lazily.\n')
 | 
						|
                        efile.write('    // Easiest thread-safe way is the initialization-on-demand holder pattern.\n')
 | 
						|
                        efile.write('    private static class %s_MappingHolder {\n' % name)
 | 
						|
                        efile.write('        private static final Map<Integer, %s> intMapping = new HashMap<>();\n' % name)
 | 
						|
                        efile.write('        static {\n')
 | 
						|
                        efile.write('            for (%s k : %s.values())\n' % (name, name))
 | 
						|
                        efile.write('                intMapping.put(k.toInt(), k);\n')
 | 
						|
                        efile.write('        }\n')
 | 
						|
                        efile.write('    }\n\n')
 | 
						|
                        efile.write('    public static final %s fromInt(int v) {\n' % name)
 | 
						|
                        efile.write('        %s k = %s_MappingHolder.intMapping.get(v);\n' % (name, name))
 | 
						|
                        efile.write('        if (k != null) return k;\n')
 | 
						|
                        efile.write('        throw new IllegalArgumentException("Illegal value " + v + " for %s");\n' % name)
 | 
						|
                        efile.write('    }\n\n')
 | 
						|
                        efile.write('    public final int toInt() { return this.intValue; }\n')
 | 
						|
                        #  efile.write(';\n  %s(int v) {}\n' % name)
 | 
						|
                        efile.write('}\n\n')
 | 
						|
                        efile.close()
 | 
						|
                    mode = SEARCHING
 | 
						|
                else:
 | 
						|
                    if words[2] != '':
 | 
						|
                        if len(words[2]) > 1 and words[2][1] == 'x':
 | 
						|
                            idx = int(words[2], 16)
 | 
						|
                        else:
 | 
						|
                            idx = int(words[2])
 | 
						|
                    decls[words[1]] = idx
 | 
						|
                    idx = idx + 1
 | 
						|
            linenum = linenum + 1
 | 
						|
        api.close()
 | 
						|
    return generated_enumeration_files
 | 
						|
 | 
						|
# Extract enumeration types from z3_api.h, and add ML definitions
 | 
						|
def mk_z3consts_ml_internal(api_files, output_dir):
 | 
						|
    """
 | 
						|
        Generate ``z3enums.ml`` from the list of API header files
 | 
						|
        in ``api_files`` and write the output file into
 | 
						|
        the ``output_dir`` directory
 | 
						|
 | 
						|
        Returns the path to the generated file.
 | 
						|
    """
 | 
						|
    assert os.path.isdir(output_dir)
 | 
						|
    assert isinstance(api_files, list)
 | 
						|
    blank_pat      = re.compile("^ *$")
 | 
						|
    comment_pat    = re.compile("^ *//.*$")
 | 
						|
    typedef_pat    = re.compile("typedef enum *")
 | 
						|
    typedef2_pat   = re.compile("typedef enum { *")
 | 
						|
    openbrace_pat  = re.compile("{ *")
 | 
						|
    closebrace_pat = re.compile("}.*;")
 | 
						|
 | 
						|
 | 
						|
    DeprecatedEnums = [ 'Z3_search_failure' ]
 | 
						|
    if not os.path.exists(output_dir):
 | 
						|
        os.mkdir(output_dir)
 | 
						|
 | 
						|
    efile  = open('%s.ml' % os.path.join(output_dir, "z3enums"), 'w')
 | 
						|
    z3consts_output_path = efile.name
 | 
						|
    efile.write('(* Automatically generated file *)\n\n')
 | 
						|
    efile.write('(** The enumeration types of Z3. *)\n\n')
 | 
						|
    for api_file in api_files:
 | 
						|
        api = open(api_file, 'r')
 | 
						|
 | 
						|
        SEARCHING  = 0
 | 
						|
        FOUND_ENUM = 1
 | 
						|
        IN_ENUM    = 2
 | 
						|
 | 
						|
        mode    = SEARCHING
 | 
						|
        decls   = {}
 | 
						|
        idx     = 0
 | 
						|
 | 
						|
        linenum = 1
 | 
						|
        for line in api:
 | 
						|
            m1 = blank_pat.match(line)
 | 
						|
            m2 = comment_pat.match(line)
 | 
						|
            if m1 or m2:
 | 
						|
                # skip blank lines and comments
 | 
						|
                linenum = linenum + 1
 | 
						|
            elif mode == SEARCHING:
 | 
						|
                m = typedef_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = FOUND_ENUM
 | 
						|
                m = typedef2_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
            elif mode == FOUND_ENUM:
 | 
						|
                m = openbrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mode  = IN_ENUM
 | 
						|
                    decls = {}
 | 
						|
                    idx   = 0
 | 
						|
                else:
 | 
						|
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
            else:
 | 
						|
                assert mode == IN_ENUM
 | 
						|
                words = re.split('[^-a-zA-Z0-9_]+', line)
 | 
						|
                m = closebrace_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    name = words[1]
 | 
						|
                    if name not in DeprecatedEnums:
 | 
						|
                        sorted_decls = sorted(decls.items(), key=lambda pair: pair[1])
 | 
						|
                        efile.write('(** %s *)\n' % name[3:])
 | 
						|
                        efile.write('type %s =\n' % name[3:]) # strip Z3_
 | 
						|
                        for k, i in sorted_decls:
 | 
						|
                            efile.write('  | %s \n' % k[3:]) # strip Z3_
 | 
						|
                        efile.write('\n')
 | 
						|
                        efile.write('(** Convert %s to int*)\n' % name[3:])
 | 
						|
                        efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_
 | 
						|
                        efile.write('  match x with\n')
 | 
						|
                        for k, i in sorted_decls:
 | 
						|
                            efile.write('  | %s -> %d\n' % (k[3:], i))
 | 
						|
                        efile.write('\n')
 | 
						|
                        efile.write('(** Convert int to %s*)\n' % name[3:])
 | 
						|
                        efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_
 | 
						|
                        efile.write('  match x with\n')
 | 
						|
                        for k, i in sorted_decls:
 | 
						|
                            efile.write('  | %d -> %s\n' % (i, k[3:]))
 | 
						|
                        # use Z3.Exception?
 | 
						|
                        efile.write('  | _ -> raise (Failure "undefined enum value")\n\n')
 | 
						|
                    mode = SEARCHING
 | 
						|
                else:
 | 
						|
                    if words[2] != '':
 | 
						|
                        if len(words[2]) > 1 and words[2][1] == 'x':
 | 
						|
                            idx = int(words[2], 16)
 | 
						|
                        else:
 | 
						|
                            idx = int(words[2])
 | 
						|
                    decls[words[1]] = idx
 | 
						|
                    idx = idx + 1
 | 
						|
            linenum = linenum + 1
 | 
						|
        api.close()
 | 
						|
    efile.close()
 | 
						|
    return z3consts_output_path
 | 
						|
    # efile  = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w')
 | 
						|
    # efile.write('(* Automatically generated file *)\n\n')
 | 
						|
    # efile.write('(** The enumeration types of Z3. *)\n\n')
 | 
						|
    # for api_file in api_files:
 | 
						|
    #     api_file_c = ml.find_file(api_file, ml.name)
 | 
						|
    #     api_file   = os.path.join(api_file_c.src_dir, api_file)
 | 
						|
 | 
						|
    #     api = open(api_file, 'r')
 | 
						|
 | 
						|
    #     SEARCHING  = 0
 | 
						|
    #     FOUND_ENUM = 1
 | 
						|
    #     IN_ENUM    = 2
 | 
						|
 | 
						|
    #     mode    = SEARCHING
 | 
						|
    #     decls   = {}
 | 
						|
    #     idx     = 0
 | 
						|
 | 
						|
    #     linenum = 1
 | 
						|
    #     for line in api:
 | 
						|
    #         m1 = blank_pat.match(line)
 | 
						|
    #         m2 = comment_pat.match(line)
 | 
						|
    #         if m1 or m2:
 | 
						|
    #             # skip blank lines and comments
 | 
						|
    #             linenum = linenum + 1
 | 
						|
    #         elif mode == SEARCHING:
 | 
						|
    #             m = typedef_pat.match(line)
 | 
						|
    #             if m:
 | 
						|
    #                 mode = FOUND_ENUM
 | 
						|
    #             m = typedef2_pat.match(line)
 | 
						|
    #             if m:
 | 
						|
    #                 mode = IN_ENUM
 | 
						|
    #                 decls = {}
 | 
						|
    #                 idx   = 0
 | 
						|
    #         elif mode == FOUND_ENUM:
 | 
						|
    #             m = openbrace_pat.match(line)
 | 
						|
    #             if m:
 | 
						|
    #                 mode  = IN_ENUM
 | 
						|
    #                 decls = {}
 | 
						|
    #                 idx   = 0
 | 
						|
    #             else:
 | 
						|
    #                 assert False, "Invalid %s, line: %s" % (api_file, linenum)
 | 
						|
    #         else:
 | 
						|
    #             assert mode == IN_ENUM
 | 
						|
    #             words = re.split('[^\-a-zA-Z0-9_]+', line)
 | 
						|
    #             m = closebrace_pat.match(line)
 | 
						|
    #             if m:
 | 
						|
    #                 name = words[1]
 | 
						|
    #                 if name not in DeprecatedEnums:
 | 
						|
    #                     efile.write('(** %s *)\n' % name[3:])
 | 
						|
    #                     efile.write('type %s =\n' % name[3:]) # strip Z3_
 | 
						|
    #                     for k, i in sorted(decls.items(), key=lambda pair: pair[1]):
 | 
						|
    #                         efile.write('  | %s \n' % k[3:]) # strip Z3_
 | 
						|
    #                     efile.write('\n')
 | 
						|
    #                     efile.write('(** Convert %s to int*)\n' % name[3:])
 | 
						|
    #                     efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_
 | 
						|
    #                     efile.write('(** Convert int to %s*)\n' % name[3:])
 | 
						|
    #                     efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_
 | 
						|
    #                     efile.write('\n')
 | 
						|
    #                 mode = SEARCHING
 | 
						|
    #             else:
 | 
						|
    #                 if words[2] != '':
 | 
						|
    #                     if len(words[2]) > 1 and words[2][1] == 'x':
 | 
						|
    #                         idx = int(words[2], 16)
 | 
						|
    #                     else:
 | 
						|
    #                         idx = int(words[2])
 | 
						|
    #                 decls[words[1]] = idx
 | 
						|
    #                 idx = idx + 1
 | 
						|
    #         linenum = linenum + 1
 | 
						|
    #     api.close()
 | 
						|
    # efile.close()
 | 
						|
    # if VERBOSE:
 | 
						|
    #     print ('Generated "%s/z3enums.mli"' % ('%s' % gendir))
 | 
						|
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions for generating a "module definition file" for MSVC
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def mk_def_file_internal(defname, dll_name, export_header_files):
 | 
						|
    """
 | 
						|
      Writes to a module definition file to a file named ``defname``.
 | 
						|
 | 
						|
      ``dll_name`` is the name of the dll (without the ``.dll`` suffix).
 | 
						|
      ``export_header_file`` is a list of header files to scan for symbols
 | 
						|
      to include in the module definition file.
 | 
						|
    """
 | 
						|
    assert isinstance(export_header_files, list)
 | 
						|
    pat1 = re.compile(".*Z3_API.*")
 | 
						|
    fout = open(defname, 'w')
 | 
						|
    fout.write('LIBRARY "%s"\nEXPORTS\n' % dll_name)
 | 
						|
    num = 1
 | 
						|
    for export_header_file in export_header_files:
 | 
						|
        api = open(export_header_file, 'r')
 | 
						|
        for line in api:
 | 
						|
            m = pat1.match(line)
 | 
						|
            if m:
 | 
						|
                words = re.split(r'\W+', line)
 | 
						|
                i = 0
 | 
						|
                for w in words:
 | 
						|
                    if w == 'Z3_API':
 | 
						|
                        f = words[i+1]
 | 
						|
                        fout.write('\t%s @%s\n' % (f, num))
 | 
						|
                    i = i + 1
 | 
						|
                num = num + 1
 | 
						|
        api.close()
 | 
						|
    fout.close()
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions for generating ``gparams_register_modules.cpp``
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def path_after_src(h_file):
 | 
						|
    h_file = h_file.replace("\\","/")
 | 
						|
    idx = h_file.rfind("src/")
 | 
						|
    if idx == -1:
 | 
						|
        return h_file
 | 
						|
    return h_file[idx + 4:]
 | 
						|
            
 | 
						|
def mk_gparams_register_modules_internal(h_files_full_path, path):
 | 
						|
    """
 | 
						|
        Generate a ``gparams_register_modules.cpp`` file in the directory ``path``.
 | 
						|
        Returns the path to the generated file.
 | 
						|
 | 
						|
        This file implements the procedure
 | 
						|
 | 
						|
        ```
 | 
						|
        void gparams_register_modules()
 | 
						|
        ```
 | 
						|
 | 
						|
        This procedure is invoked by gparams::init()
 | 
						|
    """
 | 
						|
    assert isinstance(h_files_full_path, list)
 | 
						|
    assert check_dir_exists(path)
 | 
						|
    cmds = []    
 | 
						|
    mod_cmds = []
 | 
						|
    mod_descrs = []
 | 
						|
    fullname = os.path.join(path, 'gparams_register_modules.cpp')
 | 
						|
    fout  = open(fullname, 'w')
 | 
						|
    fout.write('// Automatically generated file.\n')
 | 
						|
    fout.write('#include "util/gparams.h"\n')
 | 
						|
    reg_pat = re.compile(r'[ \t]*REG_PARAMS\(\'([^\']*)\'\)')
 | 
						|
    reg_mod_pat = re.compile(r'[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)')
 | 
						|
    reg_mod_descr_pat = re.compile(r'[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)')
 | 
						|
    for h_file in sorted_headers_by_component(h_files_full_path):
 | 
						|
        added_include = False
 | 
						|
        with io.open(h_file, encoding='utf-8', mode='r') as fin:
 | 
						|
            for line in fin:
 | 
						|
                m = reg_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    if not added_include:
 | 
						|
                        added_include = True
 | 
						|
                        fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                    cmds.append((m.group(1)))
 | 
						|
                m = reg_mod_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    if not added_include:
 | 
						|
                        added_include = True
 | 
						|
                        fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                    mod_cmds.append((m.group(1), m.group(2)))
 | 
						|
                m = reg_mod_descr_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    mod_descrs.append((m.group(1), m.group(2)))
 | 
						|
    fout.write('void gparams_register_modules() {\n')
 | 
						|
    for code in cmds:
 | 
						|
        fout.write('{ param_descrs d; %s(d); gparams::register_global(d); }\n' % code)
 | 
						|
    for (mod, code) in mod_cmds:
 | 
						|
        fout.write('{ auto f = []() { auto* d = alloc(param_descrs); %s(*d); return d; }; gparams::register_module("%s", f); }\n' % (code, mod))
 | 
						|
    for (mod, descr) in mod_descrs:
 | 
						|
        fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr))
 | 
						|
    fout.write('}\n')
 | 
						|
    fout.close()
 | 
						|
    return fullname
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions/data structures for generating ``install_tactics.cpp``
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def mk_install_tactic_cpp_internal(h_files_full_path, path):
 | 
						|
    """
 | 
						|
        Generate a ``install_tactics.cpp`` file in the directory ``path``.
 | 
						|
        Returns the path the generated file.
 | 
						|
 | 
						|
        This file implements the procedure
 | 
						|
 | 
						|
        ```
 | 
						|
        void install_tactics(tactic_manager & ctx)
 | 
						|
        ```
 | 
						|
 | 
						|
        It installs all tactics declared in the given header files
 | 
						|
        ``h_files_full_path`` The procedure looks for ``ADD_TACTIC`` and
 | 
						|
        ``ADD_PROBE``commands in the ``.h``  and ``.hpp`` files of these
 | 
						|
        components.
 | 
						|
    """
 | 
						|
    ADD_TACTIC_DATA = []
 | 
						|
    ADD_SIMPLIFIER_DATA = []
 | 
						|
    ADD_PROBE_DATA = []
 | 
						|
    def ADD_TACTIC(name, descr, cmd):
 | 
						|
        ADD_TACTIC_DATA.append((name, descr, cmd))
 | 
						|
 | 
						|
    def ADD_PROBE(name, descr, cmd):
 | 
						|
        ADD_PROBE_DATA.append((name, descr, cmd))
 | 
						|
 | 
						|
    def ADD_SIMPLIFIER(name, descr, cmd):
 | 
						|
        ADD_SIMPLIFIER_DATA.append((name, descr, cmd))
 | 
						|
 | 
						|
    eval_globals = {
 | 
						|
        'ADD_TACTIC': ADD_TACTIC,
 | 
						|
        'ADD_PROBE': ADD_PROBE,
 | 
						|
        'ADD_SIMPLIFIER': ADD_SIMPLIFIER
 | 
						|
    }
 | 
						|
 | 
						|
    assert isinstance(h_files_full_path, list)
 | 
						|
    assert check_dir_exists(path)
 | 
						|
    fullname = os.path.join(path, 'install_tactic.cpp')
 | 
						|
    fout  = open(fullname, 'w')
 | 
						|
    fout.write('// Automatically generated file.\n')
 | 
						|
    fout.write('#include "tactic/tactic.h"\n')
 | 
						|
    fout.write('#include "cmd_context/tactic_cmds.h"\n')
 | 
						|
    fout.write('#include "cmd_context/simplifier_cmds.h"\n')
 | 
						|
    fout.write('#include "cmd_context/cmd_context.h"\n')
 | 
						|
    tactic_pat   = re.compile(r'[ \t]*ADD_TACTIC\(.*\)')
 | 
						|
    probe_pat    = re.compile(r'[ \t]*ADD_PROBE\(.*\)')
 | 
						|
    simplifier_pat = re.compile(r'[ \t]*ADD_SIMPLIFIER\(.*\)')
 | 
						|
    for h_file in sorted_headers_by_component(h_files_full_path):
 | 
						|
        added_include = False
 | 
						|
        try:
 | 
						|
            with io.open(h_file, encoding='utf-8', mode='r') as fin:
 | 
						|
                for line in fin:
 | 
						|
                    if tactic_pat.match(line):
 | 
						|
                        if not added_include:
 | 
						|
                            added_include = True                        
 | 
						|
                            fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                        try:
 | 
						|
                            eval(line.strip('\n '), eval_globals, None)
 | 
						|
                        except Exception as e:
 | 
						|
                            _logger.error("Failed processing ADD_TACTIC command at '{}'\n{}".format(
 | 
						|
                                fullname, line))
 | 
						|
                            raise e
 | 
						|
                    if probe_pat.match(line):
 | 
						|
                        if not added_include:
 | 
						|
                            added_include = True
 | 
						|
                            fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                        try:
 | 
						|
                            eval(line.strip('\n '), eval_globals, None)
 | 
						|
                        except Exception as e:
 | 
						|
                            _logger.error("Failed processing ADD_PROBE command at '{}'\n{}".format(
 | 
						|
                                fullname, line))
 | 
						|
                            raise e
 | 
						|
                    if simplifier_pat.match(line):
 | 
						|
                        if not added_include:
 | 
						|
                            added_include = True
 | 
						|
                            fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                        try:
 | 
						|
                            eval(line.strip('\n '), eval_globals, None)
 | 
						|
                        except Exception as e:
 | 
						|
                            _logger.error("Failed processing ADD_SIMPLIFIER command at '{}'\n{}".format(
 | 
						|
                                fullname, line))
 | 
						|
                            raise e
 | 
						|
                        
 | 
						|
        except Exception as e:
 | 
						|
           _logger.error("Failed to read file {}\n".format(h_file))
 | 
						|
           raise e
 | 
						|
    # First pass will just generate the tactic factories
 | 
						|
    fout.write('#define ADD_TACTIC_CMD(NAME, DESCR, CODE) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, [](ast_manager &m, const params_ref &p) { return CODE; }))\n')
 | 
						|
    fout.write('#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))\n')
 | 
						|
    fout.write('#define ADD_SIMPLIFIER_CMD(NAME, DESCR, CODE) ctx.insert(alloc(simplifier_cmd, symbol(NAME), DESCR, [](auto& m, auto& p, auto &s) -> dependent_expr_simplifier* { return CODE; }))\n')
 | 
						|
    fout.write('void install_tactics(tactic_manager & ctx) {\n')
 | 
						|
    for data in ADD_TACTIC_DATA:
 | 
						|
        fout.write('  ADD_TACTIC_CMD("%s", "%s", %s);\n' % data)
 | 
						|
    for data in ADD_PROBE_DATA:
 | 
						|
        fout.write('  ADD_PROBE("%s", "%s", %s);\n' % data)
 | 
						|
    for data in ADD_SIMPLIFIER_DATA:
 | 
						|
        fout.write('  ADD_SIMPLIFIER_CMD("%s", "%s", %s);\n' % data)
 | 
						|
    fout.write('}\n')
 | 
						|
    fout.close()
 | 
						|
    return fullname
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions for generating ``mem_initializer.cpp``
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def mk_mem_initializer_cpp_internal(h_files_full_path, path):
 | 
						|
    """
 | 
						|
        Generate a ``mem_initializer.cpp`` file in the directory ``path``.
 | 
						|
        Returns the path to the generated file.
 | 
						|
 | 
						|
        This file implements the procedures
 | 
						|
 | 
						|
        ```
 | 
						|
        void mem_initialize()
 | 
						|
        void mem_finalize()
 | 
						|
        ```
 | 
						|
 | 
						|
       These procedures are invoked by the Z3 memory_manager
 | 
						|
    """
 | 
						|
    assert isinstance(h_files_full_path, list)
 | 
						|
    assert check_dir_exists(path)
 | 
						|
    initializer_cmds = []
 | 
						|
    finalizer_cmds   = []
 | 
						|
    fullname = os.path.join(path, 'mem_initializer.cpp')
 | 
						|
    fout  = open(fullname, 'w')
 | 
						|
    fout.write('// Automatically generated file.\n')
 | 
						|
    initializer_pat      = re.compile(r'[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
 | 
						|
    # ADD_INITIALIZER with priority
 | 
						|
    initializer_prio_pat = re.compile(r'[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)')
 | 
						|
    finalizer_pat        = re.compile(r'[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)')
 | 
						|
    for h_file in sorted_headers_by_component(h_files_full_path):
 | 
						|
        added_include = False
 | 
						|
        with io.open(h_file, encoding='utf-8', mode='r') as fin:
 | 
						|
            for line in fin:
 | 
						|
                m = initializer_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    if not added_include:
 | 
						|
                        added_include = True
 | 
						|
                        fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                    initializer_cmds.append((m.group(1), 0))
 | 
						|
                m = initializer_prio_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    if not added_include:
 | 
						|
                        added_include = True
 | 
						|
                        fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                    initializer_cmds.append((m.group(1), int(m.group(2))))
 | 
						|
                m = finalizer_pat.match(line)
 | 
						|
                if m:
 | 
						|
                    if not added_include:
 | 
						|
                        added_include = True
 | 
						|
                        fout.write('#include "%s"\n' % path_after_src(h_file))
 | 
						|
                    finalizer_cmds.append(m.group(1))
 | 
						|
    initializer_cmds.sort(key=lambda tup: tup[1])
 | 
						|
    fout.write('void mem_initialize() {\n')
 | 
						|
    for (cmd, prio) in initializer_cmds:
 | 
						|
        fout.write(cmd)
 | 
						|
        fout.write('\n')
 | 
						|
    fout.write('}\n')
 | 
						|
    fout.write('void mem_finalize() {\n')
 | 
						|
    for cmd in finalizer_cmds:
 | 
						|
        fout.write(cmd)
 | 
						|
        fout.write('\n')
 | 
						|
    fout.write('}\n')
 | 
						|
    fout.close()
 | 
						|
    return fullname
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions for generating ``database.h``
 | 
						|
###############################################################################
 | 
						|
 | 
						|
def mk_pat_db_internal(inputFilePath, outputFilePath):
 | 
						|
    """
 | 
						|
        Generate ``g_pattern_database[]`` declaration header file.
 | 
						|
    """
 | 
						|
    with open(inputFilePath, 'r') as fin:
 | 
						|
        with open(outputFilePath, 'w') as fout:
 | 
						|
            fout.write('static char const g_pattern_database[] =\n')
 | 
						|
            for line in fin:
 | 
						|
                fout.write('"%s\\n"\n' % line.strip('\n'))
 | 
						|
            fout.write(';\n')
 | 
						|
 | 
						|
###############################################################################
 | 
						|
# Functions and data structures for generating ``*_params.hpp`` files from
 | 
						|
# ``*.pyg`` files
 | 
						|
###############################################################################
 | 
						|
 | 
						|
UINT   = 0
 | 
						|
BOOL   = 1
 | 
						|
DOUBLE = 2
 | 
						|
STRING = 3
 | 
						|
SYMBOL = 4
 | 
						|
UINT_MAX = 4294967295
 | 
						|
 | 
						|
TYPE2CPK = { UINT : 'CPK_UINT', BOOL : 'CPK_BOOL',  DOUBLE : 'CPK_DOUBLE',  STRING : 'CPK_STRING',  SYMBOL : 'CPK_SYMBOL' }
 | 
						|
TYPE2CTYPE = { UINT : 'unsigned', BOOL : 'bool', DOUBLE : 'double', STRING : 'char const *', SYMBOL : 'symbol' }
 | 
						|
TYPE2GETTER = { UINT : 'get_uint', BOOL : 'get_bool', DOUBLE : 'get_double', STRING : 'get_str',  SYMBOL : 'get_sym' }
 | 
						|
 | 
						|
def pyg_default(p):
 | 
						|
    if p[1] == BOOL:
 | 
						|
        if p[2]:
 | 
						|
            return "true"
 | 
						|
        else:
 | 
						|
            return "false"
 | 
						|
    return p[2]
 | 
						|
 | 
						|
def pyg_default_as_c_literal(p):
 | 
						|
    if p[1] == BOOL:
 | 
						|
        if p[2]:
 | 
						|
            return "true"
 | 
						|
        else:
 | 
						|
            return "false"
 | 
						|
    elif p[1] == STRING:
 | 
						|
        return '"%s"' % p[2]
 | 
						|
    elif p[1] == SYMBOL:
 | 
						|
        return 'symbol("%s")' % p[2]
 | 
						|
    elif p[1] == UINT:
 | 
						|
        return '%su' % p[2]
 | 
						|
    else:
 | 
						|
        return p[2]
 | 
						|
 | 
						|
def to_c_method(s):
 | 
						|
    return s.replace('.', '_')
 | 
						|
 | 
						|
 | 
						|
def max_memory_param():
 | 
						|
    return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes')
 | 
						|
 | 
						|
def max_steps_param():
 | 
						|
    return ('max_steps', UINT, UINT_MAX, 'maximum number of steps')
 | 
						|
 | 
						|
def mk_hpp_from_pyg(pyg_file, output_dir):
 | 
						|
    """
 | 
						|
        Generates the corresponding header file for the input pyg file
 | 
						|
        at the path ``pyg_file``. The file is emitted into the directory
 | 
						|
        ``output_dir``.
 | 
						|
 | 
						|
        Returns the path to the generated file
 | 
						|
    """
 | 
						|
    CURRENT_PYG_HPP_DEST_DIR = output_dir
 | 
						|
    # Note OUTPUT_HPP_FILE cannot be a string as we need a mutable variable
 | 
						|
    # for the nested function to modify
 | 
						|
    OUTPUT_HPP_FILE = [ ]
 | 
						|
    # The function below has been nested so that it can use closure to capture
 | 
						|
    # the above variables that aren't global but instead local to this
 | 
						|
    # function. This avoids use of global state which makes this function safer.
 | 
						|
    def def_module_params(module_name, export, params, class_name=None, description=None):
 | 
						|
        dirname = CURRENT_PYG_HPP_DEST_DIR
 | 
						|
        assert(os.path.exists(dirname))
 | 
						|
        if class_name is None:
 | 
						|
            class_name = '%s_params' % module_name
 | 
						|
        hpp = os.path.join(dirname, '%s.hpp' % class_name)
 | 
						|
        out = open(hpp, 'w')
 | 
						|
        out.write('// Automatically generated file\n')
 | 
						|
        out.write('#pragma once\n')
 | 
						|
        out.write('#include "util/params.h"\n')
 | 
						|
        if export:
 | 
						|
            out.write('#include "util/gparams.h"\n')
 | 
						|
        out.write('struct %s {\n' % class_name)
 | 
						|
        out.write('  params_ref const & p;\n')
 | 
						|
        if export:
 | 
						|
            out.write('  params_ref g;\n')
 | 
						|
        out.write('  %s(params_ref const & _p = params_ref::get_empty()):\n' % class_name)
 | 
						|
        out.write('     p(_p)')
 | 
						|
        if export:
 | 
						|
            out.write(', g(gparams::get_module("%s"))' % module_name)
 | 
						|
        out.write(' {}\n')
 | 
						|
        out.write('  static void collect_param_descrs(param_descrs & d) {\n')
 | 
						|
        for param in params:
 | 
						|
            out.write('    d.insert("%s", %s, "%s", "%s","%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param), module_name))
 | 
						|
        out.write('  }\n')
 | 
						|
        if export:
 | 
						|
            out.write('  /*\n')
 | 
						|
            out.write("     REG_MODULE_PARAMS('%s', '%s::collect_param_descrs')\n" % (module_name, class_name))
 | 
						|
            if description is not None:
 | 
						|
                out.write("     REG_MODULE_DESCRIPTION('%s', '%s')\n" % (module_name, description))
 | 
						|
            out.write('  */\n')
 | 
						|
        # Generated accessors
 | 
						|
        for param in params:
 | 
						|
            if export:
 | 
						|
                out.write('  %s %s() const { return p.%s("%s", g, %s); }\n' %
 | 
						|
                          (TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
 | 
						|
            else:
 | 
						|
                out.write('  %s %s() const { return p.%s("%s", %s); }\n' %
 | 
						|
                          (TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
 | 
						|
        out.write('};\n')
 | 
						|
        out.close()
 | 
						|
        OUTPUT_HPP_FILE.append(hpp)
 | 
						|
 | 
						|
    # Globals to use when executing the ``.pyg`` file.
 | 
						|
    pyg_globals = {
 | 
						|
        'UINT' : UINT,
 | 
						|
        'BOOL' : BOOL,
 | 
						|
        'DOUBLE' : DOUBLE,
 | 
						|
        'STRING' : STRING,
 | 
						|
        'SYMBOL' : SYMBOL,
 | 
						|
        'UINT_MAX' : UINT_MAX,
 | 
						|
        'max_memory_param' : max_memory_param,
 | 
						|
        'max_steps_param' : max_steps_param,
 | 
						|
        # Note that once this function is entered that function
 | 
						|
        # executes with respect to the globals of this module and
 | 
						|
        # not the globals defined here
 | 
						|
        'def_module_params' : def_module_params,
 | 
						|
    }
 | 
						|
    with open(pyg_file, 'r') as fh:
 | 
						|
        eval(fh.read() + "\n", pyg_globals, None)
 | 
						|
    assert len(OUTPUT_HPP_FILE) == 1
 | 
						|
    return OUTPUT_HPP_FILE[0]
 |