Skip to content

Commit

Permalink
StringConcat for .java compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Brown committed Mar 16, 2010
1 parent dc512ad commit 83940c0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 24 deletions.
5 changes: 2 additions & 3 deletions lib/duby/ast/literal.rb
Expand Up @@ -84,11 +84,10 @@ def infer(typer)
end

class ToString < Node
attr_accessor :body
child :body

def initialize(parent, position)
super(parent, position)
@body = yield(self)[0]
end

def infer(typer)
Expand Down
2 changes: 1 addition & 1 deletion lib/duby/jvm/compiler.rb
Expand Up @@ -603,7 +603,7 @@ def to_string(body, expression)
body.inferred_type.box(@method) if body.inferred_type.primitive?
@method.invokevirtual @method.object, "toString", [@method.string]
else
@body.compile(self, false)
body.compile(self, false)
end
end

Expand Down
31 changes: 31 additions & 0 deletions lib/duby/jvm/source_compiler.rb
Expand Up @@ -579,6 +579,37 @@ def array(node, expression)
end
end

def build_string(nodes, expression)
if expression
simple = true
nodes = nodes.map do |node|
simple &&= node.expr?(self)
node.precompile(self)
end
log "nodes: #{nodes.inspect}"
if !simple
@method.print(lvalue)
end
first = true
unless nodes[0].kind_of?(Duby::AST::String)
@method.print '""'
first = false
end
nodes.each do |node|
@method.print ' + ' unless first
first = false
node.compile(self, true)
end
@method.puts ';' unless simple
else
nodes.each {|n| n.compile(self, false)}
end
end

def to_string(body, expression)
body.compile(self, expression)
end

def null
@method.print 'null'
end
Expand Down
56 changes: 36 additions & 20 deletions lib/duby/jvm/source_generator/precompile.rb
Expand Up @@ -10,18 +10,18 @@ def initialize(node, compiler=nil, value=nil)
@tempvalue = value || node
end
end

def compile(compiler, expression)
if expression
compiler.method.print @tempname
end
end

def reload(compiler)
compiler.assign(@tempname, @tempvalue)
end
end

class Node
def expr?(compiler)
true
Expand All @@ -34,18 +34,18 @@ def precompile(compiler)
temp(compiler)
end
end

def temp(compiler, value=nil)
TempValue.new(self, compiler, value)
end
end

class Body
def expr?(compiler)
false
end
end

class If
def expr?(compiler)
return false unless condition.predicate.expr?(compiler)
Expand All @@ -54,42 +54,42 @@ def expr?(compiler)
true
end
end

class Loop
def expr?(compiler)
false
end

def precompile(compiler)
compile(compiler, false)
temp(compiler, 'null')
end
end

class Call
def method(compiler=nil)
@method ||= begin
arg_types = parameters.map {|p| p.inferred_type}
target.inferred_type.get_method(name, arg_types)
end
end

def expr?(compiler)
target.expr?(compiler) &&
parameters.all? {|p| p.expr?(compiler)} &&
!method.return_type.kind_of?(Duby::AST::InlineCode) &&
!method.actual_return_type.void?
end
end

class FunctionalCall
def method(compiler)
@method ||= begin
arg_types = parameters.map {|p| p.inferred_type}
compiler.self_type.get_method(name, arg_types)
end
end

def expr?(compiler)
parameters.all? {|p| p.expr?(compiler)} &&
(cast? || !method(compiler).actual_return_type.void?)
Expand All @@ -110,13 +110,13 @@ def expr?(compiler)
!method(compiler).actual_return_type.void?
end
end

class EmtpyArray
def expr?(compiler)
size.expr?(compiler)
end
end

class LocalAssignment
def expr?(compiler)
compiler.method.local?(name) && value.expr?(compiler)
Expand All @@ -131,37 +131,53 @@ def precompile(compiler)
end
end
end


class ToString
def expr?(compiler)
body.expr?(compiler)
end

def temp(compiler, value=nil)
TempValue.new(body, compiler, value)
end
end

class StringConcat
def expr?(compiler)
children.all? {|x| x.expr?(compiler)}
end
end

class Return
def expr?(compiler)
false
end
end

class Raise
def expr?(compiler)
false
end
end

class Rescue
def expr?(compiler)
false
end
end

class Ensure
def expr?(compiler)
false
end
end

class FieldAssignment
def expr?(compiler)
false
end
end

class LocalAssignment
def expr?(compiler)
false
Expand Down
36 changes: 36 additions & 0 deletions test/test_jvm_compiler.rb
Expand Up @@ -2040,6 +2040,42 @@ def foo(name:String)
assert_output("Hello Fred.") do
cls.foo "Fred"
end

cls, = compile(<<-EOF)
def foo(x:int)
print "\#{x += 1}"
x
end
EOF

assert_output("2") do
assert_equal(2, cls.foo(1))
end

cls, = compile(<<-EOF)
def foo(a:int)
"\#{a += 1}"
a
end
EOF
assert_equal(2, cls.foo(1))
end

def test_self_dot_static_methods
cls, = compile(<<-EOF)
class ClassWithStatics
def self.a
b
end
def self.b
print "b"
end
end
EOF

assert_output("b") do
cls.a
end
end

# TODO: need a writable field somewhere...
Expand Down

0 comments on commit 83940c0

Please sign in to comment.