Пример #1
0
 def check_bounds(self, var: Dict) -> bool:
     # Make one last-ditch effort to find the symbol.
     if var['var'] is None:
         var['var'] = self.symbol_table.get_symbol(var['name']).value
     # If there isn't a value, assume all is good.
     if not var['var']:
         return True
     if var['index'] >= var['var'].size:
         raise InvalidOperation("{}[{}] is out of bounds, which has a size of {}"
                                .format(var['var'].name, var['index'], var['var'].size))
     return True
Пример #2
0
    def visitMix(self, ctx: BSParser.MixContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())
        symbol = self.symbol_table.get_local(deff['name'], self.scope_stack[-1])

        if ctx.timeIdentifier():
            temp_time = self.visitTimeIdentifier(ctx.timeIdentifier())
            time = (temp_time['quantity'], temp_time['units'])
        else:
            time = (10, BSTime.SECOND)

        uses = list()
        for fluid in ctx.variable():
            use = self.visitVariable(fluid)
            var = self.symbol_table.get_local(use['name'], self.scope_stack[-1]).value
            uses.append({'var': var, 'index': use['index'], 'name': use['name']})
        use_a = uses[0]
        use_b = uses[1]

        # Get the time modifier, should one exist.
        time_meta = None
        if ctx.timeIdentifier():
            time = self.visitTimeIdentifier(ctx.timeIdentifier())
            time_meta = TimeConstraint(IRInstruction.MIX, time['quantity'], time['units'])

        if (use_a['index'] == -1 and use_a['var'].size > 1) and (use_b['index'] == -1 and use_b['var'].size > 1):
            if use_a['var'].size != use_b['var'].size:
                raise InvalidOperation("{} is not the same size as {}".format(use_a['var'].name, use_b['var'].name))
            size = use_a['var'].size
        else:
            self.check_bounds(use_a)
            self.check_bounds(use_b)
            size = 1

        if not symbol.value:
            # Update the symbol in the symbol table with the new value.
            symbol.value = Movable(deff['name'], size)

        ir = Mix({'name': deff['name'], 'offset': deff['index'], 'size': size, 'var': symbol},
                 {'name': use_a['var'].name, 'offset': use_a['index'], 'size': use_a['var'].size, 'var': use_a['var']},
                 {'name': use_b['var'].name, 'offset': use_b['index'], 'size': use_b['var'].size, 'var': use_b['var']})
        if time_meta:
            ir.meta.append(time_meta)
        self.current_block.add(ir)

        return None
Пример #3
0
    def visitBinops(self, ctx: BSParser.BinopsContext):
        op1 = self.visitPrimary(ctx.primary(0))
        op2 = self.visitPrimary(ctx.primary(1))

        op1_var = self.symbol_table.get_symbol(op1['name'], self.scope_stack[-1])
        op2_var = self.symbol_table.get_symbol(op2['name'], self.scope_stack[-1])

        if (op1['index'] == -1 and op1_var.value.size > 1) or (op2['index'] == -1 and op2_var.value.size > 1):
            raise InvalidOperation("You provided an array to condition; you must provide a valid offset.")

        # This must come after the conditional above.  Otherwise,
        # there is no guarantee we mantain syntactic fidelity.
        op1['index'] = 0 if op1['index'] == -1 else op1['index']
        op2['index'] = 0 if op2['index'] == -1 else op2['index']

        self.check_bounds({'name': op1['name'], 'index': op1['index'], 'var': op1_var.value})
        self.check_bounds({'name': op2['name'], 'index': op2['index'], 'var': op2_var.value})

        if ctx.EQUALITY():
            operand = RelationalOps.EQUALITY
        elif ctx.NOTEQUAL():
            operand = RelationalOps.NE
        elif ctx.LT():
            operand = RelationalOps.LT
        elif ctx.LTE():
            operand = RelationalOps.LTE
        elif ctx.GT():
            operand = RelationalOps.GT
        elif ctx.GTE():
            operand = RelationalOps.GTE
        else:
            operand = RelationalOps.EQUALITY

        return {"op1": {'var': op1_var, 'offset': op1['index'], 'name': op1_var.name, 'size': op1_var.value.size},
                "op2": {'var': op2_var, 'offset': op2['index'], 'name': op2_var.name, 'size': op1_var.value.size},
                'operand': operand}
Пример #4
0
    def visitMix(self, ctx: BSParser.MixContext):
        deff = self.visitVariableDefinition(ctx.variableDefinition())

        # Start of volume parsing
        _volume = []  # A list that holds all the (if any) units parsed.

        if len(ctx.unitTracker()) == 0:
            _volume = [10, 10]

        if len(ctx.unitTracker()) == 1:

            pos_unit_tracker = -1
            pos_var_def = []

            for i in range(
                    len(ctx.children)
            ):  # Find the relative position of the unit tracker context and variable contexts

                if type(ctx.children[i]) == BSParser.VariableContext:
                    pos_var_def.append(
                        i
                    )  # Record the position of all variable contexts. There should always and only be two.

                if type(ctx.children[i]) == BSParser.UnitTrackerContext:
                    pos_unit_tracker = i  # Record the position of the unit tracker context. Since this is the case where only one parameter was passed,there should always and only be one instance in this case.

            if min(
                    pos_var_def
            ) > pos_unit_tracker:  # If the unit tracker appears before the first variable definition
                _volume.append(
                    int(ctx.unitTracker()[0].INTEGER_LITERAL().__str__())
                )  # Assume that the unit tracker is storing the parameter for the first variable
                _volume.append(10)

            else:
                _volume.append(10)
                _volume.append(
                    int(ctx.unitTracker()[0].INTEGER_LITERAL().__str__())
                )  # If it isn't the first variable's parameter, it must be the second's.

        if len(ctx.unitTracker()) == 2:
            for i in range(
                    2
            ):  # Iterate through the contents of the list returned by unitTracker()
                if type(ctx.unitTracker()[i]) != BSParser.UnitTrackerContext:
                    _volume.append(
                        10
                    )  # Default to 10 if the volume hasn't been explicitly declared
                else:
                    _volume.append(
                        int(ctx.unitTracker()[i].INTEGER_LITERAL().__str__()))

        #print(_volume)
        # end of volume parsing

        symbol = self.symbol_table.get_local(deff['name'],
                                             self.scope_stack[-1])

        if ctx.timeIdentifier():
            temp_time = self.visitTimeIdentifier(ctx.timeIdentifier())
            time = (temp_time['quantity'], temp_time['units'])
        else:
            time = (10, BSTime.SECOND)

        uses = list()
        for fluid in ctx.variable():
            use = self.visitVariable(fluid)
            var = self.symbol_table.get_local(use['name'],
                                              self.scope_stack[-1]).value
            uses.append({
                'var': var,
                'index': use['index'],
                'name': use['name']
            })
        use_a = uses[0]
        use_b = uses[1]

        # Get the time modifier, should one exist.
        time_meta = None
        if ctx.timeIdentifier():
            time = self.visitTimeIdentifier(ctx.timeIdentifier())
            time_meta = TimeConstraint(IRInstruction.MIX, time['quantity'],
                                       time['units'])

        if (use_a['index'] == -1
                and use_a['var'].size > 1) and (use_b['index'] == -1
                                                and use_b['var'].size > 1):
            if use_a['var'].size != use_b['var'].size:
                raise InvalidOperation("{} is not the same size as {}".format(
                    use_a['var'].name, use_b['var'].name))
            size = use_a['var'].size
        else:
            self.check_bounds(use_a)
            self.check_bounds(use_b)
            size = 1

        if not symbol.value:
            # Update the symbol in the symbol table with the new value
            symbol.value = Movable(deff['name'], size, volume=float(-1))

        ir = Mix(
            {
                'name': deff['name'],
                'offset': deff['index'],
                'size': size,
                'var': symbol
            }, {
                'name': use_a['var'].name,
                'offset': use_a['index'],
                'size': use_a['var'].size,
                'var': use_a['var']
            }, {
                'name': use_b['var'].name,
                'offset': use_b['index'],
                'size': use_b['var'].size,
                'var': use_b['var']
            })
        if time_meta:
            ir.meta.append(time_meta)

        self.symbol_table.get_local(
            deff['name'], self.scope_stack[-1]).volumes[ir.iid] = _volume

        self.current_block.add(ir)

        return None