Lichen

Annotated encoders.py

77:985a0cc2522b
2016-10-05 Paul Boddie Expanded the access plans to include a more complete set of details.
paul@0 1
#!/usr/bin/env python
paul@0 2
paul@0 3
"""
paul@0 4
Encoder functions, producing representations of program objects.
paul@0 5
paul@0 6
Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
paul@0 7
paul@0 8
This program is free software; you can redistribute it and/or modify it under
paul@0 9
the terms of the GNU General Public License as published by the Free Software
paul@0 10
Foundation; either version 3 of the License, or (at your option) any later
paul@0 11
version.
paul@0 12
paul@0 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@0 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@0 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@0 16
details.
paul@0 17
paul@0 18
You should have received a copy of the GNU General Public License along with
paul@0 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@0 20
"""
paul@0 21
paul@56 22
from common import first
paul@56 23
paul@0 24
# Output encoding and decoding for the summary files.
paul@0 25
paul@0 26
def encode_attrnames(attrnames):
paul@0 27
paul@0 28
    "Encode the 'attrnames' representing usage."
paul@0 29
paul@0 30
    return ", ".join(attrnames) or "{}"
paul@0 31
paul@0 32
def encode_constrained(constrained):
paul@0 33
paul@0 34
    "Encode the 'constrained' status for program summaries."
paul@0 35
paul@0 36
    return constrained and "constrained" or "deduced"
paul@0 37
paul@0 38
def encode_usage(usage):
paul@0 39
paul@0 40
    "Encode attribute details from 'usage'."
paul@0 41
paul@0 42
    all_attrnames = []
paul@0 43
    for t in usage:
paul@0 44
        all_attrnames.append(t)
paul@0 45
    return ", ".join(all_attrnames) or "{}"
paul@0 46
paul@0 47
def encode_access_location(t):
paul@0 48
paul@0 49
    "Encode the access location 't'."
paul@0 50
paul@0 51
    path, name, attrname, version = t
paul@0 52
    return "%s %s %s:%d" % (path, name or "{}", attrname, version)
paul@0 53
paul@0 54
def encode_location(t):
paul@0 55
paul@0 56
    "Encode the general location 't' in a concise form."
paul@0 57
paul@0 58
    path, name, attrname, version = t
paul@0 59
    if name is not None and version is not None:
paul@0 60
        return "%s %s:%d" % (path, name, version)
paul@0 61
    elif name is not None:
paul@0 62
        return "%s %s" % (path, name)
paul@0 63
    else:
paul@0 64
        return "%s :%s" % (path, attrname)
paul@0 65
paul@0 66
def encode_modifiers(modifiers):
paul@0 67
paul@0 68
    "Encode assignment details from 'modifiers'."
paul@0 69
paul@0 70
    all_modifiers = []
paul@0 71
    for t in modifiers:
paul@0 72
        all_modifiers.append(encode_modifier_term(t))
paul@0 73
    return "".join(all_modifiers)
paul@0 74
paul@0 75
def encode_modifier_term(t):
paul@0 76
paul@0 77
    "Encode modifier 't' representing assignment status."
paul@0 78
paul@0 79
    assignment = t
paul@0 80
    return assignment and "A" or "_"
paul@0 81
paul@0 82
def decode_modifier_term(s):
paul@0 83
paul@0 84
    "Decode modifier term 's' representing assignment status."
paul@0 85
paul@0 86
    return s == "A"
paul@0 87
paul@56 88
paul@56 89
paul@56 90
# Test generation functions.
paul@56 91
paul@56 92
def get_kinds(all_types):
paul@56 93
paul@56 94
    """ 
paul@56 95
    Return object kind details for 'all_types', being a collection of
paul@56 96
    references for program types.
paul@56 97
    """
paul@56 98
paul@56 99
    return map(lambda ref: ref.get_kind(), all_types)
paul@56 100
paul@56 101
def test_for_kind(prefix, kind):
paul@56 102
paul@56 103
    "Return a test condition identifier featuring 'prefix' and 'kind'."
paul@56 104
paul@56 105
    return "%s-%s" % (prefix, kind == "<instance>" and "instance" or "type")
paul@56 106
paul@56 107
def test_for_kinds(prefix, all_kinds):
paul@56 108
paul@56 109
    """ 
paul@67 110
    Return an identifier describing test conditions incorporating the given
paul@56 111
    'prefix' and involving 'all_kinds', being a collection of object kinds.
paul@56 112
    """
paul@56 113
paul@56 114
    return test_for_kind(prefix, first(all_kinds))
paul@56 115
paul@67 116
def test_for_type(prefix, ref):
paul@56 117
paul@56 118
    """ 
paul@67 119
    Return an identifier describing a test condition incorporating the given
paul@67 120
    'prefix' and involving 'ref', being a program type reference. The kind of
paul@67 121
    the reference is employed in the identifier.
paul@56 122
    """
paul@56 123
paul@67 124
    return test_for_kind(prefix, ref.get_kind())
paul@56 125
paul@56 126
paul@56 127
paul@0 128
# Output program encoding.
paul@0 129
paul@0 130
def encode_function_pointer(path):
paul@0 131
paul@0 132
    "Encode 'path' as a reference to an output program function."
paul@0 133
paul@0 134
    return "__fn_%s" % encode_path(path)
paul@0 135
paul@0 136
def encode_instantiator_pointer(path):
paul@0 137
paul@0 138
    "Encode 'path' as a reference to an output program instantiator."
paul@0 139
paul@0 140
    return "__new_%s" % encode_path(path)
paul@0 141
paul@0 142
def encode_path(path):
paul@0 143
paul@0 144
    "Encode 'path' as an output program object, translating special symbols."
paul@0 145
paul@0 146
    if path in reserved_words:
paul@0 147
        return "__%s" % path
paul@0 148
    else:
paul@0 149
        return path.replace("#", "__").replace("$", "__").replace(".", "_")
paul@0 150
paul@0 151
def encode_symbol(symbol_type, path=None):
paul@0 152
paul@0 153
    "Encode a symbol with the given 'symbol_type' and optional 'path'."
paul@0 154
paul@0 155
    return "__%s%s" % (symbol_type, path and "_%s" % encode_path(path) or "")
paul@0 156
paul@56 157
paul@56 158
paul@0 159
# Output language reserved words.
paul@0 160
paul@0 161
reserved_words = [
paul@0 162
    "break", "char", "const", "continue",
paul@0 163
    "default", "double", "else",
paul@0 164
    "float", "for",
paul@0 165
    "if", "int", "long",
paul@0 166
    "NULL",
paul@0 167
    "return", "struct",
paul@0 168
    "typedef",
paul@0 169
    "void", "while",
paul@0 170
    ]
paul@0 171
paul@0 172
# vim: tabstop=4 expandtab shiftwidth=4