# HG changeset patch # User Paul Boddie # Date 1488236409 -3600 # Node ID 11c6d30e098da863d9b28b69b3b3c45747f41a58 # Parent 9bc1e38e0f0a74eb52195d46b1ab42af5f74a3ee Moved translation result classes to a separate module. diff -r 9bc1e38e0f0a -r 11c6d30e098d translator.py --- a/translator.py Mon Feb 27 23:43:24 2017 +0100 +++ b/translator.py Tue Feb 28 00:00:09 2017 +0100 @@ -19,22 +19,26 @@ this program. If not, see . """ -from common import CommonModule, CommonOutput, InstructionSequence, \ +from common import CommonModule, CommonOutput, \ first, get_builtin_class, init_item, is_newer, \ predefined_constants from encoders import encode_access_instruction, encode_access_instruction_arg, \ - encode_function_pointer, encode_literal_constant, \ - encode_literal_instantiator, encode_instantiator_pointer, \ - encode_instructions, encode_path, \ - encode_symbol, encode_type_attribute, \ - is_type_attribute + encode_function_pointer, encode_literal_instantiator, \ + encode_instantiator_pointer, encode_path, encode_symbol, \ + encode_type_attribute, is_type_attribute from errors import InspectError, TranslateError from os.path import exists, join from os import makedirs from referencing import Reference +from results import Result +from transresults import TrConstantValueRef, TrInstanceRef, \ + TrLiteralSequenceRef, TrResolvedNameRef, \ + AttrResult, Expression, InstantiationResult, \ + InvocationResult, LogicalOperationResult, \ + LogicalResult, NegationResult, PredefinedConstantRef, \ + ReturnRef from StringIO import StringIO import compiler -import results import sys class Translator(CommonOutput): @@ -76,310 +80,13 @@ tm = TranslatedModule(module.name, self.importer, self.deducer, self.optimiser) tm.translate(module.filename, output_filename) -# Classes representing intermediate translation results. - -class ReturnRef: - - "Indicates usage of a return statement." - - pass - -class Expression(results.Result): - - "A general expression." - - def __init__(self, s): - self.s = s - def __str__(self): - return self.s - def __repr__(self): - return "Expression(%r)" % self.s - -class TrResolvedNameRef(results.ResolvedNameRef): - - "A reference to a name in the translation." - - def __init__(self, name, ref, expr=None, is_global=False, parameter=None, location=None): - results.ResolvedNameRef.__init__(self, name, ref, expr, is_global) - self.parameter = parameter - self.location = location - - def access_location(self): - return self.location - - def __str__(self): - - "Return an output representation of the referenced name." - - # For sources, any identified static origin will be constant and thus - # usable directly. For targets, no constant should be assigned and thus - # the alias (or any plain name) will be used. - - ref = self.static() - origin = ref and self.get_origin() - static_name = origin and encode_path(origin) - - # Determine whether a qualified name is involved. - - t = (not self.is_constant_alias() and self.get_name() or self.name).rsplit(".", 1) - parent = len(t) > 1 and t[0] or None - attrname = t[-1] and encode_path(t[-1]) - - # Assignments. - - if self.expr: - - # Eliminate assignments between constants. - - if ref and isinstance(self.expr, results.ResolvedNameRef) and self.expr.static(): - return "" - - # Qualified names must be converted into parent-relative assignments. - - elif parent: - return "__store_via_object(&%s, %s, %s)" % ( - encode_path(parent), attrname, self.expr) - - # All other assignments involve the names as they were given. - - else: - return "(%s%s) = %s" % (self.parameter and "*" or "", attrname, self.expr) - - # Expressions. - - elif static_name: - parent = ref.parent() - context = ref.has_kind("") and encode_path(parent) or None - return "__ATTRVALUE(&%s)" % static_name - - # Qualified names must be converted into parent-relative accesses. - - elif parent: - return "__load_via_object(&%s, %s)" % ( - encode_path(parent), attrname) - - # All other accesses involve the names as they were given. - - else: - return "(%s%s)" % (self.parameter and "*" or "", attrname) - -class TrConstantValueRef(results.ConstantValueRef): - - "A constant value reference in the translation." - - def __str__(self): - return encode_literal_constant(self.number) - -class TrLiteralSequenceRef(results.LiteralSequenceRef): - - "A reference representing a sequence of values." - - def __str__(self): - return str(self.node) - -class TrInstanceRef(results.InstanceRef): - - "A reference representing instantiation of a class." - - def __init__(self, ref, expr): - - """ - Initialise the reference with 'ref' indicating the nature of the - reference and 'expr' being an expression used to create the instance. - """ - - results.InstanceRef.__init__(self, ref) - self.expr = expr - - def __str__(self): - return self.expr - - def __repr__(self): - return "TrResolvedInstanceRef(%r, %r)" % (self.ref, self.expr) - -class AttrResult(results.Result, InstructionSequence): - - "A translation result for an attribute access." - - def __init__(self, instructions, refs, location, context_identity): - InstructionSequence.__init__(self, instructions) - self.refs = refs - self.location = location - self.context_identity = context_identity - - def references(self): - return self.refs - - def access_location(self): - return self.location - - def context(self): - return self.context_identity - - def get_origin(self): - return self.refs and len(self.refs) == 1 and first(self.refs).get_origin() - - def has_kind(self, kinds): - if not self.refs: - return False - for ref in self.refs: - if ref.has_kind(kinds): - return True - return False - - def __nonzero__(self): - return bool(self.instructions) - - def __str__(self): - return encode_instructions(self.instructions) - - def __repr__(self): - return "AttrResult(%r, %r, %r)" % (self.instructions, self.refs, self.location) - -class InvocationResult(results.Result, InstructionSequence): - - "A translation result for an invocation." - - def __str__(self): - return encode_instructions(self.instructions) - - def __repr__(self): - return "InvocationResult(%r)" % self.instructions - -class InstantiationResult(InvocationResult, TrInstanceRef): - - "An instantiation result acting like an invocation result." - - def __init__(self, ref, instructions): - results.InstanceRef.__init__(self, ref) - InvocationResult.__init__(self, instructions) - - def __repr__(self): - return "InstantiationResult(%r, %r)" % (self.ref, self.instructions) - -class PredefinedConstantRef(results.Result): - - "A predefined constant reference." - - def __init__(self, value, expr=None): - self.value = value - self.expr = expr - - def __str__(self): - - # Eliminate predefined constant assignments. - - if self.expr: - return "" - - # Generate the specific constants. - - if self.value in ("False", "True"): - return encode_path("__builtins__.boolean.%s" % self.value) - elif self.value == "None": - return encode_path("__builtins__.none.%s" % self.value) - elif self.value == "NotImplemented": - return encode_path("__builtins__.notimplemented.%s" % self.value) - else: - return self.value - - def __repr__(self): - return "PredefinedConstantRef(%r)" % self.value - -class LogicalResult(results.Result): - - "A logical expression result." - - def _convert(self, expr): - - "Return 'expr' converted to a testable value." - - if isinstance(expr, LogicalResult): - return expr.apply_test() - else: - return "__BOOL(%s)" % expr - -class NegationResult(LogicalResult): - - "A negation expression result." - - def __init__(self, expr): - self.expr = expr - - def apply_test(self): - - "Return the result in a form suitable for direct testing." - - expr = self._convert(self.expr) - return "(!%s)" % expr - - def __str__(self): - return "(%s ? %s : %s)" % ( - self._convert(self.expr), - PredefinedConstantRef("False"), - PredefinedConstantRef("True")) - - def __repr__(self): - return "NegationResult(%r)" % self.expr - -class LogicalOperationResult(LogicalResult): - - "A logical operation result." - - def __init__(self, exprs, conjunction): - self.exprs = exprs - self.conjunction = conjunction - - def apply_test(self): - - """ - Return the result in a form suitable for direct testing. - - Convert ... to ... - - and - ((__BOOL()) && (__BOOL())) - - or - ((__BOOL()) || (__BOOL())) - """ - - results = [] - for expr in self.exprs: - results.append(self._convert(expr)) - - if self.conjunction: - return "(%s)" % " && ".join(results) - else: - return "(%s)" % " || ".join(results) - - def __str__(self): - - """ - Convert ... to ... - - and - (__tmp_result = , !__BOOL(__tmp_result)) ? __tmp_result : - - or - (__tmp_result = , __BOOL(__tmp_result)) ? __tmp_result : - """ - - results = [] - for expr in self.exprs[:-1]: - results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, self.conjunction and "!" or "")) - results.append(str(self.exprs[-1])) - - return "(%s)" % "".join(results) - - def __repr__(self): - return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction) + def make_expression(expr): "Make a new expression from the existing 'expr'." - if isinstance(expr, results.Result): + if isinstance(expr, Result): return expr else: return Expression(str(expr)) @@ -616,7 +323,7 @@ # Handle processing requests on results. - if isinstance(node, results.Result): + if isinstance(node, Result): return node # Handle processing requests on nodes. diff -r 9bc1e38e0f0a -r 11c6d30e098d transresults.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/transresults.py Tue Feb 28 00:00:09 2017 +0100 @@ -0,0 +1,326 @@ +#!/usr/bin/env python + +""" +Translation result abstractions. + +Copyright (C) 2016, 2017 Paul Boddie + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +""" + +from common import first, InstructionSequence +from encoders import encode_instructions, encode_literal_constant, encode_path +from results import ConstantValueRef, InstanceRef, LiteralSequenceRef, \ + ResolvedNameRef, Result + +# Classes representing intermediate translation results. + +class ReturnRef: + + "Indicates usage of a return statement." + + pass + +class Expression(Result): + + "A general expression." + + def __init__(self, s): + self.s = s + def __str__(self): + return self.s + def __repr__(self): + return "Expression(%r)" % self.s + +class TrResolvedNameRef(ResolvedNameRef): + + "A reference to a name in the translation." + + def __init__(self, name, ref, expr=None, is_global=False, parameter=None, location=None): + ResolvedNameRef.__init__(self, name, ref, expr, is_global) + self.parameter = parameter + self.location = location + + def access_location(self): + return self.location + + def __str__(self): + + "Return an output representation of the referenced name." + + # For sources, any identified static origin will be constant and thus + # usable directly. For targets, no constant should be assigned and thus + # the alias (or any plain name) will be used. + + ref = self.static() + origin = ref and self.get_origin() + static_name = origin and encode_path(origin) + + # Determine whether a qualified name is involved. + + t = (not self.is_constant_alias() and self.get_name() or self.name).rsplit(".", 1) + parent = len(t) > 1 and t[0] or None + attrname = t[-1] and encode_path(t[-1]) + + # Assignments. + + if self.expr: + + # Eliminate assignments between constants. + + if ref and isinstance(self.expr, ResolvedNameRef) and self.expr.static(): + return "" + + # Qualified names must be converted into parent-relative assignments. + + elif parent: + return "__store_via_object(&%s, %s, %s)" % ( + encode_path(parent), attrname, self.expr) + + # All other assignments involve the names as they were given. + + else: + return "(%s%s) = %s" % (self.parameter and "*" or "", attrname, self.expr) + + # Expressions. + + elif static_name: + parent = ref.parent() + context = ref.has_kind("") and encode_path(parent) or None + return "__ATTRVALUE(&%s)" % static_name + + # Qualified names must be converted into parent-relative accesses. + + elif parent: + return "__load_via_object(&%s, %s)" % ( + encode_path(parent), attrname) + + # All other accesses involve the names as they were given. + + else: + return "(%s%s)" % (self.parameter and "*" or "", attrname) + +class TrConstantValueRef(ConstantValueRef): + + "A constant value reference in the translation." + + def __str__(self): + return encode_literal_constant(self.number) + +class TrLiteralSequenceRef(LiteralSequenceRef): + + "A reference representing a sequence of values." + + def __str__(self): + return str(self.node) + +class TrInstanceRef(InstanceRef): + + "A reference representing instantiation of a class." + + def __init__(self, ref, expr): + + """ + Initialise the reference with 'ref' indicating the nature of the + reference and 'expr' being an expression used to create the instance. + """ + + InstanceRef.__init__(self, ref) + self.expr = expr + + def __str__(self): + return self.expr + + def __repr__(self): + return "TrResolvedInstanceRef(%r, %r)" % (self.ref, self.expr) + +class AttrResult(Result, InstructionSequence): + + "A translation result for an attribute access." + + def __init__(self, instructions, refs, location, context_identity): + InstructionSequence.__init__(self, instructions) + self.refs = refs + self.location = location + self.context_identity = context_identity + + def references(self): + return self.refs + + def access_location(self): + return self.location + + def context(self): + return self.context_identity + + def get_origin(self): + return self.refs and len(self.refs) == 1 and first(self.refs).get_origin() + + def has_kind(self, kinds): + if not self.refs: + return False + for ref in self.refs: + if ref.has_kind(kinds): + return True + return False + + def __nonzero__(self): + return bool(self.instructions) + + def __str__(self): + return encode_instructions(self.instructions) + + def __repr__(self): + return "AttrResult(%r, %r, %r)" % (self.instructions, self.refs, self.location) + +class InvocationResult(Result, InstructionSequence): + + "A translation result for an invocation." + + def __str__(self): + return encode_instructions(self.instructions) + + def __repr__(self): + return "InvocationResult(%r)" % self.instructions + +class InstantiationResult(InvocationResult, TrInstanceRef): + + "An instantiation result acting like an invocation result." + + def __init__(self, ref, instructions): + InstanceRef.__init__(self, ref) + InvocationResult.__init__(self, instructions) + + def __repr__(self): + return "InstantiationResult(%r, %r)" % (self.ref, self.instructions) + +class PredefinedConstantRef(Result): + + "A predefined constant reference." + + def __init__(self, value, expr=None): + self.value = value + self.expr = expr + + def __str__(self): + + # Eliminate predefined constant assignments. + + if self.expr: + return "" + + # Generate the specific constants. + + if self.value in ("False", "True"): + return encode_path("__builtins__.boolean.%s" % self.value) + elif self.value == "None": + return encode_path("__builtins__.none.%s" % self.value) + elif self.value == "NotImplemented": + return encode_path("__builtins__.notimplemented.%s" % self.value) + else: + return self.value + + def __repr__(self): + return "PredefinedConstantRef(%r)" % self.value + +class LogicalResult(Result): + + "A logical expression result." + + def _convert(self, expr): + + "Return 'expr' converted to a testable value." + + if isinstance(expr, LogicalResult): + return expr.apply_test() + else: + return "__BOOL(%s)" % expr + +class NegationResult(LogicalResult): + + "A negation expression result." + + def __init__(self, expr): + self.expr = expr + + def apply_test(self): + + "Return the result in a form suitable for direct testing." + + expr = self._convert(self.expr) + return "(!%s)" % expr + + def __str__(self): + return "(%s ? %s : %s)" % ( + self._convert(self.expr), + PredefinedConstantRef("False"), + PredefinedConstantRef("True")) + + def __repr__(self): + return "NegationResult(%r)" % self.expr + +class LogicalOperationResult(LogicalResult): + + "A logical operation result." + + def __init__(self, exprs, conjunction): + self.exprs = exprs + self.conjunction = conjunction + + def apply_test(self): + + """ + Return the result in a form suitable for direct testing. + + Convert ... to ... + + and + ((__BOOL()) && (__BOOL())) + + or + ((__BOOL()) || (__BOOL())) + """ + + results = [] + for expr in self.exprs: + results.append(self._convert(expr)) + + if self.conjunction: + return "(%s)" % " && ".join(results) + else: + return "(%s)" % " || ".join(results) + + def __str__(self): + + """ + Convert ... to ... + + and + (__tmp_result = , !__BOOL(__tmp_result)) ? __tmp_result : + + or + (__tmp_result = , __BOOL(__tmp_result)) ? __tmp_result : + """ + + results = [] + for expr in self.exprs[:-1]: + results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, self.conjunction and "!" or "")) + results.append(str(self.exprs[-1])) + + return "(%s)" % "".join(results) + + def __repr__(self): + return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction) + +# vim: tabstop=4 expandtab shiftwidth=4