def const(expr): if type(expr) == tuple: expr = expr[0] if literable(expr): return (True, expr) if type(expr) == list and expr and type(expr[0]) == S: if expr[0] in const.knownFuncs: args = [] for arg in expr[1:]: (argConstP, argValue) = const(arg) if not argConstP: return (False, None) args.append(argValue) try: return (True, const.knownFuncs[arg[0]](*args)) except Exception: return (False, None) if expr[0] is S("quote"): assert len(expr) == 2 return (True, expr[1]) return (False, None)
def __call__(self,parsedExpr,scope,globalDict,localDict,*,asFunc=False): try: (expr,line)=parsedExpr except ValueError as ve: print(ve,parsedExpr) raise if type(expr)==list and expr: if type(expr[0][0])==S: (f,_,_)=self(expr[0],scope,globalDict,localDict,asFunc=True) if isinstance(f,S): required=scope.requiredScope(f) if required is Scope.root: m=self.methodFor(f) if hasattr(self,m): return getattr(self,m)(expr,line,scope, globalDict,localDict) if required[f].macroExpander: xArgs=stripLines((expr[1:],expr[1][1])) xCall=[required[f].macroExpander]+list(map(q,xArgs)) expanded=adder.runtime.eval(xCall,scope, globalDict,localDict) return self(addLines(expanded,line), scope,globalDict,localDict) scoped=[self(expr[0],scope,globalDict,localDict,asFunc=True)] for e in expr[1:]: scoped.append(self(e,scope,globalDict,localDict)) return (scoped,line,scope) if type(expr)==S: if expr.isKeyword(): return (expr,line,Scope.root) else: symbolName=str(expr) if symbolName=='current-scope': adder.runtime.getScopeById.scopes[scope.id]=scope return self(([(S('getScopeById'),line), (scope.id,line)],line),scope, globalDict,localDict) if ((symbolName!='.') and ('.' in symbolName) and not (asFunc and scope.isMacro(expr)) ): op='..' if symbolName[0]=='.' else '.' expanded=[op]+list(filter(None,symbolName.split('.'))) expanded=list(map(lambda s: (S(s),line),expanded)) return self((expanded,line), scope,globalDict,localDict,asFunc=asFunc) required=scope.requiredScope(expr) exprPy=expr.toPython() if (required is Scope.root and exprPy in globalDict and literable(globalDict[exprPy])): return (globalDict[exprPy],line,required) if (required is scope and exprPy in localDict and literable(localDict[exprPy])): return (localDict[exprPy],line,required) entry=required[expr] if entry.isBuiltinFunc and not asFunc: return self(self.wrapForApply(expr,line,scope,entry), scope,globalDict,localDict) if (entry.asConst and entry.constValueValid and (type(entry.constValue)==int or type(entry.constValue)==float or type(entry.constValue)==str or type(entry.constValue)==bool ) ): expr=entry.constValue return (expr,line,required) return (expr,line,scope)
def stripLines(parsedExpr): (expr,line)=parsedExpr if literable(expr) or type(expr)==S: return expr #assert type(expr)==list return list(map(stripLines,expr))
def addLines(expr,defLine): if literable(expr) or type(expr)==S: return (expr,defLine) #assert type(expr)==list return (list(map(lambda e: addLines(e,defLine),expr)),defLine)
def build(pyle): #collapseCallScratches(pyle) def buildPair(varAndVal): (var,val)=varAndVal return (build(var),build(val)) if isinstance(pyle,S): return Var(pyle) if not isinstance(pyle,list): assert(literable(pyle)) return Literal(pyle) assert pyle f=pyle[0] if f is S(':='): assert len(pyle)==3 return Assign(build(pyle[1]),build(pyle[2])) if f is S('return'): assert len(pyle) in [1,2] if len(pyle)==1: return Return() else: return Return(build(pyle[1])) if f is S('yield'): assert len(pyle)==2 return Yield(build(pyle[1])) if f is S('mk-list'): return MkList(list(map(build,pyle[1:]))) if f is S('mk-tuple'): return MkTuple(list(map(build,pyle[1:]))) if f is S('mk-set'): return MkSet(list(map(build,pyle[1:]))) if f is S('mk-dict'): return MkDict(list(map(buildPair,pyle[1:]))) if f is S('try'): klassClauses=[] finallyClause=None assert len(pyle)>=2 sawFinally=False finallyBody=None for clause in pyle[2:]: assert not sawFinally assert len(clause) in [2,3] if len(clause)==2: assert clause[0] is S(':finally') sawFinally=True finallyBody=build(clause[1]) else: assert isinstance(clause[0],S) assert isinstance(clause[1],S) assert str(clause[0])[0]==':' klassClauses.append((Var(S(str(clause[0])[1:])), Var(clause[1]), build(clause[2]))) return Try(build(pyle[1]),klassClauses,finallyBody) if f is S('raise'): assert len(pyle)==2 return Raise(build(pyle[1])) if f is S('reraise'): assert len(pyle)==1 return Reraise() if f is S('binop'): assert len(pyle)==4 return Binop(build(pyle[1]), build(pyle[2]), build(pyle[3])) if f is S('quote'): assert len(pyle)==2 def q(r): if isinstance(r,list): return List(list(map(q,r))) else: return Literal(r) return Quote(q(pyle[1])) if f is S('if'): assert len(pyle) in [3,4] cond=build(pyle[1]) thenClause=build(pyle[2]) elseClause=build(pyle[3]) if len(pyle)==4 else None return If(cond,thenClause,elseClause) if f is S('while'): assert len(pyle)==3 cond=build(pyle[1]) body=build(pyle[2]) return While(cond,body) if f is S('def'): assert len(pyle)==4 name=build(pyle[1]) body=build(pyle[3]) posArgs=[] nonlocals=[] optionalArgs=[] kwArgs=[] restArgs=[] globals=[] states={'&optional': optionalArgs, '&key': kwArgs, '&rest': restArgs, '&global': globals, '&nonlocal': nonlocals} cur=posArgs for arg in pyle[2]: isS=isinstance(arg,S) assert isS or (cur is optionalArgs and isinstance(arg,list) and len(arg)==2 and isinstance(arg[0],S)) if isS and arg[0]=='&': cur=states[str(arg)] else: if cur is optionalArgs: if isinstance(arg,list): (arg,default)=arg else: default=None cur.append((build(arg),build(default))) else: cur.append(build(arg)) return Def(name,posArgs,optionalArgs,kwArgs,restArgs, globals,nonlocals,body) if f is S('class'): assert len(pyle)>=3 name=build(pyle[1]) bases=list(map(build,pyle[2])) body=list(map(build,pyle[3:])) return Class(name,bases,body) if f is S('break'): assert len(pyle)==1 return Break() if f is S('continue'): assert len(pyle)==1 return Continue() if f is S('pass'): assert len(pyle)==1 return Pass() if f is S('nop'): return Pass() if f is S('begin'): return Begin(list(map(build,pyle[1:]))) if f is S('import'): assert len(pyle)==2 return Import(build(pyle[1])) if f is S('import'): assert len(pyle)==2 return Import(build(pyle[1])) if f is S('.'): assert len(pyle)>2 return Dot(build(pyle[1]), list(map(build,pyle[2:]))) if f is S('[]'): assert len(pyle)==3 return Subscript(build(pyle[1]),build(pyle[2])) if f is S('slice'): assert len(pyle)==4 return Slice(build(pyle[1]),build(pyle[2]),build(pyle[3])) if f is S('call'): assert len(pyle)==4 if isinstance(pyle[2],list): posArgs=list(map(build,pyle[2])) else: posArgs=build(pyle[2]) if isinstance(pyle[3],list): kwArgs=list(map(buildPair,pyle[3])) else: kwArgs=build(pyle[3]) return Call(build(pyle[1]),posArgs,kwArgs) print(pyle) pdb.set_trace() assert False