Permalink
Browse files

Add quick hack to add methods in scripts

  • Loading branch information...
1 parent 3606acd commit 3885b37644ccec8f6147a9fb92f488d063974041 Evan Phoenix committed Feb 5, 2011
Showing with 86 additions and 0 deletions.
  1. +50 −0 lib/prattle/evaluator.rb
  2. +36 −0 test/test_method.rb
@@ -66,7 +66,57 @@ def add_variable(name)
end
end
+ def add_method(n)
+ name = n.initial.receiver.name
+ sig = n.cascades[0]
+ body = n.cascades[1].arguments[0]
+
+ puts "Adding method #{sig.method_name} to #{name}"
+
+ begin
+ const = Object.const_get(name)
+ rescue NameError
+ const = Class.new
+ Object.const_set name, const
+ end
+
+ const.dynamic_method sig.method_name.to_sym do |g|
+ g.total_args = sig.arguments.size
+ g.required_args = g.total_args
+ g.local_count = g.required_args
+
+ scope = Scope.new
+ g.push_state(scope)
+
+ sig.arguments.each do |arg|
+ scope.add_variable arg.name
+ end
+
+ body.body.each_with_index do |node,idx|
+ g.pop unless idx == 0
+ node.bytecode(g)
+ end
+
+ g.ret
+ end
+ end
+
+ def detect_methods
+ @nodes.delete_if do |n|
+ if n.kind_of? AST::CascadeSend
+ init = n.initial
+ if init.kind_of? AST::UnarySend and init.method_name == "define"
+ add_method(n)
+ next true
+ end
+ end
+
+ false
+ end
+ end
+
def compile
+ detect_methods
cm = @lobby.metaclass.dynamic_method :call do |g|
scope = Scope.new
g.push_state(scope)
View
@@ -0,0 +1,36 @@
+require 'test/unit'
+require 'prattle/parser'
+
+class TestMethod < Test::Unit::TestCase
+ def test_syntax
+ str = <<-STR
+Blah define; add: x to: y; as: [ x + y ]
+ STR
+
+ parser = Prattle::Parser.new(str)
+ node = parser.parse.first
+
+ assert_kind_of Prattle::AST::CascadeSend, node
+ start = node.initial
+
+ assert_kind_of Prattle::AST::UnarySend, start
+ assert_equal "define", start.method_name
+ assert_equal "Blah", start.receiver.name
+
+ sig = node.cascades[0]
+ assert_kind_of Prattle::AST::CascadeSend::SubSend, sig
+ assert_equal "add:to:", sig.method_name
+ assert_equal "x", sig.arguments[0].name
+ assert_equal "y", sig.arguments[1].name
+
+ body = node.cascades[1]
+ assert_kind_of Prattle::AST::CascadeSend::SubSend, body
+ assert_equal "as:", body.method_name
+
+ block = body.arguments[0]
+ assert_kind_of Prattle::AST::Block, block
+ assert_equal "+", block.body.first.operator
+ assert_equal "x", block.body.first.lhs.name
+ assert_equal "y", block.body.first.rhs.name
+ end
+end

0 comments on commit 3885b37

Please sign in to comment.