Created
October 30, 2010 02:42
-
-
Save headius/654845 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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