Skip to content

Instantly share code, notes, and snippets.

@headius
Created October 30, 2010 02:42
Show Gist options
  • Save headius/654845 to your computer and use it in GitHub Desktop.
Save headius/654845 to your computer and use it in GitHub Desktop.
diff --git a/lib/mirah/ast/class.rb b/lib/mirah/ast/class.rb
index 92a69eb..a0b4f8b 100644
--- a/lib/mirah/ast/class.rb
+++ b/lib/mirah/ast/class.rb
@@ -190,11 +190,13 @@ module Duby::AST
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 @@ module Duby::AST
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 @@ module Duby::AST
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 @@ module Duby::AST
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
diff --git a/lib/mirah/compiler.rb b/lib/mirah/compiler.rb
index 3f3ea4e..d6cedaa 100644
--- a/lib/mirah/compiler.rb
+++ b/lib/mirah/compiler.rb
@@ -229,14 +229,14 @@ module Duby
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
@@ -244,7 +244,7 @@ module Duby
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
diff --git a/lib/mirah/jvm/compiler.rb b/lib/mirah/jvm/compiler.rb
index 5f5360a..642652e 100644
--- a/lib/mirah/jvm/compiler.rb
+++ b/lib/mirah/jvm/compiler.rb
@@ -564,7 +564,7 @@ module Duby
@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
@@ -574,7 +574,7 @@ module Duby
# load self object unless static
method.aload 0 unless static
- if static
+ if static || static_field
@method.getstatic(@class, name, type)
else
@method.getfield(@class, name, type)
@@ -586,11 +586,11 @@ module Duby
@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,12 +599,12 @@ module Duby
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
@@ -620,7 +620,7 @@ module Duby
method.send instruction
end
- if static
+ if static || static_field
@method.putstatic(@class, name, real_type)
else
@method.putfield(@class, name, real_type)
diff --git a/lib/mirah/transform2.rb b/lib/mirah/transform2.rb
index e06dfa0..5c93788 100644
--- a/lib/mirah/transform2.rb
+++ b/lib/mirah/transform2.rb
@@ -399,6 +399,28 @@ module Duby::AST
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)
+ 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]
diff --git a/lib/mirah/typer.rb b/lib/mirah/typer.rb
index 95d3e8c..58e838a 100644
--- a/lib/mirah/typer.rb
+++ b/lib/mirah/typer.rb
@@ -135,6 +135,14 @@ module Duby
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 @@ module Duby
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}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment