def eval(self, code): if type(code) == str: toks = tokenize.tokenize(code) else: toks = code for tok in toks: #print(tok) # Push any literals to the stack if tok.type.startswith("lit_"): self.stack.push(tok) # Create a list elif tok.type == "listend": contents = [] while True: thing = self.stack.pop() if hasattr(thing, "type") and thing.type == "lit_liststart": break contents.append(thing) self.stack.push(tokenize.Token("lit_list", list(reversed(contents)))) # "Call" something elif tok.type == "call": val = self.lookup(tok.val) if type(val) in self.FUNCTION_TYPES: # If the final value is a function, we call it. This is how extension modules work self.call_external(val) elif type(val) == tokenize.Token and val.type == "lit_code": # We got a Nustack function, so we should call it. namesplit = tok.val.split("::") if len(namesplit) > 1: newscope = self.scope.getGlobal(namesplit[0]) else: newscope = None self.scope.pushScope(newscope) self.eval(val.val) self.scope.popScope() else: # Else, we got a literal and we should push it on the stack self.stack.push(val)
def _parse(self): self._toks = tokenize.tokenize(self._code)
def eval(self, code): if type(code) == str: toks = tokenize.tokenize(code) else: toks = code for tok in toks: # Push any literals to the stack if tok.type.startswith("lit_"): self.stack.push(tok) # Create a list elif tok.type == "listend": contents = [] while True: thing = self.stack.pop() if thing.type == "lit_liststart": break contents.append(thing) self.stack.push(tokenize.Token("lit_list", list(reversed(contents)))) # "Call" something elif tok.type == "call": # This is the tricky one # First, if we are actually loading something from a module ("Mod::thing"), split it up around the "::" if "::" in tok.val: valname = tok.val.split("::") else: # Else, we are only getting the top-leval object valname = [tok.val] # Now we locate it try: # First, we try to look it up through the scpes val = self.scope.lookup(valname[0]) except ScopeLookupError: # If it's not defined by the program, it might be a builtin. If it's not, the builtins module will raise a NotDefinedError f = builtins.getword(valname[0]) f(self) else: # The scope lookup completed without an error # If len(valname) > 1, we need to lookup any sub-modules if len(valname) > 1: # Lookup any sub-modules top = valname[0] valname = valname[1:] for name in valname: val = val.get(name) if type(val) == types.FunctionType: # If the final value is a function, we call it. This is how extension modules work val(self) elif val.type == "lit_code": # We got a Nustack function, so we should call it. topscope = self.scope.getGlobal(top) self.scope.pushScope(topscope.scope) self.eval(val.val) self.scope.popScope() else: # Else, we got a iteral and we should push it on the stack self.stack.push(val) # Otherwise, we just directly handle the value elif val.type != "lit_code": # If the value is not code, push it to the stack self.stack.push(val) else: # Else, call it with a new scope. self.scope.pushScope() self.eval(val.val) self.scope.popScope()