Artifact Content
Not logged in

Artifact fe3f0c39a200a0bc488e1e7a36ac7ce352a1b40e


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