def inner_qq(inargs): # print "in args", inargs if first(inargs) is mksym("unquote"): # (unquote x) -> (eval x) assert rest(rest(inargs)) is nil return first(rest(inargs)).scm_eval(env) elif first(inargs) is mksym("quasiquote"): # (quasiquote x) -> (quasiquote x) assert rest(rest(inargs)) is nil return inargs elif first(inargs) is mksym("unquote-splicing"): raise Exception("Not implemented") else: # recurse the list checking each elm # return the newly formed list newlist = [] while isinstance(inargs, LispPair): if isinstance(first(inargs), LispPair): newlist.append(inner_qq(first(inargs))) else: newlist.append(first(inargs)) inargs = rest(inargs) # deal with the final element (which is probably a nil) if isinstance(inargs, LispPair): newlist.append(inner_qq(inargs)) else: newlist.append(inargs) # put the list back into sexp return from_list(newlist)
def define_func(args, env): if isinstance(first(args), LispSymbol): # we have the first form args = to_list(args) assert args[-1] is nil assert len(args) == 3 var = args[0] value = args[1] elif isinstance(first(args), LispPair): # we have the second form var = first(first(args)) param = rest(first(args)) body = rest(args) assert isinstance(var, (LispSymbol, LispPair)) value = from_list([mksym("lambda"), param, body]) else: raise Exception("invalid form") assert isinstance(var, LispSymbol) result = value.scm_eval(env) # todo set the datatype env.define(var.name, None, result) return nil
def inner_parse(tokens): """take the token list from the lexer and make it into an object""" tok = tokens.next() assert len(tok) != 0, "zero sized token" assert tok != ".", "found '.' outside of pair" assert tok != ")", "found ')' mismatched bracket" if tok == "'": return from_list([quote, inner_parse(tokens), nil]) elif tok[0] == '`': return from_list([quasiquote, inner_parse(tokens), nil]) elif tok[0] == ',': return from_list([unquote, inner_parse(tokens), nil]) elif tok[0] == '"': return LispString(tok[1:-1]) elif tok == "(": tok = tokens.next() if tok == ")": return nil tokens.undo(tok) tok_list = [inner_parse(tokens)] while (tokens.peek() not in [")", "."]): tok_list.append(inner_parse(tokens)) tok = tokens.next() if tok == ".": tok_list.append(inner_parse(tokens)) assert tokens.next() == ")", "expected one sexp after a fullstop" else: tok_list.append(nil) assert tok == ")", "missing close bracket of pair" return from_list(tok_list) elif isnumber(tok): return LispInteger(int(tok)) else: # we have a symbol assert valid_symbol_name(tok), "invalid atom in symbol '%s'" % tok if tok == "nil": return nil if tok == "true": return true if tok == "false": return false return mksym(tok)
assert not isnumber("_5") assert not isnumber("asdf") assert not isnumber("5a") assert not isnumber("a5") assert not isnumber("5a5") assert not isnumber("a5a") assert not isnumber("+a1") assert not isnumber("+9a") assert not isnumber("-9a") assert not isnumber("-a3") assert not isnumber("-10+") test_isnumber() # ----------------------------------------------------------------------------- quote = mksym("quote") quasiquote = mksym("quasiquote") unquote = mksym("unquote") def valid_symbol_name(text): return set(text).issubset(normalchars) def inner_parse(tokens): """take the token list from the lexer and make it into an object""" tok = tokens.next() assert len(tok) != 0, "zero sized token" assert tok != ".", "found '.' outside of pair" assert tok != ")", "found ')' mismatched bracket"