def pattern(arg, scope): assert arg is nil or type(arg) is Pair or isinstance(arg, Node) if arg is nil: return ValuePattern(nil, scope) if type(arg) is Pair: arg = arg.car if type(arg) is IdentifierNode: return IdentifierPattern(arg, scope) elif type(arg) is ValueNode and isinstance(arg.value, Pattern): return eval_node(arg, scope) elif type(arg) is FormNode: car = eval_node(arg.car, scope) # TODO: add tests that verify this is not evaluated more than once arg = FormNode(ValueNode('CACHE', car), arg.cdr) if car is cons: return ConsPattern(arg.cdr, scope) elif car is list_: # there might be a more elegant way to do this. perhaps. if arg.cdr is nil: return ValuePattern(arg.cdr) else: return ConsPattern(arg.cdr, scope, True) elif car is slash: return _get_aliased_pattern(arg.cdr, scope) elif car is pattern_with_predicate: return pattern_with_predicate(arg.cdr, scope) elif car is pattern_with_default: return pattern_with_default(arg.cdr, scope) elif car is pattern: return pattern(arg.cdr, scope) return ValuePattern(eval_node(arg, scope))
def eq(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil first = eval_node(arg.car, scope) second = eval_node(arg.cdr.car, scope) return first == second
def match(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil pattern = eval_node(arg.car, scope) target = eval_node(arg.cdr.car, scope) new_scope = Scope({}, scope) return pattern.match(target, new_scope)
def pattern_with_default(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil base_pattern = pattern(arg.car, scope) value_node = arg.cdr.car return DefaultedPattern(base_pattern, eval_node(value_node, scope))
def set(self, arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil key_node = arg.car assert type(key_node) is IdentifierNode # TODO: maybe allow something else value = eval_node(arg.cdr.car, scope) self.dict[key_node.identifier] = value
def apply(arg, scope): assert type(arg) is Pair function = eval_node(arg.car, scope) assert type(arg.cdr) is Pair argument = eval_node(arg.cdr.car, scope) assert type(argument) is Pair assert eval_node(arg.cdr.cdr, scope) is nil return function(argument, scope)
def get(self, arg, scope): assert type(arg) is Pair key_node = arg.car if type(key_node) is IdentifierNode: super().get(arg, scope) assert eval_node(arg.cdr, scope) is nil return self.data[eval_node(key_node, scope)]
def redef(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil assert type(arg.car) is IdentifierNode value = eval_node(arg.cdr.car, scope) scope.set_recursive(arg.car.identifier, value) return value
def get_slot(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil obj = eval_node(arg.car, scope) key = eval_node(arg.cdr.car, scope) assert type(key) is Symbol return obj.get_slot(key.value)
def set(self, arg, scope): assert type(arg) is Pair key_node = arg.car if type(key_node) is IdentifierNode: super().set(arg, scope) assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil self.data[eval_node(key_node, scope)] = eval_node(arg.cdr.car, scope)
def add(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil first = eval_node(arg.car, scope) second = eval_node(arg.cdr.car, scope) assert type(first) is int and type(second) is int return first + second
def bind(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil method = eval_node(arg.car, scope) if type(method) is BoundMethod: raise Exception("you cannot rebind a method...yet") assert type(method) is Method obj = eval_node(arg.cdr.car, scope) return BoundMethod(method, obj)
def object(arg, scope): obj = Object() while arg is not nil: assert type(arg) is Pair slot = arg.car if type(slot) is FormNode: func = eval_node(slot.car, scope) slot = FormNode(ValueNode('CACHE', func), slot.cdr) # this ensures we only eval the car of the form once if func is cons: assert type(slot.cdr) is Pair obj.set(slot.cdr, scope) elif func is get: assert type(slot.cdr) is Pair assert type(slot.cdr.cdr) is Pair key_node = slot.cdr.cdr.car obj.set(Pair(key_node, Pair(slot, nil)), scope) else: raise Exception("I don't know what to do with that yet") elif type(slot) is IdentifierNode: obj.set(Pair(slot, Pair(slot, nil)), scope) else: raise Exception("syntax error!") arg = arg.cdr return obj
def pattern_with_predicate(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil base_pattern = pattern(arg.car, scope) predicate_node = arg.cdr.car # if it's a FormNode, turn it into a mini function. # if it's a Type, its predicate is curryauto-add the instance? predicate # if it's a function, use it as the predicate # for now we will insist that it be a predicate function predicate = eval_node(arg.cdr.car, scope) assert type(predicate) is FunctionType return PredicatedPattern(base_pattern, predicate)
def curry(arg, scope): assert type(arg) is Pair function = eval_node(arg.car, scope) assert type(arg.cdr) is Pair arguments = eval_node(arg.cdr, scope) last = arguments while last.cdr is not nil: assert type(last) is Pair last = last.cdr def curried(more_args, scope): assert type(more_args) is Pair last.cdr = more_args return function(arguments, scope) return curried
def _get_aliased_pattern(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert eval_node(arg.cdr.cdr, scope) is nil left_pattern = pattern(arg.car, scope) right_pattern = pattern(arg.cdr.car, scope) return AliasedPattern(left_pattern, right_pattern)
def if_(arg, scope): assert type(arg) is Pair assert type(arg.cdr) is Pair assert type(arg.cdr.cdr) is Pair assert eval_node(arg.cdr.cdr.cdr, scope) is nil predicate_value = eval_node(arg.car, scope) then_node = arg.cdr.car else_node = arg.cdr.cdr.car # TODO: should perform boolean coercion here if predicate_value is True: return eval_node(then_node, scope) elif predicate_value is False: return eval_node(else_node, scope) else: raise Exception("I can't perform boolean coercion yet")
def get(self, arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil key_node = arg.car assert type(key_node) is IdentifierNode # TODO: maybe allow something else result = self.get_slot(key_node.identifier) if type(result) is Method: return BoundMethod(result, self) else: return result
def dictionary(arg, scope): dct = Dictionary() while arg is not nil: assert type(arg) is Pair pair = eval_node(arg.car, scope) dct.set(Pair(ValueNode('CACHE', pair.car), Pair(ValueNode('CACHE', pair.cdr), nil)), scope) arg = arg.cdr return dct
def get(self, arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil key_node = arg.car assert type(key_node) is IdentifierNode identifier = key_node.identifier if identifier == 'car': return self.car elif identifier == 'cdr-slot': return self.cdr elif identifier == 'cdr': if type(self.cdr) is Promise: return self.cdr.get_value() else: return self.cdr else: raise Exception("Pair has no property %s" % identifier)
def cons(arg, scope): car = arg.car cdr = arg.cdr.car return Pair(eval_node(car, scope), eval_node(cdr, scope))
def get_value(self): if 'value' not in self.__dict__: self.value = eval_node(self.node, self.scope) del self.node del self.scope return self.value
def __init__(self, arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil self.node = arg.car self.scope = scope
def set(arg, scope): assert type(arg) is Pair obj = eval_node(arg.car, scope) return obj.set(arg.cdr, scope)
def call(arg, scope): assert type(arg) is Pair function = eval_node(arg.car, scope) assert type(arg.cdr) is Pair return function(arg.cdr, scope)
def cdr(arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil val = eval_node(arg.car, scope) return val.get(Pair(IdentifierNode('cdr'), nil), scope)
def car(arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil return eval_node(arg.car, scope).car
def print_(arg, scope): print(eval_node(arg.car, scope)) return nil
def force(arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil promise = eval_node(arg.car, scope) assert type(promise) is Promise return promise.get_value()
def even(arg, scope): assert type(arg) is Pair assert eval_node(arg.cdr, scope) is nil arg = eval_node(arg.car, scope) assert type(arg) is int return arg % 2 == 0