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

TemplateExtractor should merge partial definitions

This commit is contained in:
Kevin Glynn 2011-05-31 09:17:50 +02:00
parent c785f8985e
commit 9d45e3adef
2 changed files with 157 additions and 48 deletions

View File

@ -2231,10 +2231,14 @@ scope NSContext,SymTab;
$SymTab::symtab["this"] = classTypeRep; $SymTab::symtab["this"] = classTypeRep;
ClassRepTemplate baseType = ObjectType; ClassRepTemplate baseType = ObjectType;
if (classTypeRep.Inherits != null && classTypeRep.Inherits.Length > 0) { if (classTypeRep.Inherits != null && classTypeRep.Inherits.Length > 0) {
// if Inherits[0] is a class then it is parent, else system.object // if Inherits[0] Take first class as super
ClassRepTemplate parent = AppEnv.Search(classTypeRep.Uses, classTypeRep.Inherits[0], ObjectType) as ClassRepTemplate; foreach (String super in classTypeRep.Inherits) {
if (parent != null) ClassRepTemplate parent = AppEnv.Search(classTypeRep.Uses, super, null) as ClassRepTemplate;
baseType = parent; if (parent != null) {
baseType = parent;
break;
}
}
} }
$SymTab::symtab["super"] = baseType; $SymTab::symtab["super"] = baseType;
} }

View File

@ -29,7 +29,6 @@ scope NSContext {
{ {
using System; using System;
using System.Text; using System.Text;
using System.Linq;
using Twiglet.CS2J.Translator.TypeRep; using Twiglet.CS2J.Translator.TypeRep;
} }
@ -78,6 +77,62 @@ scope NSContext {
return rets.ToArray(); return rets.ToArray();
} }
} }
protected T[] MergeArray<T>(T[] arr1, T el) {
if (arr1 == null) {
return new T[] {el};
}
if (Array.IndexOf(arr1, el) < 0) {
List<T> ret = new List<T>(arr1.Length + 1);
ret.AddRange(arr1);
ret.Add(el);
return ret.ToArray();
}
return arr1;
}
protected T[] MergeArray<T>(T[] arr1, T[] arr2) {
if (arr1 == null || arr1.Length == 0) {
return arr2;
}
if (arr2 == null || arr2.Length == 0) {
return arr1;
}
List<T> ret = new List<T>(arr1);
foreach (T v in arr2) {
if (Array.IndexOf(arr1, v) < 0) {
ret.Add(v);
}
}
return ret.ToArray();
}
// Updates l
protected void MergeList<T>(IList<T> l, T el) {
if (l == null) {
throw new ArgumentNullException("l");
}
if (!l.Contains(el)) {
l.Add(el);
}
}
protected void MergeList<T>(IList<T> l1, IList<T> l2) {
if (l1 == null) {
throw new ArgumentNullException("l1");
}
if (l2 != null) {
foreach (T v in l2) {
MergeList(l1,v);
}
}
}
protected string ParentNameSpace { protected string ParentNameSpace {
get { get {
@ -174,12 +229,12 @@ namespace_member_declaration:
namespace_declaration namespace_declaration
| attributes? modifiers? type_declaration ; | attributes? modifiers? type_declaration ;
type_declaration: type_declaration:
('partial') => p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (class_declaration ('partial') => p='partial' (class_declaration[true]
| struct_declaration | struct_declaration[true]
| interface_declaration) | interface_declaration[true])
| class_declaration | class_declaration[false]
| struct_declaration | struct_declaration[false]
| interface_declaration | interface_declaration[false]
| enum_declaration | enum_declaration
| delegate_declaration ; | delegate_declaration ;
// Identifiers // Identifiers
@ -200,11 +255,11 @@ class_member_declaration:
m=modifiers? m=modifiers?
( 'const' ct=type constant_declarators[$ct.thetext] ';' ( 'const' ct=type constant_declarators[$ct.thetext] ';'
| event_declaration // 'event' | event_declaration // 'event'
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (method_declaration["/* partial */"] | p='partial' ({ Warning($p.line, "[UNSUPPORTED] 'partial' method definition"); } method_declaration["/* partial */"]
| interface_declaration | interface_declaration[true]
| class_declaration | class_declaration[true]
| struct_declaration) | struct_declaration[true])
| interface_declaration // 'interface' | interface_declaration[false] // 'interface'
| 'void' method_declaration["System.Void"] | 'void' method_declaration["System.Void"]
| rt=type ( (member_name '(') => method_declaration[$rt.thetext] | rt=type ( (member_name '(') => method_declaration[$rt.thetext]
| (member_name '{') => property_declaration[$rt.thetext] | (member_name '{') => property_declaration[$rt.thetext]
@ -215,8 +270,8 @@ class_member_declaration:
) )
// common_modifiers// (method_modifiers | field_modifiers) // common_modifiers// (method_modifiers | field_modifiers)
| class_declaration // 'class' | class_declaration[false] // 'class'
| struct_declaration // 'struct' | struct_declaration[false] // 'struct'
| enum_declaration // 'enum' | enum_declaration // 'enum'
| delegate_declaration // 'delegate' | delegate_declaration // 'delegate'
| conversion_operator_declaration | conversion_operator_declaration
@ -702,35 +757,52 @@ attribute_argument_expression:
// Class Section // Class Section
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
class_declaration class_declaration[bool isPartial]
scope NSContext; scope NSContext;
@init { @init {
$NSContext::searchpath = new List<string>(); $NSContext::searchpath = new List<string>();
$NSContext::aliases = new List<AliasRepTemplate>(); $NSContext::aliases = new List<AliasRepTemplate>();
ClassRepTemplate klass = new ClassRepTemplate(); ClassRepTemplate klass = null;
} }
: :
'class' type_or_generic c='class' type_or_generic
{ {
DebugDetail("Processing class: " + $type_or_generic.type); DebugDetail("Processing " + ($isPartial ? "partial" : "") + " class: " + $type_or_generic.type);
// For class System.Dictionary<K,V> // For class System.Dictionary<K,V>
// The Type Rep has TypeName "System.Dictionary", TypeArgs "K","V" is stored at System/Dictionary'2.xml // The Type Rep has TypeName "System.Dictionary", TypeArgs "K","V" is stored at System/Dictionary'2.xml
// and will be used as [System.]Dictionary[Type1,Type2] // and will be used as [System.]Dictionary[Type1,Type2]
String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($type_or_generic.type, $type_or_generic.generic_arguments); String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($type_or_generic.type, $type_or_generic.generic_arguments);
TypeRepTemplate tmpTyRep;
bool exists = AppEnv.TryGetValue(genericNameSpace, out tmpTyRep);
if (exists && !$isPartial) {
{ Error($c.line, "Found multiple definitions for " + genericNameSpace); }
}
if (exists) {
klass = tmpTyRep as ClassRepTemplate;
if (klass == null) {
{ Error($c.line, "Found conflicting type definitions for " + genericNameSpace); }
// This klass is not put in AppEnv so its just thrown away in this case
klass = new ClassRepTemplate();
}
}
else {
klass = new ClassRepTemplate();
AppEnv[genericNameSpace] = klass;
}
klass.TypeName = NSPrefix(ParentNameSpace) + $type_or_generic.type; klass.TypeName = NSPrefix(ParentNameSpace) + $type_or_generic.type;
if ($type_or_generic.generic_arguments.Count > 0) { if ($type_or_generic.generic_arguments.Count > 0) {
klass.TypeParams = $type_or_generic.generic_arguments.ToArray(); // If we already have klass.TypeParams then they must match
klass.TypeParams = $type_or_generic.generic_arguments.ToArray();
} }
// Nested types can see things in this space // Nested types can see things in this space
$NSContext::searchpath.Add(genericNameSpace); $NSContext::searchpath.Add(genericNameSpace);
$NSContext::currentNS = genericNameSpace; $NSContext::currentNS = genericNameSpace;
$NSContext::currentTypeRep = klass; $NSContext::currentTypeRep = klass;
AppEnv[genericNameSpace] = klass; klass.Uses = MergeArray(klass.Uses, this.CollectUses);
klass.Uses = this.CollectUses; klass.Aliases = MergeArray(klass.Aliases, this.CollectAliases);
klass.Aliases = this.CollectAliases;
klass.Imports = new string[] {klass.TypeName}; klass.Imports = new string[] {klass.TypeName};
} }
(cb=class_base { klass.Inherits = $cb.typeList.ToArray(); } )? (cb=class_base { klass.Inherits = MergeArray($cb.typeList.ToArray(), klass.Inherits); } )?
type_parameter_constraints_clauses? class_body ';'? ; type_parameter_constraints_clauses? class_body ';'? ;
class_base returns [List<string> typeList] class_base returns [List<string> typeList]
@ -1035,18 +1107,35 @@ parameter_array returns [ParamRepTemplate param]:
'params' t=type i=identifier { $param=new ParamRepTemplate($t.thetext, $i.text, false); } ; 'params' t=type i=identifier { $param=new ParamRepTemplate($t.thetext, $i.text, false); } ;
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
interface_declaration interface_declaration[bool isPartial]
scope NSContext; scope NSContext;
@init { @init {
$NSContext::searchpath = new List<string>(); $NSContext::searchpath = new List<string>();
$NSContext::aliases = new List<AliasRepTemplate>(); $NSContext::aliases = new List<AliasRepTemplate>();
InterfaceRepTemplate iface = new InterfaceRepTemplate(); InterfaceRepTemplate iface = null;
} }
: :
'interface' identifier variant_generic_parameter_list? i='interface' identifier variant_generic_parameter_list?
{ {
DebugDetail("Processing interface: " + $identifier.text); DebugDetail("Processing interface: " + $identifier.text);
String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.text, $variant_generic_parameter_list.tyargs); String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.text, $variant_generic_parameter_list.tyargs);
TypeRepTemplate tmpTyRep;
bool exists = AppEnv.TryGetValue(genericNameSpace, out tmpTyRep);
if (exists && !$isPartial) {
{ Error($i.line, "Found multiple definitions for " + genericNameSpace); }
}
if (exists) {
iface = tmpTyRep as InterfaceRepTemplate;
if (iface == null) {
{ Error($i.line, "Found conflicting type definitions for " + genericNameSpace); }
// This iface is not put in AppEnv so its just thrown away in this case
iface = new InterfaceRepTemplate();
}
}
else {
iface = new InterfaceRepTemplate();
AppEnv[genericNameSpace] = iface;
}
iface.TypeName = NSPrefix(ParentNameSpace) + $identifier.text; iface.TypeName = NSPrefix(ParentNameSpace) + $identifier.text;
if ($variant_generic_parameter_list.tyargs != null && $variant_generic_parameter_list.tyargs.Count > 0) { if ($variant_generic_parameter_list.tyargs != null && $variant_generic_parameter_list.tyargs.Count > 0) {
iface.TypeParams = $variant_generic_parameter_list.tyargs.ToArray(); iface.TypeParams = $variant_generic_parameter_list.tyargs.ToArray();
@ -1055,12 +1144,11 @@ scope NSContext;
$NSContext::searchpath.Add(iface.TypeName); $NSContext::searchpath.Add(iface.TypeName);
$NSContext::currentNS = iface.TypeName; $NSContext::currentNS = iface.TypeName;
$NSContext::currentTypeRep = iface; $NSContext::currentTypeRep = iface;
AppEnv[genericNameSpace] = iface; iface.Uses = MergeArray(iface.Uses, this.CollectUses);
iface.Uses = this.CollectUses; iface.Aliases = MergeArray(iface.Aliases, this.CollectAliases);
iface.Aliases = this.CollectAliases;
iface.Imports = new string[] {iface.TypeName}; iface.Imports = new string[] {iface.TypeName};
} }
(interface_base { iface.Inherits = $interface_base.typeList.ToArray(); } )? (interface_base { iface.Inherits = MergeArray($interface_base.typeList.ToArray(), iface.Inherits); } )?
type_parameter_constraints_clauses? interface_body ';'? ; type_parameter_constraints_clauses? interface_body ';'? ;
interface_modifiers: interface_modifiers:
modifier+ ; modifier+ ;
@ -1123,18 +1211,36 @@ method_modifiers:
modifier+ ; modifier+ ;
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
struct_declaration struct_declaration[bool isPartial]
scope NSContext; scope NSContext;
@init { @init {
$NSContext::searchpath = new List<string>(); $NSContext::searchpath = new List<string>();
$NSContext::aliases = new List<AliasRepTemplate>(); $NSContext::aliases = new List<AliasRepTemplate>();
StructRepTemplate strukt = new StructRepTemplate(); StructRepTemplate strukt = null;
} }
: :
'struct' type_or_generic s='struct' type_or_generic
{ {
DebugDetail("Processing struct: " + $type_or_generic.type); DebugDetail("Processing struct: " + $type_or_generic.type);
String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($type_or_generic.type, $type_or_generic.generic_arguments); String genericNameSpace = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($type_or_generic.type, $type_or_generic.generic_arguments);
TypeRepTemplate tmpTyRep;
bool exists = AppEnv.TryGetValue(genericNameSpace, out tmpTyRep);
if (exists && !$isPartial) {
{ Error($s.line, "Found multiple definitions for " + genericNameSpace); }
}
if (exists) {
strukt = tmpTyRep as StructRepTemplate;
if (strukt == null) {
{ Error($s.line, "Found conflicting type definitions for " + genericNameSpace); }
// This strukt is not put in AppEnv so its just thrown away in this case
strukt = new StructRepTemplate();
}
}
else {
strukt = new StructRepTemplate();
AppEnv[genericNameSpace] = strukt;
}
strukt.TypeName = NSPrefix(ParentNameSpace) + $type_or_generic.type; strukt.TypeName = NSPrefix(ParentNameSpace) + $type_or_generic.type;
if ($type_or_generic.generic_arguments.Count > 0) { if ($type_or_generic.generic_arguments.Count > 0) {
strukt.TypeParams = $type_or_generic.generic_arguments.ToArray(); strukt.TypeParams = $type_or_generic.generic_arguments.ToArray();
@ -1143,11 +1249,10 @@ scope NSContext;
$NSContext::searchpath.Add(strukt.TypeName); $NSContext::searchpath.Add(strukt.TypeName);
$NSContext::currentNS = strukt.TypeName; $NSContext::currentNS = strukt.TypeName;
$NSContext::currentTypeRep = strukt; $NSContext::currentTypeRep = strukt;
AppEnv[genericNameSpace] = strukt; strukt.Uses = MergeArray(strukt.Uses, this.CollectUses);
strukt.Uses = this.CollectUses; strukt.Aliases = MergeArray(strukt.Aliases, this.CollectAliases);
strukt.Aliases = this.CollectAliases;
strukt.Imports = new string[] {strukt.TypeName}; strukt.Imports = new string[] {strukt.TypeName};
} (si=struct_interfaces { strukt.Inherits = $si.typeList.ToArray(); })? } (si=struct_interfaces { strukt.Inherits = MergeArray($si.typeList.ToArray(), strukt.Inherits); })?
type_parameter_constraints_clauses? struct_body ';'? ; type_parameter_constraints_clauses? struct_body ';'? ;
struct_modifiers: struct_modifiers:
struct_modifier+ ; struct_modifier+ ;
@ -1163,13 +1268,13 @@ struct_member_declaration:
attributes? m=modifiers? attributes? m=modifiers?
( 'const' ct=type constant_declarators[$ct.thetext] ';' ( 'const' ct=type constant_declarators[$ct.thetext] ';'
| event_declaration // 'event' | event_declaration // 'event'
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (method_declaration["/* partial */"] | p='partial' ({ Warning($p.line, "[UNSUPPORTED] 'partial' method definition"); } method_declaration["/* partial */"]
| interface_declaration | interface_declaration[true]
| class_declaration | class_declaration[true]
| struct_declaration) | struct_declaration[true])
| interface_declaration // 'interface' | interface_declaration[false] // 'interface'
| class_declaration // 'class' | class_declaration[false] // 'class'
| 'void' method_declaration["System.Void"] | 'void' method_declaration["System.Void"]
| rt=type ( (member_name '(') => method_declaration[$rt.thetext] | rt=type ( (member_name '(') => method_declaration[$rt.thetext]
| (member_name '{') => property_declaration[$rt.thetext] | (member_name '{') => property_declaration[$rt.thetext]
@ -1180,7 +1285,7 @@ struct_member_declaration:
) )
// common_modifiers// (method_modifiers | field_modifiers) // common_modifiers// (method_modifiers | field_modifiers)
| struct_declaration // 'struct' | struct_declaration[false] // 'struct'
| enum_declaration // 'enum' | enum_declaration // 'enum'
| delegate_declaration // 'delegate' | delegate_declaration // 'delegate'
| conversion_operator_declaration | conversion_operator_declaration