mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
add support for iterables
This commit is contained in:
parent
5ece315769
commit
1fe7bceade
@ -7,6 +7,10 @@
|
|||||||
<Inherits>
|
<Inherits>
|
||||||
<Type>System.Object</Type>
|
<Type>System.Object</Type>
|
||||||
</Inherits>
|
</Inherits>
|
||||||
|
<Iterable>
|
||||||
|
<ReturnType>System.Char</ReturnType>
|
||||||
|
<Java>${expr}.toCharArray()</Java>
|
||||||
|
</Iterable>
|
||||||
<Methods>
|
<Methods>
|
||||||
<Method>
|
<Method>
|
||||||
<Imports>
|
<Imports>
|
||||||
|
@ -373,6 +373,77 @@ namespace RusticiSoftware.Translator.CLR
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class IterableRepTemplate : TranslationBase, IEquatable<IterableRepTemplate>
|
||||||
|
{
|
||||||
|
|
||||||
|
public String ReturnType {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string mkJava() {
|
||||||
|
return "${expr}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public IterableRepTemplate () : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public IterableRepTemplate (String ty) : base()
|
||||||
|
{
|
||||||
|
ReturnType = ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IterableRepTemplate (String ty, string[] imps, string javaRep) : base(imps, javaRep)
|
||||||
|
{
|
||||||
|
ReturnType = ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Apply(Dictionary<string,TypeRepTemplate> args)
|
||||||
|
{
|
||||||
|
if (ReturnType != null)
|
||||||
|
{
|
||||||
|
TemplateUtilities.SubstituteInType(ReturnType, args);
|
||||||
|
}
|
||||||
|
base.Apply(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Equality
|
||||||
|
|
||||||
|
public bool Equals (IterableRepTemplate other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ReturnType == other.ReturnType && base.Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
IterableRepTemplate temp = obj as IterableRepTemplate;
|
||||||
|
|
||||||
|
if (!Object.ReferenceEquals (temp, null))
|
||||||
|
return this.Equals (temp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator == (IterableRepTemplate a1, IterableRepTemplate a2)
|
||||||
|
{
|
||||||
|
return Object.Equals (a1, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator != (IterableRepTemplate a1, IterableRepTemplate a2)
|
||||||
|
{
|
||||||
|
return !(a1 == a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return base.GetHashCode () ^ ReturnType.GetHashCode();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
public class ConstructorRepTemplate : TranslationBase, IEquatable<ConstructorRepTemplate>
|
public class ConstructorRepTemplate : TranslationBase, IEquatable<ConstructorRepTemplate>
|
||||||
{
|
{
|
||||||
@ -1412,6 +1483,24 @@ namespace RusticiSoftware.Translator.CLR
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual ResolveResult ResolveIterable(DirectoryHT<TypeRepTemplate> AppEnv)
|
||||||
|
{
|
||||||
|
if (Inherits != null)
|
||||||
|
{
|
||||||
|
foreach (String b in Inherits)
|
||||||
|
{
|
||||||
|
TypeRepTemplate baseType = BuildType(b, AppEnv);
|
||||||
|
if (baseType != null)
|
||||||
|
{
|
||||||
|
ResolveResult ret = baseType.ResolveIterable(AppEnv);
|
||||||
|
if (ret != null)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if other is a subclass, or implements our interface
|
// Returns true if other is a subclass, or implements our interface
|
||||||
public virtual bool IsA (TypeRepTemplate other, DirectoryHT<TypeRepTemplate> AppEnv) {
|
public virtual bool IsA (TypeRepTemplate other, DirectoryHT<TypeRepTemplate> AppEnv) {
|
||||||
if (other.TypeName == this.TypeName)
|
if (other.TypeName == this.TypeName)
|
||||||
@ -1898,7 +1987,6 @@ namespace RusticiSoftware.Translator.CLR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
private List<IndexerRepTemplate> _indexers = null;
|
private List<IndexerRepTemplate> _indexers = null;
|
||||||
[XmlArrayItem("Indexer")]
|
[XmlArrayItem("Indexer")]
|
||||||
public List<IndexerRepTemplate> Indexers {
|
public List<IndexerRepTemplate> Indexers {
|
||||||
@ -1909,6 +1997,16 @@ namespace RusticiSoftware.Translator.CLR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IterableRepTemplate _iterable = null;
|
||||||
|
public IterableRepTemplate Iterable {
|
||||||
|
get {
|
||||||
|
return _iterable;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_iterable = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public InterfaceRepTemplate () : base()
|
public InterfaceRepTemplate () : base()
|
||||||
{
|
{
|
||||||
Inherits = null;
|
Inherits = null;
|
||||||
@ -2088,6 +2186,19 @@ namespace RusticiSoftware.Translator.CLR
|
|||||||
return base.ResolveIndexer(args, AppEnv);
|
return base.ResolveIndexer(args, AppEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ResolveResult ResolveIterable(DirectoryHT<TypeRepTemplate> AppEnv)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Iterable != null)
|
||||||
|
{
|
||||||
|
ResolveResult res = new ResolveResult();
|
||||||
|
res.Result = Iterable;
|
||||||
|
res.ResultType = BuildType(Iterable.ReturnType, AppEnv);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return base.ResolveIterable(AppEnv);
|
||||||
|
}
|
||||||
|
|
||||||
#region Equality
|
#region Equality
|
||||||
public bool Equals (InterfaceRepTemplate other)
|
public bool Equals (InterfaceRepTemplate other)
|
||||||
{
|
{
|
||||||
|
@ -218,15 +218,15 @@ options {
|
|||||||
public string cleanTemplate(string template) {
|
public string cleanTemplate(string template) {
|
||||||
// Are there any markers in the template? Mostly, the answer will be no and we can return tout-de-suite
|
// Are there any markers in the template? Mostly, the answer will be no and we can return tout-de-suite
|
||||||
String ret = template;
|
String ret = template;
|
||||||
if (Regex.IsMatch(ret, "\\$\\{.*\\}")) {
|
if (Regex.IsMatch(ret, "\\$\\{\\w+\\}")) {
|
||||||
// ${this}.fred -> fred
|
// ${this}.fred -> fred
|
||||||
ret = Regex.Replace(ret, "\\$\\{.*\\}\\.", String.Empty);
|
ret = Regex.Replace(ret, "\\$\\{\\w+?\\}\\.", String.Empty);
|
||||||
// (a,${var},b) -> (a,b)
|
// (a,${var},b) -> (a,b)
|
||||||
ret = Regex.Replace(ret, "\\$\\{.*\\},", String.Empty);
|
ret = Regex.Replace(ret, "\\$\\{\\w+?\\},", String.Empty);
|
||||||
// (a,${var}) -> (a)
|
// (a,${var}) -> (a)
|
||||||
ret = Regex.Replace(ret, ",\\$\\{.*\\}", String.Empty);
|
ret = Regex.Replace(ret, ",\\$\\{\\w+?\\}", String.Empty);
|
||||||
// (${var}) -> ()
|
// (${var}) -> ()
|
||||||
ret = Regex.Replace(ret, "\\$\\{.*\\}", String.Empty);
|
ret = Regex.Replace(ret, "\\$\\{\\w+?\\}", String.Empty);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -208,8 +208,9 @@ scope SymTab {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// counter to ensure that the catch vars we introduce are unique
|
// counter to ensure that the vars we introduce are unique
|
||||||
protected int dummyScrutVarCtr = 0;
|
protected int dummyScrutVarCtr = 0;
|
||||||
|
protected int dummyForeachVarCtr = 0;
|
||||||
|
|
||||||
protected CommonTree convertSectionsToITE(List sections) {
|
protected CommonTree convertSectionsToITE(List sections) {
|
||||||
CommonTree ret = null;
|
CommonTree ret = null;
|
||||||
@ -256,6 +257,33 @@ scope SymTab {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// embeddedStatement is either ";", "{ .... }", or a single statement
|
||||||
|
protected CommonTree prefixCast(CommonTree ty, CommonTree id, CommonTree foreachVar, CommonTree embeddedStatement, IToken tok) {
|
||||||
|
CommonTree root = embeddedStatement;
|
||||||
|
if (!embeddedStatement.IsNil && adaptor.GetType(embeddedStatement) == SEMI) {
|
||||||
|
// Do nothing, id is unused
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Make cast statement
|
||||||
|
CommonTree kast = (CommonTree)adaptor.Nil;
|
||||||
|
kast = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(CAST_EXPR, tok, "CAST"), kast);
|
||||||
|
adaptor.AddChild(kast, (CommonTree)adaptor.DupTree(ty));
|
||||||
|
adaptor.AddChild(kast, (CommonTree)adaptor.DupTree(foreachVar));
|
||||||
|
CommonTree vardec = (CommonTree)adaptor.Nil;
|
||||||
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(ty));
|
||||||
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(id));
|
||||||
|
adaptor.AddChild(vardec, (CommonTree)adaptor.Create(ASSIGN, tok, "="));
|
||||||
|
adaptor.AddChild(vardec, (CommonTree)adaptor.DupTree(kast));
|
||||||
|
root = (CommonTree)adaptor.Nil;
|
||||||
|
// Make a { <cast> statement }
|
||||||
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
||||||
|
adaptor.AddChild(root, vardec);
|
||||||
|
// todo: strip "{ }"
|
||||||
|
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(embeddedStatement));
|
||||||
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(OPEN_BRACE, tok, "{"));
|
||||||
|
}
|
||||||
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compilation_unit
|
compilation_unit
|
||||||
@ -1459,11 +1487,54 @@ iteration_statement
|
|||||||
scope SymTab;
|
scope SymTab;
|
||||||
@init {
|
@init {
|
||||||
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
$SymTab::symtab = new Dictionary<string,TypeRepTemplate>();
|
||||||
|
CommonTree ret = null;
|
||||||
|
CommonTree newType = null;
|
||||||
|
CommonTree newIdentifier = null;
|
||||||
|
CommonTree newExpression = null;
|
||||||
|
CommonTree newEmbeddedStatement = null;
|
||||||
|
}
|
||||||
|
@after {
|
||||||
|
if (ret != null)
|
||||||
|
$iteration_statement.tree = ret;
|
||||||
}:
|
}:
|
||||||
^('while' boolean_expression SEP embedded_statement)
|
^('while' boolean_expression SEP embedded_statement)
|
||||||
| do_statement
|
| do_statement
|
||||||
| ^('for' for_initializer? SEP for_condition? SEP for_iterator? SEP embedded_statement)
|
| ^('for' for_initializer? SEP for_condition? SEP for_iterator? SEP embedded_statement)
|
||||||
| ^('foreach' local_variable_type identifier expression SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement);
|
| ^(f='foreach' local_variable_type identifier expression s=SEP { $SymTab::symtab[$identifier.thetext] = $local_variable_type.dotNetType; } embedded_statement)
|
||||||
|
magicObjectType[$f.token] magicForeachVar[$f.token]
|
||||||
|
{
|
||||||
|
newType = $local_variable_type.tree;
|
||||||
|
newIdentifier = $identifier.tree;
|
||||||
|
newExpression = $expression.tree;
|
||||||
|
newEmbeddedStatement = $embedded_statement.tree;
|
||||||
|
TypeRepTemplate exprType = $expression.dotNetType;
|
||||||
|
TypeRepTemplate elType = null;
|
||||||
|
// translate expression, if available
|
||||||
|
if (exprType != null) {
|
||||||
|
ResolveResult iterable = exprType.ResolveIterable(AppEnv);
|
||||||
|
if (iterable != null) {
|
||||||
|
Dictionary<string,CommonTree> myMap = new Dictionary<string,CommonTree>();
|
||||||
|
myMap["expr"] = wrapExpression($expression.tree, $expression.tree.Token);
|
||||||
|
newExpression = mkJavaWrapper(iterable.Result.Java, myMap, $expression.tree.Token);
|
||||||
|
Imports.Add(iterable.Result.Imports);
|
||||||
|
elType = iterable.ResultType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool needCast = true;
|
||||||
|
if (elType != null && $local_variable_type.dotNetType != null) {
|
||||||
|
if (elType.IsA($local_variable_type.dotNetType, AppEnv)) {
|
||||||
|
needCast = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Construct new foreach using newExpression and needCast
|
||||||
|
if (needCast) {
|
||||||
|
newType = $magicObjectType.tree;
|
||||||
|
newIdentifier = $magicForeachVar.tree;
|
||||||
|
newEmbeddedStatement = prefixCast($local_variable_type.tree, $identifier.tree, newIdentifier, $embedded_statement.tree, $embedded_statement.tree.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-> ^($f { newType } { newIdentifier } { newExpression } $s { newEmbeddedStatement })
|
||||||
|
;
|
||||||
do_statement:
|
do_statement:
|
||||||
'do' embedded_statement 'while' '(' boolean_expression ')' ';' ;
|
'do' embedded_statement 'while' '(' boolean_expression ')' ';' ;
|
||||||
for_initializer:
|
for_initializer:
|
||||||
@ -1577,6 +1648,15 @@ magicScrutineeVar [IToken tok] returns [String thetext]
|
|||||||
}:
|
}:
|
||||||
-> IDENTIFIER[tok,$thetext];
|
-> IDENTIFIER[tok,$thetext];
|
||||||
|
|
||||||
|
magicForeachVar [IToken tok] returns [String thetext]
|
||||||
|
@init {
|
||||||
|
$thetext = "__dummyForeachVar" + dummyForeachVarCtr++;
|
||||||
|
}:
|
||||||
|
-> IDENTIFIER[tok,$thetext];
|
||||||
|
|
||||||
|
magicObjectType [IToken tok]:
|
||||||
|
-> ^(TYPE[tok, "TYPE"] OBJECT[tok, "System.Object"]);
|
||||||
|
|
||||||
magicCastOperator[CommonTree mods, String methodName, CommonTree header, CommonTree body]
|
magicCastOperator[CommonTree mods, String methodName, CommonTree header, CommonTree body]
|
||||||
@init {
|
@init {
|
||||||
IToken tok = ((CommonTree)$header.Children[0]).Token;
|
IToken tok = ((CommonTree)$header.Children[0]).Token;
|
||||||
|
@ -61,6 +61,7 @@ tokens {
|
|||||||
THROW = 'throw';
|
THROW = 'throw';
|
||||||
ELSE = 'else';
|
ELSE = 'else';
|
||||||
BREAK = 'break';
|
BREAK = 'break';
|
||||||
|
OBJECT = 'object';
|
||||||
|
|
||||||
OPEN_BRACKET='[';
|
OPEN_BRACKET='[';
|
||||||
CLOSE_BRACKET=']';
|
CLOSE_BRACKET=']';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user