def env_with_prelude(): """Return a fresh environment where the prelude has already been evaluated. """ # todo: document TRIFLEPATH # todo: should we inline the prelude, so changing TRIFLEPATH doens't break this? trifle_path = getenv_llimpl("TRIFLEPATH") or "." prelude_path = os.path.join(trifle_path, "prelude.tfl") # Trifle equivalent of PYTHONPATH. try: code = get_contents(prelude_path) except OSError: # TODO: work out which error occurred (not found/wrong # permissions/other) and be more helpful. print "Could not find prelude.tfl. Have you set TRIFLEPATH?" raise # TODO: either of these could return errors, and we should handle that. lexed_tokens = lex(code) parse_tree = parse(lexed_tokens) env = fresh_environment() result = evaluate_all(parse_tree, env) assert not is_thrown_exception(result, error), "Error when evaluating prelude: %s" % result return env
def eval(self, program): """Evaluate this program in a fresh environment with the prelude already included. Returns the result of the last expression. """ # Fresh copy of the environment so tests don't interfere with one another. env = Environment([Scope({})]) global_scope = self.env.scopes[0] for key, value in global_scope.bindings.iteritems(): # We do a deep copy of mutable values. if isinstance(value, List): env.set(key, deepcopy(value)) elif isinstance(value, String): env.set(key, deepcopy(value)) elif isinstance(value, Bytestring): env.set(key, deepcopy(value)) else: env.set(key, value) parse_tree = parse(lex(program)) if isinstance(parse_tree, TrifleExceptionInstance): self.fail("Parse error on: %r" % program) result = NULL for expression in parse_tree.values: result = evaluate(expression, env) if is_thrown_exception(result, error): return result return result
def entry_point(argv): """Either a file name: $ ./trifle ~/files/foo.tfl A code snippet: $ ./trifle -i '1 2' """ if len(argv) == 2: # open the file filename = argv[1] if not os.path.exists(filename): print 'No such file: %s' % filename return 2 try: env = env_with_prelude() except OSError: return 2 code = get_contents(filename) lexed_tokens = lex(code) if is_thrown_exception(lexed_tokens, error): print u'Uncaught error: %s: %s' % ( lexed_tokens.exception_type.name, lexed_tokens.message) return 1 parse_tree = parse(lexed_tokens) try: result = evaluate_all(parse_tree, env) if is_thrown_exception(result, error): # TODO: a proper stack trace. print u'Uncaught error: %s: %s' % (result.exception_type.name, result.message) return 1 except SystemExit: return 0 return 0 elif len(argv) == 3: if argv[1] == '-i': try: env = env_with_prelude() except OSError: return 2 code_snippet = argv[2].decode('utf-8') lexed_tokens = lex(code_snippet) if is_thrown_exception(lexed_tokens, error): print u'Uncaught error: %s: %s' % ( lexed_tokens.exception_type.name, lexed_tokens.message) return 1 parse_tree = parse(lexed_tokens) try: result = evaluate_all(parse_tree, env) if is_thrown_exception(result, error): # TODO: a proper stack trace. print u'Uncaught error: %s: %s' % (result.exception_type.name, result.message) return 1 else: print result.repr().encode('utf-8') except SystemExit: return 0 return 0 print USAGE return 1