1
0
mirror of https://github.com/twiglet/cs2j.git synced 2025-01-18 13:15:17 +01:00

Use parseString to generate (java) Collection methods when translating a type that implements ICollection

This commit is contained in:
Kevin Glynn 2011-04-13 11:45:38 +02:00
parent 18fb3d4063
commit dafcee91d6
5 changed files with 468 additions and 11 deletions

View File

@ -42,6 +42,16 @@
<Name>CopyTo</Name>
<Return>System.Void</Return>
</Method>
<Method>
<Imports>
<Import>CS2JNet.JavaSupport.Collections.Generic.EnumeratorSupport</Import>
</Imports>
<Java>new EnumeratorSupport*[T]*(${this}.iterator())</Java>
<Params>
</Params>
<Name>GetEnumerator</Name>
<Return>System.Collections.Generic.IEnumerator*[T]*</Return>
</Method>
</Methods>
<Properties>
<Property>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is
Copyright 2010,2011 Kevin Glynn (kevin.glynn@twigletsoftware.com)
-->
<Interface xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:www.twigletsoftware.com:schemas:txtemplate:1:0">
<Imports>
<Import>CS2JNet.System.Collections.Generic.IEnumeratorSupport</Import>
</Imports>
<Java>IEnumeratorSupport</Java>
<Name>System.Collections.IEnumerator</Name>
<Properties>
<Type>System.Object</Type>
<Name>Current></Name>
<Get>${this:16}.getcurrent()</Get>
</Properties>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>jEYi0rdl/kMLr7uBNG0M9LMlbCQ=</DigestValue></Reference></SignedInfo><SignatureValue>C/hbBQnMGlWnPvwE61XrMusMlyKT+K792pEYR7D7CnpO7Td1gFgCCfkSdFVZ1axk+sLzebWIQKH8+NFRC6+hlNpViODt46v/300e+fi2Yx8BWhpq5e51zfNAhHIdaUemMqHMHNG5BMOngpFx1yrO/zxHvj7HPJqGBwJV7w8yPtU=</SignatureValue></Signature></Interface>

View File

@ -20,12 +20,14 @@
package CS2JNet.System.Collections.Generic;
import java.util.Collection;
/**
* @author kevin.glynn@twigletsoftware.com
*
*/
public interface ICollectionSupport<T> extends Iterable<T> {
public interface ICollectionSupport<T> extends Collection<T> {
public boolean Contains(T x) throws Exception;

View File

@ -0,0 +1,181 @@
/*
Copyright 2010,2011 Kevin Glynn (kevin.glynn@twigletsoftware.com)
*/
using System;
using System.Collections.Generic;
using Antlr.Runtime.Tree;
namespace Twiglet.CS2J.Translator
{
public class Fragments
{
public static string GenericCollectorMethods(string T, string S)
{
return genericCollectorMethodsStr.Replace("${T}", T).Replace("${S}", S);
}
private static string genericCollectorMethodsStr = @"
public Iterator<${T}> iterator() {
Iterator<${T}> ret = null;
try
{
ret = this.GetEnumerator().iterator();
}
catch (Exception e)
{
e.printStackTrace();
}
return ret;
}
public boolean add(${T} el) {
try
{
this.Add(el);
}
catch (Exception e)
{
e.printStackTrace();
}
return true;
}
public boolean addAll(Collection<? extends ${T}> c) {
for (${T} el : c) {
this.add(el);
}
return true;
}
public void clear() {
try
{
this.Clear();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public boolean contains(Object o) {
boolean ret = false;
try
{
ret = this.Contains((${T}) o);
}
catch (Exception e)
{
e.printStackTrace();
}
return ret;
}
public boolean containsAll(Collection<?> c) {
boolean ret = true;
for (Object el : c) {
if (!this.contains(el)) {
ret = false;
break;
}
}
return ret;
}
public boolean isEmpty() {
return this.size() == 0;
}
public boolean remove(Object o) {
boolean ret = false;
try
{
ret = this.Remove((${T}) o);
}
catch (Exception e)
{
e.printStackTrace();
}
return ret;
}
public boolean removeAll(Collection<?> c) {
boolean ret = false;
for (Object el : c) {
ret = ret | this.remove(el);
}
return ret;
}
public boolean retainAll(Collection<?> c) {
boolean ret = false;
Object[] thisCopy = this.toArray();
for (Object el : thisCopy) {
if (!c.contains(el)) {
ret = ret | this.remove(el);
}
}
return false;
}
public int size() {
int ret = -1;
try {
return this.getCount();
}
catch (Exception e)
{
e.printStackTrace();
}
return ret;
}
public Object[] toArray() {
Object[] ret = new Object[this.size()];
int i = 0;
for (Object el : this) {
ret[i] = el;
}
return ret;
}
// NOTE: Moved <S> to after the method name, like C# not Java, to help the poor parser.
public ${S}[] toArray<${S}>(${S}[] a) {
ArrayList<${T}> ret = new ArrayList<${T}>(this.size());
for (${T} el : this) {
ret.add(el);
}
return ret.toArray(a);
}
";
public static string GenIterator = @"
public Iterator<${T}> iterator() {
Iterator<${T}> ret = null;
try
{
ret = this.GetEnumerator().iterator();
}
catch (Exception e)
{
e.printStackTrace();
}
return ret;
}";
private static Dictionary<string, CommonTree> _fragmentsLibrary = null;
public static Dictionary<string, CommonTree> FragmentsLibrary
{ get
{
if (_fragmentsLibrary == null)
{
_fragmentsLibrary = new Dictionary<string, CommonTree>();
}
return _fragmentsLibrary;
}
}
}
}

View File

@ -26,6 +26,11 @@ scope NSContext {
List<string> typeVariables;
// all typevariables in all scopes
List<string> globalTypeVariables;
// Does this type implement ICollection?
bool IsGenericICollection;
string GenericICollectionTyVar;
bool IsICollection;
}
// A scope to keep track of the mapping from variables to types
@ -185,7 +190,6 @@ scope MkNonGeneric {
}
private ClassRepTemplate dateType = null;
protected ClassRepTemplate DateType {
get {
if (dateType == null) {
@ -195,6 +199,26 @@ scope MkNonGeneric {
}
}
private InterfaceRepTemplate iCollectionType = null;
protected InterfaceRepTemplate ICollectionType {
get {
if (iCollectionType == null) {
iCollectionType = (InterfaceRepTemplate)findType("System.Collections.ICollection");
}
return iCollectionType;
}
}
private InterfaceRepTemplate genericICollectionType = null;
protected InterfaceRepTemplate GenericICollectionType {
get {
if (genericICollectionType == null) {
genericICollectionType = (InterfaceRepTemplate)findType("System.Collections.Generic.ICollection", new TypeRepTemplate[] {ObjectType});
}
return genericICollectionType;
}
}
// Map of Java built in types to their object based equivalents
Dictionary<string, string> primitive_to_object_type_map = new Dictionary<string, string>()
{
@ -319,6 +343,7 @@ scope MkNonGeneric {
protected int dummyScrutVarCtr = 0;
protected int dummyForeachVarCtr = 0;
protected int dummyStaticConstructorCatchVarCtr = 0;
protected int dummyTyVarCtr = 0;
// It turns out that 'default:' doesn't have to be last in the switch statement, so
// we need some jiggery pokery when converting to if-then-else.
@ -518,6 +543,11 @@ scope NSContext, PrimitiveRep, MkNonGeneric;
$NSContext::typeVariables = new List<string>();
$NSContext::globalTypeVariables = new List<string>();
$NSContext::IsGenericICollection = false;
$NSContext::GenericICollectionTyVar = "";
$NSContext::IsICollection = false;
}:
^(pkg=PACKAGE ns=PAYLOAD { $NSContext::currentNS = $ns.text; } dec=type_declaration )
-> ^($pkg $ns { mkImports() } $dec);
@ -1630,6 +1660,11 @@ scope NSContext,SymTab;
$NSContext::globalNamespaces = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalNamespaces);
$NSContext::typeVariables = new List<string>();
$NSContext::globalTypeVariables = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalTypeVariables);
$NSContext::IsGenericICollection = false;
$NSContext::GenericICollectionTyVar = "";
$NSContext::IsICollection = false;
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
}
:
@ -1659,6 +1694,12 @@ scope NSContext,SymTab;
}
$SymTab::symtab["super"] = baseType;
}
if ($NSContext::IsICollection) {
Debug(10, $NSContext::currentNS + " is a Collection");
}
if ($NSContext::IsGenericICollection) {
Debug(10, $NSContext::currentNS + " is a Generic Collection");
}
}
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
@ -1680,7 +1721,8 @@ class_extend:
// If first implements type is a class then convert to extends
class_implements returns [bool hasExtends, TypeRepTemplate extendDotNetType]:
class_implement_or_extend { $hasExtends = $class_implement_or_extend.hasExtends; $extendDotNetType = $class_implement_or_extend.extendDotNetType; }class_implement* ;
class_implement_or_extend { $hasExtends = $class_implement_or_extend.hasExtends; $extendDotNetType = $class_implement_or_extend.extendDotNetType; }
class_implement* ;
class_implement_or_extend returns [bool hasExtends, TypeRepTemplate extendDotNetType]
@init {
@ -1691,18 +1733,36 @@ class_implement_or_extend returns [bool hasExtends, TypeRepTemplate extendDotNet
$hasExtends = true;
$extendDotNetType = $t.dotNetType;
}
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
if($t.dotNetType.IsA(GenericICollectionType,AppEnv)) {
$NSContext::IsGenericICollection = true;
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
}
} )
-> { $t.dotNetType is ClassRepTemplate }? ^(EXTENDS[$i.token, "extends"] type)
-> ^($i $t);
class_implement:
^(IMPLEMENTS type) ;
^(IMPLEMENTS t=type
{
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
if($t.dotNetType.IsA(GenericICollectionType,AppEnv)) {
$NSContext::IsGenericICollection = true;
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
}
}) ;
interface_type_list:
type (',' type)* ;
class_body:
'{' class_member_declarations? '}' ;
class_body
@init {
CommonTree collectorNodes = null;
if ($NSContext::IsGenericICollection) {
collectorNodes = this.parseString("class_member_declarations", Fragments.GenericCollectorMethods($NSContext::GenericICollectionTyVar, $NSContext::GenericICollectionTyVar + "__" + dummyTyVarCtr++));
AddToImports("java.util.Iterator");
AddToImports("java.util.Collection");
AddToImports("java.util.ArrayList");
}
}:
'{' class_member_declarations? '}' -> '{' class_member_declarations? { dupTree(collectorNodes) } '}' ;
class_member_declarations:
class_member_declaration+ ;
@ -1816,6 +1876,10 @@ scope NSContext,SymTab;
$NSContext::globalNamespaces = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalNamespaces);
$NSContext::typeVariables = new List<string>();
$NSContext::globalTypeVariables = new List<string>(((NSContext_scope)$NSContext.ToArray()[1]).globalTypeVariables);
$NSContext::IsGenericICollection = false;
$NSContext::IsICollection = false;
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
}
:
@ -1881,8 +1945,6 @@ interface_declaration:
class_extends? interface_body ) ;
interface_modifiers:
modifier+ ;
interface_base:
':' interface_type_list ;
interface_body:
'{' interface_member_declarations? '}' ;
interface_member_declarations:
@ -2384,3 +2446,185 @@ magicThrowableType[bool isOn, IToken tok]:
magicEventCollectionType[IToken tok, CommonTree type]:
-> ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "IEventCollection"] LTHAN[tok, "<"] { dupTree(type) } GT[tok, ">"] )
;
// METHOD{ public TYPE{ Iterator < TYPE{ JAVAWRAPPER{ T } } > } kiterator { TYPE{ Iterator < TYPE{ JAVAWRAPPER{ T } } > } ret = null ; try{ { ret = APPLY{ .{ JAVAWRAPPER{ ${this:16}.GetEnumerator() this EXPRESSION{ this } } iterator } } ; } catch{ TYPE{ JAVAWRAPPER{ Exception } } e { APPLY{ .{ e printStackTrace } } ; } } } return{ ret } } Exception }
//
magicXXGenericIterator[bool isOn, IToken tok, String tyVar]
@init {
if (isOn) AddToImports("java.util.Iterator");
}
:
-> {isOn}? ^(METHOD[tok, "METHOD"]
PUBLIC[tok, "public"]
^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"] LTHAN[tok, "<"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, tyVar]) GT[tok, ">"])
IDENTIFIER[tok, "iterator"]
OPEN_BRACE[tok, "{"]
// Iterator<T> ret = null;
^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"] LTHAN[tok, "<"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, tyVar]) GT[tok, ">"]) IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] NULL[tok,"null"] SEMI[tok, ";"]
// try { ret = this.GetEnumerator().iterator(); } catch (Exception e) { e.printstackTrace(); }}
^(TRY[tok, "try"]
OPEN_BRACE[tok, "{"]
IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
CLOSE_BRACE[tok, "}"]
^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
OPEN_BRACE[tok, "{"]
^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
CLOSE_BRACE[tok, "}"]
)
)
// return ret;
^(RETURN[tok, "return"] IDENTIFIER[tok, "ret"])
CLOSE_BRACE[tok, "}"]
)
->
;
// IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
magicGenericIterator[bool isOn, IToken tok, String tyVar]
@init {
if (isOn) AddToImports("java.util.Iterator");
}
:
magicType[isOn, tok, "Iterator", new string[\] {tyVar}]
n=magicToken[isOn, tok, NULL, "null"]
magicAssignment[isOn, tok, $magicType.tree, "ret", $n.tree]
thisT=magicToken[isOn, tok, THIS, "this"]
thisEnum=magicDot[isOn, tok, $thisT.tree, "GetEnumerator"]
mkIter=magicDot[isOn, tok, $thisEnum.tree, "iterator"]
tryBody=magicApply[isOn, tok, $mkIter.tree, null]
magicTryCatch[isOn, tok, $tryBody.tree]
magicMethod[isOn, tok, "iterator", $magicType.tree, null, $magicTryCatch.tree]
-> {isOn}? magicMethod
->
;
magicIterator[bool isOn, IToken tok]
@init {
if (isOn) AddToImports("java.util.Iterator");
}
:
magicType[isOn, tok, "Iterator", null]
n=magicToken[isOn, tok, NULL, "null"]
magicAssignment[isOn, tok, $magicType.tree, "ret", $n.tree]
// magicSmotherExceptions[isOn, tok, ]
magicMethod[isOn, tok, "iterator", $magicType.tree, null, $magicAssignment.tree]
-> {isOn}? magicMethod
// ^(METHOD[tok, "METHOD"]
// PUBLIC[tok, "public"]
// ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"])
// IDENTIFIER[tok, "iterator"]
// OPEN_BRACE[tok, "{"]
// // Iterator ret = null;
// ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "Iterator"]) IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] NULL[tok,"null"] SEMI[tok, ";"]
// // try { ret = this.GetEnumerator().iterator(); } catch (Exception e) { e.printstackTrace(); }}
// ^(TRY[tok, "try"]
// OPEN_BRACE[tok, "{"]
// IDENTIFIER[tok, "ret"] ASSIGN[tok,"="] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] THIS[tok, "this"] IDENTIFIER[tok, "GetEnumerator"])) IDENTIFIER[tok,"iterator"])) SEMI[tok,";"]
// CLOSE_BRACE[tok, "}"]
// ^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
// OPEN_BRACE[tok, "{"]
// ^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
// CLOSE_BRACE[tok, "}"]
// )
// )
// // return ret;
// ^(RETURN[tok, "return"] IDENTIFIER[tok, "ret"])
// CLOSE_BRACE[tok, "}"]
// )
//
->
;
magicToken[bool isOn, IToken tok, int tokenType, string text]
@init {
CommonTree ret = null;
if (isOn)
ret = (CommonTree)adaptor.Create(tokenType, tok, text);
}:
-> {isOn}? { ret }
->
;
// public <retType> <name> <args> { <body> }
magicMethod[bool isOn, IToken tok, string name, CommonTree retType, CommonTree args, CommonTree body]:
-> {isOn}?
^(METHOD[tok, "METHOD"]
PUBLIC[tok, "public"]
{ dupTree(retType) }
IDENTIFIER[tok, name]
{ dupTree(args) }
OPEN_BRACE[tok, "{"]
{ dupTree(body) }
CLOSE_BRACE[tok, "}"]
)
->
;
magicType[bool isOn, IToken tok, string name, string[\] args]
@init {
CommonTree argsTree = null;
if (args != null && args.Length > 0) {
CommonTree root = (CommonTree)adaptor.Nil;
adaptor.AddChild(root, (CommonTree)adaptor.Create(LTHAN, tok, "<"));
foreach (string a in args) {
CommonTree root0 = (CommonTree)adaptor.Nil;
root0 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(TYPE, tok, "TYPE"), root0);
adaptor.AddChild(root0, (CommonTree)adaptor.Create(IDENTIFIER, tok, a));
adaptor.AddChild(root, root0);
}
adaptor.AddChild(root, (CommonTree)adaptor.Create(GT, tok, ">"));
argsTree = (CommonTree)adaptor.RulePostProcessing(root);
}
}
:
-> {isOn}?
^(TYPE[tok, "TYPE"]
IDENTIFIER[tok, name]
{ dupTree(argsTree) }
)
->
;
// <type>? <name> = exp ;
magicAssignment[bool isOn, IToken tok, CommonTree type, string name, CommonTree exp]:
-> {isOn}?
{ dupTree(type) }
IDENTIFIER[tok, name]
ASSIGN[tok, "="]
{ dupTree(exp) }
SEMI[tok, ";"]
->
;
magicTryCatch[bool isOn, IToken tok, CommonTree body]:
-> {isOn}?
^(TRY[tok, "try"]
OPEN_BRACE[tok, "{"]
{ dupTree(body) }
CLOSE_BRACE[tok, "}"]
^(CATCH[tok, "catch"] ^(TYPE[tok,"TYPE"] IDENTIFIER[tok, "Exception"]) IDENTIFIER[tok, "e"]
OPEN_BRACE[tok, "{"]
^(APPLY[tok, "APPLY"] ^(DOT[tok, "."] IDENTIFIER[tok, "e"] IDENTIFIER[tok,"printStackTrace"])) SEMI[tok,";"]
CLOSE_BRACE[tok, "}"]
)
)
->
;
magicDot[bool isOn, IToken tok, CommonTree lhs, string rhs]:
-> {isOn}? ^(DOT[tok, "."] { dupTree(lhs) } IDENTIFIER[tok, rhs])
->
;
magicApply[bool isOn, IToken tok, CommonTree methodExp, CommonTree args]:
-> {isOn}? ^(APPLY[tok, "APPLY"] { dupTree(methodExp) } { dupTree(args) })
->
;