def check_number_operands(self, operator, left, right): if not isinstance(left, (float, int)): raise RuntimeException( operator, "Left operand '{}' must be number.".format( self.stringify(left))) if not isinstance(right, (float, int)): raise RuntimeException( operator, "Right operand '{}' must be number.".format( self.stringify(right)))
def get_function(self, fn): if not self.has_function(fn): raise RuntimeException("undefined function: " + fn) if (fn in self.builtin_map): return self.builtin_map[fn] if (fn in self.function_map): return self.function_map[fn] raise RuntimeException("Environment error on fetching function " + fn)
def visit_binary_expr(self, expr): left = self.evaluate(expr.left) right = self.evaluate(expr.right) if expr.operator.type == TT.MINUS: self.check_number_operands(expr.operator, left, right) return left - right elif expr.operator.type == TT.SLASH: self.check_number_operands(expr.operator, left, right) if right == 0: raise RuntimeException(expr.operator, "Attempted to divide by zero.") return left / right elif expr.operator.type == TT.STAR: self.check_number_operands(expr.operator, left, right) return left * right elif expr.operator.type == TT.PLUS: # Allow both float+float and str+str if type(left) == type(right): return left + right # Case of int + float if (isinstance(left, (int, float)) and isinstance(right, (int, float))): return left + right raise RuntimeException( expr.operator, "Operands must both be numbers or strings.") elif expr.operator.type == TT.GREATER: if left is False or right is False: return False self.check_number_operands(expr.operator, left, right) return right if left > right else False elif expr.operator.type == TT.GREATER_EQUAL: if left is False or right is False: return False self.check_number_operands(expr.operator, left, right) return right if left >= right else False elif expr.operator.type == TT.LESS: if left is False or right is False: return False self.check_number_operands(expr.operator, left, right) return right if left < right else False elif expr.operator.type == TT.LESS_EQUAL: if left is False or right is False: return False self.check_number_operands(expr.operator, left, right) return right if left <= right else False elif expr.operator.type == TT.BANG_EQUAL: return right if not self.is_equal(left, right) else False elif expr.operator.type == TT.EQUAL: return right if self.is_equal(left, right) else False elif expr.operator.type == TT.HAT: self.check_number_operands(expr.operator, left, right) return left**right
def get(self, name): if name.lexeme in self.values: if self.values[name.lexeme].assigned: return self.values[name.lexeme].value else: raise RuntimeException( name, "Can not get value of unassigned variable '{}'.".format( name.lexeme)) if self.enclosing is not None: return self.enclosing[name] raise RuntimeException(name, "Undefined variable '{}'.".format(name.lexeme))
def call(self, interpreter, arguments): try: return float(*arguments) except TypeError as err: raise RuntimeException( _self.global_token("tonumber"), "Invalid argument type for tonumber")
def get_at(self, distance, name): if self.ancestor(distance).values[name.lexeme].assigned: return self.ancestor(distance).values[name.lexeme].value else: raise RuntimeException( name, "Can not get value of unassigned variable '{}'.".format( name.lexeme))
def is_true_value(self, val): """ Decide if the val is agreeable to True. Right now keep it simple however.""" rval = False self.dbg_msg("is_true_value? " + str(val.__class__)) try: #print val, type(val) #if hasattr(val,'num'): # fval = val.num if (hasattr(val, 'evaluate')): fval = val.evaluate(None) elif (isinstance(val, float) or isinstance(val, int)): fval = val else: raise Exception("Unknown case, cannot identify truth @ " + self.get_pos() + " for value " + str(val)) if (fval > 0.0): rval = True ## all other cases later. except Exception as pyEx: """ objects where is_true_value() is not supported """ print(pyEx) raise RuntimeException(pyEx) self.dbg_msg('Is True Value? ' + str(rval) + str(val.__class__)) return rval
def call_function(self, fn): """ set call stack, used in function calls. Also check overflow""" if (len(self.call_stack) >= self.max_recursion_depth): raise RuntimeException("Maximum recursion depth [ " + str(self.max_recursion_depth) + " ]exceeded, stack overflow") self.call_stack.append(fn)
def evaluate(self, env): self.dbg_msg("Eval-if-stmt" + str(self.expr)) rval = None self.dbg_msg("eval-if stmt") if (self.is_true_value(self.expr.evaluate(env))): self.dbg_msg("ifstmt: true condition") rval = self.body.evaluate(env) return rval self.dbg_msg("ifstmt: false condition") for elseif_or_else in self.next_stmt: if (isinstance(elseif_or_else, IfStmt)): if (self.is_true_value(elseif_or_else.expr.evaluate(env))): rval = elseif_or_else.body.evaluate(env) return rval else: # elseif branch was found to be false. Continue continue elif (isinstance(elseif_or_else, ElseStmt)): rval = elseif_or_else.evaluate(env) return rval else: raise RuntimeException( "IF-ELSEIF-ELSE was parsed wrongly, unknown construct found" ) # its perfectly legal to not have an else statement return rval
def visit_call_expr(self, expr): callee = self.evaluate(expr.callee) arguments = [] for argument in expr.arguments: argument = self.evaluate(argument) arguments.append(argument) if len(arguments) != callee.arity(): raise RuntimeException( expr.paren, "Expected " + str(callee.arity()) + " arguments, but got " + str(len(arguments)) + ".") try: return callee.call(self, arguments) except Exception as e: raise e raise RuntimeException(expr.paren, "Can only call functions")
def call_function(self, fn): """ set call stack, used in function calls. Also check overflow""" if (len(self.call_stack) >= self.max_recursion_depth): raise RuntimeException("Maximum recursion depth [ " + unicode(self.max_recursion_depth) + " ] exceeded; stack overflow.") self.dbg_msg(u"calling function" + unicode(fn)) self.call_stack.append(fn)
def get(self, name): if name in self.fields: return self.fields[name] method = self.klasse.find_method(self, name.lexeme) if method is not None: return method raise RuntimeException(name, f"Undefined property {name.lexeme}.")
def assign(self, value): if Attribute.MUTABLE in self.attributes: if Attribute.UNSTABLE not in self.attributes: if self.value is not None and Type.type( self.value) != Type.type(value): raise RuntimeException( self.name, "Variable '{}' is type stable and can not change type to '{}'" .format(self.name.lexeme, Type.type(value))) self.value = value elif self.assigned: raise RuntimeException( self.name, "Variable '{}' is immutable and can not be reassigned.".format( self.name.lexeme)) else: self.value = value self.assigned = True
def assign(self, name, value): if name.lexeme in self.values: self.values[name.lexeme].assign(value) return else: if self.enclosing is not None: return self.enclosing.assign(name, value) raise RuntimeException( name, "Undefined variable '{}'.".format(name.lexeme))
def getVersion(cls): """ Returns the software version. """ try: properties = Properties() stream = cls.getResourceAsStream( "/META-INF/pywktl-version.properties") properties.load(stream) return properties.getProperty("pywktl.version") except IOException as e: raise RuntimeException(e)
def get_id(self, idee): val = None if idee in ['True', 'False']: return (idee == 'True') if not self.has_id(idee): raise RuntimeException("Identifier %s not found" % idee) variables = self.local_vars[-1] val = variables[idee] self.dbg_msg("get_id: val = " + str(val)) return val
def do_unaryop(self, tval): if (self.unaryop.kind == Token.LOGICAL_NOT): if not tval: return Boolean(True) else: return Boolean(False) else: raise RuntimeException(" unknown Unary Operation - " + str(self.unaryop) + " not supported") return
def evaluate(self, env): term = self.term.evaluate(env) if (self.debug): print(term, type(term)) if self.unaryop.kind in Token.UNARYOP: tval = Expr.normalize_values(self, term, env) if (self.debug): print(tval, type(tval)) term = self.do_unaryop(tval) else: raise RuntimeException(" unknown Unary Operation - " + str(self.unaryop) + " not supported") if (self.debug): print("term = ", term, term.__class__) return term
def evaluate(self, env): term = self.term.evaluate(env) if (self.debug): print term, type(term) if self.binop.kind in Token.BINOP: tnext = self.next_expr.evaluate(env) tval = Expr.normalize_values(self, term, env) tval2 = Expr.normalize_values(self, tnext, env) if (self.debug): print tval, type(tval), tval2, type(tval2) try: term = self.do_binop(tval, tval2, self.binop.kind) except Exception as binOp_Except: raise RuntimeException("binary operation " + str(self.term) + str(self.binop) + str(self.next_expr) + " failed with exception " + str(binOp_Except)) else: raise RuntimeException( " unknown Binary Operation - Binary operation " + str(self.binop) + " not supported") if (self.debug): print "term = ", term, term.__class__ return term
def fillContent(self, context): """ Add word list to senseEntry. """ posEntry = context.findEntry() if posEntry is None: raise RuntimeException("posEntry is None " + context.getPartOfSpeech()) for wordList in self.relationList: matchingSense = self.findMatchingSense_(posEntry, wordList) for target in wordList: matchingSense.addRelation( WiktionaryRelation(target, self.relationType))
def visit_listconstructor_expr(self, expr): start = self.evaluate(expr.start) if not isinstance(start, (int, float)): raise RuntimeException(expr.token, "Start must be iterable.") next_is_none = False if expr.next is not None: next = self.evaluate(expr.next) if not isinstance(next, (int, float)): raise RuntimeException(expr.token, "Next must be iterable.") else: next_is_none = True stop = self.evaluate(expr.stop) if not isinstance(stop, (int, float)): raise RuntimeException(expr.token, "Stop must be iterable.") if next_is_none: return list(range(start, stop + 1)) else: return list(range(start, stop + 1, next - start))
def get_id(self, idee): val = None if idee in self.readonly_global_vars: return self.readonly_global_vars[idee] if not self.has_id(idee): note = '' if idee in keyword.kwlist: note = 'Did you possibly confuse the Python english keyword %s for Ezhil keyword ?' % idee raise RuntimeException("Identifier %s not found" % idee) variables = self.local_vars[-1] val = variables[idee] self.dbg_msg("get_id: val = " + unicode(val)) return val
def evaluate(self, env): ## push stuff into the call-stack env.call_function(self.name) ## check arguments match, otherwise raise error args = env.get_args() #.get_list() env.set_local({}) if (self.use_adicity and len(args) < self.padic): raise RuntimeException("Too few args to bulitin function " + self.name) # keep evaluating for as many evaluate object-methods are available # because Python libraries don't recognize ezhil AST objects. while (any(filter(lambda x: hasattr(x, 'evaluate'), args))): args_ = [] for a in args: if hasattr(a, 'evaluate'): a = a.evaluate(env) #print(a,a.__class__) args_.append(a) args = args_ if (self.use_adicity): if (self.debug): print(self.fn, args, self.padic) rval = self.fn(*args) else: try: if (self.aslist): rval = self.fn(*[args]) else: rval = self.fn(*args) except Exception as excep: raise RuntimeException(str(excep)) env.clear_call() ## pop stuff into the call-stack env.return_function(self.name) return rval
def evaluate(self, env): self.dbg_msg(str(env)) if (env.has_function(self.fname)): self.dbg_msg("calling function " + self.fname) fval = env.get_function(self.fname) ## use applicative order evaluation. eval_arglist = [i.evaluate(env) for i in self.arglist.get_list()] env.set_args(eval_arglist) rval = fval.evaluate(env) self.dbg_msg("function retval =" + str(rval) + str(type(rval))) else: raise RuntimeException("undefined function: %s near ( %d, %d )" % (self.fname, self.line, self.col)) return rval
def normalize_values(obj, term, env): if (hasattr(term, 'evaluate')): if (term.__class__ == Number): tval = term.num elif (term.__class__ == String): tval = term.string else: ## possibly leads to inf- recursion ## tval = term.evaluate( env ) raise RuntimeException(" unknown clause to evaluate @ " + obj.get_pos()) else: tval = (term) #float cast not required. return tval
def evaluate(self, env): if (env.has_id(self.id)): val = env.get_id(self.id) if (hasattr(val, 'evaluate')): val = val.evaluate(env) elif (val.__class__ == str): #val = val pass else: #val = val pass self.dbg_msg(str(self) + " = val [" + str(val) + "]") return val raise RuntimeException("Cannot Find Identifier %s at \ Line %d, col %d" % (self.id, self.line, self.col)) return None
def normalize_values(obj, term, env): if (hasattr(term, 'evaluate')): if (isinstance( term, Number)): #work for both Number, and derived Boolean class tval = term.num elif (isinstance(term, String)): tval = term.string else: ## print term.__class__,term,str(term) ## possibly leads to inf- recursion ## tval = term.evaluate( env ) raise RuntimeException( " cannot normalize token; unknown clause," + str(term) + ", to evaluate @ " + obj.get_pos()) # elif isinstance(term,list) and len(term) == 1: # tval = term[0] else: tval = term #float cast not required. return tval
def parseWikisaurusEntries(self, title, text): result = set() reader = StringReader(text) currentLang = None currentPos = None currentRelType = None inList = False inRelation = False inSense = False wikisaurusSense = None try: for line in reader.readLines(): line = line.strip() if not len(line): continue countSectionIdentifier = 0 while countSectionIdentifier < len( line) and line[countSectionIdentifier] == '=': countSectionIdentifier += 1 line = line.replace("=", "") if wikisaurusSense is not None and 2 <= countSectionIdentifier < 4 \ or (countSectionIdentifier == 4 and line.startswith("{{ws sense")): result.add(wikisaurusSense) wikisaurusSense = None if countSectionIdentifier == 2: # Language currentLang = Language.findByName(line) inRelation = False inSense = False elif countSectionIdentifier == 3: # POS currentPos = PartOfSpeech.findByName( line) # TODO: language-specific POS tags? inRelation = False inSense = False elif countSectionIdentifier == 4 and line.startswith( "{{ws sense"): # Sense senseDef = self.extractSenseDefinition(line) wikisaurusSense = WikisaurusEntry(title, currentPos, currentLang, senseDef) inRelation = False inSense = True elif (countSectionIdentifier == 5 or countSectionIdentifier == 4) and inSense: # Relation type currentRelType = self.relTypeMap.get(line.strip().lower()) inRelation = True if currentRelType is None: print(title + " RELATION NOT FOUND: " + line) if line in self.notFoundRelation: self.notFoundRelation[ line] = self.notFoundRelation[line] + 1 else: self.notFoundRelation[line] = 1 elif line.startswith("{{ws beginlist"): inList = True elif line.startswith("{{ws endlist"): inList = False elif line.startswith("{{ws|") and inRelation and inList: target = self.extractRelTarget(line) if currentRelType is not None: wikisaurusSense.addRelation(target[0], target[1], currentRelType) if wikisaurusSense is not None: result.add(wikisaurusSense) except IOException as e: raise RuntimeException( "Error while parsing text of Wikisaurus page " + title, e) return result
def return_function(self, fn): va = self.call_stack.pop() if (fn != va): raise RuntimeException("function %s doesnt match Top-of-Stack" % fn) return va
def assign_at(self, distance, name, value): try: self.ancestor(distance).values[name.lexeme].assign(value) except RuntimeException as exc: raise RuntimeException(name, exc.msg)