def set_target(self): from stalk.object import SL_String, compile_signature scope = self.e_scope expr = self.e_expr # Leading keyword without target then it's a send if type(expr) == S_Keyword: self.do_send() return # Peek ahead nexti = self.e_ec + 1 if (nexti) < self.e_end: nexpr = self.expressions[nexti] if type(expr) == S_Identifier and type(nexpr) == S_Operator and \ nexpr.get_value() == "=": #/if self.expressions.pop(nexti) self.expressions.insert(0, nexpr) self.e_ec += 2 # Move it to the next expr after the = ret = self.eval_assign() if self.e_target: self.e_target.send( compile_signature([nexpr]), # [S_Operator(=)] [SL_String(expr.get_value()), ret] ) else: scope.set_local(expr.get_value(), ret) self.e_ec = self.e_end return # TODO: Ensure 100% eval-availability so we can ditch this. # Includes having to deal with comments. try: ev = expr.eval except AttributeError as e: raise NotImplementedError("Unknown expression: "+str(expr.__class__)) self.e_target = ev(scope)
def match_send(self, recv): from stalk.object import compile_signature # Reset the send data self.e_send_sig = None self.e_send_params = None # if self.e_target: # recv = self.e_target # Receiver of the call. # else: # recv = self.e_scope expr = self.e_expr if not expr: return False #sigs = [m.get_signature() for m in recv.methods.values()] sigs = recv.get_signatures() if expr.__class__ == S_Identifier: for sig in sigs: if len(sig) != 1: next s0 = sig[0] if type(s0) == S_Identifier and s0.get_value() == expr.get_value(): self.e_send_sig = compile_signature(sig) self.e_send_params = [] return True if expr.__class__ == S_Operator: nexpr = self.next() if not nexpr: raise Exception("Need expression following "+ expr.__repr__()+" operator") if nexpr.__class__ == S_Keyword: raise Exception("Keyword cannot follow operator") for sig in sigs: if len(sig) != 2: next s0 = sig[0] #if type(s0) == S_Operator and s0.get_value() == expr.get_value(): if s0.eq(expr): self.e_send_sig = compile_signature(sig) self.e_send_params = [nexpr] return True # Filter out to just be keyword sigs now _sigs = [] for sig in sigs: if type(sig[0]) == S_Keyword: _sigs.append(sig) sigs = _sigs exprs = [] si = 0 is_keyword = True prev_e_ec = self.e_ec while expr: if len(sigs) == 0: return False if is_keyword: if expr.__class__ != S_Keyword: # TODO: Decide whether this should be greedy or not #self.prev() # Rewind to before the one we just consumed self.reset_to_counter(prev_e_ec) break # <- non-greedy #raise Exception("Unexpected non-keyword: "+expr.__repr__()) _sigs = [] for sig in sigs: if si < len(sig): se = sig[si] # TODO: Return to this and make it just one if (currently # the first one is just to appease PyPy). #if isinstance(expr, S_Keyword) and isinstance(se, S_Keyword): # if expr.get_value() == se.get_value(): if expr.eq(se): _sigs.append(sig) #/if #if expr.get_value() != se.get_value(): sigs = _sigs else: if expr.__class__ != S_Keyword: exprs.append(expr) else: raise Exception("Unexpected keyword: "+expr.__repr__()) prev_e_ec = self.e_ec expr = self.next() is_keyword = not is_keyword # Flip for style! si += 1 if len(sigs) > 0: # Sort in descending order (longest matched sig first) SigSort(sigs).sort() self.e_send_sig = compile_signature(sigs[0]) self.e_send_params = exprs return True # Didn't match! return False