module meman;
import std.conv, std.string, std.stdio;
import std.container;
import core.memory;
import std.format;
import std.traits;
import std.range;
import core.vararg;
enum : ubyte{
IL_HLT,
IL_PRINT,
IL_STRING, IL_INT, IL_FLOAT, IL_NONE, IL_BOOL,
IL_GETSUB, IL_SETSUB,
IL_FCALL,
IL_INDEX, IL_SLICE,
IL_INDEXEQ, IL_SLICEEQ,
IL_PUSH, IL_FINIT,
IL_INC, IL_DEC,
IL_ADD, IL_SUB, IL_MUL, IL_DIV, IL_MOD,
IL_EQ, IL_MULEQ, IL_DIVEQ, IL_MODEQ, IL_ADDEQ, IL_SUBEQ,
IL_LOADVAR, IL_DEFINE,
IL_isLower, IL_isLowerEquals,
IL_isGreater, IL_isGreaterEquals,
IL_isEquals, IL_isNotEquals,
IL_isIn,
IL_jmpoint, IL_delpoint, IL_jneset,
IL_LOR, IL_LAND,
IL_CMPLOAD,
IL_HASVALUE,
IL_MATHSTART, IL_MATHEND, IL_ARRAY, IL_DICT,
IL_INDEXINIT,
IL_LOOPSTART, IL_LOOPEND,
IL_CONTINUE, IL_BREAK,
IL_INTERMEDIATE,
IL_LAYERINIT, IL_LAYEREND,
IL_JNEL,
IL_IFSTART, IL_IFEND,
IL_ELIFSTART, IL_ELIFEND,
IL_PARAMETER, IL_FUNCTION, IL_FUNCTION_END,
IL_PARAMCHECK, IL_PARAMCHECK2,
IL_PARACODES, IL_PARACODES_END, IL_PARACODES_LOAD, IL_ASSO,
IL_ECHO,
}
private string[ubyte] names;
static this(){
names = [
IL_HASVALUE: "hasvalue?", IL_ADD: "add", IL_MUL: "mul",
IL_DIV: "div", IL_SUB: "sub", IL_isLower:"<",
IL_isLowerEquals:"<=", IL_isGreater:">", IL_isGreaterEquals:">=",
IL_isEquals:"==", IL_isNotEquals:"!=", IL_isIn:"in",
IL_LOR: "or", IL_LAND: "and", IL_jneset: "jneset", IL_jmpoint: "IL_jmpoint",
IL_delpoint: "IL_delpoint", IL_MATHSTART: "IL_MATHSTART", IL_MATHEND: "IL_MATHEND",
IL_INDEXEQ: "IL_INDEXEQ", IL_NONE: "IL_NONE", IL_INC: "IL_INC",
IL_EQ: "IL_EQ", IL_DEC: "IL_DEC", IL_FINIT: "IL_FINIT",
IL_PUSH: "push", IL_INDEX: "IL_INDEX",
IL_CMPLOAD: "IL_CMPLOAD", IL_SLICE: "IL_SLICE", IL_SLICEEQ: "IL_SLICEEQ",
IL_DEFINE: "define", IL_LOADVAR: "lodvar", IL_SETSUB: "setsub",
IL_GETSUB: "IL_GETSUB", IL_STRING: "load", IL_PRINT: "print",
IL_INT: "load", IL_FCALL: "call",
IL_ARRAY: "array", IL_DICT: "dict", IL_INDEXINIT: "indexinit",
IL_LOOPSTART: "LOOPSTART", IL_LOOPEND: "LOOPEND",
IL_CONTINUE: "continue", IL_INTERMEDIATE: "IL_INTERMEDIATE",
IL_FUNCTION: "function", IL_PARAMETER: "parameter", IL_FUNCTION_END: "function end",
IL_PARAMCHECK: "IL_PARAMCHECK", IL_PARAMCHECK2: "IL_PARAMCHECK2",
IL_PARACODES_END: "IL_PARACODES_END", IL_PARACODES: "IL_PARACODES",
IL_ECHO: "echo",
];
}
class RIL{
MEM memory;
MEM codes;
this(){
memory = new MEM(256);
codes = new MEM(256);
}
final void load(MEM www){
codes.load(
http://www.memory[0..www.freeLocated ]);
}
final MEM newCache(int size = 256){
codes = new MEM(size);
return codes;
}
final void loadMEM(MEM old){
codes = old;
}
final void load(ubyte operand, ... ){
codes.load(operand);
foreach(arg; _arguments) {
if(arg
typeid(string) || arg
typeid(immutable(string)) || arg
typeid(const(string))){
codes.load(memory.load(va_arg!(char[])(_argptr)));
}else if(arg
typeid(string[]) || arg
typeid(immutable(string[])) || arg
typeid(const(string[]))){
codes.load(memory.load(va_arg!(char[][])(_argptr)));
}else if (arg
typeid(int) || arg
typeid(immutable(int)) || arg
typeid(const(int))) {
codes.load(memory.load(va_arg!int(_argptr)));
}else if (arg
typeid(float) || arg
typeid(immutable(float)) || arg
typeid(const(float))) {
codes.load(memory.load(va_arg!float(_argptr)));
}else if (arg
typeid(bool) || arg
typeid(immutable(bool)) || arg
typeid(const(bool))) {
codes.load(memory.load(va_arg!bool(_argptr)));
}else if (arg
typeid(byte) || arg
typeid(immutable(byte)) || arg
typeid(const(byte))) {
codes.load(memory.load(va_arg!bool(_argptr)));
}else assert(0, "invalid type " ~ arg.toString() );
}
}
final auto get(T)(ref ubyte* ptr) if (!isArray!T){
scope(exit) ptr+=int.sizeof;
return *cast(T*) &memory.memory[*cast(int*) ptr];
}
final auto get(T)(ref ubyte* ptr) if (isArray!T){
auto mem = &memory.memory[*cast(int*) ptr];
auto len = *cast(typeof(T.length)*) mem;
mem += typeof(T.length).sizeof;
scope(exit) ptr+=int.sizeof;
return cast(T) (cast(ElementEncodingType!(T)*) mem)[0..len];
}
string disAssembly(){
string result;
auto mbp = codes.memory.ptr;
startp:
switch(*mbp){
case IL_PARAMETER: mbp++;
get!byte(mbp);
get!int(mbp);
result ~= "Parameter %s n".format(get!string(mbp));
goto startp;
case IL_FCALL, IL_INT, IL_ARRAY, IL_DICT, IL_PARAMCHECK:
result ~= "%s %s n".format(*mbp in names? names[*mbp] : to!string(*mbp), get!int(++mbp));
goto startp;
case IL_FLOAT: mbp++;
result ~= "load %sn".format(get!float(mbp));
goto startp;
case IL_BOOL: mbp++;
result ~= "load %sn".format(get!bool(mbp) ? "true": "false");
goto startp;
case IL_FUNCTION, IL_GETSUB, IL_SETSUB, IL_LOADVAR, IL_DEFINE, IL_STRING, IL_PRINT, IL_ASSO:
result ~= "%s %sn".format(*mbp in names? names[*mbp] : to!string(*mbp), get!string(++mbp));
goto startp;
case IL_HLT:
break;
case IL_MATHSTART, IL_MATHEND:
mbp++;
goto startp;
default:
if(*mbp in names) result ~= "%sn".format(names[*mbp]);
else result ~= "undefined: %sn".format(*mbp);
mbp++;
goto startp;
}
return result;
}
}
class MEM {
public:
ubyte[] memory;
size_t freeLocated, memSize;
immutable byteSize = 8;
this(size_t minSize) {
size_t isOverload = minSize % byteSize;
memory = new ubyte[](minSize - isOverload);
memSize = memory.length;
}
final auto load(T)(T data) if (!isArray!T){
auto ret = freeLocated;
auto mem = cast(T*) malloc(data.sizeof);
*mem = data;
return ret;
}
final auto load(T)(T data) if (isArray!T && !is(ElementType!T == ubyte)){
auto ret = freeLocated;
static if(isArray!(ElementEncodingType!(T))){
throw new Exception("Invalid type!");
}else{
auto mem = cast(ElementEncodingType!(T)*) malloc(data.length * ElementEncodingType!(T).sizeof + typeof(T.length).sizeof);
*(cast(typeof(T.length)*)mem) = cast(typeof(T.length)) data.length;
mem[typeof(T.length).sizeof..data.length+typeof(T.length).sizeof] = data;
}
return ret;
}
final auto load(T)(T data) if (isArray!T && is(ElementType!T == ubyte)){
auto ret = freeLocated;
auto mem = cast(ElementEncodingType!(T)*) malloc(data.length);
mem[0..data.length] = data;
return ret;
}
private void extendMem() {
memory.length += memSize * 2;
memSize = memory.length;
}
final void* malloc(size_t size) {
if(memSize < freeLocated + size) {
extendMem();
}
scope(exit) freeLocated += size;
return &memory[freeLocated];
}
final void memWrite(inout(string) data) @property {
auto mem = cast(char*) malloc(data.length);
mem[0..data.length] = data;
}
final uint memReserveAddress() {
scope(exit) malloc(int.sizeof);
return freeLocated;
}
final void memSetAddress(uint adrl) {
*cast(uint*) &memory[adrl] = memory.length;
}
override string toString() const{
import std.range : repeat;
string memImage = " DECIMAL MEMORY DUMP ASCII n";
memImage ~= format("%sn", repeat('-', memImage.length)) ;
for(int i; i < memory.length; i += byteSize) {
auto row = memory[i..i + byteSize].dup;
foreach(ref ubyte address; row) {
if(address == 0){
address = 0xFF;
memImage ~= " ";
}else if(address < 10) memImage ~= " ";
else if(address < 100) memImage ~= " ";
else if(address < 256) memImage ~= " ";
memImage ~= to!string(address);
}
memImage ~= " ";
foreach(c; row){
memImage ~= c;
}
memImage ~= "n";
}
writeln(format("%s>Total %s bytes<n", repeat(' ', 10), memory.length));
return memImage ~ format("%s>Total %s bytes<n", repeat(' ', 10), memory.length);
}
}