Example #1
0
def evaluate(ast, env):
    if is_list(ast):
        first_exp = ast[0]
        if first_exp == "atom":     return is_atom(evaluate(ast[1],env))
        elif first_exp == "define": return eval_define(ast[1:], env)
        elif first_exp == "if":     return eval_if_statement(ast[1:], env)
        elif first_exp == "lambda": return eval_lambda(ast[1:], env)
        elif first_exp == "quote":  return ast[1];
        elif first_exp == "eq":     return eval_equation(ast[1:], env)
        elif first_exp == "cons":   return eval_list_cons(ast[1:], env)
        elif first_exp == "head":   return eval_list_head(ast[1:], env)    
        elif first_exp == "tail":   return eval_list_tail(ast[1:], env)  
        elif first_exp == "empty":  return eval_list_empty(ast[1:], env)
        elif first_exp in math_operands:    return eval_math_operation(first_exp, ast[1:], env)
        elif first_exp == "<":  return evaluate(ast[1], env) < evaluate(ast[2], env)
        elif first_exp == "<=":  return evaluate(ast[1], env) <= evaluate(ast[2], env)
        elif first_exp == ">":  return evaluate(ast[1], env) > evaluate(ast[2], env)
        elif first_exp == ">=":  return evaluate(ast[1], env) >= evaluate(ast[2], env)
        elif is_list(first_exp) or is_symbol(first_exp): 
            eval_first = evaluate(first_exp, env)
            return evaluate([eval_first]+ast[1:], env)
        elif is_closure(first_exp):
            arguments = ast[1:]
            return evaluate(first_exp.body, first_exp.env.extend(evaluate_function_arguments(first_exp, arguments, env)))
        else:
            raise LispError('{0} not a function'.format(first_exp))

    elif is_symbol(ast): return env.lookup(ast)
    elif is_atom(ast): return ast    
Example #2
0
    def __init__(self, variables=None):
        from ast import is_boolean, is_atom, is_symbol, is_list, is_closure, is_integer

        self.variables = variables if variables else {}

        arithmetic = {
            '+': operator.add,
            '-': operator.sub,
            '*': operator.mul,
            '/': operator.div,
            'mod': operator.mod,
            '<': operator.lt,
            '<=': operator.le,
            '>': operator.gt,
            '>=': operator.ge,
        }

        for op, fun in arithmetic.iteritems():
            self.variables[op] = partial(_arithmetic_function, fun)
        
        self.variables['eq'] = lambda x, y: is_atom(x) and is_atom(y) and x == y
        self.variables['cons'] = lambda x, y: [x] + y
        self.variables['head'] = partial(_require_nonempty_list, lambda x: x[0])
        self.variables['tail'] = lambda x: x[1:]
        self.variables['empty'] = lambda x: len(x) == 0
Example #3
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    math_operators = ["+", "-", "*", "/", "mod", ">"]
    exprs = {
    	"quote" : lambda ast: ast[1],
    	"atom" : lambda ast: is_atom(evaluate(ast[1], env)),
    	"eq" : lambda ast: (evaluate(["atom", ast[1]], env) and
    		evaluate(["atom", ast[2]], env) and
    		evaluate(ast[1], env) == evaluate(ast[2], env)),
    	"if" : lambda ast: eval_if_statement(ast, env),
    	"define" : lambda ast: eval_define(ast, env),
    	"lambda" : lambda ast: eval_lambda(ast, env),
    	"cons" : lambda ast: eval_cons(ast, env),
    	"head" : lambda ast: eval_head(ast, env),
    	"tail" : lambda ast: eval_tail(ast, env),
    	"empty" : lambda ast: eval_empty(ast, env),
    	"env" : lambda ast: eval_in_env(ast, env)
    }
    exprs.update(exprs.fromkeys(math_operators,
    	lambda ast: eval_math_operators(ast, env)))
	
    if is_symbol(ast):
    	return env.lookup(ast)
    elif is_atom(ast):
    	return ast
    elif is_list(ast):
    	expr = ast[0] if not(is_list(ast[0])) else "env"
    	return exprs.get(expr, exprs["env"])(ast)
Example #4
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    

    if is_list(ast):
        if ast[0] == "quote":
            return ast[1]

        if ast[0] == "define":
            if not len(ast) == 3:
                raise LispError("Wrong number of arguments")
            if not is_symbol(ast[1]):
                raise LispError("non-symbol")
            env.set(ast[1], evaluate(ast[2], env))
            return

        if ast[0] == "if":
            if evaluate(ast[1], env):
                return evaluate(ast[2], env)
            else:
                return evaluate(ast[3], env)

        if ast[0] == "atom":
            return is_atom(evaluate(ast[1], env))

        if ast[0] == "eq":
            if not is_atom(evaluate(ast[1], env)) or not is_atom(evaluate(ast[2], env)):
                return False
            return evaluate(ast[1], env) == evaluate(ast[2], env)

        try:
            if ast[0] == "+":
                return evaluate(ast[1], env) + evaluate(ast[2], env)
            if ast[0] == "-":
                return evaluate(ast[1], env) - evaluate(ast[2], env)
            if ast[0] == "/":
                return evaluate(ast[1], env) / evaluate(ast[2], env)
            if ast[0] == "*":
                return evaluate(ast[1], env) * evaluate(ast[2], env)
            if ast[0] == "mod":
                return evaluate(ast[1], env) % evaluate(ast[2], env)
            if ast[0] == "<":
                return evaluate(ast[1], env) < evaluate(ast[2], env)
            if ast[0] == ">":
                return evaluate(ast[1], env) > evaluate(ast[2], env)
        except TypeError:
            raise LispError("TypeError")


    if is_symbol(ast):
        return env.lookup(ast)
    else:
        return ast
Example #5
0
def eq(ast, env):
  assert_exp_length(ast, 2)
  
  a = evaluate(ast[0], env)
  if not is_atom(a):
    return False

  b = evaluate(ast[1], env)
  if not is_atom(b):
    return False

  return a == b
Example #6
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_boolean(ast) or is_integer(ast):
        return ast
    elif is_symbol(ast):
        return env.lookup(ast)

    if not is_atom(ast[0]):
        ast[0] = evaluate(ast[0], env)
    elif is_symbol(ast[0]):
        if ast[0] in keywords:
            return keywords[ast[0]](ast, env)
        elif ast[0] in math_operators:
            return eval_math(ast, env)
        else:
            ast[0] = env.lookup(ast[0])

    if is_closure(ast[0]):
        args = [evaluate(x, env) for x in ast[1:]]
        num_args = len(args)
        num_params = len(ast[0].params)
        if num_args != num_params:
            raise LispError('wrong number of arguments, expected %d got %d'
                    % (num_params, num_args))
        bindings = dict(zip(ast[0].params, args))
        return evaluate(ast[0].body, ast[0].env.extend(bindings))

    raise LispError('not a function: %s' % unparse(ast[0]))
Example #7
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment.
    """
    print ast
    if is_atom(ast) or ast == []: 
        if is_symbol(ast):
            return evaluate(env.lookup(ast), env)
        else: 
            return ast 

    if is_list(ast[0]): 
        ast[0] = evaluate(ast[0], env)

    if ast[0] in MATH_EXP.keys():
        return _evaluate_math(ast, env)

    for _map in (CONTROL_EXP, EVAL_EXP, VAR_EXP, CLOSURE_EXP, LIST_EXP): 
        if ast[0] in _map.keys(): 
            func = _map[ast[0]]
            return evaluate(func(ast[1:], env), env)

    if is_symbol(ast[0]): 
        ast[0] = env.lookup(ast[0])

    if is_closure(ast[0]):
        if len(ast[1:]) != len(ast[0].params): 
            raise LispError('wrong number of arguments, expected %s got %s' % (len(ast[0].params), len(ast[1:])))
        arguments = [evaluate(arg, env) for arg in ast[1:]] 
        parameters = dict(zip(ast[0].params, arguments))
        env = ast[0].env.extend(parameters)
        return evaluate(ast[0].body, env)

    return [evaluate(a, env) for a in ast]
Example #8
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_symbol(ast):
        if ast[0] == '"':
            return ast
        return env.lookup(ast)
    elif is_atom(ast):
        return ast
    elif is_list(ast):
        return eval_list(ast, env)
    else:
        raise LispError('Syntax error: %s' % unparse(ast))
Example #9
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_symbol(ast):
        if ast[0] == '"':
            return ast
        return env.lookup(ast)
    elif is_atom(ast):
        return ast
    elif is_list(ast):
        return eval_list(ast, env)
    else:
        raise LispError('Syntax error: %s' % unparse(ast))
Example #10
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_boolean(ast):
	return ast
    elif is_integer(ast):
	return ast
    elif ast[0] in ['+', '-', '*', '/']:
	return eval_math(ast, env)
    elif is_list(ast):
	if ast[0] == "atom":
	    return is_atom(evaluate(ast[1], env))
	    #return is_atom(ast[1])
	elif ast[0] == "quote":
	    return ast[1]
	elif ast[0] == "eq":
	    assert_exp_length(ast, 3)
	    v1 = evaluate(ast[1], env)
	    v2 = evaluate(ast[2], env)
	    if not is_atom(v1) or not is_atom(v2):
		return False
	    else:
		return (v1 == v2)
Example #11
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    if is_atom(ast):
      if is_symbol(ast):
        return forms[ast] if ast in forms else env.lookup(ast)
      else:
        return ast
    else:
      if (len(ast) == 0):
        return []

      fn   = evaluate(ast[0], env)
      args = ast[1:] if len(ast) > 1 else []

      if callable(fn):
        return fn(args, env)
      if is_closure(fn):
        return apply(fn, args, env)
      elif is_list(fn):
        return evaluate([evaluate(fn, env)] + args, env)
      else:
        raise LispError("%s is not a function." % unparse(fn))
Example #12
0
def evaluate(ast, env):
	"""Evaluate an Abstract Syntax Tree in the specified environment.
	"""
	if is_boolean(ast) or is_integer(ast): # evaluate booleans and integers
		return ast
	elif is_symbol(ast): # evaluate symbols
		return env.lookup(ast)
	elif is_list(ast): # evaluate lists
		if is_closure(ast[0]): # evaluate closure
			return eval_closure(ast, env)
		elif ast[0] == 'quote': # evaluate quotes
			return ast[1]
		elif ast[0] == 'atom': # evaluate atoms
			return is_atom(evaluate(ast[1], env))
		elif ast[0] == 'eq': # evaluate equality
			return eval_eq(ast, env)
		# evaluate basic math operators:
		elif ast[0] in ['+', '-', '/', '*', 'mod', '>', '<', '=']:
			return eval_math(ast, env)
		elif ast[0] == 'if': # evaluate if expression
			return eval_if(ast, env)
		elif ast[0] == 'define': # evaluate define statement
			eval_define(ast, env)
		elif ast[0] == 'lambda': # evaluate lambda statement
			return eval_lambda(ast, env)
		elif ast[0] == 'cons': # evaluate cons statement
			return eval_cons(ast, env)
		elif ast[0] == 'head': # evaluate head statement
			return eval_head(ast, env)
		elif ast[0] == 'tail': # evaluate tail statement
			return eval_tail(ast, env)
		elif ast[0] == 'empty': # evaluate empty statement
			return eval_empty(ast, env)
		elif is_symbol(ast[0]) or is_list(ast[0]): # evaluate closure from env
			return eval_closure_env(ast, env)
		else:
			raise LispError('Argument is not a function!')
Example #13
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    # Simple types
    if is_symbol(ast):
        splitast = ast.split(' ')
        if splitast[0] == 'define':
            return Environment.extend(env, dict(zip(splitast[1:2], splitast[2::])))
        else:
            return Environment.lookup(env, ast)

    if is_boolean(ast) or is_integer(ast):
        return ast

    if is_list(ast):
        # Basic arithmetic
        if ast[0] == '+':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) + evaluate(ast[2], env)
        if ast[0] == '-':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) - evaluate(ast[2], env)
        if ast[0] == '/':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) / evaluate(ast[2], env)
        if ast[0] == '*':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) * evaluate(ast[2], env)
        if ast[0] == 'mod':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) % evaluate(ast[2], env)
        if ast[0] == '>':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) > evaluate(ast[2], env)
        if ast[0] == '<':
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) < evaluate(ast[2], env)

        # Atoms, quotes and equal
        if ast[0] == 'atom':
            return is_atom(evaluate(ast[1], env))
        if ast[0] == 'quote':
            return ast[1]
        if ast[0] == 'eq':
            return ( is_atom(evaluate(ast[1], env)) and is_atom(evaluate(ast[2], env))
                     and evaluate(ast[1], env) == evaluate(ast[2], env) )

        # If statement
        if ast[0] == 'if':
            if evaluate(ast[1], env) == True:
                return evaluate(ast[2], env)
            if evaluate(ast[1], env) == False:
                return evaluate(ast[3], env)

        # Lists
        if ast[0] == 'cons':
            head = evaluate(ast[1], env)
            tail = evaluate(ast[2], env)
            return [head] + tail

        if ast[0] == 'head':
            eval_new_ast = evaluate(ast[1], env)
            if eval_new_ast == []:
                raise LispError
            else:
                return eval_new_ast[0]

        if ast[0] == 'tail':
            eval_new_ast = evaluate(ast[1], env)
            if eval_new_ast == []:
                raise LispError
            else:
                return eval_new_ast[1:]

        if ast[0] == 'empty':
            if evaluate(ast[1], env) == []:
                return True
            else:
                return False

        # Functions
        if ast[0] == 'define':
            assert_valid_definition(ast[1:])
            symbol = ast[1]
            value = evaluate(ast[2], env)
            env.set(symbol, value)
            return symbol

        if ast[0] == 'lambda':
            if len(ast) != 3:
                raise LispError("Wrong number of arguments")
            if not is_list(ast[1]):
                raise LispError("Parameters are not in list-form")
            else:
                return Closure(env, ast[1], ast[2])

        if is_closure(ast[0]):
            closure = ast[0]
            arguments = ast[1:]
            if len(arguments) != len(closure.params):
               errormessage = "wrong number of arguments, expected " + str(len(closure.params)) + " got " + str(len(arguments))
               raise LispError(errormessage)
            arguments = [evaluate(a, env) for a in arguments]
            bindings = dict(zip(closure.params, arguments))
            new_env = closure.env.extend(bindings)
            return evaluate(closure.body, new_env)

        if is_list(ast[0]) or is_symbol(ast[0]):
                closure = evaluate(ast[0], env)
                return evaluate([closure] + ast[1:], env)

        else:
            raise LispError("not a function")

    else:
        raise LispError
Example #14
0
def eval_equation(args, env):
    eval1 = evaluate(args[0],env)
    eval2 = evaluate(args[1],env)
    if not (is_atom(eval1) and is_atom(eval2)):  
        return False
    return eval1 == eval2
Example #15
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    if ast == "#t":
        return True

    if ast == "#f":
        return False

    if is_symbol(ast):
        symbol_value = env.lookup(ast)
        # if is_closure(symbol_value):
        #     return evaluate(symbol_value, env)
        return symbol_value

    if is_integer(ast):
        return ast

    first_element = ast[0]

    if first_element == "quote":
        if len(ast) == 2:
            return ast[1]
        else:
            return []

    if first_element == "atom":
        return is_atom(evaluate(ast[1], env))

    if first_element == "if":
        if evaluate(ast[1], env):
            return evaluate(ast[2], env)
        else:
            return evaluate(ast[3], env)

    if first_element == "define":
        if len(ast) != 3:
            raise LispError("Wrong number of arguments")

        symbol_name = ast[1]

        if not is_symbol(symbol_name):
            raise LispError("non-symbol")

        value = evaluate(ast[2], env)
        env.set(symbol_name, value)
        return value

    if first_element == "eq":
        evaluated_items = [evaluate(item, env) for item in ast[1:]]
        for i in range(len(evaluated_items) - 1):
            return is_atom(evaluated_items[i]) and evaluated_items[i] == evaluated_items[i + 1]
        else:
            return True

    if first_element in ["+", "-", "*", "/", "mod", "<", ">"] and not (is_integer(evaluate(ast[1], env)) and is_integer(
            evaluate(ast[2], env))):
        error_message = "Math functions only take integer args but you tried to do (%s, %s, %s)" % (
        first_element, (evaluate(ast[1], env)), (evaluate(ast[2], env)))
        raise LispError(error_message)

    if first_element == "+":
        return evaluate(ast[1], env) + evaluate(ast[2], env)

    if first_element == "-":
        return evaluate(ast[1], env) - evaluate(ast[2], env)

    if first_element == "*":
        return evaluate(ast[1], env) * evaluate(ast[2], env)

    if first_element == "/":
        return evaluate(ast[1], env) / evaluate(ast[2], env)

    if first_element == "mod":
        return evaluate(ast[1], env) % evaluate(ast[2], env)

    if first_element == ">":
        return evaluate(ast[1], env) > evaluate(ast[2], env)

    if first_element == "<":
        return evaluate(ast[1], env) < evaluate(ast[2], env)

    # List functions

    if first_element == "cons":
        if len(ast) != 3:
            raise LispError("cons requires 2 arguments")
        element = evaluate(ast[1], env)
        list = evaluate(ast[2], env)
        if not is_list(list):
            raise LispError("cons requires second arg to be list but got %s" % unparse(ast[2]))
        list.insert(0, element)
        return list

    if first_element == "head":
        if len(ast) != 2:
            raise LispError("head requires 1 argument")
        list_expression = evaluate(ast[1], env)
        if not is_list(list_expression) or len(list_expression) < 1:
            raise LispError("head requires a list of at least length 1")
        return list_expression[0]

    if first_element == "tail":
        if len(ast) != 2:
            raise LispError("tail requires 1 argument")
        list_expression = evaluate(ast[1], env)
        if not is_list(list_expression) or len(list_expression) < 1:
            raise LispError("tail requires a list argument")
        return list_expression[1:]

    if first_element == "empty":
        if len(ast) != 2:
            raise LispError("empty requires 1 argument")
        list_expression = evaluate(ast[1], env)
        if not is_list(list_expression):
            raise LispError("empty requires a list argument")
        return len(list_expression) == 0

    # Function functions

    if first_element == "lambda":
        if len(ast) != 3:
            raise LispError("number of arguments")
        params = ast[1]
        if not is_list(params):
            raise LispError("params must be a list")
        body = ast[2]
        return Closure(env, params, body)

    if first_element == "quit":
        raise QuitError("Bye!")

    if first_element == "print":
        print "".join((str(evaluate(i, env)) for i in ast[1:]))
        return []

    if first_element == "pp":
        print " ".join((str(evaluate(i, env)) for i in ast[1:]))
        return []

    if first_element == "do":
        for i in ast[1:-1]:
            evaluate(i, env)
        return evaluate(ast[-1], env)

    if is_list(ast):
        if len(ast) == 0:
            return []

        if is_symbol(first_element) and env.has_symbol(first_element):
            closure = env.lookup(first_element)

        elif is_closure(first_element):
            closure = first_element

        else:
            closure = evaluate(first_element, env)
            if not is_closure(closure):
                raise LispError("not a function")

        argument_bindings = {}
        if len(ast) > 1:
            param_values = ast[1:]
            closure_params = closure.params
            if len(closure_params) != len(param_values):
                raise LispError("wrong number of arguments, expected %i got %i" % (len(closure_params), len(param_values)))
            for i in range(len(closure_params)):
                param_name = closure_params[i]
                argument_bindings[param_name] = evaluate(param_values[i], env)

        result = evaluate(closure.body, closure.env.extend(argument_bindings))
        if is_closure(result):
            return evaluate(result.body, result.env)
        return result
Example #16
0
def _eval_eq(ast, env):
    ast = evaluate(ast, env)
    if not is_atom(ast[0]) or not is_atom(ast[1]): 
        return False 
    return ast[0] == ast[1]
Example #17
0
  assert_symbol(symbol)

  if symbol in forms:
    return "<form/%s>" % symbol
  else:
    val = env.lookup(symbol)

    if is_closure(val):
      return "(lambda %s %s)" % (unparse(val.params), unparse(val.body))
    else:
      return val

forms = {
  "+"      : math(lambda a, b: a + b)
, "-"      : math(lambda a, b: a - b)
, "/"      : math(lambda a, b: a / b)
, "*"      : math(lambda a, b: a * b)
, ">"      : math(lambda a, b: a > b)
, "mod"    : math(lambda a, b: a % b)
, "if"     : cond
, "eq"     : eq
, "cons"   : cons
, "head"   : head
, "tail"   : tail
, "empty"  : empty
, "atom"   : lambda ast, env: is_atom(evaluate(ast[0], env))
, "quote"  : lambda ast, env: ast[0]
, "source" : source
, "lambda" : fn
, "define" : defn
}
Example #18
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    # evaluating booleans, integers, symbols and quotes
    if is_boolean(ast):
        return ast
    elif is_integer(ast):
        return ast
    elif is_symbol(ast):
        return env.lookup(ast)
    elif ast[0] == "quote":
        return ast[1]

    # everything else is of list form
    elif is_list(ast):

        # evaluating atom and eq functions
        if ast[0] == "atom":
            return is_atom(evaluate(ast[1], env))
        elif ast[0] == "eq":
            aste = [evaluate(s, env) for s in ast[1:]]
            return is_atom(aste[0]) and aste[0] == aste[1]

        # evaluating basic math operators
        elif ast[0] == "+":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) + evaluate(ast[2], env)
            else:
                raise LispError('Arguments must be integers')

        elif ast[0] == "-":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) - evaluate(ast[2], env)
            else:
                raise LispError('Arguments must be integers')

        elif ast[0] == "*":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) * evaluate(ast[2], env)
            else:
                raise LispError('Arguments must be integers')

        elif ast[0] == "mod":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) % evaluate(ast[2], env)
            else:
                raise LispError('Arguments must be integers')

        elif ast[0] == "/":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) / evaluate(ast[2], env)
            else:
                raise LispError('Arguments must be integers')

        elif ast[0] == ">":
            return evaluate(ast[1], env) > evaluate(ast[2], env)
        elif ast[0] == "<":
            return evaluate(ast[1], env) < evaluate(ast[2], env)

        # Evaluating complex expressions

        # basic if statement
        elif ast[0] == 'if':
            if (evaluate(ast[1], env)) is True:
                return evaluate(ast[2], env)
            else:
                return evaluate(ast[3], env)

        # definitions of variables
        elif ast[0] == "define":
            if is_symbol(ast[1]):
                if len(ast) == 3:
                    return env.set(ast[1], evaluate(ast[2], env))
                else:
                    raise LispError("Wrong number of arguments")
            else:
                raise LispError("non-symbol")

        # evaluating a list in which the first element is a closure
        elif is_closure(ast[0]):
            closure = ast[0]
            arguments = ast[1:]
            parameters = closure.params

            if len(arguments) != len(parameters):
                raise LispError('wrong number of arguments, expected 2 got 3')

            bindings = {}
            for x in range(len(ast[1:])):
                arg1 = evaluate(arguments[x], env)
                param1 = parameters[x]
                bindings.update({param1: arg1})
            return evaluate(closure.body, closure.env.extend(bindings))

        elif ast[0] == 'lambda':
            if not is_list(ast[1]):
                raise LispError('not a list')
            if len(ast) == 3:
                return Closure(env, ast[1], ast[2])
            else:
                raise LispError('number of arguments')

        # new forms such as cons, head, tail and empty

        elif ast[0] == "cons":
            if len(ast) != 3:
                raise LispError("expected 2 arguments")
            else:
                list = [evaluate(x, env) for x in ast[1:]]
                return [list[0]] + list[1]

        elif ast[0] == "head":
            list = [evaluate(x, env) for x in ast[1:]]
            if list[0] == []:
                raise LispError('empty list')
            return list[0][0]

        elif ast[0] == "tail":
            list = evaluate(ast[1], env)
            if list == []:
                raise LispError('empty list')
            else:
                return list[1:]

        elif ast[0] == "empty":
            list = evaluate(ast[1], env)
            return (list == [])

        elif is_symbol(ast[0]) or is_list(ast[0]):
            closure = evaluate(ast[0], env)
            return evaluate([closure] + ast[1:], env)
        else:
            raise LispError("not a function")
Example #19
0
def eval_eq(ast, env):
    assert_exp_length(ast, 3)
    args = [evaluate(x, env) for x in ast[1:]]
    return is_atom(args[0]) and args[0] == args[1]
Example #20
0
def _eval_atom(ast, env):
    return is_atom(evaluate(ast[0], env))
Example #21
0
def evalAtomCommand(args, env):
	if len(args) != 1:
		raise LispError("atom command expects exactly one argument")
	
	return is_atom(args[0])
Example #22
0
 def evaluate(self, env):
     return is_atom(evaluate(self.ast[1], env))
Example #23
0
def eval_eq(ast, env):
	"""Evaluate an eq statement in the specified environment.
	"""
	a1 = evaluate(ast[1], env)
	a2 = evaluate(ast[2], env)
	return is_atom(a1) and is_atom(a2) and a1 == a2
Example #24
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    print ast, env.variables


    # otherwise, it will be a function
    op = ast[0]
    args = ast[1:]

    # Simple Evaluation
    # quote evaluation
    if op == "quote":
        assert_exp_length(args, 1)
        return evaluate(args[0], env)

    # atom function
    if op == "atom":
        assert_exp_length(args, 1)
        return is_atom(evaluate(args[0], env))

    # arithematic evaluation
    if op in ['+', '-', '*', '/', 'mod', '>']:
        assert_exp_length(args, 2)
        
        arg1 = evaluate(args[0], env)
        arg2 = evaluate(args[1], env)

        if not (is_integer(arg1) and is_integer(arg2)):
            raise LispError("Arguments of arithmetic operator should be numbers")

        return eval_arithmetic(op, arg1, arg2)

    # define evaluation
    if op == "define":
        try:
            assert_exp_length(args, 2)
        except LispError:
            raise LispError("Wrong number of arguments")

        var_name = args[0]
        var_value = evaluate(args[1], env)

        if not is_symbol(var_name):
            raise LispError("non-symbol: %s" % var_name)

        env.set(var_name, var_value)
        return var_name
        
    # equal evaluation
    if op == "eq":
        eval_arg1 = evaluate(args[0], env)
        eval_arg2 = evaluate(args[1], env)

        return is_atom(eval_arg1) and is_atom(eval_arg2) and eval_arg1 == eval_arg2

    # Complex Evaluation
    # if evaluation
    if op == "if":
        assert_exp_length(args, 3)

        eval_predicate = evaluate(args[0], env)

        if eval_predicate:
            return evaluate(args[1], env)
        else:
            return evaluate(args[2], env)

    if op == 'lambda':
        try:
            assert_exp_length(args, 2)
        except LispError:
            raise LispError("number of arguments")
        print len(args)

        lambda_params = args[0]
        lambda_body = args[1]

        return Closure(env, lambda_params, lambda_body)

    if is_closure(op):
        closure = op

        assert_exp_length(args, len(closure.params))

        new_env = Environment(closure.env.variables.copy())

        for n, param in enumerate(closure.params):
            new_env.set(param, evaluate(args[n], new_env))

        return evaluate(closure.body, new_env)

    # fundamental
    if is_symbol(ast):
        print 'is_symbol'
        try:
            return evaluate(env.lookup(ast), env)
        except:
            if len(ast) == 1:
                raise LispError("undefined: %s" % ast[0])
            else:
                raise LispError("not a function: %s" % ast[0])

    if is_atom(ast):
        print 'is_atom'
        return ast

    if is_list(ast):
        print 'is_list'
        return evaluate(map(lambda inner_ast: evaluate(inner_ast, env), ast), env)
Example #25
0
 def evaluate(self, env):
     if not is_atom(evaluate(self.ast[1], env)) or not is_atom(evaluate(self.ast[2], env)):
         return False
     return evaluate(self.ast[1], env) ==evaluate(self.ast[2], env) 
Example #26
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_boolean(ast) or is_integer(ast):
        return ast
    elif is_symbol(ast):
        return env.lookup(ast)
    elif is_list(ast):
        f = ast[0]
        params = ast[1:]

        if is_list(f):
            c = evaluate(f, env)
            return evaluate([c] + params, env)
        elif f == 'quote':
            return params[0]
        elif f == 'atom':
            return is_atom(evaluate(params[0], env))
        elif f == 'if':
            test = evaluate(params[0], env)
            if not is_boolean(test):
                raise LispError("First argument to if must be boolean")

            if test:
                return evaluate(params[1], env)
            else:
                return evaluate(params[2], env)
        elif f == 'define':
            if len(params) != 2:
                raise LispError("Wrong number of arguments")
            elif not is_symbol(params[0]):
                raise LispError("First argument to define is a non-symbol")
            env.set(params[0], evaluate(params[1], env))
        elif f == 'lambda':
            if len(params) != 2:
                raise LispError("Wrong number of arguments")
            return Closure(env, params[0], params[1])
        elif is_closure(f):
            evaled_params = {}
            for i, symbol in enumerate(f.params):
                evaled_params[symbol] = evaluate(params[i], env)

            return evaluate(f.body, f.env.extend(evaled_params))
        elif is_symbol(f):
            evaled = evaluate(f, env)
            
            if callable(evaled):  # python function 
                evaled_params = []
                for p in params:
                    evaled_params.append(evaluate(p, env))
                return evaled(*evaled_params)
            elif is_closure(evaled):
                expected_arg_length = len(evaled.params)
                actual_arg_length = len(params)
                if expected_arg_length != actual_arg_length:
                    raise LispError("wrong number of arguments, expected " + str(expected_arg_length) + " got " + str(actual_arg_length))

                return evaluate([evaled] + params, env)
            else:
                raise LispError()
        else:
            raise LispError(str(ast) + "is not a function")
    else:
        raise LispError("xxx")
Example #27
0
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""

    # evaluating atoms
    if is_symbol(ast):
        return env.lookup(ast)
    if is_boolean(ast):
        return ast
    if is_integer(ast):
        return ast

    if is_list(ast):

        # lists
        if ast[0] == "cons":
            if len(ast) != 3:
                raise LispError("expected 2 arguments")
            else:
                value = evaluate(ast[1], env)
                list = evaluate(ast[2], env)
                new_list = [value]
                for i in list:
                    new_list.append(i)
                return new_list

        if ast[0] == "head":
            list = evaluate(ast[1], env)
            if list == []:
                raise LispError
            else: return list[0]

        if ast[0] == "tail":
            list = evaluate(ast[1], env)
            if list == []:

                raise LispError
            else: return list[1:]

        if ast[0] == "empty":
            list = evaluate(ast[1], env)
            if list == []:
                return True
            else: return False

        if ast[0] == "quote":
            return ast[1]
        # functions


        if is_closure(ast[0]):
            closure = ast[0]
            arguments = ast[1:]
            params = closure.params
            number_of_arguments = len(arguments)
            number_of_params = len(params)

            if number_of_arguments != number_of_params:
                raise LispError("wrong number of arguments, expected %(param)d got %(arg)d" %
                                {"arg": number_of_arguments, "param": number_of_params})
            variables = {}
            for i in range(number_of_arguments):
                arg = evaluate(arguments[i], env)
                param = params[i]
                variables.update({param: arg})
            environment = closure.env.extend(variables)

            return evaluate(closure.body, environment)

        if ast[0] == "lambda":
            if not is_list(ast[1]):
                raise LispError
            if len(ast) == 3:
                return Closure(env, ast[1], ast[2])
            else:
                raise LispError("number of arguments")

        # defining variables
        if ast[0] == "define":
            if is_symbol(ast[1]):
                if len(ast) == 3:
                    return env.set(ast[1], evaluate(ast[2], env))
                else:
                    raise LispError("Wrong number of arguments")
            else:
                raise LispError("non-symbol")

        #typechecks
        if ast[0] == "atom":
            return is_atom(evaluate(ast[1], env))
        if ast[0] == "eq":
            return evaluate(ast[1], env) == evaluate(ast[2], env) and \
                   is_atom(evaluate(ast[1], env)) and is_atom(evaluate(ast[2], env))

        #arithmetic:
        # elif is_arith_op(ast[0]):
        #     try:
        #         return arith_ops[ast[0]](evaluate(ast[1], env), evaluate(ast[2], env))
        # make dicitonary of these operators

        if ast[0] == "+":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) + evaluate(ast[2], env)
            else:
                raise LispError
        if ast[0] == "-":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) - evaluate(ast[2], env)
            else:
                raise LispError
        if ast[0] == "*":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) * evaluate(ast[2], env)
            else:
                raise LispError
        if ast[0] == "/":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) / evaluate(ast[2], env)
            else:
                raise LispError
        if ast[0] == "mod":
            if is_integer(evaluate(ast[1], env)) and is_integer(evaluate(ast[2], env)):
                return evaluate(ast[1], env) % evaluate(ast[2], env)
            else:
                raise LispError

        # boolean operators
        if ast[0] == ">":
            return evaluate(ast[1], env) > evaluate(ast[2], env)
        if ast[0] == "<":
            return evaluate(ast[1], env) < evaluate(ast[2], env)

        # control-flow
        if ast[0] == 'if':
            pred = ast[1]
            then = ast[2]
            elsee = ast[3]
            if evaluate(pred, env):
                return evaluate(then, env)
            else:
                return evaluate(elsee, env)

        if is_symbol(ast[0]) or is_list(ast[0]):
            closure = evaluate(ast[0], env)
            return evaluate([closure] + ast[1:], env)

        else:
            raise LispError("not a function")
Example #28
0
def eval_atom(ast, env):
    assert_exp_length(ast, 2)
    return is_atom(evaluate(ast[1], env))