Beispiel #1
0
    def visitMix(self, ctx: BSParser.MixContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())

        symbol = Symbol(deff['name'], self.scope_stack[-1],
                        self.resolve_types(deff))
        # Look through the RHS vars.
        for fluid in ctx.variable():
            temp = self.visitVariable(fluid)
            var = self.symbol_table.get_local(temp['name'])
            if not var:
                raise UndefinedVariable("{}.{} is not defined.".format(
                    self.scope_stack[-1], temp['name']))
            if not ChemTypeResolver.is_mat_in_set(var.types):
                # This is the best we can do at this point.
                # We won't be able to further classify anything
                # further because if the identifier hasn't
                # figured anything out by now, it won't.
                var.types.update(
                    self.resolve_types({
                        'name': var.name,
                        'types': var.types
                    }))
            # Update the RHS types.
            self.symbol_table.update_symbol(var)
            # Union the types of the RHS with the LHS
            symbol.types.update(var.types)
        # Add the symbol to the table.
        self.symbol_table.add_local(symbol)
        return None
Beispiel #2
0
    def visitGradient(self, ctx: BSParser.GradientContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())
        symbol = Symbol(deff['name'], self.scope_stack[-1],
                        self.resolve_types(deff))
        for var_def in ctx.variable():
            use = self.visitVariable(var_def)
            var = self.symbol_table.get_local(use['name'],
                                              self.scope_stack[-1])
            if not var:
                raise UndefinedVariable("{} is not defined.".format(
                    use['name']))
            if not ChemTypeResolver.is_mat_in_set(var.types):
                var.types.add(ChemTypes.MAT)
            self.symbol_table.update_symbol(var)
            symbol.types.update(var.types)

        self.symbol_table.add_local(symbol)

        start = float(ctx.FLOAT_LITERAL(0).__str__())
        end = float(ctx.FLOAT_LITERAL(1).__str__())
        at = float(ctx.FLOAT_LITERAL(2).__str__())

        if start >= end:
            raise UnsupportedOperation(
                "The beginning concentration must be smaller than the ending concentration."
            )
        if at <= 0.0:
            raise UnsupportedOperation("You cannot have a negative rate.")

        return None
Beispiel #3
0
 def visitFormalParameter(self, ctx: BSParser.FormalParameterContext):
     if ctx.unionType():
         types = self.visitUnionType(ctx.unionType())
     else:
         types = {ChemTypes.UNKNOWN}
     var = ctx.IDENTIFIER().__str__()
     symbol = Symbol(var, self.scope_stack[-1], types)
     self.symbol_table.add_local(symbol)
     return symbol
Beispiel #4
0
 def visitDispense(self, ctx: BSParser.DispenseContext):
     deff = self.visitVariableDefinition(ctx.variableDefinition())
     deff['types'].update(
         self.symbol_table.get_global(ctx.IDENTIFIER().__str__()).types)
     self.symbol_table.add_local(
         Symbol(deff['name'], self.scope_stack[-1],
                self.resolve_types(deff)))
     if not self.symbol_table.get_global(ctx.IDENTIFIER().__str__()):
         raise UndefinedVariable(
             "{} isn't declared in the manifest.".format(
                 ctx.IDENTIFIER().__str__()))
     return None
Beispiel #5
0
 def visitSplit(self, ctx: BSParser.SplitContext):
     deff = self.visitVariableDefinition(ctx.variableDefinition())
     use = self.visitVariable(ctx.variable())
     if not self.symbol_table.get_local(use['name']):
         raise UndefinedVariable("{} is not defined.".format(use['name']))
     if not ChemTypeResolver.is_mat_in_set(deff['types']):
         deff['types'].update(
             self.identifier.identify(deff['name'], deff['types']))
     if ChemTypes.UNKNOWN in deff['types']:
         deff['types'].remove(ChemTypes.UNKNOWN)
     deff['types'].update(self.symbol_table.get_local(use['name']).types)
     self.symbol_table.add_local(
         Symbol(deff['name'], self.scope_stack[-1], deff['types']))
     return None
Beispiel #6
0
    def visitMethodInvocation(self, ctx: BSParser.MethodInvocationContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())

        method_name, args = self.visitMethodCall(ctx.methodCall())

        if len(args) != len(self.symbol_table.functions[method_name].args):
            raise UnsupportedOperation(
                "Function {} takes {} arguments; {} arguments provided.".
                format(method_name,
                       len(self.symbol_table.functions[method_name].args),
                       len(args)))

        symbol = Symbol(deff['name'], self.scope_stack[-1],
                        self.symbol_table.functions[method_name].types)

        self.symbol_table.add_local(symbol)

        return None
Beispiel #7
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)
Beispiel #8
0
 def visitDetect(self, ctx: BSParser.DetectContext):
     deff = self.visitVariableDefinition(ctx.variableDefinition())
     self.symbol_table.add_local(
         Symbol(deff['name'], self.scope_stack[-1],
                ChemTypeResolver.numbers()))
     use = self.visitVariable(ctx.variable())
     var = self.symbol_table.get_local(use['name'])
     if not var:
         raise UndefinedVariable("{} is not defined.".format(use['name']))
     module = self.symbol_table.get_global(ctx.IDENTIFIER().__str__())
     if not module:
         raise UndefinedVariable(
             "{} isn't declared in the manifest.".format(
                 ctx.IDENTIFIER().__str__()))
     if ChemTypes.MODULE not in module.types:
         raise UndefinedVariable(
             "There is no module named {} declared in the manifest.".format(
                 module.name))
     if not ChemTypeResolver.is_mat_in_set(var.types):
         var.types.add(ChemTypes.MAT)
         self.symbol_table.update_symbol(var)
     return None
Beispiel #9
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)
Beispiel #10
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()