[pypy-svn] r46043 - in pypy/dist/pypy/lang/scheme: . test

jlg at codespeak.net jlg at codespeak.net
Mon Aug 27 17:39:03 CEST 2007


Author: jlg
Date: Mon Aug 27 17:39:03 2007
New Revision: 46043

Added:
   pypy/dist/pypy/lang/scheme/macro.py
      - copied, changed from r46033, pypy/dist/pypy/lang/scheme/object.py
Modified:
   pypy/dist/pypy/lang/scheme/execution.py
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
object.py split part 1 - derived macros -> macro.py

Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py	(original)
+++ pypy/dist/pypy/lang/scheme/execution.py	Mon Aug 27 17:39:03 2007
@@ -1,4 +1,5 @@
 import pypy.lang.scheme.object as ssobject
+import pypy.lang.scheme.macro as ssmacro
 from pypy.lang.scheme.ssparser import parse
 import py
 
@@ -7,13 +8,14 @@
         self.obj = w_obj
 
 OPERATION_MAP = {}
-for obj_name in dir(ssobject):
-    obj = getattr(ssobject, obj_name)
-    try:
-        issubclass(obj, ssobject.W_Callable)
-        OPERATION_MAP[obj._symbol_name] = obj(obj._symbol_name)
-    except (TypeError, AttributeError):
-        pass
+for mod in (ssobject, ssmacro):
+    for obj_name in dir(mod):
+        obj = getattr(mod, obj_name)
+        try:
+            issubclass(obj, ssobject.W_Callable)
+            OPERATION_MAP[obj._symbol_name] = obj(obj._symbol_name)
+        except (TypeError, AttributeError):
+            pass
 
 de_file = py.magic.autopath().dirpath().join("r5rs_derived_expr.ss")
 de_code = de_file.read()
@@ -50,7 +52,7 @@
             self.globalscope = globalscope
 
     def _dispatch(self, symb):
-        if isinstance(symb, ssobject.SymbolClosure):
+        if isinstance(symb, ssmacro.SymbolClosure):
             return (symb.closure, symb.name)
 
         elif isinstance(symb, ssobject.W_Symbol):

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Mon Aug 27 17:39:03 2007
@@ -716,7 +716,7 @@
 ##
 # Number Predicates
 ##
-class NumberPredicate(W_Procedure):
+class PredicateNumber(W_Procedure):
     def procedure(self, ctx, lst):
         if len(lst) != 1:
             raise WrongArgsNumber
@@ -730,7 +730,7 @@
     def predicate(self, w_obj):
         raise NotImplementedError
 
-class IntegerP(NumberPredicate):
+class IntegerP(PredicateNumber):
     _symbol_name = "integer?"
 
     def predicate(self, w_obj):
@@ -739,7 +739,7 @@
 
         return True
 
-class RealP(NumberPredicate):
+class RealP(PredicateNumber):
     _symbol_name = "real?"
 
     def predicate(self, w_obj):
@@ -748,7 +748,7 @@
 class RationalP(RealP):
     _symbol_name = "rational?"
 
-class NumberP(NumberPredicate):
+class NumberP(PredicateNumber):
     _symbol_name = "number?"
 
     def predicate(self, w_obj):
@@ -757,25 +757,25 @@
 class ComplexP(NumberP):
     _symbol_name = "complex?"
 
-class ExactP(NumberPredicate):
+class ExactP(PredicateNumber):
     _symbol_name = "exact?"
 
     def predicate(self, w_obj):
         return w_obj.exact
 
-class InexactP(NumberPredicate):
+class InexactP(PredicateNumber):
     _symbol_name = "inexact?"
 
     def predicate(self, w_obj):
         return not w_obj.exact
 
-class ZeroP(NumberPredicate):
+class ZeroP(PredicateNumber):
     _symbol_name = "zero?"
 
     def predicate(self, w_obj):
         return w_obj.to_number() == 0.0
 
-class OddP(NumberPredicate):
+class OddP(PredicateNumber):
     _symbol_name = "odd?"
 
     def predicate(self, w_obj):
@@ -784,7 +784,7 @@
 
         return w_obj.round() % 2 != 0
 
-class EvenP(NumberPredicate):
+class EvenP(PredicateNumber):
     _symbol_name = "even?"
 
     def predicate(self, w_obj):
@@ -1180,438 +1180,8 @@
         return W_Promise(lst.car, ctx)
 
 ##
-# DerivedMacros
+# Continuations
 ##
-class SyntaxRules(W_Macro):
-    _symbol_name = "syntax-rules"
-
-    def call(self, ctx, lst):
-        if not isinstance(lst, W_Pair):
-            raise SchemeSyntaxError
-
-        w_literals = lst.car
-        if not isinstance(w_literals, W_List):
-            raise SchemeSyntaxError
-
-        literals_map = {}
-        while isinstance(w_literals, W_Pair):
-            if not isinstance(w_literals.car, W_Symbol):
-                raise SchemeSyntaxError
-
-            #XXX locations here
-            literal_name = w_literals.car.to_string()
-            w_temp = ctx.get_location(literal_name)
-
-            literals_map[literal_name] = w_temp
-
-            w_literals = w_literals.cdr
-
-        w_syntax_lst = lst.cdr
-        syntax_lst = []
-        while isinstance(w_syntax_lst, W_Pair):
-            w_syntax = w_syntax_lst.car
-            if not isinstance(w_syntax, W_Pair):
-                raise SchemeSyntaxError
-
-            w_pattern = w_syntax.car
-            w_template = w_syntax.get_cdr_as_pair().car
-
-            #do stuff with w_syntax rules
-            syntax_lst.append(SyntaxRule(w_pattern, w_template, literals_map))
-            
-            w_syntax_lst = w_syntax_lst.cdr
-
-        #closes template in syntactic enviroment at the point of definition
-        return W_Transformer(syntax_lst, ctx)
-
-class Ellipsis(W_Root):
-    def __init__(self, mdict_lst):
-        self.mdict_lst = mdict_lst
-
-    def __repr__(self):
-        return "#<e: " + str(self.mdict_lst) + ">"
-
-class EllipsisException(SchemeException):
-    def __init__(self, length):
-        self.length = length
-
-class EllipsisTemplate(SchemeException):
-    pass
-
-class EllipsisPattern(SchemeException):
-    pass
-
-class MatchError(SchemeException):
-    pass
-
-class SyntaxRule(object):
-    def __init__(self, pattern, template, literals):
-        assert isinstance(pattern, W_Pair)
-        self.pattern = pattern
-        self.template = template
-        self.literals = literals
-
-    def __str__(self):
-        return self.pattern.to_string() + " -> " + self.template.to_string()
-
-    def match(self, ctx, w_expr):
-        #we use .cdr here, because keyword should not be a macro variable
-        assert isinstance(w_expr, W_Pair)
-        return self.matchr(ctx, self.pattern.cdr, w_expr.cdr)
-
-    def matchr(self, ctx, w_patt, w_expr):
-        #print "  >", w_patt.to_string(), w_expr.to_string()
-        if isinstance(w_patt, W_Pair):
-            w_pattcar = w_patt.car
-            w_pattcdr = w_patt.cdr
-            if isinstance(w_expr, W_Pair):
-                mdict_car = self.matchr(ctx, w_pattcar, w_expr.car)
-                try:
-                    #we catch EllipsisPattern here because in car
-                    # we dont know how to deal with it
-                    mdict_cdr = self.matchr(ctx, w_pattcdr, w_expr.cdr)
-                except EllipsisPattern:
-                    #print "ellipsis matched", w_patt, w_expr
-
-                    mdict_lst = []
-                    w_pair = w_expr
-                    while isinstance(w_pair, W_Pair):
-                        mdict = self.matchr(ctx, w_pattcar, w_pair.car)
-                        mdict_lst.append(mdict)
-                        w_pair = w_pair.cdr
-
-                    mdict_cdr = {}
-                    ellipsis = Ellipsis(mdict_lst)
-                    for name in mdict_lst[0].keys():
-                        mdict_cdr[name] = ellipsis
-
-                    return mdict_cdr
-
-                mdict_car.update(mdict_cdr)
-                return mdict_car
-
-            if w_expr is w_nil:
-                #one matched to ellipsis, previous (up) w_expr.car
-                if w_pattcar is w_ellipsis:
-                    raise EllipsisPattern
-
-                #zero matched to ellipsis
-                if isinstance(w_pattcdr, W_Pair) and \
-                        w_pattcdr.car is w_ellipsis:
-                    #all symbols from w_pattcar match zero length Ellipsis
-                    return self.dict_traverse_expr(w_pattcar, Ellipsis([]))
-
-        if w_patt is w_ellipsis:
-            raise EllipsisPattern
-
-        if isinstance(w_patt, W_Symbol):
-            try:
-                w_literal = self.literals[w_patt.name]
-                if not isinstance(w_expr, W_Symbol):
-                    raise MatchError
-
-                if w_patt.name != w_expr.name:
-                    raise MatchError
-
-                w_form = ctx.get_location(w_expr.name)
-
-                if w_form is not w_literal:
-                    raise MatchError
-
-            except KeyError:
-                pass
-
-            return {w_patt.name: w_expr}
-
-        if w_patt is w_nil and w_expr is w_nil:
-            return {}
-
-        #w_patt is w_nil, but w_expr is not
-        # or w_patt is W_Pair but w_expr is not
-        raise MatchError
-
-    def dict_traverse_expr(self, expr, val=None):
-        if isinstance(expr, W_Pair):
-            dict_car = self.dict_traverse_expr(expr.car, val)
-            dict_cdr = self.dict_traverse_expr(expr.cdr, val)
-            dict_car.update(dict_cdr)
-            return dict_car
-
-        if isinstance(expr, W_Symbol) and not expr is w_ellipsis:
-            return {expr.name: val}
-
-        return {}
-
-class SymbolClosure(W_Symbol):
-    def __init__(self, ctx, symbol):
-        assert isinstance(symbol, W_Symbol)
-        assert not isinstance(symbol, SymbolClosure)
-        self.symbol = symbol
-        self.name = symbol.name
-        self.closure = ctx
-
-    def eval_tr(self, ctx):
-        #this symbol is in Syntactic Closure 
-        return self.symbol.eval_tr(self.closure)
-
-    def to_string(self):
-        #return "#<closure: " + self.sexpr.to_string() + ">"
-        return self.symbol.to_string()
-
-    def __repr__(self):
-        return "<sc:W_Symbol " + self.to_string() + ">"
-
-class PairClosure(W_Pair):
-    def __init__(self, ctx, pair):
-        assert isinstance(pair, W_Pair)
-        assert not isinstance(pair, PairClosure)
-        self.pair = pair
-        self.car = pair.car
-        self.cdr = pair.cdr
-        self.closure = ctx
-
-    def eval_tr(self, ctx):
-        #this pair is in Syntactic Closure 
-        return self.pair.eval_tr(self.closure)
-
-    def to_string(self):
-        #return "#<closure: " + self.sexpr.to_string() + ">"
-        return self.pair.to_string()
-
-    def __repr__(self):
-        return "<sc:W_Pair " + self.to_string() + ">"
-
-class W_Transformer(W_Procedure):
-    def __init__(self, syntax_lst, ctx, pname=""):
-        self.pname = pname
-        self.syntax_lst = syntax_lst
-        self.closure = ctx
-
-    def match(self, ctx, w_expr):
-        for rule in self.syntax_lst:
-            try:
-                #print "m>", rule.pattern.to_string()
-                match_dict = rule.match(ctx, w_expr)
-                return (rule.template, match_dict)
-            except MatchError:
-                pass
-
-        raise MatchError
-
-    def expand(self, ctx, w_expr):
-        try:
-            #print w_expr.to_string()
-            (template, match_dict) = self.match(ctx, w_expr)
-        except MatchError:
-            raise SchemeSyntaxError
-
-        return self.substitute(ctx, template, match_dict)
-
-    def find_elli(self, expr, mdict):
-        #filter mdict, returning only ellipsis which appear in expr
-        if isinstance(expr, W_Pair):
-            edict_car = self.find_elli(expr.car, mdict)
-            edict_cdr = self.find_elli(expr.cdr, mdict)
-            edict_car.update(edict_cdr)
-            return edict_car
-
-        if isinstance(expr, W_Symbol):
-            val = mdict.get(expr.name, None)
-            if val is None:
-                return {}
-
-            if isinstance(val, Ellipsis):
-                return {expr.name: val}
-
-        return {}
-
-    def plst_append(self, plst, w_cdr=None):
-        if len(plst) == 0:
-            return w_cdr
-        first_cons = plst[0]
-
-        last_cons = None
-        for lst in plst:
-            if last_cons is not None:
-                last_cons.cdr = lst
-
-            while isinstance(lst, W_Pair):
-                last_cons = lst
-                lst = lst.cdr
-
-        if w_cdr is not None:
-            assert isinstance(last_cons, W_Pair)
-            last_cons.cdr = w_cdr
-
-        return first_cons
-
-    def substituter(self, ctx, sexpr, match_dict, flatten=False):
-        if isinstance(sexpr, W_Pair):
-            w_car = self.substituter(ctx, sexpr.car, match_dict)
-            try:
-                w_cdr = self.substituter(ctx, sexpr.cdr, match_dict)
-            except EllipsisTemplate:
-                #print "ellipsis expand", sexpr
-                sexprcdr = sexpr.get_cdr_as_pair()
-                try:
-                    #we can still have something behind ellipsis
-                    w_cdr = self.substituter(ctx, sexprcdr.cdr, match_dict)
-                except EllipsisTemplate:
-                    #it can also be ellipsis
-                    # lets pretend its usual <(obj ...) ...>
-                    # instead of <obj ... ...>
-                    # we will *flatten* the result later
-                    w_inner = W_Pair(sexpr.car, W_Pair(sexprcdr.car, w_nil))
-                    w_outer = W_Pair(w_inner, sexprcdr.cdr)
-                    return self.substituter(ctx, w_outer, match_dict, True)
-
-                plst = []
-                #find_elli gets ellipses from match_dict relevant to sexpr.car
-                mdict_elli = self.find_elli(sexpr.car, match_dict)
-                elli_len = 0
-                for (key, val) in mdict_elli.items():
-                    if elli_len == 0 or elli_len == len(val.mdict_lst):
-                        elli_len = len(val.mdict_lst)
-                    else:
-                        #we can treat is as an error if ellipsis has
-                        # different match length
-                        # # or get the shortest one
-                        raise SchemeSyntaxError
-
-                #generate elli_len substitutions for ellipsis
-                for i in range(elli_len):
-                    #one level of ellipsis nesting lower
-                    new_mdict = match_dict.copy()
-                    for (key, val) in mdict_elli.items():
-                        new_mdict[key] = val.mdict_lst[i][key]
-
-                    sub = self.substituter(ctx, sexpr.car, new_mdict)
-                    plst.append(sub)
-
-                if flatten:
-                    #we have to flatten these list, it means append them
-                    # together, and remember about w_cdr
-                    w_lst = self.plst_append(plst, w_cdr)
-
-                else:
-                    w_lst = plst2lst(plst, w_cdr)
-
-                return w_lst
-
-            w_pair = W_Pair(w_car, w_cdr)
-            if isinstance(w_car, W_Symbol):
-                try:
-                    w_macro = ctx.get(w_car.name)
-                    # recursive macro expansion
-                    if isinstance(w_macro, W_DerivedMacro):
-                        if w_macro.transformer is self:
-                            return w_macro.expand(ctx, w_pair)
-                except UnboundVariable:
-                    pass
-
-            return w_pair
-
-        if isinstance(sexpr, W_Symbol):
-            if sexpr is w_ellipsis:
-                raise EllipsisTemplate
-
-            w_sub = match_dict.get(sexpr.name, None)
-            if w_sub is not None:
-                #Hygenic macros close their input forms in the syntactic
-                # enviroment at the point of use
-
-                if isinstance(w_sub, Ellipsis):
-                    return w_sub
-
-                #not always needed, because w_sub can have no W_Symbol inside
-                if isinstance(w_sub, W_Symbol) and \
-                        not isinstance(w_sub, SymbolClosure):
-                    return SymbolClosure(ctx, w_sub)
-
-                if isinstance(w_sub, W_Pair) and \
-                        not isinstance(w_sub, PairClosure):
-                    return PairClosure(ctx, w_sub)
-
-                return w_sub
-
-        return sexpr
-
-    substitute = substituter
-
-    def expand_eval(self, ctx, sexpr):
-        #we have lexical scopes:
-        # 1. macro was defined - self.closure
-        # 2. macro is called   - ctx
-        # 3. macro is expanded, can introduce new bindings - expand_ctx
-        expanded = self.expand(ctx, sexpr)
-        expand_ctx = self.closure.copy()
-        return expanded.eval(expand_ctx)
-
-    def procedure(self, ctx, lst):
-        return self.expand_eval(ctx, lst[0])
-
-class W_DerivedMacro(W_Macro):
-    def __init__(self, name, transformer):
-        self.name = name
-        self.transformer = transformer
-
-    def to_string(self):
-        return "#<derived-macro %s>" % (self.name,)
-
-    def call(self, ctx, lst):
-        return self.transformer.expand_eval(ctx,
-                W_Pair(W_Symbol(self.name), lst))
-
-    def expand(self, ctx, lst):
-        return self.transformer.expand(ctx, lst)
-
-class DefineSyntax(W_Macro):
-    _symbol_name = "define-syntax"
-
-    def call(self, ctx, lst):
-        if not isinstance(lst, W_Pair):
-            raise SchemeSyntaxError
-
-        w_def = lst.car
-        if not isinstance(w_def, W_Symbol):
-            raise SchemeSyntaxError
-
-        w_syntax_rules = lst.get_cdr_as_pair().car
-        w_transformer = w_syntax_rules.eval(ctx)
-        if not isinstance(w_transformer, W_Transformer):
-            raise SchemeSyntaxError
-
-        w_macro = W_DerivedMacro(w_def.name, w_transformer)
-        ctx.set(w_def.name, w_macro)
-        return w_macro #undefined
- 
-class LetSyntax(W_Macro):
-    #XXX letrec-syntax missing
-    _symbol_name = "let-syntax"
-
-    def call_tr(self, ctx, lst):
-        #let uses eval_body, so it is tail-recursive aware
-        if not isinstance(lst, W_Pair):
-            raise SchemeSyntaxError
-        local_ctx = ctx.copy()
-        w_formal = lst.car
-        while isinstance(w_formal, W_Pair):
-            w_def = w_formal.get_car_as_pair()
-            w_transformer = w_def.get_cdr_as_pair().car.eval(ctx)
-            if not isinstance(w_transformer, W_Transformer):
-                raise SchemeSyntaxError
-
-            w_name = w_def.car
-            if not isinstance(w_name, W_Symbol):
-                raise SchemeSyntaxError
-
-            w_macro = W_DerivedMacro(w_name.name, w_transformer)
-
-            local_ctx.put(w_name.name, w_macro)
-            w_formal = w_formal.cdr
-
-        return Body(lst.cdr).eval_tr(local_ctx)
-
 class ContinuationReturn(SchemeException):
     def __init__(self, result):
         self.result = result

Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_macro.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_macro.py	Mon Aug 27 17:39:03 2007
@@ -2,6 +2,7 @@
 from pypy.lang.scheme.ssparser import parse
 from pypy.lang.scheme.execution import ExecutionContext
 from pypy.lang.scheme.object import *
+from pypy.lang.scheme.macro import *
 
 def eval_(ctx, expr):
     return parse(expr)[0].eval(ctx)



More information about the Pypy-commit mailing list