Permalink
Browse files

Merge branch 'master' of git@github.com:mirah/mirah

* 'master' of git@github.com:mirah/mirah:
  Add support for class vars as static fields.
  • Loading branch information...
2 parents 453afea + 91c66d3 commit e8f084c6fa251eb07aac4a540a97ce6a7bf2f92f @ribrdb ribrdb committed Nov 2, 2010
Showing with 84 additions and 22 deletions.
  1. +25 −6 lib/mirah/ast/class.rb
  2. +3 −3 lib/mirah/compiler.rb
  3. +13 −13 lib/mirah/jvm/compiler.rb
  4. +22 −0 lib/mirah/transform2.rb
  5. +21 −0 lib/mirah/typer.rb
View
@@ -190,11 +190,13 @@ class FieldDeclaration < Node
child :type_node
attr_accessor :type
+ attr_accessor :static
- def initialize(parent, position, name, annotations=[], &block)
+ def initialize(parent, position, name, annotations=[], static = false, &block)
@annotations = annotations
super(parent, position, &block)
@name = name
+ @static = static
end
def infer(typer)
@@ -205,7 +207,11 @@ def infer(typer)
end
def resolved!(typer)
- typer.learn_field_type(class_scope, name, @inferred_type)
+ if static
+ typer.learn_static_field_type(class_scope, name, @inferred_type)
+ else
+ typer.learn_field_type(class_scope, name, @inferred_type)
+ end
super
end
end
@@ -217,17 +223,23 @@ class FieldAssignment < Node
include ClassScoped
child :value
+ attr_accessor :static
- def initialize(parent, position, name, annotations=[], &block)
+ def initialize(parent, position, name, annotations=[], static = false, &block)
@annotations = annotations
super(parent, position, &block)
@name = name
+ @static = static
end
def infer(typer)
resolve_if(typer) do
@annotations.each {|a| a.infer(typer)} if @annotations
- typer.learn_field_type(class_scope, name, typer.infer(value))
+ if static
+ typer.learn_static_field_type(class_scope, name, typer.infer(value))
+ else
+ typer.learn_field_type(class_scope, name, typer.infer(value))
+ end
end
end
end
@@ -236,17 +248,24 @@ class Field < Node
include Annotated
include Named
include ClassScoped
+
+ attr_accessor :static
- def initialize(parent, position, name, annotations=[], &block)
+ def initialize(parent, position, name, annotations=[], static = false, &block)
@annotations = annotations
super(parent, position, &block)
@name = name
+ @static = static
end
def infer(typer)
resolve_if(typer) do
@annotations.each {|a| a.infer(typer)} if @annotations
- typer.field_type(class_scope, name)
+ if static
+ typer.static_field_type(class_scope, name)
+ else
+ typer.field_type(class_scope, name)
+ end
end
end
end
View
@@ -229,22 +229,22 @@ def compile(compiler, expression)
class FieldDeclaration
def compile(compiler, expression)
- compiler.field_declare(name, inferred_type, annotations)
+ compiler.field_declare(name, inferred_type, annotations, static)
end
end
class FieldAssignment
def compile(compiler, expression)
compiler.line(line_number)
- compiler.field_assign(name, inferred_type, expression, value, annotations)
+ compiler.field_assign(name, inferred_type, expression, value, annotations, static)
end
end
class Field
def compile(compiler, expression)
compiler.line(line_number)
if expression
- compiler.field(name, inferred_type, annotations)
+ compiler.field(name, inferred_type, annotations, static)
end
end
end
View
@@ -564,17 +564,17 @@ def captured_local_assign(node, expression)
@method.putfield(scope.binding_type, name, type)
end
- def field(name, type, annotations)
+ def field(name, type, annotations, static_field)
name = name[1..-1] if name =~ /^@/
real_type = declared_fields[name] || type
- declare_field(name, real_type, annotations)
+ declare_field(name, real_type, annotations, static_field)
# load self object unless static
- method.aload 0 unless static
+ method.aload 0 unless static || static_field
- if static
+ if static || static_field
@method.getstatic(@class, name, type)
else
@method.getfield(@class, name, type)
@@ -586,11 +586,11 @@ def declared_fields
@declared_fields[@class] ||= {}
end
- def declare_field(name, type, annotations)
+ def declare_field(name, type, annotations, static_field)
# TODO confirm types are compatible
unless declared_fields[name]
declared_fields[name] = type
- field = if static
+ field = if static || static_field
@class.private_static_field name, type
else
@class.private_field name, type
@@ -599,28 +599,28 @@ def declare_field(name, type, annotations)
end
end
- def field_declare(name, type, annotations)
+ def field_declare(name, type, annotations, static_field)
name = name[1..-1] if name =~ /^@/
- declare_field(name, type, annotations)
+ declare_field(name, type, annotations, static_field)
end
- def field_assign(name, type, expression, value, annotations)
+ def field_assign(name, type, expression, value, annotations, static_field)
name = name[1..-1] if name =~ /^@/
real_type = declared_fields[name] || type
- declare_field(name, real_type, annotations)
+ declare_field(name, real_type, annotations, static_field)
- method.aload 0 unless static
+ method.aload 0 unless static || static_field
value.compile(self, true)
if expression
instruction = 'dup'
instruction << '2' if type.wide?
- instruction << '_x1' unless static
+ instruction << '_x1' unless static || static_field
method.send instruction
end
- if static
+ if static || static_field
@method.putstatic(@class, name, real_type)
else
@method.putfield(@class, name, real_type)
View
@@ -399,6 +399,28 @@ def transform_inst_var_assign(node, parent)
end
end
+ def transform_class_var(node, parent)
+ name = node[1]
+ name = transform(name, nil) unless name.kind_of?(::String)
+ Field.new(parent, position(node), name, transformer.annotations, true)
+ end
+
+ def transform_class_var_assign(node, parent)
+ name = node[1]
+ name = transform(name, nil) unless name.kind_of?(::String)
+ value_node = node[2]
+ position = position(node)
+ case value_node[0]
+ when 'Symbol', 'Constant'
+ FieldDeclaration.new(parent, position,
+ name, transformer.annotations, true) do |field_decl|
+ [transform(value_node, field_decl)]
+ end
+ else
+ FieldAssignment.new(parent, position, name, transformer.annotations, true) {|field| [transformer.transform(value_node, field)]}
+ end
+ end
+
def transform_if(node, parent)
condition = node[1]
then_body = node[2]
View
@@ -135,6 +135,14 @@ def field_type_hash(cls)
field_types[cls] ||= {}
end
+ def static_field_types
+ @static_field_types ||= {}
+ end
+
+ def static_field_type_hash(cls)
+ static_field_types[cls] ||= {}
+ end
+
def infer_signature(method_def)
end
@@ -151,6 +159,19 @@ def field_type(cls, name)
field_type_hash(cls)[name]
end
+ def learn_static_field_type(cls, name, type)
+ log "Learned field type under #{cls} : #{name} = #{type}"
+
+ # TODO check for compatibility?
+ static_field_type_hash(cls)[name] ||= known_types[type] || type
+
+ type
+ end
+
+ def static_field_type(cls, name)
+ static_field_type_hash(cls)[name]
+ end
+
def learn_method_type(target_type, name, parameter_types, type, exceptions)
log "Learned method #{name} (#{parameter_types}) on #{target_type} = #{type}"

0 comments on commit e8f084c

Please sign in to comment.