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

resolve indexers

This commit is contained in:
Kevin Glynn 2011-01-25 18:26:47 +01:00
parent 27e774356d
commit 43323f46ea
3 changed files with 283 additions and 22 deletions

View File

@ -822,10 +822,9 @@ namespace RusticiSoftware.Translator.CLR
// guessing that normally imports will be the same for both)
public class PropRepTemplate : FieldRepTemplate, IEquatable<PropRepTemplate>
{
private string _javaGet = null;
protected string _javaGet = null;
[XmlElementAttribute("Get")]
public string JavaGet {
public virtual string JavaGet {
get {
if (!CanRead) return null;
if (_javaGet == null) {
@ -842,7 +841,7 @@ namespace RusticiSoftware.Translator.CLR
}
set { _javaGet = value; }
}
public override string Java
{
get
@ -851,9 +850,9 @@ namespace RusticiSoftware.Translator.CLR
}
}
private string _javaSet = null;
protected string _javaSet = null;
[XmlElementAttribute("Set")]
public string JavaSet {
public virtual string JavaSet {
get {
if (_javaSet == null) {
return (CanWrite ? "${this}.set" + Name + "(${value})" : null);
@ -939,6 +938,152 @@ namespace RusticiSoftware.Translator.CLR
#endregion
}
// An indexer is like a unnamed property that has params
public class IndexerRepTemplate : PropRepTemplate, IEquatable<IndexerRepTemplate>
{
private List<ParamRepTemplate> _params = null;
[XmlArrayItem("Param")]
public List<ParamRepTemplate> Params {
get {
if (_params == null)
_params = new List<ParamRepTemplate> ();
return _params;
}
}
private List<ParamRepTemplate> _setParams = null;
private List<ParamRepTemplate> SetParams {
get {
if (_setParams == null)
{
_setParams = new List<ParamRepTemplate> ();
foreach (ParamRepTemplate p in Params)
{
_setParams.Add(p);
}
_setParams.Add(new ParamRepTemplate(Type,"value"));
}
return _setParams;
}
}
[XmlElementAttribute("Get")]
public override string JavaGet {
get {
if (!CanRead) return null;
if (_javaGet == null) {
if (_java == null) {
return (CanRead ? "${this}.get___idx" + mkJavaParams(Params) : null);
}
else {
return _java;
}
}
else {
return _javaGet;
}
}
set { _javaGet = value; }
}
[XmlElementAttribute("Set")]
public override string JavaSet {
get {
if (_javaSet == null) {
return (CanWrite ? "${this}.set___idx" + mkJavaParams(SetParams): null);
}
else {
return _javaSet;
}
}
set { _javaSet = value; }
}
public IndexerRepTemplate () : base()
{
}
public IndexerRepTemplate (string fType, List<ParamRepTemplate> pars) : base(fType, "this")
{
_params = pars;
}
public IndexerRepTemplate (string fType, List<ParamRepTemplate> pars, string[] imps, string javaGet, string javaSet) : base(fType, "this",imps,javaGet,javaSet)
{
_params = pars;
}
public override void Apply(Dictionary<string,TypeRepTemplate> args)
{
if (Params != null)
{
foreach(ParamRepTemplate p in Params)
{
p.Apply(args);
}
}
if (_setParams != null)
{
foreach(ParamRepTemplate p in _setParams)
{
p.Apply(args);
}
}
base.Apply(args);
}
#region Equality
public bool Equals (IndexerRepTemplate other)
{
if (other == null)
return false;
if (Params != other.Params) {
if (Params == null || other.Params == null || Params.Count != other.Params.Count)
return false;
for (int i = 0; i < Params.Count; i++) {
if (Params[i] != other.Params[i])
return false;
}
}
return base.Equals(other);
}
public override bool Equals (object obj)
{
IndexerRepTemplate temp = obj as IndexerRepTemplate;
if (!Object.ReferenceEquals (temp, null))
return this.Equals (temp);
return false;
}
public static bool operator == (IndexerRepTemplate a1, IndexerRepTemplate a2)
{
return Object.Equals (a1, a2);
}
public static bool operator != (IndexerRepTemplate a1, IndexerRepTemplate a2)
{
return !(a1 == a2);
}
public override int GetHashCode ()
{
int hashCode = 0;
foreach (ParamRepTemplate o in Params) {
hashCode = hashCode ^ o.GetHashCode() ;
}
return base.GetHashCode () ^ hashCode;
}
#endregion
}
// A member of an enum, may also have a numeric value
public class EnumMemberRepTemplate : TranslationBase, IEquatable<EnumMemberRepTemplate>
{
@ -1169,6 +1314,25 @@ namespace RusticiSoftware.Translator.CLR
return null;
}
// Resolve a indexer call (arg types)
public virtual ResolveResult ResolveIndexer(List<TypeRepTemplate> args, DirectoryHT<TypeRepTemplate> AppEnv)
{
if (Inherits != null)
{
foreach (String b in Inherits)
{
TypeRepTemplate baseType = BuildType(b, AppEnv);
if (baseType != null)
{
ResolveResult ret = baseType.ResolveIndexer(args,AppEnv);
if (ret != null)
return ret;
}
}
}
return null;
}
// Resolve a cast from this type to castTo
public virtual ResolveResult ResolveCastTo(TypeRepTemplate castTo, DirectoryHT<TypeRepTemplate> AppEnv)
{
@ -1734,12 +1898,13 @@ namespace RusticiSoftware.Translator.CLR
}
}
private List<MethodRepTemplate> _indexers = null;
[XmlIgnore]
private List<IndexerRepTemplate> _indexers = null;
[XmlArrayItem("Indexer")]
public List<MethodRepTemplate> Indexers {
public List<IndexerRepTemplate> Indexers {
get {
if (_indexers == null)
_indexers = new List<MethodRepTemplate> ();
_indexers = new List<IndexerRepTemplate> ();
return _indexers;
}
}
@ -1753,7 +1918,7 @@ namespace RusticiSoftware.Translator.CLR
{
}
protected InterfaceRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> es, List<MethodRepTemplate> ixs, string[] imps, string javaTemplate)
protected InterfaceRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> es, List<IndexerRepTemplate> ixs, string[] imps, string javaTemplate)
: base(tName, tParams, usePath, aliases, imps, javaTemplate)
{
Inherits = inherits;
@ -1789,7 +1954,7 @@ namespace RusticiSoftware.Translator.CLR
}
if (Indexers != null)
{
foreach(MethodRepTemplate i in Indexers)
foreach(IndexerRepTemplate i in Indexers)
{
i.Apply(args);
}
@ -1878,6 +2043,50 @@ namespace RusticiSoftware.Translator.CLR
return base.Resolve(name, args, AppEnv);
}
public override ResolveResult ResolveIndexer(List<TypeRepTemplate> args, DirectoryHT<TypeRepTemplate> AppEnv)
{
if (Indexers != null)
{
foreach (IndexerRepTemplate i in Indexers)
{
bool matchingArgs = true;
// If either params are null then make sure both represent zero length args
if (i.Params == null || args == null)
{
// Are they both zero length?
matchingArgs = (i.Params == null || i.Params.Count == 0) && (args == null || args.Count == 0);
}
else
{
// Are num args the same?
if (i.Params.Count != args.Count)
{
matchingArgs = false;
}
else
{
// check that for each argument in the caller its type 'IsA' the type of the formal argument
for (int idx = 0; idx < i.Params.Count; idx++) {
if (args[idx] == null || !args[idx].IsA(BuildType(i.Params[idx].Type, AppEnv, new UnknownRepTemplate(i.Params[idx].Type)),AppEnv))
{
matchingArgs = false;
break;
}
}
}
if (matchingArgs)
{
ResolveResult res = new ResolveResult();
res.Result = i;
res.ResultType = BuildType(i.Type, AppEnv);
return res;
}
}
}
}
return base.ResolveIndexer(args, AppEnv);
}
#region Equality
public bool Equals (InterfaceRepTemplate other)
@ -1977,7 +2186,7 @@ namespace RusticiSoftware.Translator.CLR
}
}
if (Indexers != null) {
foreach (MethodRepTemplate e in Indexers) {
foreach (IndexerRepTemplate e in Indexers) {
hashCode ^= e.GetHashCode();
}
}
@ -2039,7 +2248,7 @@ namespace RusticiSoftware.Translator.CLR
{
}
public ClassRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<MethodRepTemplate> ixs, List<CastRepTemplate> cts,
public ClassRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<IndexerRepTemplate> ixs, List<CastRepTemplate> cts,
string[] imports, string javaTemplate)
: base(tName, tParams, usePath, aliases, inherits, ms, ps, es, ixs, imports, javaTemplate)
{
@ -2048,7 +2257,7 @@ namespace RusticiSoftware.Translator.CLR
_casts = cts;
}
public ClassRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<MethodRepTemplate> ixs, List<CastRepTemplate> cts)
public ClassRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<IndexerRepTemplate> ixs, List<CastRepTemplate> cts)
: base(tName, tParams, usePath, aliases, inherits, ms, ps, es, ixs, null, null)
{
_constructors = cs;
@ -2111,7 +2320,7 @@ namespace RusticiSoftware.Translator.CLR
return base.Resolve(name, AppEnv);
}
public virtual ResolveResult Resolve(List<TypeRepTemplate> args, DirectoryHT<TypeRepTemplate> AppEnv)
public ResolveResult Resolve(List<TypeRepTemplate> args, DirectoryHT<TypeRepTemplate> AppEnv)
{
if (Constructors != null)
@ -2259,13 +2468,13 @@ namespace RusticiSoftware.Translator.CLR
{
}
public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<MethodRepTemplate> ixs, List<CastRepTemplate> cts,
public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<IndexerRepTemplate> ixs, List<CastRepTemplate> cts,
string[] imports, string javaTemplate) : base(tName, tParams, usePath, aliases, inherits, cs, ms, ps, fs, es, ixs, cts,
imports, javaTemplate)
{
}
public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<MethodRepTemplate> ixs, List<CastRepTemplate> cts)
public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List<ConstructorRepTemplate> cs, List<MethodRepTemplate> ms, List<PropRepTemplate> ps, List<FieldRepTemplate> fs, List<FieldRepTemplate> es, List<IndexerRepTemplate> ixs, List<CastRepTemplate> cts)
: base(tName, tParams, usePath, aliases, inherits, cs, ms, ps, fs, es, ixs, cts, null, null)
{
}

View File

@ -322,7 +322,29 @@ scope {
if (ret != null)
$primary_expression.tree = ret;
}:
^(INDEX expression expression_list?)
^(INDEX ie=expression expression_list?)
{
if ($ie.dotNetType != null) {
ResolveResult indexerResult = $ie.dotNetType.ResolveIndexer($expression_list.expTypes ?? new List<TypeRepTemplate>(), AppEnv);
if (indexerResult != null) {
IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
if (!String.IsNullOrEmpty(indexerRep.JavaGet)) {
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
// if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
}
}
ret = mkJavaWrapper(indexerResult.Result.Java, myMap, $ie.tree.Token);
Imports.Add(indexerResult.Result.Imports);
$dotNetType = indexerResult.ResultType;
}
}
}
}
| (^(APPLY (^('.' expression identifier)|identifier) argument_list?)) =>
^(APPLY (^('.' e2=expression {expType = $e2.dotNetType; implicitThis = false;} i2=identifier)|i2=identifier) argument_list?)
{
@ -745,8 +767,14 @@ expression returns [TypeRepTemplate dotNetType, String rmId, TypeRepTemplate typ
(unary_expression assignment_operator) => assignment { $dotNetType = VoidType; }
| non_assignment_expression { $dotNetType = $non_assignment_expression.dotNetType; $rmId = $non_assignment_expression.rmId; $typeofType = $non_assignment_expression.typeofType; }
;
expression_list:
expression (',' expression)* ;
expression_list returns [List<TypeRepTemplate> expTypes, List<CommonTree> expTrees, List<TypeRepTemplate> expTreeTypeofTypes]
@init {
$expTypes = new List<TypeRepTemplate>();
$expTrees = new List<CommonTree>();
$expTreeTypeofTypes = new List<TypeRepTemplate>();
}:
e1=expression { $expTypes.Add($e1.dotNetType); $expTrees.Add(dupTree($e1.tree)); $expTreeTypeofTypes.Add($e1.typeofType); }
(',' en=expression { $expTypes.Add($en.dotNetType); $expTrees.Add(dupTree($en.tree)); $expTreeTypeofTypes.Add($en.typeofType); })* ;
assignment
@init {
@ -774,6 +802,30 @@ assignment
}
}
}
| (^(INDEX expression expression_list?) '=') =>
^(INDEX ie=expression expression_list?) ia='=' irhs=expression
{
if ($ie.dotNetType != null) {
ResolveResult indexerResult = $ie.dotNetType.ResolveIndexer($expression_list.expTypes ?? new List<TypeRepTemplate>(), AppEnv);
if (indexerResult != null) {
IndexerRepTemplate indexerRep = indexerResult.Result as IndexerRepTemplate;
if (!String.IsNullOrEmpty(indexerRep.JavaSet)) {
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
myMap["this"] = wrapExpression($ie.tree, $ie.tree.Token);
myMap["value"] = wrapExpression($irhs.tree, $irhs.tree.Token);
for (int idx = 0; idx < indexerRep.Params.Count; idx++) {
myMap[indexerRep.Params[idx].Name] = wrapArgument($expression_list.expTrees[idx], $ie.tree.Token);
if (indexerRep.Params[idx].Name.StartsWith("TYPEOF") && $expression_list.expTreeTypeofTypes[idx] != null) {
// if this argument is a typeof expression then add a TYPEOF_TYPEOF-> typeof's type mapping
myMap[indexerRep.Params[idx].Name + "_TYPE"] = wrapTypeOfType($expression_list.expTreeTypeofTypes[idx], $ie.tree.Token);
}
}
ret = mkJavaWrapper(indexerRep.JavaSet, myMap, $ie.tree.Token);
Imports.Add(indexerRep.Imports);
}
}
}
}
| unary_expression assignment_operator expression ;

View File

@ -1013,7 +1013,7 @@ interface_event_declaration:
interface_indexer_declaration [string returnType]:
// attributes? 'new'? type
'this' '[' fpl=formal_parameter_list ']' '{' interface_accessor_declarations '}'
{ ((InterfaceRepTemplate)$NSContext::currentTypeRep).Indexers.Add(new MethodRepTemplate($returnType, "this", null, $fpl.paramlist)); }
{ ((InterfaceRepTemplate)$NSContext::currentTypeRep).Indexers.Add(new IndexerRepTemplate($returnType, $fpl.paramlist)); }
{ Debug("Processing interface indexer declaration"); }
;
interface_accessor_declarations returns [bool hasGetter, bool hasSetter]
@ -1104,7 +1104,7 @@ indexer_declaration [string returnType, string prefix]:
indexer_declarator [string returnType, string prefix]:
//(type_name '.')?
'this' '[' fpl=formal_parameter_list ']'
{ ((InterfaceRepTemplate)$NSContext::currentTypeRep).Indexers.Add(new MethodRepTemplate($returnType, $prefix+"this", null, $fpl.paramlist)); }
{ ((InterfaceRepTemplate)$NSContext::currentTypeRep).Indexers.Add(new IndexerRepTemplate($returnType, $fpl.paramlist)); }
{ Debug("Processing indexer declaration"); }
;