Artifact Content
Not logged in

Artifact cd634c9bb4b6ba1401e35e9d05a3458f079e18e4


     1  /**
     2   * Authors: k.inaba
     3   * License: NYSL 0.9982 http://www.kmonos.net/nysl/
     4   *
     5   * Convert values between Polemy and D
     6   */
     7  module polemy.valueconv;
     8  import polemy._common;
     9  import polemy.failure;
    10  import polemy.ast;
    11  import polemy.layer;
    12  import polemy.value;
    13  import std.string;
    14  
    15  LexPosition extractPos( Table t )
    16  {
    17  	if(auto tt = t.access!Table(ValueLayer, "pos"))
    18  	{
    19  		auto fn = tt.access!StrValue(ValueLayer, "filename");
    20  		auto ln = tt.access!IntValue(ValueLayer, "lineno");
    21  		auto cl = tt.access!IntValue(ValueLayer, "column");
    22  		if(fn !is null && ln !is null && cl !is null)
    23  			return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt);
    24  	}
    25  	return LexPosition.dummy;
    26  }
    27  
    28  /// Experimental!! Convert Polemy value to D Value
    29  
    30  T polemy2d(T)(Value _v, LexPosition callpos=null)
    31  {
    32  	static if(is(T==BigInt))
    33  	{
    34  		if(auto v = cast(IntValue)_v)
    35  			return v.data;
    36  	}
    37  	else
    38  	static if(isIntegral!(T))
    39  	{
    40  		if(auto v = cast(IntValue)_v)
    41  			return cast(T) v.data.toLong();
    42  	}
    43  	else
    44  	static if(is(T==string))
    45  	{
    46  		if(auto v = cast(StrValue)_v)
    47  			return v.data;
    48  	}
    49  	else
    50  	static if(is(T S : S[]))
    51  	{
    52  		if(auto t = cast(Table)_v)
    53  		{
    54  			S[] result;
    55  			foreach(e; t.toList())
    56  				result ~= polemy2d!(S)(e, callpos);
    57  			return result;
    58  		}
    59  	}
    60  	else
    61  	static if(is(T == AST))
    62  	{
    63  		if(auto t = cast(Table)_v)
    64  		{
    65  			LexPosition pos = extractPos(t);
    66  
    67  			StrValue typ = cast(StrValue) t.access!StrValue(ValueLayer, "is");
    68  			if( typ is null )
    69  				throw genex!RuntimeException(callpos, text(`Invalid AST (no "is" field): `, _v));
    70  
    71  			foreach(AT; ListOfASTTypes)
    72  				if(typ.data == typeid(AT).name.split(".")[$-1])
    73  				{
    74  					typeof(AT.tupleof) mems;
    75  					foreach(i,m; mems)
    76  					{
    77  						string name = AT.tupleof[i].stringof.split(".")[$-1];
    78  						Value vm = t.access!Value(ValueLayer, name);
    79  						if( vm is null )
    80  							throw genex!RuntimeException(callpos, 
    81  								text(`Invalid AST (no "`,name,`" field) for "`, typ, `" node: `, _v));
    82  						mems[i] = polemy2d!(typeof(m))(vm, callpos);
    83  					}
    84  					return new AT(pos,mems);
    85  				}
    86  			throw genex!RuntimeException(callpos, text(`Invalid AST (unknown "is" field): `, typ));
    87  		}
    88  		throw genex!RuntimeException(callpos, text(`Invalid AST (not a table): `, _v));
    89  	}
    90  	else
    91  	static if(is(T == class))
    92  	{
    93  		if(auto t = cast(Table)_v)
    94  		{
    95  			typeof(T.tupleof) mems;
    96  			foreach(i,m; mems)
    97  				mems[i] = polemy2d!(typeof(m))(t.get(T.tupleof[i].stringof.split(".")[$-1], ValueLayer), callpos);
    98  			return new T(mems);
    99  		}
   100  	}
   101  	else
   102  		static assert(false, "unknown type <"~T.stringof~"> during polemy2d decoding");
   103  	throw genex!RuntimeException(callpos, text("Cannot convert ",_v," to ",T.stringof));
   104  }
   105  
   106  /// Cons of two pairs
   107  
   108  Table makeCons(Value a, Value d)
   109  {
   110  	Table t = new Table;
   111  	t.set("car", ValueLayer, a);
   112  	t.set("cdr", ValueLayer, d);
   113  	return t;
   114  }
   115  
   116  /// Experimental!! Convert D value (except AST) to  Polemy Value
   117  
   118  Value d2polemy(T)(T e)
   119  {
   120  	return ast2table(e, delegate Value(AST){ assert(false); });
   121  }
   122  
   123  /// Convert AST to Table so that it can be used in Polemy
   124  
   125  Value ast2table(T)(T e, Value delegate(AST) rec)
   126  {
   127  	static if(is(T==BigInt) || isIntegral!(T))
   128  		return new IntValue(e);
   129  	else
   130  	static if(is(Unqual!(T)==string))
   131  		return new StrValue(e);
   132  	else
   133  	static if(is(T S : S[]))
   134  	{
   135  		Table lst = new Table;
   136  		foreach_reverse(a; e)
   137  			static if(is(S : AST))
   138  				lst = makeCons(rec(a), lst);
   139  			else
   140  				lst = makeCons(ast2table(a,rec), lst);
   141  		return lst;
   142  	}
   143  	else
   144  	static if(is(T : AST))
   145  	{
   146  		assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) );
   147  		auto t = new Table;
   148  		if(e.pos is null) // special treatment
   149  		{
   150  			Table post = new Table;
   151  			post.set("filename", ValueLayer, new StrValue("nullpo"));
   152  			post.set("lineno", ValueLayer, new IntValue(0));
   153  			post.set("column", ValueLayer, new IntValue(0));
   154  			t.set("pos", ValueLayer, post);
   155  		}
   156  		else
   157  			t.set("pos", ValueLayer, ast2table(e.pos,rec));
   158  		t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1]));
   159  		foreach(i,m; e.tupleof)
   160  			static if(is(typeof(m) : AST))
   161  				t.set(e.tupleof[i].stringof.split(".")[$-1], ValueLayer, rec(m));
   162  			else
   163  				t.set(e.tupleof[i].stringof.split(".")[$-1], ValueLayer, ast2table(m,rec));
   164  		return t;
   165  	}
   166  	else
   167  	static if(is(T == class))
   168  	{
   169  		auto t = new Table;
   170  		foreach(i,m; e.tupleof)
   171  			static if(is(typeof(m) : AST))
   172  				t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
   173  			else
   174  				t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
   175  		return t;
   176  	}
   177  	else
   178  		static assert(false, "unknown type <"~T.stringof~"> during AST encoding");
   179  }