aboutsummaryrefslogtreecommitdiff
path: root/ql/ast/visitors/reference_visitor.py
blob: 5cbbcc75d929ed13f95d8d4ede7f8b4c4e34ddab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from multimethods import multimethod

from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode
from ql.ast.nodes.expressions.literals.literal import LiteralNode
from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode
from ql.ast.nodes.expressions.variable import VariableNode
from ql.ast.nodes.statements.form_statement import FormNode
from ql.ast.nodes.statements.if_statement import IfNode
from ql.ast.nodes.statements.question_statement import QuestionNode


class ReferenceVisitor:
    def __init__(self):
        self.__current_block = []
        self.__current_scope = {}

    @property
    def identifier_scopes(self):
        return self.__current_scope

    @multimethod(FormNode)
    def visit(self, node):
        self.__current_scope = {
            'content':  [],
            'children': [],
        }
        self.__current_block = []

        for child in node.block:
            child.accept(self)

        self.__current_scope['content'] = self.__current_block

    @multimethod(IfNode)
    def visit(self, node):
        node.condition.accept(self)

        self.__current_scope['content'] += self.__current_block
        previous_scope = self.__current_scope
        previous_block = self.__current_block
        self.__current_block = []
        self.__current_scope = {
            'content':  [],
            'children': [],
        }

        for child in node.block:
            child.accept(self)

        self.__current_scope['content'] = self.__current_block
        previous_scope['children'].append(self.__current_scope)
        self.__current_block = previous_block
        self.__current_scope = previous_scope

    @multimethod(QuestionNode)
    def visit(self, node):
        self.__current_block.append(dict({
            'name': node.identifier,
            'type': node.answer_type,
            'line': node.metadata.line,
        }))

        if node.computed:
            node.answer.accept(self)

    @multimethod(BinaryOperatorNode)
    def visit(self, node):
        node.left_expression.accept(self)
        node.right_expression.accept(self)

    @multimethod(UnaryOperatorNode)
    def visit(self, node):
        node.expression.accept(self)

    @multimethod(VariableNode)
    def visit(self, node):
        name = node.identifier
        self.__current_block.append({
            'name': name,
            'type': [],
            'line': node.metadata.line,
        })

    @multimethod(LiteralNode)
    def visit(self, node):
        pass