diff --git a/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs b/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs index 202886d..32146ee 100644 --- a/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs +++ b/CSharpTranslator/antlr3/src/cs2j/CLR/TranslationTemplate.cs @@ -321,14 +321,14 @@ namespace RusticiSoftware.Translator.CLR public override string mkJava() { string constructorName = "CONSTRUCTOR"; - if (SurroundingTypeName != null) { + if (!String.IsNullOrEmpty(SurroundingTypeName)) { constructorName = SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1); } return "new " + constructorName + mkJavaParams(Params); } public override string[] mkImports() { - if (SurroundingTypeName != null) { + if (!String.IsNullOrEmpty(SurroundingTypeName)) { return new string[] {SurroundingTypeName}; } else { @@ -454,12 +454,12 @@ namespace RusticiSoftware.Translator.CLR public override string mkJava() { StringBuilder methStr = new StringBuilder(); if (IsStatic) { - if (SurroundingTypeName != null) { - methStr.Append(SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1) + "."); - } - else { - methStr.Append("TYPENAME."); - } + if (!String.IsNullOrEmpty(SurroundingTypeName)) { + methStr.Append(SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1) + "."); + } + else { + methStr.Append("TYPENAME."); + } } else { methStr.Append("${this}."); @@ -565,11 +565,11 @@ namespace RusticiSoftware.Translator.CLR } public override string[] mkImports() { - if (From == null || To == null) { - return null; + if (!String.IsNullOrEmpty(SurroundingTypeName)) { + return new string[] {SurroundingTypeName}; } else { - return new string[] {"CS2JNet." + From}; + return null; } } @@ -578,7 +578,13 @@ namespace RusticiSoftware.Translator.CLR return null; } else { - return From.Substring(From.LastIndexOf('.') + 1) + ".__cast_" + To.Replace('.','_') + "(${expr})"; + if (!String.IsNullOrEmpty(SurroundingTypeName)) { + return SurroundingTypeName.Substring(SurroundingTypeName.LastIndexOf('.') + 1) + ".__castto_" + To.Replace('.','_') + "(${expr})"; + } + else + { + return "__cast_" + To.Replace('.','_') + "(${expr})"; + } } } diff --git a/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g b/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g index 44117ef..1c4a824 100644 --- a/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g +++ b/CSharpTranslator/antlr3/src/cs2j/CSharp/NetMaker.g @@ -147,6 +147,13 @@ scope SymTab { return (CommonTree)adaptor.RulePostProcessing(root); } + protected CommonTree wrapTypeOfType(TypeRepTemplate t, IToken tok) { + CommonTree root = (CommonTree)adaptor.Nil; + root = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(JAVAWRAPPEREXPRESSION, tok, "EXPRESSION"), root); + adaptor.AddChild(root, (CommonTree)adaptor.Create(IDENTIFIER, tok, t.Java)); + return (CommonTree)adaptor.RulePostProcessing(root); + } + protected CommonTree dupTree(CommonTree t) { return (CommonTree)adaptor.DupTree(t); } @@ -264,7 +271,7 @@ class_member_declaration: | ^(OPERATOR attributes? modifiers? type operator_declaration) | ^(ENUM attributes? modifiers? enum_declaration) | ^(DELEGATE attributes? modifiers? delegate_declaration) - | ^(CONVERSION_OPERATOR attributes? modifiers? conversion_operator_declaration) + | ^(CONVERSION_OPERATOR attributes? modifiers? conversion_operator_declaration[$attributes.tree, $modifiers.tree]) -> conversion_operator_declaration | ^(CONSTRUCTOR attributes? modifiers? identifier formal_parameter_list? block exception*) | ^(STATIC_CONSTRUCTOR attributes? modifiers? block) ; @@ -274,7 +281,7 @@ exception: // rmId is the rightmost ID in an expression like fdfd.dfdsf.returnme, otherwise it is null // used in switch labels to strip down qualified types, which Java doesn't grok -primary_expression returns [TypeRepTemplate dotNetType, String rmId] +primary_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType] scope { bool parentIsApply; } @@ -303,6 +310,10 @@ scope { } for (int idx = 0; idx < methodRep.Params.Count; idx++) { myMap[methodRep.Params[idx].Name] = wrapArgument($argument_list.argTrees[idx], $i2.tree.Token); + if (methodRep.Params[idx].Name.StartsWith("TYPEOF") && $argument_list.argTreeTypeofTypes[idx] != null) { + // if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping + myMap[methodRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($argument_list.argTreeTypeofTypes[idx], $i2.tree.Token); + } } ret = mkJavaWrapper(methodResult.Result.Java, myMap, $i2.tree.Token); Imports.Add(methodResult.Result.Imports); @@ -432,7 +443,7 @@ scope { | unchecked_expression // unchecked {...} | default_value_expression // default | anonymous_method_expression // delegate (int foo) {} - | typeof_expression // typeof(Foo).Name + | typeof_expression { $dotNetType = $typeof_expression.dotNetType; $typeofType = $typeof_expression.typeofType; } // typeof(Foo).Name ; primary_expression_start returns [TypeRepTemplate dotNetType]: @@ -456,31 +467,32 @@ paren_expression: '(' expression ')' ; arguments: '(' argument_list? ')' ; -argument_list returns [List argTypes, List argTrees] +argument_list returns [List argTypes, List argTrees, List argTreeTypeofTypes] @init { $argTypes = new List(); $argTrees = new List(); + $argTreeTypeofTypes = new List(); }: - ^(ARGS (argument { $argTypes.Add($argument.dotNetType); $argTrees.Add(dupTree($argument.tree)); })+); + ^(ARGS (argument { $argTypes.Add($argument.dotNetType); $argTrees.Add(dupTree($argument.tree)); $argTreeTypeofTypes.Add($argument.typeofType); })+); // 4.0 -argument returns [TypeRepTemplate dotNetType]: - argument_name argument_value { $dotNetType = $argument_value.dotNetType; } - | argument_value { $dotNetType = $argument_value.dotNetType; } +argument returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]: + argument_name argument_value { $dotNetType = $argument_value.dotNetType; $typeofType = $argument_value.typeofType; } + | argument_value { $dotNetType = $argument_value.dotNetType; $typeofType = $argument_value.typeofType; } ; argument_name: identifier ':'; -argument_value returns [TypeRepTemplate dotNetType]: - expression { $dotNetType = $expression.dotNetType; } - | ref_variable_reference { $dotNetType = $ref_variable_reference.dotNetType; } - | 'out' variable_reference { $dotNetType = $variable_reference.dotNetType; } ; -ref_variable_reference returns [TypeRepTemplate dotNetType]: +argument_value returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]: + expression { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; } + | ref_variable_reference { $dotNetType = $ref_variable_reference.dotNetType; $typeofType = $ref_variable_reference.typeofType; } + | 'out' variable_reference { $dotNetType = $variable_reference.dotNetType; $typeofType = $variable_reference.typeofType; } ; +ref_variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]: 'ref' (('(' type ')') => '(' type ')' (ref_variable_reference | variable_reference) { $dotNetType = $type.dotNetType; } // SomeFunc(ref (int) ref foo) // SomeFunc(ref (int) foo) - | v1=variable_reference { $dotNetType = $v1.dotNetType; }); // SomeFunc(ref foo) + | v1=variable_reference { $dotNetType = $v1.dotNetType; $typeofType = $v1.typeofType; }); // SomeFunc(ref foo) // lvalue -variable_reference returns [TypeRepTemplate dotNetType]: - expression { $dotNetType = $expression.dotNetType; }; +variable_reference returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]: + expression { $dotNetType = $expression.dotNetType; $typeofType = $expression.typeofType; }; rank_specifiers: rank_specifier+ ; rank_specifier: @@ -501,9 +513,9 @@ member_declarator_list: member_declarator (',' member_declarator)* ; member_declarator: qid ('=' expression)? ; -primary_or_array_creation_expression returns [TypeRepTemplate dotNetType, String rmId]: +primary_or_array_creation_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType]: (array_creation_expression) => array_creation_expression - | primary_expression { $dotNetType = $primary_expression.dotNetType; $rmId = $primary_expression.rmId; } + | primary_expression { $dotNetType = $primary_expression.dotNetType; $rmId = $primary_expression.rmId; $typeofType = $primary_expression.typeofType; } ; // new Type[2] { } array_creation_expression: @@ -581,8 +593,8 @@ initializer_value: /////////////////////////////////////////////////////// -typeof_expression: - ^('typeof' (unbound_type_name | type | 'void') ) ; +typeof_expression returns [TypeRepTemplate dotNetType, TypeRepTemplate typeofType]: + ^('typeof' (unbound_type_name | type { $typeofType = $type.dotNetType; } | 'void' { $typeofType = AppEnv.Search("System.Void"); }) ) { $dotNetType = AppEnv.Search("System.Type"); }; // unbound type examples //foo>> //bar::foo<> @@ -694,9 +706,9 @@ statement_list: /////////////////////////////////////////////////////// // Expression Section /////////////////////////////////////////////////////// -expression returns [TypeRepTemplate dotNetType, String rmId]: +expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType]: (unary_expression assignment_operator) => assignment { $dotNetType = VoidType; } - | non_assignment_expression { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; } + | non_assignment_expression { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; $typeofType = $non_assignment_expression.typeofType; } ; expression_list: expression (',' expression)* ; @@ -730,12 +742,12 @@ assignment | unary_expression assignment_operator expression ; -unary_expression returns [TypeRepTemplate dotNetType, String rmId]: +unary_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType]: //('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression //(cast_expression) => cast_expression ^(CAST_EXPR type unary_expression) { $dotNetType = $type.dotNetType; } - | primary_or_array_creation_expression { $dotNetType = $primary_or_array_creation_expression.dotNetType; $rmId = $primary_or_array_creation_expression.rmId; } + | primary_or_array_creation_expression { $dotNetType = $primary_or_array_creation_expression.dotNetType; $rmId = $primary_or_array_creation_expression.rmId; $typeofType = $primary_or_array_creation_expression.typeofType; } | ^(MONOPLUS u1=unary_expression) { $dotNetType = $u1.dotNetType; } | ^(MONOMINUS u2=unary_expression) { $dotNetType = $u2.dotNetType; } | ^(MONONOT u3=unary_expression) { $dotNetType = $u3.dotNetType; } @@ -744,7 +756,7 @@ unary_expression returns [TypeRepTemplate dotNetType, String rmId]: | ^(PREDEC u6=unary_expression) { $dotNetType = $u6.dotNetType; } | ^(MONOSTAR unary_expression) { $dotNetType = ObjectType; } | ^(ADDRESSOF unary_expression) { $dotNetType = ObjectType; } - | ^(PARENS expression) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; } + | ^(PARENS expression) { $dotNetType = $expression.dotNetType; $rmId = $expression.rmId; $typeofType = $expression.typeofType; } ; //cast_expression: // '(' type ')' non_assignment_expression ; @@ -759,7 +771,7 @@ assignment_operator: //addressof_expression: // '&' unary_expression ; -non_assignment_expression returns [TypeRepTemplate dotNetType, String rmId]: +non_assignment_expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typeofType]: //'non ASSIGNment' (anonymous_function_signature '=>') => lambda_expression | (query_expression) => query_expression @@ -786,7 +798,7 @@ non_assignment_expression returns [TypeRepTemplate dotNetType, String rmId]: | ^('/' n12=non_assignment_expression non_assignment_expression) {$dotNetType = $n12.dotNetType; } | ^('%' n13=non_assignment_expression non_assignment_expression) {$dotNetType = $n13.dotNetType; } // | ^(UNARY_EXPRESSION unary_expression) - | unary_expression {$dotNetType = $unary_expression.dotNetType; $rmId = $unary_expression.rmId; } + | unary_expression {$dotNetType = $unary_expression.dotNetType; $rmId = $unary_expression.rmId; $typeofType = $unary_expression.typeofType; } ; // /////////////////////////////////////////////////////// @@ -1172,10 +1184,15 @@ binary_operator_declarator: overloadable_binary_operator: /*'+' | '-' | */ '*' | '/' | '%' | '&' | '|' | '^' | '<<' | '>' '>' | '==' | '!=' | '>' | '<' | '>=' | '<=' ; -conversion_operator_declaration: - conversion_operator_declarator operator_body ; -conversion_operator_declarator: - ('implicit' | 'explicit') 'operator' type '(' type identifier ')' ; +// rewrite to a method +conversion_operator_declaration[CommonTree atts, CommonTree mods] +scope SymTab; +@init { + $SymTab::symtab = new Dictionary(); +}: + h=conversion_operator_declarator { $SymTab::symtab[$h.var] = $h.varTy; } b=operator_body meth=magicCastOperator[$mods, $h.tree, $b.tree] -> $meth; +conversion_operator_declarator returns [ String var, TypeRepTemplate varTy ] : + ('implicit' | 'explicit') o='operator' t=type '(' f=type n=identifier ')' { $var = $n.thetext; $varTy = $f.dotNetType; } -> $o $t $f $n; operator_body: block ; @@ -1455,3 +1472,17 @@ magicScrutineeVar [IToken tok] returns [String thetext] $thetext = "__dummyScrutVar" + dummyScrutVarCtr++; }: -> IDENTIFIER[tok,$thetext]; + +magicCastOperator[CommonTree mods, CommonTree header, CommonTree body] +@init { + IToken tok = ((CommonTree)$header.Children[0]).Token; + CommonTree toType = dupTree((CommonTree)$header.Children[1]); + CommonTree fromType = dupTree((CommonTree)$header.Children[2]); + CommonTree paramName = dupTree((CommonTree)$header.Children[3]); +}: +-> ^(METHOD[tok, "METHOD"] + { dupTree($mods) } + { toType } IDENTIFIER[tok, "__cast"] ^(PARAMS[tok, "PARAMS"] { fromType } { paramName}) + { dupTree(body) } + EXCEPTION[tok, "Throwable"]) +; diff --git a/CSharpTranslator/antlr3/src/cs2j/CSharp/TemplateExtracter.g b/CSharpTranslator/antlr3/src/cs2j/CSharp/TemplateExtracter.g index 1b73169..9d34970 100644 --- a/CSharpTranslator/antlr3/src/cs2j/CSharp/TemplateExtracter.g +++ b/CSharpTranslator/antlr3/src/cs2j/CSharp/TemplateExtracter.g @@ -1136,7 +1136,10 @@ conversion_operator_declaration: conversion_operator_declarator operator_body ; conversion_operator_declarator: (i='implicit' { Warning($i.line, "[UNSUPPORTED] implicit user defined casts, an explicit cast is always required."); } | 'explicit') 'operator' tt=type '(' tf=type identifier ')' - { ((ClassRepTemplate)$NSContext::currentTypeRep).Casts.Add(new CastRepTemplate($tf.thetext, $tt.thetext)); + { + CastRepTemplate kast = new CastRepTemplate($tf.thetext, $tt.thetext); + kast.SurroundingTypeName = $NSContext::currentTypeRep.TypeName; + ((ClassRepTemplate)$NSContext::currentTypeRep).Casts.Add(kast); Debug("Processing conversion declaration"); } ;