Salih hocamın hazırladığı Hafıza yönetimi sınıfını biraz daha geliştirdim ve şu anki parser sisteminin alt yapısında kullanmaya başladım burada ona tekrardan teşekkür etmek isterim :)
Kodların şu anki hali aşağıdaki gibi. RIL sınıfı oluşturdum (Rhodeus Intermediate Language) yani Rhodeus Ara Dili. İçerisinde 2 tane MEM sınıfı var birisi verileri saklamak için diğeri ise operandları saklamak için içerisine verileri yazmak için de
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!string(_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 assert(0, "invalid type " ~ arg.toString() );
}
}
Kodlarını yazdım burada D dilinin vararg özelliğini kullandım. Bu sayede runtime olarak parametreleri kontrol edebiliyorum ve sınırsız sayıda veri gönderebiliyorum Template de kullanabilirdim ama ilk defa gördüğüm bir özellik ve gerçekten çok hoşuma gitti :)
memory.load(IL_FLOAT, to!float(token.value));
Şeklinde memory ye yazıyorum ilk veri burada operand diğer veri float verisi yani operandın paramtresi oldu aslında burada uzun zamandır yapmak istediğim serbest parametreli sistemi uygulamış oldum.
class RIL{
MEM memory;
MEM codes;
this(){
memory = new MEM(256);
codes = new MEM(256);
}
final void load(MEM www){
codes.load(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!string(_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 assert(0, "invalid type " ~ arg.toString() );
}
}
auto getString(int ptr){
auto mem = &memory.memory[ptr];
int len = *cast(int*) mem;
mem += int.sizeof;
return cast(string) (cast(char*) mem)[0..len];
}
auto getInt(int ptr){
return *cast(int*) &memory.memory[ptr];
}
auto getFloat(int ptr){
return *cast(float*) &memory.memory[ptr];
}
auto getBool(int ptr){
return *cast(bool*) &memory.memory[ptr];
}
enum 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"
];
string disAssembly(){
string result;
auto mbp = codes.memory.ptr;
startp:
switch(*mbp){
case IL_PRINT:
mbp++;
result ~= "print %s\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_INT:
mbp++;
result ~= "load %s\n".format(getInt(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_STRING:
mbp++;
result ~= "load \"%s\"\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_NONE:
mbp++;
result ~= "load none\n";
goto startp;
case IL_BOOL:
mbp++;
result ~= "load %s\n".format(getBool(*mbp) ? "true": "false");
mbp+=int.sizeof;
goto startp;
case IL_GETSUB:
mbp++;
result ~= "getsub %s\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_SETSUB:
mbp++;
result ~= "setsub %s\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_LOADVAR:
mbp++;
result ~= "loadvar %s\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_DEFINE:
mbp++;
result ~= "define %s\n".format(getString(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_INC:
mbp++;
result ~= "inc\n";
goto startp;
case IL_EQ:
mbp++;
result ~= "equal\n";
goto startp;
case IL_DEC:
mbp++;
result ~= "dec\n";
goto startp;
case IL_FINIT:
mbp++;
result ~= "function init\n";
goto startp;
case IL_FCALL:
mbp++;
result ~= "fcall (%s) \n".format(getInt(*cast(int*)mbp));
mbp+=int.sizeof;
goto startp;
case IL_PUSH:
mbp++;
result ~= "push\n".format();
goto startp;
case IL_INDEX:
mbp++;
result ~= "index\n".format();
goto startp;
case IL_CMPLOAD:
mbp++;
result ~= "cmpload\n".format();
goto startp;
case IL_SLICE:
mbp++;
result ~= "slice\n".format();
goto startp;
case IL_INDEXEQ:
mbp++;
result ~= "index_equal\n".format();
goto startp;
case IL_SLICEEQ:
mbp++;
result ~= "slice_equal\n".format();
goto startp;
case IL_HLT:
break;
default:
if(*mbp in names)
result ~= "%s\n".format(names[*mbp]);
else
result ~= "undefined: %s\n".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(inout int data) @property {
auto ret = freeLocated;
auto mem = cast(int*) malloc(data.sizeof);
*mem = data;
return ret;
}
final auto load(inout bool data) @property {
auto ret = freeLocated;
auto mem = cast(bool*) malloc(data.sizeof);
*mem = data;
return ret;
}
final auto load(inout float data) @property {
auto ret = freeLocated;
auto mem = cast(float*) malloc(data.sizeof);
*mem = data;
return ret;
}
final void load(inout ubyte data) @property {
auto mem = cast(ubyte*) malloc(data.sizeof);
*mem = data;
}
final void load(inout byte data) @property {
auto mem = cast(byte*) malloc(data.sizeof);
*mem = data;
}
final auto load(inout string data) @property {
auto ret = freeLocated;
auto mem = cast(char*) malloc(data.length + int.sizeof);
*(cast(int*)mem) = cast(int) data.length;
mem[int.sizeof..data.length+int.sizeof] = data;
return ret;
}
final auto load(inout ubyte[] data) @property {
auto ret = freeLocated;
auto mem = cast(ubyte*) malloc(data.length);
mem[0..data.length] = data;
return ret;
}
private void extendMem() {
memory.length += memSize * 2;
memSize = memory.length;
}
final void memLoadBytes(inout ubyte[] data) @property {
auto mem = cast(ubyte*) malloc(data.length);
mem[0..data.length] = data;
}
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("%s\n", 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);
}
}
Kodları şu an tam olarak tamamlayamadım hala sıkıntılar var (VM kısmında) tamamladığım takdirde GITHUB da paylaşacağım hem o zaman tam çalışan halini görebilirsiniz :)
Zekeriya
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]