Artifact Content
Not logged in

Artifact 38155bcc400d812fb6116b2a92e36eb0d05110c8


     1  /**
     2   * Authors: k.inaba
     3   * License: NYSL 0.9982 http://www.kmonos.net/nysl/
     4   *
     5   * Runtime data structures for Polemy programming language.
     6   */
     7  module polemy.value;
     8  import polemy._common;
     9  import polemy.lex;
    10  
    11  /// Raised when something went wrong in runtime
    12  
    13  class RuntimeException : Exception
    14  {
    15  	const LexPosition pos;
    16  
    17  	this( const LexPosition pos, string msg )
    18  		{ super(sprintf!"%s at [%s]"(msg, pos)); this.pos = pos; }
    19  }
    20  
    21  /// Runtime values of Polemy
    22  
    23  abstract class Value
    24  {
    25  }
    26  
    27  class IntValue : Value
    28  {
    29  	BigInt data;
    30  
    31  	mixin SimpleConstructor;
    32  	mixin SimpleCompare;
    33  	override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); }
    34  }
    35  
    36  class StrValue : Value
    37  {
    38  	string data;
    39  
    40  	mixin SimpleConstructor;
    41  	mixin SimpleCompare;
    42  	override string toString() const { return data; }
    43  }
    44  
    45  class FunValue : Value
    46  {
    47  	Value delegate(immutable LexPosition pos, Value[]) data;
    48  
    49  	mixin SimpleConstructor;
    50  	alias data call;
    51  	override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); }
    52  }
    53  
    54  /// Layer ID
    55  
    56  alias string Layer;
    57  
    58  /// Context (variable environment)
    59  /// Simlar to prototype chain of ECMAScript etc.
    60  /// But extended with the notion of "Layer"
    61  
    62  class Table : Value
    63  {
    64  	enum Kind {PropagateSet, NotPropagateSet};
    65  
    66  	this( Table proto=null, Kind k = Kind.PropagateSet )
    67  		{ this.prototype = proto; this.kind = k; }
    68  
    69  	void set(string i, Layer lay, Value v, in LexPosition pos=null)
    70  	{
    71  		if( setIfExist(i, lay, v) )
    72  			return;
    73  		data[i][lay] = v;
    74  	}
    75  
    76  	Value get(string i, Layer lay, in LexPosition pos=null)
    77  	{
    78  		if( i in data )
    79  			return data[i][lay];
    80  		if( prototype is null )
    81  			throw new RuntimeException(pos, sprintf!"variable %s not found"(i));
    82  		return prototype.get(i, lay);
    83  	}
    84  
    85  private:
    86  	Table                prototype;
    87  	Kind                 kind;
    88  	Value[Layer][string] data;
    89  
    90  	bool setIfExist(string i, Layer lay, Value v)
    91  	{
    92  		if( i in data )
    93  		{
    94  			data[i][lay] = v;
    95  			return true;
    96  		}
    97  		if( kind==Kind.PropagateSet && prototype !is null )
    98  			return prototype.setIfExist(i, lay, v);
    99  		return false;
   100  	}
   101  }
   102  
   103  unittest
   104  {
   105  	Table c0 = new Table;
   106  	Table c01 = new Table(c0, Table.Kind.NotPropagateSet);
   107  	Table c012 = new Table(c01, Table.Kind.PropagateSet);
   108  	Table c013 = new Table(c01, Table.Kind.PropagateSet);
   109  
   110  	assert_nothrow( c012.set("x", "@val", new IntValue(BigInt(12))) );
   111  	assert_throw!RuntimeException( c013.get("x", "@val") );
   112  	assert_nothrow( c013.set("x", "@val", new IntValue(BigInt(13))) );
   113  	assert_eq( c013.get("x", "@val"), new IntValue(BigInt(13)) );
   114  	assert_eq( c012.get("x", "@val"), new IntValue(BigInt(12)) );
   115  	assert_throw!RuntimeException( c01.get("x", "@val") );
   116  
   117  	assert_nothrow( c01.set("y", "@val", new IntValue(BigInt(1))) );
   118  	assert_eq( c013.get("y", "@val"), new IntValue(BigInt(1)) );
   119  	assert_eq( c012.get("y", "@val"), new IntValue(BigInt(1)) );
   120  	assert_eq( c01.get("y", "@val"), new IntValue(BigInt(1)) );
   121  
   122  	assert_nothrow( c0.set("z", "@val", new IntValue(BigInt(0))) );
   123  	assert_eq( c013.get("z", "@val"), new IntValue(BigInt(0)) );
   124  	assert_eq( c012.get("z", "@val"), new IntValue(BigInt(0)) );
   125  	assert_eq( c01.get("z", "@val"), new IntValue(BigInt(0)) );
   126  	assert_eq( c0.get("z", "@val"), new IntValue(BigInt(0)) );
   127  
   128  	assert_nothrow( c012.set("y", "@val", new IntValue(BigInt(444))) );
   129  	assert_eq( c013.get("y", "@val"), new IntValue(BigInt(444)) );
   130  	assert_eq( c012.get("y", "@val"), new IntValue(BigInt(444)) );
   131  	assert_eq( c01.get("y", "@val"), new IntValue(BigInt(444)) );
   132  
   133  	assert_nothrow( c012.set("z", "@val", new IntValue(BigInt(555))) );
   134  	assert_eq( c013.get("z", "@val"), new IntValue(BigInt(0)) );
   135  	assert_eq( c012.get("z", "@val"), new IntValue(BigInt(555)) );
   136  	assert_eq( c01.get("z", "@val"), new IntValue(BigInt(0)) );
   137  	assert_eq( c0.get("z", "@val"), new IntValue(BigInt(0)) );
   138  
   139  	// [TODO] define the semantics and test @layers
   140  }