def evaluate(atom, called_from="", return_object=False): if atom.quote: atom.quote -= 1 return atom elif atom.type == Atom.KEYWORD: return atom.data elif atom.type == Atom.SYMBOL: value = Environment.get_symbol_value(atom.data) if value is not None: return value else: raise LispError("%s: Undefined symbol %s" % (called_from, atom.data)) elif atom.type == Atom.CONS: if atom.data.quote: atom.data.quote -= 1 return atom fun = atom.data.first.data if fun not in Functions.functions: raise LispError("%s: Undefined function %s" % (called_from, fun)) args = cons_to_list(atom.data.second.data) result = Functions.functions[fun](fun, args) return result else: return atom if return_object else atom.data
def symbol_read_line(fun, args): handle = eval(args[0], fun) if handle not in file_handles: raise LispError("READ-LINE: File handle not active") try: while True: line = file_handles[handle].readline() if not line: raise LispError("READ-LINE: End of file") if line != "\n": break if line[-1] == "\n": line = line[:-1] return Atom.Atom(Atom.Atom.STRING, line) except Exception as e: raise LispError(e.__str__())
def symbol_read_char(fun, args): handle = eval(args[0], fun) if handle not in file_handles: raise LispError("READ-CHAR: File handle not active") ch = file_handles[handle].read(1) if not ch: return Atom.make_symbol("EOF") return "\"%s\"" % ch
def symbol_slash(fun, args): result = float(eval(args[0], fun)) for x in args[1:]: x = eval(x, fun) if x == 0: raise LispError("/: Division by zero") result /= x return result
def symbol_read(fun, args): handle = eval(args[0], fun) if handle not in file_handles: raise LispError("READ: File handle not active") try: parser = LispParser.LispParser(file_handles[handle]) return parser.read_object() except StopIteration: return Atom.make_symbol("EOF")
def symbol_open(fun, args): global file_handles, next_handle filename = eval(args[0], fun) try: file_handles[next_handle] = open(filename) next_handle += 1 return next_handle - 1 except Exception as e: raise LispError("OPEN: Couldn't open '%s' (%s)" % (filename, e.__str__()))
def _process_character(self, ch): if self._in_comment: if ch == "\n": # end comment self._in_comment = False elif self._in_quotation or self._in_character_quote: if self._in_escape: self._in_escape = False if ch == "\\": self._token += "\\" elif ch == "\r": self._token += "\r" elif ch == "\n": self._token += "\n" elif ch == "\t": self._token += "\t" elif ch == "\"": self._token += "\"" else: raise LispError("Unknown escape sequence \\%s" % ch) elif ch == "\\": self._in_escape = True return else: self._token += ch if ch == "\"" and not self._in_character_quote: self._in_quotation = False self._finish_token = self._token self._token = "" self._in_character_quote = False elif ch == ";": # begin comment self._in_comment = True elif ch == "'": # quoted object begins here self._quote_level = self._level #self._quote_atom = self._this_atom elif ch.isspace() or ch == ",": # token delimiter if self._last and not self._last.isspace(): self._finish_token = self._token self._token = "" elif ch == "(": if self._last == "#": self._token = "#(" while True: peek = self._input.read(1) self._token += peek if peek == ")": break self._finish_token = self._token self._token = "" else: # open s-expression self._level += 1 self._open_paren = True elif ch == "[": # open m-expression self._place_first_atom = Atom.detect_type(self._token) self._token = "" self._level += 1 self._open_paren = True elif ch == ")" or ch == "]": if self._level: # close s- or m-expression self._close_paren = True self._finish_token = self._token self._token = "" else: self._finish_token = self._token self._token = "" self._input.putback(")") elif ch == "\"": # open/close string self._token += ch self._in_quotation = True else: # add to token self._token += ch if self._token == "#\\": self._in_character_quote = True self._last = ch
def symbol_close(fun, args): handle = eval(args[0], fun) if handle not in file_handles: raise LispError("CLOSE: File handle not active") file_handles[handle].close() file_handles.pop(handle)