source: proto/Compiler/pablo_error_handling.py @ 3571

Last change on this file since 3571 was 3571, checked in by nmedfort, 6 years ago

start of error rewriting work. some clean up done to pablo.py; a few classes in it were moved to pablo_util.py.

File size: 4.3 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4import ast
5import mkast
6import re
7from pablo_util import TempifyBuiltins
8from carryInfo import *
9
10# what if an error is used as part of an expression? it'd have to be 'tempified' and the replacement used appropriately
11# what if an error is set to a value? that ought to be replaced with an OR.
12
13# if we're outermost operation on an error computation is an Advance, the actual advancement is meaningless
14# since we only want to  determine whether there is an error. However, the temporary error value could be
15# used in some other statement.
16
17#if is_BuiltIn_Call(node.value, 'Advance', 1):
18#    print ast.dump(node.value)   
19
20class RewriteErrorStatements(ast.NodeTransformer):
21   
22    def __init__(self, tempifier):       
23        self.tempifier = tempifier       
24        self.tempified = dict()
25        self.anyErrorNode = ast.Name("__any_error", ast.Load())
26                         
27    def xfrm(self, node):
28        return self.generic_visit(node)         
29       
30    def visit_Call(self, node):
31        self.generic_visit(node)
32        # scan through and replace any error node with its temporary name
33        for i in range(0, len(node.args)):                                   
34            node.args[i] = self.subsituteErrorNode(node.args[i])
35        return node
36       
37    def subsituteErrorNode(self, node):
38        if self.isErrorNode(node) and node in self.tempified:
39            return self.tempified[node]
40        return node
41
42    def visit_Assign(self, node):               
43        self.generic_visit(node)
44        # have we found an assignment that is assigning a value to an error type?
45        if self.isErrorNode(node.targets[0]): 
46            # if we're simply initializing an error to 0, remove the node entirely.           
47            if self.isConstant0(node.value):
48                return None
49            # else, tempify the value           
50            temporaryVariable = self.generateNameNode(node.targets[0])
51            trasformedNode = ast.Assign([temporaryVariable], node.value)           
52            # rescan the node value to tempify any "error.x = error.x OP y" type statements           
53            self.generic_visit(trasformedNode)           
54            trasformedNode = self.simplifyAssignmentStatement(trasformedNode)           
55            # check once more to see if, after transforming the node, we're ORing in 0; if so, remove the node.           
56            if self.isConstant0(trasformedNode.value):
57                return None           
58            return [trasformedNode] + [ast.Assign([self.anyErrorNode], mkast.call('simd_or', [self.anyErrorNode, temporaryVariable]))]   
59        return node   
60       
61    def isErrorNode(self, x):
62        return isinstance(x, ast.Attribute) and isinstance(x.value, ast.Name) and x.value.id == 'errors'       
63       
64    def generateNameNode(self, name):
65        if name in self.tempified:
66            return self.tempified[name]
67        else:
68            temporaryVariable = ast.Name(self.tempifier.genVar(), ast.Load())
69            self.tempified[name] = temporaryVariable
70            return temporaryVariable
71         
72    def isConstant0(self, x):
73        if isinstance(x, ast.Call) and isinstance(x.func, ast.Name):           
74            return x.func.id == 'simd<1>::constant<0>'
75        return False
76       
77    def simplifyAssignmentStatement(self, node):
78        # change any "error.x = error.x | y" into "temp_error_x = y"
79        if isinstance(node.value, ast.Call) and is_BuiltIn_Call(node.value, "simd_or", 2):           
80            if node.targets[0] == node.value.args[0]:
81                return ast.Assign(node.targets, self.scanForOrStatement(node.targets[0], node.value.args[1]))
82            if node.targets[0] == node.value.args[1]:
83                return ast.Assign(node.targets, self.scanForOrStatement(node.targets[0], node.value.args[0]))
84        return node
85       
86    def scanForOrStatement(self, target, node):
87        # scan any internal ORs to see if the tempified value is being OR'd with itself prior to initialization
88        if isinstance(node, ast.Call) and is_BuiltIn_Call(node, "simd_or", 2):
89            if target == node.args[0]:
90                return self.simplifyOrStatement(target, node.args[1])
91            elif target == node.args[1]:
92                return self.simplifyOrStatement(target, node.args[0])
93        return node
Note: See TracBrowser for help on using the repository browser.