Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implemented basic eval function. Added output spec.

  • Loading branch information...
commit a97e8c9e49d3b602d98b68abeb822f4fe679dae8 1 parent d3350af
@vic authored
View
3  examples/eval.py
@@ -0,0 +1,3 @@
+a = 22
+b = eval("a * 33")
+print b
View
19 lib/typhon/code_loader.rb
@@ -18,6 +18,25 @@ def self.pythonize_literals(cm)
cm
end
+ def self.execute_code(code, binding, from_module)
+ print = Compiler::Print.new
+ cm = pythonize_literals(Compiler.compile_for_eval(code, binding.variables,
+ "(eval)", 1, print))
+ cm.scope = binding.static_scope.dup
+ cm.name = :__eval__
+
+ script = Rubinius::CompiledMethod::Script.new(cm, "(eval)", true)
+ script.eval_binding = binding
+ script.eval_source = code
+
+ cm.scope.script = script
+
+ be = Rubinius::BlockEnvironment.new
+ be.under_context(binding.variables, cm)
+ be.from_eval!
+ be.call
+ end
+
# Takes a .py file name, compiles it if needed and executes it.
# Sets the module name to be __main__, so this should be called
# only on the main program. For loading other python modules from
View
19 lib/typhon/compiler/compiler.rb
@@ -28,7 +28,7 @@ def self.compile_file(file, output = nil, print = Print.new)
parser.input file
- compiler.generator.root Rubinius::AST::Script
+ compiler.generator.root = Rubinius::AST::Script
compiler.writer.name = output || compiled_filename(file)
parser.print = print
@@ -41,7 +41,22 @@ def self.compile_file(file, output = nil, print = Print.new)
end
end
- class Error < StandardError
+ def self.compile_for_eval(code, variable_scope, file = "(eval)", line = 0, print = Print.new)
+ compiler = new :typhon_code, :compiled_method
+ parser = compiler.parser
+
+ parser.input code, file, line
+ compiler.generator.root = Rubinius::AST::EvalExpression
+ compiler.generator.variable_scope = variable_scope
+
+ parser.print = print
+ compiler.packager.print.bytecode = true if print.asm?
+
+ begin
+ compiler.run
+ rescue Exception => e
+ compiler_error "Error trying to compile python: #{file}", e
+ end
end
class Print < Struct.new(:sexp, :ast, :asm)
View
38 lib/typhon/compiler/stages.rb
@@ -10,7 +10,7 @@ class Stage
# simply calls the bytecode method on them.
class Generator < Rubinius::Compiler::Stage
next_stage Rubinius::Compiler::Encoder
- attr_accessor :variable_scope
+ attr_accessor :variable_scope, :root
def initialize(compiler, last)
super
@@ -19,10 +19,6 @@ def initialize(compiler, last)
compiler.generator = self
end
- def root(root)
- @root = root
- end
-
def run
root = @root.new @input
root.file = @compiler.parser.filename
@@ -37,10 +33,40 @@ def run
end
+ # AST trasnformation for evaling source string.
+ #
+ # This stage removes the ModuleNode from root of AST tree if
+ # the code being compiled is going to be used for eval. We remove
+ # the module, because in eval we must not return the module object
+ # Also if the last statement is a DiscardNode, we replace it with
+ # its inner expression, in order to return a value.
+ #
+ # If the source is not being compiled for eval, then output is
+ # the same AST given as input.
+ class EvalExpr < Rubinius::Compiler::Stage
+ next_stage Generator
+
+ def initialize(compiler, last)
+ @compiler = compiler
+ super
+ end
+
+ def run
+ @output = @input
+ if @compiler.generator.root == Rubinius::AST::EvalExpression
+ @output = @output.node # drop top module node, only use stmt
+ if @output.nodes.last.kind_of?(AST::DiscardNode)
+ @output.nodes[-1] = @output.nodes.last.expr
+ end
+ end
+ run_next
+ end
+ end
+
# This stage takes a ruby array as produced by bin/astpretty.py
# and produces a tree of Typhon::AST nodes.
class PyAST < Rubinius::Compiler::Stage
- next_stage Generator
+ next_stage EvalExpr
def initialize(compiler, last)
@compiler = compiler
View
7 lib/typhon/environment/built_ins.rb
@@ -17,6 +17,13 @@ module Environment
require 'debugger'
Debugger.start
end
+
+ python_method(:eval) do |code|
+ bnd = Binding.setup(Rubinius::VariableScope.of_sender,
+ Rubinius::CompiledMethod.of_sender,
+ Rubinius::StaticScope.of_sender)
+ CodeLoader.execute_code code, bnd, py_from_module
+ end
end
# stuff that was defined before this needs to be changed
View
2  spec/examples/eval.out
@@ -0,0 +1,2 @@
+#! typhon examples/eval.py
+726
Please sign in to comment.
Something went wrong with that request. Please try again.