Skip to content

Commit

Permalink
Added support for append_args and multiple prepend arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
gaspard committed Jun 27, 2011
1 parent 79ca5fc commit eb1e65f
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 11 deletions.
5 changes: 5 additions & 0 deletions History.txt
@@ -1,3 +1,8 @@
== 0.8.5

* Minor enhancements
* Added support for append_args and multiple prepend arguments.

== 0.8.4 2011-06-15

* Minor enhancements
Expand Down
13 changes: 13 additions & 0 deletions README.rdoc
Expand Up @@ -65,6 +65,19 @@ You can look at the tests for an idea of how to declare things. If you have more

http://zenadmin.org/community

== TRICKS:

If you define your own 'safe_method_type' resolution methods, or you define a method by providing a symbol (method executed to get type), you can use the special :prepend_args and :append_args elements in the type response. You need to provide a TypedString or an array of TypedString and these elements will be inserted in the final method. This can be used to provide default values:

safe_method_type [:parse_date, String] => :get_parse_date

def get_parse_date(signature)
{:class => Time, :append_args => RubyLess::TypedString.new('visitor.tz', :class => TZInfo::Timezone)}
end

# parse_date('2003-12-01')
# ==> parse_date('2003-12-01', visitor.tz)

== WARNING:

Changing the safe methods during runtime removes the cache for all classes and
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_less/info.rb
@@ -1,3 +1,3 @@
module RubyLess
VERSION = '0.8.4'
VERSION = '0.8.5'
end
22 changes: 22 additions & 0 deletions lib/ruby_less/processor.rb
Expand Up @@ -400,6 +400,9 @@ def get_lit_class(lit)

def args_with_prepend(args, opts)
if prepend_args = opts[:prepend_args]
if prepend_args.kind_of?(Array)
prepend_args = array_to_arguments(prepend_args)
end
if args
prepend_args.append_argument(args)
args = prepend_args
Expand All @@ -408,6 +411,17 @@ def args_with_prepend(args, opts)
end
end

if append_args = opts[:append_args]
if append_args.kind_of?(Array)
append_args = array_to_arguments(append_args)
end
if args
args.append_argument(append_args)
else
args = append_args
end
end

if append_hash = opts[:append_hash]
last_arg = args.list.last
unless last_arg.klass.kind_of?(Hash)
Expand All @@ -422,5 +436,13 @@ def args_with_prepend(args, opts)
end
args
end

def array_to_arguments(args)
code = t('')
args.each do |arg|
code.append_argument(arg)
end
code
end
end
end
4 changes: 2 additions & 2 deletions rubyless.gemspec
Expand Up @@ -5,11 +5,11 @@

Gem::Specification.new do |s|
s.name = %q{rubyless}
s.version = "0.8.4"
s.version = "0.8.5"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Gaspard Bucher"]
s.date = %q{2011-06-15}
s.date = %q{2011-06-16}
s.description = %q{RubyLess is an interpreter for "safe ruby". The idea is to transform some "unsafe" ruby code into safe, type checked ruby, eventually rewriting some variables or methods.}
s.email = %q{gaspard@teti.ch}
s.extra_rdoc_files = [
Expand Down
23 changes: 19 additions & 4 deletions test/RubyLess/basic.yml
Expand Up @@ -118,10 +118,25 @@ instance_variable:
tem: "node.mazette"
res: "Mazette !"

prepend_arg:
src: "prepend_test(4)"
tem: "add(10, 4)"
res: "14"
prepend_one:
src: "prepend_one(4) + prepend_one"
tem: "(add(10, 4)+add(10))"
res: "24"

prepend_many:
src: "prepend_many(4) + prepend_many"
tem: "(add(10, 20, 4)+add(10, 20))"
res: "64"

append_one:
src: "append_one(4) + append_one"
tem: "(add(4, 10)+add(10))"
res: "24"

append_many:
src: "append_many(4) + append_many"
tem: "(add(4, 10, 20)+add(10, 20))"
res: "64"

safe_property:
src: "dog_name"
Expand Down
12 changes: 9 additions & 3 deletions test/RubyLess_test.rb
Expand Up @@ -98,8 +98,14 @@ def safe_const_type(constant)
# Example to dynamically rewrite method calls during compilation
def safe_method_type(signature, receiver = nil)
unless res = super
if signature == ['prepend_test', Number]
if signature == ['prepend_one'] || signature == ['prepend_one', Number]
res ={:class => Number, :prepend_args => RubyLess::TypedString.new('10', :class => Number), :method => 'add'}
elsif signature == ['prepend_many'] || signature == ['prepend_many', Number]
res ={:class => Number, :prepend_args => [RubyLess::TypedString.new('10', :class => Number), RubyLess::TypedString.new('20', :class => Number)], :method => 'add'}
elsif signature == ['append_one'] || signature == ['append_one', Number]
res ={:class => Number, :append_args => RubyLess::TypedString.new('10', :class => Number), :method => 'add'}
elsif signature == ['append_many'] || signature == ['append_many', Number]
res ={:class => Number, :append_args => [RubyLess::TypedString.new('10', :class => Number), RubyLess::TypedString.new('20', :class => Number)], :method => 'add'}
elsif context && res = context[:node_class].safe_method_type(signature)
# try to execute method in the current var "var.method"
res = res[:class].call(self, signature) if res[:class].kind_of?(Proc)
Expand Down Expand Up @@ -145,8 +151,8 @@ def str
"str"
end

def add(a,b)
a+b
def add(*args)
args.inject(0) {|s,a| s+a}
end

def vowel_count(str)
Expand Down
9 changes: 8 additions & 1 deletion test/typed_string_test.rb
Expand Up @@ -11,9 +11,16 @@ class TypedStringTest < Test::Unit::TestCase
should 'render with name' do
assert_equal 'foo', subject.to_s
end

should 'return class of content on klass' do
assert_equal Number, subject.klass
end

should 'maintain opts on dup' do
other = subject.dup
assert_equal TypedString, other.class
assert_equal subject.opts, other.opts
assert_equal subject.opts.object_id, other.opts.object_id
end
end
end

0 comments on commit eb1e65f

Please sign in to comment.