contrib/jwrapper: big rewrite of the AST visitor
authorAlexis Laferrière <alexis.laf@xymus.net>
Wed, 22 Jul 2015 13:50:20 +0000 (09:50 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Fri, 24 Jul 2015 13:44:24 +0000 (09:44 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

contrib/jwrapper/grammar/javap.sablecc
contrib/jwrapper/src/javap_visitor.nit
contrib/jwrapper/src/model.nit

index 34785d5..dc46557 100644 (file)
@@ -9,6 +9,7 @@ separator = ('.'|'/');
 brackets = '[]';
 wildcard = '?';
 compiled_from = 'Compiled from "' (Any-'"')* '"';
+dots = '...';
 
 // ---
 Parser
@@ -25,23 +26,23 @@ class_or_interface = 'class'|'interface';
 
 modifier
        = 'public'|'private'|'protected'|'static'|'final'|'native'|'synchronized'|'abstract'|'threadsafe'|'transient'|'volatile'|'strictfp';
-type = primitive_type brackets*;
-primitive_type
-       = 'boolean'|'byte'|'char'|'short'|'int'|'float'|'long'|'double'
-       | type_ref;
 
-type_ref
-       = full_class_name
-       | generic_identifier 'extends' type_bound
-       | wildcard;
+type = base_type brackets*;
+
+base_type
+       = {primitive:} primitive_base_type
+       | {class:} full_class_name
+       | {extends:} generic_identifier 'extends' type_bound
+       | {super:} generic_identifier 'super' type_bound
+       | {wildcard:} wildcard
+       | {void:} 'void';
+
+primitive_base_type = 'boolean'|'byte'|'char'|'short'|'int'|'float'|'long'|'double';
+
 type_bound
        = {tail:} type_bound '&' full_class_name
        | {head:} full_class_name;
 
-generic_param = '<' generic_parameter_list '>';
-generic_parameter_list
-       = {tail:} generic_parameter_list ',' parameter
-       | {head:} parameter;
 generic_identifier
        = full_class_name
        | wildcard;
@@ -49,22 +50,19 @@ generic_identifier
 full_class_name
        = {tail:} full_class_name separator class_name
        | {head:} class_name;
-class_name = identifier generic_param?;
+class_name = identifier generic_parameters?;
 
-parameter
-       = type '...'?
-       | {wildcard:} wildcard 'super' full_class_name ;
-parameter_list
-       = {tail:} parameter_list ',' parameter
-       | {head:} parameter;
+generic_parameters = '<' parameters '>';
 
-attribute_id = identifier brackets*;
-method_id = identifier;
+parameter = type dots?;
+parameters
+       = {tail:} parameters ',' parameter
+       | {head:} parameter;
 
 property_declaration
-       = {method:} modifier* generic_param? type method_id '(' parameter_list? ')' throws_declaration? ';'
-       | {constructor:} modifier* generic_param? full_class_name '(' parameter_list? ')' throws_declaration? ';'
-       | {attribute:} modifier* type attribute_id throws_declaration? ';'
+       = {method:} modifier* generic_parameters? type identifier '(' parameters? ')' throws_declaration? ';'
+       | {constructor:} modifier* generic_parameters? full_class_name '(' parameters? ')' throws_declaration? ';'
+       | {attribute:} modifier* type identifier brackets* throws_declaration? ';'
        | {static:} modifier* '{' '}' ';'
        | ';';
 
index e94eedb..3721b21 100644 (file)
@@ -31,207 +31,29 @@ class JavaVisitor
        # Model of all the analyzed classes
        var model: JavaModel
 
+       # Java class in construction
        var java_class: JavaClass is noinit
 
-       var declaration_type: nullable String =  null
-       var declaration_element: nullable String = null
-       var class_type: JavaType is noinit
-
-       var variable_id = ""
-       var variable_type = new JavaType is lazy
-
-       var is_generic_param = false
-       var is_generic_id = false
-       var generic_id = ""
-       var gen_params_index = 0
-
-       # Used to resolve generic return types (T -> foo.faz.Bar)
-       var generic_map = new HashMap[String, Array[String]]
-
-       var is_primitive_array = false
-
-       var method_id = ""
-       var method_return_type = new JavaType is lazy
-       var method_params = new Array[JavaType]
-       var param_index = 0
-
        redef fun visit(n) do n.accept_visitor(self)
-
-       # Add the identifier from `token` to the current context
-       fun add_identifier(token: String)
-       do
-               if declaration_type == "variable" then
-                       if declaration_element == "type" then
-                               if is_generic_param then
-                                       variable_type.generic_params[gen_params_index].identifier.add token
-                               else
-                                       variable_type.identifier.add(token)
-                               end
-                       end
-               else if declaration_type == "method" then
-                       if declaration_element == "return_type" then
-                               if is_generic_param then
-                                       method_return_type.generic_params[gen_params_index].identifier.add token
-                               else
-                                       method_return_type.identifier.add(token)
-                               end
-                       else if declaration_element == "parameter_list" then
-                               if is_generic_param then
-                                       method_params[param_index].generic_params[gen_params_index].identifier.add token
-                               else
-                                       method_params[param_index].identifier.add(token)
-                               end
-                       end
-               end
-       end
 end
 
 redef class Node
-       fun accept_visitor(v: JavaVisitor) do visit_children(v)
-end
-
-redef class Nidentifier
-       redef fun accept_visitor(v)
-       do
-               if v.declaration_type == "class_header" then
-                       # Class declaration
-                       if v.declaration_element == "id" then
-                               v.class_type.identifier.add text
-                               return
-                       end
-
-               else if v.declaration_type == "variable" then
-                       # Attribute declaration
-                       if v.declaration_element == "id" then
-                               v.variable_id += text
-                               return
-                       end
-
-               else if v.declaration_type == "method" then
-
-                       if v.declaration_element == "id" then
-                               # Method id
-                               v.method_id = self.text
-                               return
-                       else if v.declaration_element == "return_type" then
-                               if self.text == "void" then
-                                       # void return type
-                                       v.method_return_type.is_void = true
-                                       return
-                               end
-                       else if v.declaration_element == "parameter_list" then
-                               # Parameters, leave it to add_identifier
-
-                       else if v.is_generic_param then
-                               # Creates a map to resolve generic return types
-                               # Example : public **<T extends android/os/Bundle>** T foo();
-                               if v.is_generic_id then
-                                       v.generic_id = self.text
-                                       v.generic_map[self.text] = new Array[String]
-
-                                       if not v.method_return_type.has_unresolved_types then v.method_return_type.has_unresolved_types = true
-                               else
-                                       v.generic_map[v.generic_id].add text
-                               end
-                       end
-               end
-
-               v.add_identifier text
-       end
-end
-
-# Primitive array node
-redef class Nbrackets
-       redef fun accept_visitor(v)
-       do
-               if v.declaration_type == "variable" then
-                       if v.declaration_element == "type" then
-                               if v.is_generic_param then
-                                       v.variable_type.generic_params[v.gen_params_index].array_dimension += 1
-                               else
-                                       v.variable_type.array_dimension += 1
-                               end
-                       end
-
-               else if v.declaration_type == "method" then
-
-                       if v.declaration_element == "return_type" then
-                               if v.is_generic_param then
-                                       v.method_return_type.generic_params[v.gen_params_index].array_dimension += 1
-                               else
-                                       v.method_return_type.array_dimension += 1
-                               end
-                       else if v.declaration_element == "parameter_list" then
-                               if v.is_generic_param then
-                                       v.method_params[v.param_index].generic_params[v.gen_params_index].array_dimension += 1
-                               else
-                                       v.method_params[v.param_index].array_dimension += 1
-                               end
-                       end
-
-               end
-
-               super
-       end
-end
-
-redef class N_39dchar_39d
-       redef fun accept_visitor(v) do v.add_identifier text
+       private fun accept_visitor(v: JavaVisitor) do visit_children(v)
 end
 
-redef class N_39dboolean_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39dfloat_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39ddouble_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39dbyte_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39dshort_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39dint_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class N_39dlong_39d
-       redef fun accept_visitor(v) do v.add_identifier text
-end
-
-redef class Nwildcard
-       # TODO use the lower bound
-       redef fun accept_visitor(v) do v.add_identifier "Object"
-end
-
-#                                  #
-#    C L A S S     H E A D E R     #
-#                                  #
+# ---
+# Class Header
 
 redef class Nclass_declaration
        redef fun accept_visitor(v)
        do
-               v.java_class = new JavaClass
+               var jtype = n_full_class_name.to_java_type
+
+               v.java_class = new JavaClass(jtype)
                v.model.classes.add v.java_class
-               v.class_type = new JavaType
 
-               v.declaration_type = "class_header"
-               v.declaration_element = "id"
+               # Visit all properties
                super
-
-               # Exit class declaration
-               v.declaration_type = null
-               v.declaration_element = null
-
-               v.java_class.class_type = v.class_type
        end
 end
 
@@ -239,9 +61,7 @@ end
 redef class Nextends_declaration
        redef fun accept_visitor(v)
        do
-               v.declaration_element = "extends"
-               super
-               v.declaration_element = null
+               # TODO
        end
 end
 
@@ -249,33 +69,29 @@ end
 redef class Nimplements_declaration
        redef fun accept_visitor(v)
        do
-               v.declaration_element = "implements"
-               super
-               v.declaration_element = null
+               # TODO
        end
 end
 
-#                                            #
-# P R O P E R T Y    D E C L A R A T I O N S #
-#                                            #
+# ---
+# Properties
 
 # Method declaration
 redef class Nproperty_declaration_method
        redef fun accept_visitor(v)
        do
-               v.declaration_type = "method"
-               v.declaration_element = null
-               super
-               v.declaration_type = null
+               var id = n_identifier.text
+               var return_jtype = n_type.to_java_type
 
-               if v.method_return_type.has_unresolved_types then v.method_return_type.resolve_types(v.generic_map)
+               # Collect parameters
+               var n_parameters = n_parameters
+               var params
+               if n_parameters != null then
+                       params = n_parameters.to_a
+               else params = new Array[JavaType]
 
-               var method = new JavaMethod(v.method_return_type, v.method_params.clone)
-               v.java_class.methods[v.method_id].add method
-
-               v.method_params.clear
-               v.method_id = ""
-               v.method_return_type = new JavaType
+               var method = new JavaMethod(return_jtype, params)
+               v.java_class.methods[id].add method
        end
 end
 
@@ -283,9 +99,7 @@ end
 redef class Nproperty_declaration_constructor
        redef fun accept_visitor(v)
        do
-               v.declaration_type = "constructor"
-               super
-               v.declaration_type = null
+               # TODO
        end
 end
 
@@ -293,14 +107,14 @@ end
 redef class Nproperty_declaration_attribute
        redef fun accept_visitor(v)
        do
-               v.declaration_type = "variable"
-               super
-               v.declaration_type = null
+               var id = n_identifier.text
+               var jtype = n_type.to_java_type
 
-               v.java_class.attributes[v.variable_id] = v.variable_type
+               # Manually count the array depth as it is after the id
+               var brackets = n_brackets
+               if brackets != null then jtype.array_dimension += brackets.children.length
 
-               v.variable_id = ""
-               v.variable_type = new JavaType
+               v.java_class.attributes[id] = jtype
        end
 end
 
@@ -308,153 +122,130 @@ end
 redef class Nproperty_declaration_static
        redef fun accept_visitor(v)
        do
-               v.declaration_type = "static"
-               super
-               v.declaration_type = null
+               # TODO
        end
 end
 
-# Identifier of a variable
-redef class Nattribute_id
-       redef fun accept_visitor(v)
+# ---
+# Services
+
+redef class Ntype
+       private fun to_java_type: JavaType
        do
-               v.declaration_element = "id"
-               super
-               v.declaration_element = null
+               var jtype = n_base_type.to_java_type
+
+               var brackets = n_brackets
+               if brackets != null then jtype.array_dimension += brackets.children.length
+
+               return jtype
        end
 end
 
-# Identifier of the method
-redef class Nmethod_id
-       redef fun accept_visitor(v)
+redef class Nbase_type
+       private fun to_java_type: JavaType
        do
-               v.declaration_element = "id"
-               super
-               v.declaration_element = null
+               # By default, everything is bound by object
+               # TODO use a more precise bound
+               var jtype = new JavaType
+               jtype.identifier.add_all(["java", "lang", "object"])
+               return jtype
        end
 end
 
-redef class Ntype
-       redef fun accept_visitor(v)
+redef class Nbase_type_class
+       redef fun to_java_type do return n_full_class_name.to_java_type
+end
+
+redef class Nbase_type_primitive
+       redef fun to_java_type
        do
-               if v.declaration_type == "variable" and v.declaration_element != "id" then
-                       v.declaration_element = "type"
-               end
+               # All the concrete nodes under this production are tokens
+               for node in depth do
+                       if not node isa NToken then continue
 
-               if v.declaration_type == "method" and v.declaration_element == null then
-                       # Makes sure it is not the generic return type definition
-                       if not (v.method_return_type.identifier.is_empty and v.is_generic_param) then
-                               v.declaration_element = "return_type"
-                       end
+                       var jtype = new JavaType
+                       jtype.identifier.add node.text
+                       return jtype
                end
 
-               super
+               abort
+       end
+end
 
-               if v.declaration_element == "variable" then
-                       v.declaration_element = null
-               end
+redef class Nbase_type_void
+       redef fun to_java_type
+       do
+               var jtype = new JavaType
+               jtype.is_void = true
+               return jtype
        end
 end
 
-redef class Ngeneric_param
-       redef fun accept_visitor(v)
+redef class Nfull_class_name
+       # All the identifiers composing this class name
+       private fun to_a: Array[String] is abstract
+
+       # Access `n_class_name` on both alternatives
+       private fun n_class_name_common: Nclass_name is abstract
+
+       private fun to_java_type: JavaType
        do
-               # Ignore the weird generic return type declaration
-               if v.declaration_type == "method" then
-                       if v.declaration_element == null then
-                               v.is_generic_param = true
-                       else
-                               v.is_generic_param = true
-                               v.gen_params_index = 0
-
-                               if v.declaration_element == "return_type" then
-                                       v.method_return_type.generic_params = new Array[JavaType]
-                               else if v.declaration_element == "parameter_list" then
-                                       v.method_params[v.param_index].generic_params = new Array[JavaType]
-                               end
-                       end
-               else if v.declaration_type == "variable" then
-                       if v.declaration_element == "type" then
-                               v.is_generic_param = true
-                               v.gen_params_index = 0
-                               v.variable_type.generic_params = new Array[JavaType]
-                       end
-               end
+               var jtype = new JavaType
+               jtype.identifier = to_a
 
-               super
+               # Generic parameters
+               var n_params = n_class_name_common.n_generic_parameters
+               if n_params != null then jtype.generic_params = n_params.n_parameters.to_a
 
-               v.declaration_element = null
-               v.is_generic_param = false
+               return jtype
        end
 end
 
-redef class Ngeneric_identifier
-       redef fun accept_visitor(v)
-       do
-               if v.declaration_type == "method" then
-                       if v.declaration_element == null then
-                               v.is_generic_id = true
-                       end
-               end
+redef class Nfull_class_name_head
+       redef fun n_class_name_common do return n_class_name
 
-               super
+       redef fun to_a do return [n_class_name.n_identifier.text]
+end
 
-               v.is_generic_id = false
+redef class Nfull_class_name_tail
+       redef fun n_class_name_common do return n_class_name
 
+       redef fun to_a
+       do
+               var a = n_full_class_name.to_a
+               a.add n_class_name.n_identifier.text
+               return a
        end
 end
 
-redef class Nparameter_list
-       redef fun accept_visitor(v)
+redef class Nparameters
+       # Get the types composing this list of parameters
+       #
+       # This is used both on methods signatures and type parameters.
+       private fun to_a: Array[JavaType] is abstract
+end
+
+redef class Nparameters_head
+       redef fun to_a do return [n_parameter.to_java_type]
+end
+
+redef class Nparameters_tail
+       redef fun to_a
        do
-               v.declaration_element = "parameter_list"
-               v.param_index = 0
-               super
-               v.declaration_element = null
-               v.param_index = 0
+               var a = n_parameters.to_a
+               a.add n_parameter.to_java_type
+               return a
        end
 end
 
 redef class Nparameter
-       redef fun accept_visitor(v)
+       private fun to_java_type: JavaType
        do
-               if v.declaration_type == "method" then
-                       if v.declaration_element == "parameter_list" then
-                               if v.is_generic_param then
-                                       v.method_params[v.param_index].generic_params.add new JavaType
-
-                                       super
-
-                                       v.gen_params_index += 1
-                               else
-                                       v.method_params.add new JavaType
-
-                                       super
+               var jtype = n_type.to_java_type
 
-                                       v.param_index += 1
-                               end
-                       else if v.declaration_element == "return_type" and v.is_generic_param then
+               var dots = n_dots
+               if dots != null then jtype.is_vararg = true
 
-                               v.method_return_type.generic_params.add new JavaType
-
-                               super
-
-                               v.gen_params_index += 1
-
-                       # For generic return type definition
-                       else if v.declaration_element == null then
-                               super
-                       end
-               else if v.declaration_type == "variable" then
-                       if v.declaration_element == "type" and v.is_generic_param then
-                               v.variable_type.generic_params.add new JavaType
-
-                               super
-
-                               v.gen_params_index += 1
-                       end
-               else
-                       super
-               end
+               return jtype
        end
 end
index dfa7694..ffc68d1 100644 (file)
@@ -25,8 +25,13 @@ import jtype_converter
 class JavaType
        var identifier = new Array[String]
        var generic_params: nullable Array[JavaType] = null
+
+       # Is this a void return type?
        var is_void = false
 
+       # Is this type a vararg?
+       var is_vararg = false is writable
+
        # Has some generic type to be resolved (T extends foo => T is resolved to foo)
        var has_unresolved_types = false
 
@@ -211,7 +216,7 @@ end
 # Model of a single Java class
 class JavaClass
        # Type of this class
-       var class_type = new JavaType
+       var class_type: JavaType
 
        # Attributes of this class
        var attributes = new HashMap[String, JavaType]