コード例 #1
0
ファイル: evaluator.py プロジェクト: tsubik/diy-lisp
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    
コード例 #2
0
ファイル: evaluator.py プロジェクト: anmonteiro/diy-lisp
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)
コード例 #3
0
ファイル: evaluator.py プロジェクト: lraccomando/diy-lisp
def _define_closure(ast, env): 
    if len(ast) != 2: 
        raise LispError("Wrong number of arguments")

    if not is_list(ast[0]): 
        raise LispError("Params of lambda must be a list")
    return Closure(env, ast[0], ast[1])
コード例 #4
0
ファイル: evaluator.py プロジェクト: lraccomando/diy-lisp
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]
コード例 #5
0
ファイル: evaluator.py プロジェクト: mstade/diy-lisp
def assert_list(rest, env):
  rest = evaluate(rest, env)

  if is_list(rest):
    return rest
  else:
    raise LispError("Expected list, got: %s" % unparse(rest))
コード例 #6
0
ファイル: evaluator.py プロジェクト: shelbyd/diy-lisp
def build_evaluator(ast):
    if is_list(ast):
        if is_closure(ast[0]):
            return ClosureEvaluator(ast)
        if ast[0] == "quote":
            return QuoteEvaluator(ast)
        if ast[0] == "if":
            return IfEvaluator(ast)
        if ast[0] == "define":
            return DefineEvaluator(ast)
        if ast[0] == "lambda":
            return LambdaEvaluator(ast)
        if ast[0] == "atom":
            return AtomEvaluator(ast)
        if ast[0] == "eq":
            return EqEvaluator(ast)
        if ast[0] in ["+", "-", "/", "*", "mod", ">"]:
            return MathEvaluator(ast)
        if ast[0] == "cons":
            return ConsEvaluator(ast)
        if ast[0] == "head":
            return HeadEvaluator(ast)
        if ast[0] == "tail":
            return TailEvaluator(ast)
        if ast[0] == "empty":
            return EmptyEvaluator(ast)
    return Evaluator(ast)
コード例 #7
0
ファイル: evaluator.py プロジェクト: anmonteiro/diy-lisp
def eval_lambda(ast, env):
	# arguments should be type list
	validate_num_args(ast, 2)
	if not(is_list(ast[1])):
		err_syntax(ast)
	result = Closure(env, ast[1], ast[2])
	return result
コード例 #8
0
ファイル: evaluator.py プロジェクト: theJollySin/slowloris
def eval_lambda(ast, env):
    if len(ast) != 3:
        raise LispError('Wrong number of arguments to lambda form')

    if not is_list(ast[1]):
        raise LispError('The parameters of lambda should be a list.')

    return Closure(env, ast[1], ast[2])
コード例 #9
0
ファイル: evaluator.py プロジェクト: tsubik/diy-lisp
def eval_lambda(args, env):
    if not len(args) == 2:
        raise LispError("number of arguments")
    params = args[0]
    body = args[-1]
    if not (is_list(params)):
        raise LispError('arguments of lambda must be a list')
    return Closure(env, params, body)
コード例 #10
0
def eval_rhead(ast, env):
    assert_exp_length(ast, 2)
    ls = evaluate(ast[1], env)
    if not is_list(ls):
        raise LispError('The argument of rhead should be a list.')
    elif len(ls) == 0:
        raise LispError('And empty list has no reverse head.')
    return ls[-1]
コード例 #11
0
def eval_lambda(ast, env):
    if len(ast) != 3:
        raise LispError('Wrong number of arguments to lambda form')

    if not is_list(ast[1]):
        raise LispError('The parameters of lambda should be a list.')

    return Closure(env, ast[1], ast[2])
コード例 #12
0
ファイル: evaluator.py プロジェクト: shelbyd/diy-lisp
 def evaluate(self, env):
     if is_list(self.ast[1]):
         if len(self.ast) == 3:
             return Closure(env, self.ast[1], self.ast[2]) 
         else:
             raise LispError("number of arguments")
     else:
         raise LispError
コード例 #13
0
ファイル: evaluator.py プロジェクト: theJollySin/slowloris
def eval_rhead(ast, env):
    assert_exp_length(ast, 2)
    ls = evaluate(ast[1], env)
    if not is_list(ls):
        raise LispError('The argument of rhead should be a list.')
    elif len(ls) == 0:
        raise LispError('And empty list has no reverse head.')
    return ls[-1]
コード例 #14
0
ファイル: types.py プロジェクト: littleq0903/diy-lisp
    def __init__(self, env, params, body):
        from ast import is_list

        if not is_list(params):
            raise LispError("param %s is not a list")

        self.env = env
        self.params = params
        self.body = body
コード例 #15
0
ファイル: evaluator.py プロジェクト: nholtappels/diy-lisp
def eval_lambda(ast, env):
	"""Evaluate a 'lambda' statement in the specified environment.
	"""
	if len(ast) != 3:
		raise LispError("Wrong number of arguments: %d" % (len(ast) - 2))
	elif not is_list(ast[1]):
		raise LispError("The parameters to lambda need to be a list!")
	else:
		return Closure(env, ast[1], ast[2])
コード例 #16
0
ファイル: evaluator.py プロジェクト: sveinung/diy-lisp
def evaluate_function(ast, env):
    if is_list(ast[0]):
        function = evaluate(ast[0], env)
        return do_function(function, ast, env)
    elif ast[0] in env.variables:
        function = env.lookup(ast[0])
        return do_function(function, ast, env)
    else:
        raise LispError("not a function")
コード例 #17
0
ファイル: evaluator.py プロジェクト: nholtappels/diy-lisp
def eval_cons(ast, env):
	"""Evaluate a 'cons' statement in the specified environment.
	Cons an element onto a list.
	"""
	if len(ast) != 3:
		raise LispError("Wrong number of arguments to 'cons'")
	s2 = evaluate(ast[2], env)
	if not is_list(s2):
		raise LispError("Cannot cons to a non-list!")
	else:
		return [evaluate(ast[1], env)] + s2
コード例 #18
0
ファイル: evaluator.py プロジェクト: shlomifruchter/diy-lisp
def evalEmptyCommand(args, env):

	if len(args) != 1:
		raise LispError("tail command expects exactly one argument")

	arg = evaluate(args[0], env)

	if not is_list(arg):
		raise LispError("tail command expects a list as argument")

	return len(arg) == 0
コード例 #19
0
ファイル: evaluator.py プロジェクト: dyladan/diy-lisp
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
コード例 #20
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))
コード例 #21
0
ファイル: evaluator.py プロジェクト: theJollySin/slowloris
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))
コード例 #22
0
ファイル: evaluator.py プロジェクト: shlomifruchter/diy-lisp
def evalHeadCommand(args, env):
	if len(args) != 1:
		raise LispError("head command expects exactly one argument")

	arg = evaluate(args[0], env)

	if not is_list(arg):
		raise LispError("head command expects a list as argument")

	if len(arg) == 0:
		raise LispError("head command expect non-empty list")

	return arg[0]
コード例 #23
0
ファイル: parser.py プロジェクト: ktp-forked-repos/slowloris
def unparse(ast):
    """Turns an AST back into lisp program source"""

    if is_boolean(ast):
        return 'True' if ast else 'False'
    elif is_list(ast):
        if len(ast) > 0 and ast[0] == "quote":
            return "'%s" % unparse(ast[1])
        else:
            return "(%s)" % " ".join([unparse(x) for x in ast])
    else:
        # integers or symbols (or lambdas)
        return str(ast)
コード例 #24
0
ファイル: parser.py プロジェクト: anmonteiro/diy-lisp
def unparse(ast):
    """Turns an AST back into lisp program source"""

    if is_boolean(ast):
        return "#t" if ast else "#f"
    elif is_list(ast):
        if len(ast) > 0 and ast[0] == "quote":
            return "'%s" % unparse(ast[1])
        else:
            return "(%s)" % " ".join([unparse(x) for x in ast])
    else:
        # integers or symbols (or lambdas)
        return str(ast)
コード例 #25
0
def eval_list(ast, env):
    """evaluate all the built-in functions"""
    if ast[0] == 'quote':
        return eval_quote(ast, env)
    elif ast[0] == 'exit':
        return eval_exit(ast)
    elif ast[0] == 'print':
        return eval_print(ast, env)
    elif ast[0] == 'atom':
        return eval_atom(ast, env)
    elif ast[0] == 'let':
        return eval_let(ast, env)
    elif ast[0] == 'def':
        return eval_def(ast, env)
    elif ast[0] == 'lambda':
        return eval_lambda(ast, env)
    elif ast[0] == 'eq':
        return eval_eq(ast, env)
    elif ast[0] == 'set':
        return eval_set(ast, env)
    elif ast[0] == 'if':
        return eval_if(ast, env)
    elif ast[0] == 'cons':
        return eval_cons(ast, env)
    elif ast[0] == 'head':
        return eval_head(ast, env)
    elif ast[0] == 'tail':
        return eval_tail(ast, env)
    elif ast[0] == 'rhead':
        return eval_rhead(ast, env)
    elif ast[0] == 'rtail':
        return eval_rtail(ast, env)
    elif ast[0] == 'empty':
        return eval_empty(ast, env)
    elif ast[0] in [
            '+', '-', '*', '**', '/', 'mod', '<', '<=', '=', '!=', '>=', '>'
    ]:
        return eval_math(ast, env)
    elif ast[0] == 'random':
        return eval_random()
    elif ast[0] in ['int', 'float', 'str', 'type']:
        return eval_types(ast, env)
    elif ast[0] in ['str_append', 'str_split']:
        return eval_string(ast, env)
    elif is_closure(ast[0]):
        return apply(ast, env)
    elif is_symbol(ast[0]) or is_list(ast[0]):
        return evaluate([evaluate(ast[0], env)] + ast[1:], env)
    else:
        raise LispError('%s is not a function' % unparse(ast[0]))
コード例 #26
0
ファイル: evaluator.py プロジェクト: shlomifruchter/diy-lisp
def evalConsCommand(args, env):
	if len(args) != 2:
		raise LispError("cons command expects exactly two arguments")

	head = evaluate(args[0], env)
	rest = evaluate(args[1], env)

	if not is_list(rest):
		raise LispError("cons command expects a list as second argument")

	output = list(rest)
	output.insert(0, head)

	return output
コード例 #27
0
ファイル: evaluator.py プロジェクト: nholtappels/diy-lisp
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!')
コード例 #28
0
ファイル: evaluator.py プロジェクト: shlomifruchter/diy-lisp
def evalLambdaCommand(args, env):
	if len(args) != 2:
		raise LispError("lambda command expects exactly two arguments")

	params = args[0]
	body = args[1]

	if not is_list(params):
		raise LispError("lambda first parameter is expected to be a list")

	# In case the lambda has no parameters, evaluate its body and return the result
	if len(params) == 0:
		return evaluate(body, env)
	else:
		return Closure(env, params, body)
コード例 #29
0
ファイル: evaluator.py プロジェクト: theJollySin/slowloris
def eval_list(ast, env):
    """evaluate all the built-in functions"""
    if ast[0] == 'quote':
        return eval_quote(ast, env)
    elif ast[0] == 'exit':
        return eval_exit(ast)
    elif ast[0] == 'print':
        return eval_print(ast, env)
    elif ast[0] == 'atom':
        return eval_atom(ast, env)
    elif ast[0] == 'let':
        return eval_let(ast, env)
    elif ast[0] == 'def':
        return eval_def(ast, env)
    elif ast[0] == 'lambda':
        return eval_lambda(ast, env)
    elif ast[0] == 'eq':
        return eval_eq(ast, env)
    elif ast[0] == 'set':
        return eval_set(ast, env)
    elif ast[0] == 'if':
        return eval_if(ast, env)
    elif ast[0] == 'cons':
        return eval_cons(ast, env)
    elif ast[0] == 'head':
        return eval_head(ast, env)
    elif ast[0] == 'tail':
        return eval_tail(ast, env)
    elif ast[0] == 'rhead':
        return eval_rhead(ast, env)
    elif ast[0] == 'rtail':
        return eval_rtail(ast, env)
    elif ast[0] == 'empty':
        return eval_empty(ast, env)
    elif ast[0] in ['+', '-', '*', '**', '/', 'mod', '<', '<=', '=', '!=', '>=', '>']:
        return eval_math(ast, env)
    elif ast[0] == 'random':
        return eval_random()
    elif ast[0] in ['int', 'float', 'str', 'type']:
        return eval_types(ast, env)
    elif ast[0] in ['str_append', 'str_split']:
        return eval_string(ast, env)
    elif is_closure(ast[0]):
        return apply(ast, env)
    elif is_symbol(ast[0]) or is_list(ast[0]):
        return evaluate([evaluate(ast[0], env)] + ast[1:], env)
    else:
        raise LispError('%s is not a function' % unparse(ast[0]))
コード例 #30
0
ファイル: evaluator.py プロジェクト: shelbyd/diy-lisp
    def evaluate(self, env):
        if is_list(self.ast):
            if is_symbol(self.ast[0]):
                # self.ast[0] is possibly a function name
                block = [env.lookup(self.ast[0])]
            if is_closure(evaluate(self.ast[0], env)):
                block = [evaluate(self.ast[0], env)]
            else:
                raise LispError("not a function")
            block.extend(self.ast[1:])
            return evaluate(block, env)

        try:
            return env.lookup(self.ast)
        except Exception as e:
            if is_symbol(self.ast):
                raise e
            return self.ast
コード例 #31
0
ファイル: evaluator.py プロジェクト: sveinung/diy-lisp
def evaluate(ast, env):
    """Evaluate an Abstract Syntax Tree in the specified environment."""
    if is_integer(ast):
        return ast
    elif ast[0] == "quote":
        return ast[1]
    elif ast[0] == "atom":
        return atom(ast[1], env)
    elif ast[0] == "eq":
        first = evaluate(ast[1], env)
        second = evaluate(ast[2], env)
        return first == second
    elif ast[0] == "+":
        return do_math(ast, op.add, env)
    elif ast[0] == "-":
        return do_math(ast, op.sub, env)
    elif ast[0] == "/":
        return do_math(ast, op.div, env)
    elif ast[0] == "*":
        return do_math(ast, op.mul, env)
    elif ast[0] == "mod":
        return do_math(ast, op.mod, env)
    elif ast[0] == ">":
        return do_math(ast, op.gt, env)
    elif ast[0] == "if":
        return do_if(ast, env)
    elif ast[0] == "define":
        define(ast, env)
    elif ast[0] == "lambda":
        return closure(ast, env)
    elif ast[0] == "cons":
        return cons(ast, env)
    elif ast[0] == "car":
        return car(ast, env)
    elif ast[0] == "cdr":
        return cdr(ast, env)
    elif is_closure(ast[0]):
        return evaluate_closure(ast, env)
    elif is_list(ast):
        return evaluate_function(ast, env)
    else:
        return env.lookup(ast)
コード例 #32
0
ファイル: evaluator.py プロジェクト: shlomifruchter/diy-lisp
def evaluate(ast, env):
	"""Evaluate an Abstract Syntax Tree in the specified environment."""

	if is_symbol(ast):
		return env.lookup(ast)
	elif is_boolean(ast) or is_integer(ast):
		return ast
	elif is_closure(ast):
		return evalClosure(ast, [], env)
	elif is_list(ast) and len(ast) > 0:
		first = ast[0]

		# handle string commands
		if isinstance(first, basestring):
			if first in commands:
				return evalCommand(first, ast[1:], env)
			# When a non-keyword symbol is the first element of the AST list, it is resolved to its value in
			# the environment (which should be a function closure). An AST with the variables
			# replaced with its value should then be evaluated instead.
			else:
				func = env.lookup(first)
				if not is_closure(func):
					raise LispError("Symbol %s must evaluate to a function" % first)

				ast[0] = func
				return evaluate(ast, env)
		# handle closure objects
		elif is_closure(first):
			return evalClosure(first, ast[1:], env)
		else: # otherwise - evaluate the first expression on the list
			firstEval = evaluate(first, env);
			if is_closure(firstEval): # if closure - treat the rest of the list as arguments
				return evalClosure(first, ast[1:], env)
			else : # not a closure, just evaluate the rest of the list and return the last expression
				if len(ast) > 1:
					return evaluate(ast[1:], env)
				else:
					return firstEval

	raise LispError("Invalid AST: %s" % ast)
コード例 #33
0
ファイル: evaluator.py プロジェクト: krisbellemans/diy-lisp
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)
コード例 #34
0
ファイル: evaluator.py プロジェクト: mstade/diy-lisp
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))
コード例 #35
0
ファイル: evaluator.py プロジェクト: wissebarkhof/diy-lisp
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")
コード例 #36
0
def eval_cons(ast, env):
    assert_exp_length(ast, 3)
    ls = evaluate(ast[2], env)
    if not is_list(ls):
        raise LispError('The second argument of cons should be a list.')
    return [evaluate(ast[1], env)] + ls
コード例 #37
0
def eval_empty(ast, env):
    assert_exp_length(ast, 2)
    ls = evaluate(ast[1], env)
    if not is_list(ls):
        raise LispError('The argument of empty should be a list.')
    return len(ls) == 0