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
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
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
def visitStore(self, ctx: BSParser.StoreContext): use = self.visitVariable(ctx.variable()) symbol = self.symbol_table.get_local(use['name']) if not symbol: raise UndefinedVariable("{} is not defined.".format(use['name'])) if not ChemTypeResolver.is_mat_in_set(symbol.types): symbol.types.add(ChemTypes.MAT) self.symbol_table.update_symbol(symbol) return None
def visitDispose(self, ctx: BSParser.DisposeContext): name = self.visitVariable(ctx.variable())['name'] use = self.symbol_table.get_local(name) if not use: raise UndefinedVariable("{} is not defined.".format(name)) if not ChemTypeResolver.is_mat_in_set(use.types): use.types.add(ChemTypes.MAT) self.symbol_table.update_symbol(use) return None
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
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
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