Example #1
0
 def update_symbol(self, symbol: Symbol) -> Symbol:
     self.current_scope.locals[symbol.name] = symbol
     #if symbol.value == None and symbol.scope is not 'main' and next(iter(self.scope_map[symbol.scope].locals)) == symbol.name:
         #symbol.value = Reagent(symbol.name, 1, 10.0, BSVolume.MICROLITRE) #add a pseudo value
     if symbol.value == None and symbol.scope is not 'main' and symbol.name in self.scope_map[symbol.scope].locals:
         symbol.value = Reagent(symbol.name, 1, 10.0, BSVolume.MICROLITRE)  # add a pseudo value
     elif symbol.value == None and len(symbol.types) == 2:
         symbol.value = Reagent(symbol.name, 1, 10.0, BSVolume.MICROLITRE)  # add a pseudo value
     return symbol
Example #2
0
    def visitRepeat(self, ctx: BSParser.RepeatContext):
        # 'repeat value times' is translated in the IR as while (value > 0), with a decrement
        #   appended to the end of the expression block; hence,
        #    to ease translation later, we add a global for const(0) and const(1)
        if not self.symbol_table.get_global('CONST_0'):
            globalz = Symbol('CONST_0', 'global', ChemTypeResolver.numbers())
            globalz.value = Number('CONST_0', 1, 0)
            self.symbol_table.add_global(globalz)

        if not self.symbol_table.get_global('CONST_1'):
            globalz = Symbol('CONST_1', 'global', ChemTypeResolver.numbers())
            globalz.value = Number('CONST_1', 1, 1)
            self.symbol_table.add_global(globalz)

        self.visitChildren(ctx)
Example #3
0
    def visitMath(self, ctx: BSParser.MathContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())
        symbol = Symbol(deff['name'], self.scope_stack[-1],
                        ChemTypeResolver.numbers())

        for use in ctx.primary():
            var = self.visitPrimary(use)

            # This places any constants into the global symbol table.
            # By doing this, it makes it significantly easier to handle
            # arithmetic later in the compilation process.
            if 'value' in var.keys() and not self.symbol_table.get_global(
                    var['name']):
                globalz = Symbol(var['name'], 'global',
                                 ChemTypeResolver.numbers())
                globalz.value = Number(var['name'], 1, var['value'])
                self.symbol_table.add_global(globalz)

            if not ChemTypeResolver.is_number_in_set(var['types']):
                local = self.symbol_table.get_local(var['name'])
                if not local:
                    raise UndefinedVariable("{} is not defined.".format(
                        var['name']))
                local.types.update(ChemTypeResolver.numbers())
                if ChemTypes.UNKNOWN in local.types:
                    local.types.remove(ChemTypes.UNKNOWN)
                self.symbol_table.update_symbol(local)

        self.symbol_table.add_local(symbol)

        return None
Example #4
0
    def visitBinops(self, ctx: BSParser.BinopsContext):
        op1 = self.visitPrimary(ctx.primary(0))
        op2 = self.visitPrimary(ctx.primary(1))

        # This places any constants into the global symbol table.
        # By doing this, it makes it significantly easier to handle
        # arithmetic later in the compilation process.
        if 'value' in op1.keys() and not self.symbol_table.get_global(
                op1['name']):
            globalz = Symbol(op1['name'], 'global', ChemTypeResolver.numbers())
            globalz.value = Number(op1['name'], 1, op1['value'])
            self.symbol_table.add_global(globalz)
        if 'value' in op2.keys() and not self.symbol_table.get_global(
                op2['name']):
            globalz = Symbol(op2['name'], 'global', ChemTypeResolver.numbers())
            globalz.value = Number(op2['name'], 1, op2['value'])
            self.symbol_table.add_global(globalz)
Example #5
0
 def visitExpressionList(self, ctx: BSParser.ExpressionListContext):
     args = list()
     for primary in ctx.primary():
         arg = self.visitPrimary(primary)
         if 'value' in arg.keys() and self.symbol_table.get_global(
                 "CONST_{}".format(arg['value'])) is None:
             const = Symbol('CONST_{}'.format(arg['value']), 'global',
                            arg['value'])
             const.value = Number(const.name, 1, arg['value'])
             self.symbol_table.add_global(const)
         args.append(self.visitPrimary(primary))
     return args
Example #6
0
 def visitNumberAssignment(self, ctx: BSParser.NumberAssignmentContext):
     deff = self.visitVariableDefinition(ctx.variableDefinition())
     symbol = Symbol(deff['name'], self.scope_stack[-1],
                     ChemTypeResolver.numbers())
     self.symbol_table.add_local(symbol)
     # Yes, this is assigning value to something,
     # But this is a constant.  So we know all
     # of the values up front.  This also makes
     # the IRVisitor easier to work with.
     value = self.visitLiteral(ctx.literal())
     const = Symbol('CONST_{}'.format(value), 'global',
                    ChemTypeResolver.numbers())
     const.value = Number('CONST_{}'.format(value), 1, value)
     self.symbol_table.add_global(const)
Example #7
0
    def visitRepeat(self, ctx: BSParser.RepeatContext):
        # get the (statically defined!) repeat value and add to local symbol table
        value = self.visitLiteral(ctx)
        val = {
            'name': "REPEAT_{}".format(value),
            "index": 0,
            'value': value,
            'types': ChemTypeResolver.numbers()
        }

        if 'value' in val.keys() and not self.symbol_table.get_local(
                val['name']):
            localz = Symbol(val['name'], 'global', ChemTypeResolver.numbers())
            localz.value = Number(val['name'], 1, val['value'])
            self.symbol_table.add_local(localz)

        # finished with this block
        self.functions[self.scope_stack[-1]]['blocks'][
            self.current_block.nid] = self.current_block

        # insert header block for the conditional
        header_block = BasicBlock()
        header_label = Label("bsbbr_{}_h".format(header_block.nid))
        self.labels[header_label.name] = header_block.nid
        header_block.add(header_label)
        self.graph.add_node(header_block.nid,
                            function=self.scope_stack[-1],
                            label=header_label.label)
        self.functions[self.scope_stack[-1]]['blocks'][
            header_block.nid] = header_block
        self.graph.add_edge(self.current_block.nid, header_block.nid)

        zero = self.symbol_table.get_global('CONST_0')
        op = BinaryOp(left={
            'name': val['name'],
            'offset': 0,
            'size': 1,
            'var': self.symbol_table.get_local(val['name'])
        },
                      right={
                          'name': zero.name,
                          'offset': 0,
                          'size': 1,
                          'var': zero
                      },
                      op=RelationalOps.GT)
        condition = Conditional(
            RelationalOps.GT, op.left,
            op.right)  # Number('Constant_{}'.format(0), 1, 0))
        header_block.add(condition)

        self.control_stack.append(header_block)

        # set up the true block
        true_block = BasicBlock()
        true_label = Label("bsbbr_{}_t".format(true_block.nid))
        self.labels[true_label.name] = true_block.nid
        true_block.add(true_label)
        self.graph.add_node(true_block.nid, function=self.scope_stack[-1])
        self.functions[self.scope_stack[-1]]['blocks'][
            true_block.nid] = true_block
        condition.true_branch = true_label
        self.graph.add_edge(header_block.nid, true_block.nid)

        self.current_block = true_block
        self.visitBlockStatement(ctx.blockStatement())

        # repeat is translated to a while loop as: while (exp > 0);
        # hence, we update exp by decrementing.
        one = self.symbol_table.get_global('CONST_1')

        ir = Math(
            {
                'name': val['name'],
                'offset': 0,
                'size': 1,
                'var': self.symbol_table.get_local(val['name'])
            }, {
                'name': val['name'],
                'offset': 0,
                'size': 1,
                'var': self.symbol_table.get_local(val['name'])
            }, {
                'name': one.name,
                'offset': 0,
                'size': 1,
                'var': one
            }, BinaryOps.SUBTRACT)

        self.current_block.add(ir)

        # the block statement may contain nested loops
        # If so, the current block is the last false block created for the inner-most loop
        #    otherwise, the current block is the true_block created above
        # Either way, we can pop the control stack to find where to place the back edge
        #   and immediately make the back edge (from 'current block' to the parent
        parent_block = self.control_stack.pop()
        self.graph.add_edge(self.current_block.nid, parent_block.nid)

        # we now deal with the false branch
        false_block = BasicBlock()

        false_label = Label("bsbbr_{}_f".format(false_block.nid))
        self.labels[false_label.name] = false_block.nid
        false_block.add(false_label)
        condition.false_branch = false_label
        self.graph.add_edge(header_block.nid, false_block.nid)
        # We are done, so we need to handle the book keeping for
        # next basic block generation.
        self.graph.add_node(false_block.nid, function=self.scope_stack[-1])
        self.functions[self.scope_stack[-1]]['blocks'][
            false_block.nid] = false_block

        self.current_block = false_block

        return NOP()