def backtick(ast): def lstQ(a): return std.isSequential(a) and std.notEmpty(a) if not lstQ(ast): rc = std.pair(std.symbol("quote"), ast) elif std.isSymbol(ast[0], "unquote"): rc = ast[1] elif lstQ(ast[0]) and std.isSymbol(ast[0][0], "splice-unquote"): rc = std.pair(std.symbol("concat*"), ast[0][1], backtick(ast.slice(1))) else: rc = std.pair(std.symbol("cons*"), backtick(ast[0]), backtick(ast[1:])) return rc
def evalEx(ast, env): rc = ast if std.isStr(ast): rc = std.unquoteStr(ast) elif std.isNil(ast): rc = None elif std.isSimple(ast): #primitive data rc = ast elif std.isKeyword(ast): #keyword data rc = str(ast) elif std.isSymbol(ast): rc = _resolveSymbol(ast, env) elif std.isVec(ast): for i, v in enumerate(ast): ast[i] = compute(v, env) elif std.isMap(ast) or std.isSet(ast): pass elif std.isPair(ast): rc = std.pair() for v in ast: rc.append(compute(v, env)) else: throwE(f"eval* failed: {std.prn(ast,1)}") return rc
def readBlock(tree, ends): ast,token= std.pair(), popToken(tree) cur,jso,expr,ok,start=None,None,None,True,token ### if ends[0]=="[": ast=std.vector() if ends[0]=="(": expr=True if token.value != ends[0]: throwE(token, "expected '", ends[0], "'") while True: cur = peekToken(tree) if not cur: throwE(start, "expected '", ends[1], "', got EOF") if ends[1] == cur.value: break addAst(ast, readAst(tree)) ##get rid of the last token popToken(tree) if jso: ast.insert(0,std.symbol("object*")) elif expr: if ast and std.isSymbol(ast[0]): cmd=str(ast[0]) if cmd== "hash-map": ast[0].value="hashmap*" elif cmd== "hash-set": ast[0].value="hashset*" elif cmd== "list": ast[0].value="list*" elif cmd== "vec" or cmd=="vector": ast[0].value="vector*" elif cmd=="js-obj" or cmd== "object": ast[0].value="object*" elif ends[0]=="#{": ast.insert(0,std.symbol("hashset*")) elif ends[0]=="{": ast.insert(0,std.symbol("hashmap*")) return copyTokenData(start, ast)
def clone(obj): rc = None if std.isVec(obj): rc = std.into(std.vector(), obj) elif std.isMap(obj): rc = obj.copy() elif std.isSet(obj): rc = obj.copy() elif std.isPair(obj): rc = std.into(std.pair(), obj) elif std.isStr(obj) or type(obj) == list: rc = obj[:] elif std.isFunction(obj): rc = None #TODO elif std.isObject(obj): rc = copy.copy(obj) else: throwE(f"clone of non-collection: {obj}") return rc
def _f_(ast): nonlocal env if not std.isPair(ast): res = std.atom(evalEx(ast, env)) elif 0 == len(ast): res = std.atom(std.pair()) else: cmd = str(ast[0]) cmd = _spec_forms_.get(cmd) if std.isFunction(cmd): res = cmd(ast, env) else: #a general form res = [compute(a, env) for a in ast] cmd = res[0] res = std.atom(res if not std.isFunction(cmd) else cmd( *res[1:])) ### if std.isPair(res): env = res[1] res = recur(expandMacro(res[0], env)) return res
def lspec(tree): z,c,base=0,0,std.gensym().value + "__" tree=readAst(tree) def scan(ast): nonlocal z,c for i,a in enumerate(ast): if isinstance(a,list): scan(a) elif isinstance(a, LambdaArg): z=int(a.value[1:]) if z>c: c=z #replace it with symbol ast[i]=std.symbol(f"{base}{z}") ### if not std.isPair(tree): throwE(tree, "expected pair") scan(tree) args= std.vector() i=1 while i<=c: args.append(std.symbol(f"{base}{i}")) i+=1 return std.pair(std.symbol("lambda*"), args, tree)
def _do(a, e): for x in a[1:-1]: compute(x, e) return std.pair(a[-1], e)
def doLET(ast, env): i, binds, e = 0, ast[1], LEXEnv(env) while i < len(binds): e.set(binds[i], compute(binds[i + 1], e)) i += 2 return std.pair(ast[2], e)
def _map(f, arr): out = std.pair() for k, v in enumerate(arr): out.append(f(v, k, arr)) return out
"not=": lambda a, b: not (a is b), "=": lambda a, b: a is b, "!=": lambda a, b: a != b, "==": lambda a, b: a == b, "is-contains?": std.contains, "is-vector?": std.isVec, "is-pair?": std.isPair, "is-map?": std.isMap, "is-set?": std.isSet, "is-macro?": lambda a: getMacro(str(a)) != None, "object*": std.jsobj, "vector*": std.vector, "list*": std.pair, "hashmap*": lambda *xs: std.hashmap(*xs), "hashset*": lambda *xs: std.hashset(*xs), "values*": lambda a: std.into(std.pair(), list(a.values())), "keys*": lambda a: std.into(std.pair(), list(a.keys())), "get*": lambda a, b: std.getProp(a, b), "not*": lambda a: False if a else True, "dec*": lambda a: a - 1, "inc*": lambda a: a + 1, "is-even?": lambda a: 0 == a % 2, "is-odd?": lambda a: 1 == a % 2, "is-sequential?": std.isSequential, "concat*": std.concat, "count*": std.count, "cons*": std.cons, "rest*": lambda a: a[1:] if a else std.pair(), "nth*": lambda coll, pos: std.getProp(coll, pos), "first*": lambda a: std.getProp(a, 0), "is-empty?": lambda a: 0 == std.count(a),
def _rspec(s): return lambda a: std.pair(std.symbol(s), readAst(a))
def _metaFunc(a1): t= readAst(a1) return std.pair(std.symbol("with-meta"), readAst(a1), t)