/* * */ import object; import utf; /* unary operators */ const char[] OP_NEGATE = "-"; const char[] OP_TILDE = "~"; const char[] OP_POST_INC = "++"; const char[] OP_POST_DEC = "--"; /* binary operators */ const char[] OP_ADD = "+"; const char[] OP_SUB = "-"; const char[] OP_MUL = "*"; const char[] OP_DIV = "/"; const char[] OP_MOD = "%"; const char[] OP_AND = "&"; const char[] OP_OR = "|"; const char[] OP_XOR = "^"; const char[] OP_SHL = "<<"; const char[] OP_SHR = ">>"; const char[] OP_USHR = ">>>"; const char[] OP_CAT = "~"; /* comparison */ //const char[] OP_EQ = "=="; //const char[] OP_CMP = "<=>"; /* modify operators */ const char[] OP_ADD_MODIFY = "+="; const char[] OP_SUB_MODIFY = "-="; const char[] OP_MUL_MODIFY = "*="; const char[] OP_DIV_MODIFY = "/="; const char[] OP_MOD_MODIFY = "%="; const char[] OP_AND_MODIFY = "&="; const char[] OP_OR_MODIFY = "|="; const char[] OP_XOR_MODIFY = "^="; const char[] OP_SHL_MODIFY = "<<="; const char[] OP_SHR_MODIFY = ">>="; const char[] OP_USHR_MODIFY = ">>>="; const char[] OP_CAT_MODIFY = "~="; class MissingOperation : Exception { this( char[] reason ) { super( reason ); } this( char[] op, BaseOperand a ) { super( "Missing unary op " ~ op ~ " (" ~ a.classinfo.name ~ ")" ); } this( char[] op, BaseOperand a, bit modifier ) { if ( modifier ) { super( "Missing unary modifier op " ~ op ~ " (" ~ a.classinfo.name ~ ")" ); } else { super( "Missing unary op " ~ op ~ " (" ~ a.classinfo.name ~ ")" ); } } this( char[] op, BaseOperand a, BaseOperand b ) { super( "Missing binary op " ~ op ~ " (" ~ a.classinfo.name ~ "," ~ b.classinfo.name ~ ")" ); } this( char[] op, BaseOperand a, BaseOperand b, bit modifier ) { if ( modifier ) { super( "Missing binary modifier op " ~ op ~ " (" ~ a.classinfo.name ~ "," ~ b.classinfo.name ~ ")" ); } else { super( "Missing binary op " ~ op ~ " (" ~ a.classinfo.name ~ "," ~ b.classinfo.name ~ ")" ); } } } class BaseOperand { // c = a + b => c = binaryop( a, b ) alias BaseOperand function( BaseOperand, BaseOperand ) binaryop; // c = -a => c = unaryop( a ) alias BaseOperand function( BaseOperand ) unaryop; // c *= a => c = c.modifyop( a ) alias BaseOperand function( BaseOperand, BaseOperand ) modifyop; // c = (a==b) => c = eqop( a, b ) alias bit function( BaseOperand, BaseOperand ) equalsop; // c = (a c = cmpop( a, b ) alias int function( BaseOperand, BaseOperand ) compareop; static unaryop[ClassInfo][char[]] unaries; static binaryop[ClassInfo][ClassInfo][char[]] binaries; static modifyop[ClassInfo][char[]] modifies; static equalsop[ClassInfo][ClassInfo] equals; static compareop[ClassInfo][ClassInfo] compares; BaseOperand neg() { return unary_operator( OP_NEGATE, this ); } BaseOperand com() { return unary_operator( OP_TILDE, this ); } BaseOperand postinc() { return unary_operator( OP_POST_INC, this ); } BaseOperand postdec() { return unary_operator( OP_POST_DEC, this ); } BaseOperand add( BaseOperand b ) { return binary_operator( OP_ADD, this, b ); } BaseOperand sub( BaseOperand b ) { return binary_operator( OP_SUB, this, b ); } BaseOperand mul( BaseOperand b ) { return binary_operator( OP_MUL, this, b ); } BaseOperand div( BaseOperand b ) { return binary_operator( OP_DIV, this, b ); } BaseOperand mod( BaseOperand b ) { return binary_operator( OP_MOD, this, b ); } BaseOperand and( BaseOperand b ) { return binary_operator( OP_AND, this, b ); } BaseOperand or( BaseOperand b ) { return binary_operator( OP_OR, this, b ); } BaseOperand xor( BaseOperand b ) { return binary_operator( OP_XOR, this, b ); } BaseOperand shl( BaseOperand b ) { return binary_operator( OP_SHL, this, b ); } BaseOperand shr( BaseOperand b ) { return binary_operator( OP_SHR, this, b ); } BaseOperand ushr(BaseOperand b ) { return binary_operator( OP_USHR, this, b ); } BaseOperand cat( BaseOperand b ) { return binary_operator( OP_CAT, this, b ); } /* why is this not bit ? */ // int eq( Object o ) { return (cast(int)(cast(void*)this)) == (cast(int)(cast(void*)o)); } // int cmp( Object o ) { return (cast(int)(cast(void*)this)) - (cast(int)(cast(void*)o)); } int eq( Object o ) { if ( this === o ) { return true; } if( this === null ) { return false; } BaseOperand bo = cast(BaseOperand)o; // this is also o === null :) if ( !o ) { return false; } return eq_operator( this, bo ); } int cmp( Object o ) { if ( this === o ) { return 0; } if( this === null ) { return 1; } BaseOperand bo = cast(BaseOperand)o; // this is also o === null :) if ( !o ) { return -1; } return eq_operator( this, bo ); } BaseOperand addass( BaseOperand b ) { return modify_operator( OP_ADD_MODIFY, this, b ); } BaseOperand subass( BaseOperand b ) { return modify_operator( OP_SUB_MODIFY, this, b ); } BaseOperand mulass( BaseOperand b ) { return modify_operator( OP_MUL_MODIFY, this, b ); } BaseOperand divass( BaseOperand b ) { return modify_operator( OP_DIV_MODIFY, this, b ); } BaseOperand modass( BaseOperand b ) { return modify_operator( OP_MOD_MODIFY, this, b ); } BaseOperand andass( BaseOperand b ) { return modify_operator( OP_AND_MODIFY, this, b ); } BaseOperand orass( BaseOperand b ) { return modify_operator( OP_OR_MODIFY, this, b ); } BaseOperand xorass( BaseOperand b ) { return modify_operator( OP_XOR_MODIFY, this, b ); } BaseOperand shlass( BaseOperand b ) { return modify_operator( OP_SHL_MODIFY, this, b ); } BaseOperand shrass( BaseOperand b ) { return modify_operator( OP_SHR_MODIFY, this, b ); } BaseOperand ushrass(BaseOperand b ) { return modify_operator( OP_USHR_MODIFY,this, b ); } BaseOperand catass( BaseOperand b ) { return modify_operator( OP_CAT_MODIFY, this, b ); } static BaseOperand unary_operator( char[] op, BaseOperand a ) { unaryop unop = unaries[op][a.classinfo]; if ( !unop ) throw new MissingOperation( op, a ); return unop( a ); } static BaseOperand binary_operator( char[] op, BaseOperand a, BaseOperand b ) { binaryop binop = binaries[op][a.classinfo][b.classinfo]; if ( !binop ) throw new MissingOperation( op, a, b ); return binop( a, b ); } static BaseOperand modify_operator( char[] op, BaseOperand a, BaseOperand b ) { modifyop modop = modifies[op][a.classinfo]; if ( !modop ) throw new MissingOperation( op, a, b, true ); return modop( a, b ); } static bit eq_operator( BaseOperand a, BaseOperand b ) { equalsop eqop = equals[a.classinfo][b.classinfo]; if ( !eqop ) throw new MissingOperation( "==", a, b ); return eqop( a, b ); } static int cmp_operator( BaseOperand a, BaseOperand b ) { compareop cmpop = compares[a.classinfo][b.classinfo]; if ( !cmpop ) throw new MissingOperation( "<=>", a, b ); return cmpop( a, b ); } static void register_unary_operation( char[] op, unaryop unop, ClassInfo a_ci ) { printf("registering op[%.*s]class[%.*s]\n", op, a_ci.name ); unaries[op][a_ci] = unop; } static void register_binary_operation( char[] op, binaryop binop, ClassInfo a_ci, ClassInfo b_ci ) { printf("registering binop[%.*s]classes[%.*s,%.*s]\n", op, a_ci.name, b_ci.name ); binaries[op][a_ci][b_ci] = binop; } static void register_modify_operation( char[] op, modifyop modop, ClassInfo a_ci ) { printf("registering modify[%.*s]class[%.*s]\n", op, a_ci.name ); modifies[op][a_ci] = modop; } static void register_eq_operation( equalsop eqop, ClassInfo a_ci, ClassInfo b_ci ) { printf("registering eq classes[%.*s,%.*s]\n", a_ci.name, b_ci.name ); equals[a_ci][b_ci] = eqop; } static void register_cmp_operation( compareop cmpop, ClassInfo a_ci, ClassInfo b_ci ) { printf("registering cmp classes[%.*s,%.*s]\n", a_ci.name, b_ci.name ); compares[a_ci][b_ci] = cmpop; } }