MSL FL (SP) - Компилятор своими руками. Шаг 3. Что вы знаете о переменных?

Oct 14, 2013 16:26

Итак, сразу ссылки на исходники anon:anon@svn://svn.loglist.org/usr/svn/opensource/msl-fl/ и anon:anon@svn://svn.loglist.org/usr/svn/opensource/msvlib . Исходный код будет еще и тут: http://pastebin.com/G8PKZLq5 . Версия: #define USE_MSLFL_VER 3

Следующая задача: .
Немного подумать и можно писать код. Но для начала: а что мы вобще такое пишем? Интерпретатор с синтаксисом c++ и php, последний нам ближе. Так что же, у нас, такое переменные? Это динамический массив в каждый элемент которого можно запихнуть такой же массив. То есть структура проста: ключ, значение, указаель на следующий элемент и указатель на массив, хранящийся в этом массиве.
Класс:
class msl_value{
    // prev, next, up first, up end
    msl_value *_p, *_n, *_a, *_e;
    MString key, val;
};

Теперь я беру свой шаблон OMatrixT, который разрулит всеми указателями и пишу функции New() - выделяющую память под переменную, Find() - ищет переменную по имени, Get() - возвращает значение переменной, Set() - соответственно устанавливает. В итоге:
class msl_value : public OMatrixT{
public:
    // prev, next, up first, up end
    msl_value *_p, *_n;
    MString key, val;

msl_value(){ _p=0; _n=0; }

msl_value* New(){
        msl_value *p=new msl_value;
        if(!p) return 0;

OMAdd(p);
        return p;
    }

msl_value* Find(VString key){
        if(!this) return 0;

for(msl_value*p=_a; p; p=p->_n){
            if(p->key==key) return p;
        }

return 0;
    }

void Set(VString key, VString val){
        msl_value *p=Find(key);
        if(p){
            p->val=val;
        } else{
            p=New();
            if(p){
                p->key=key; p->val=val;
            }
        }
        return ;
    }

VString Get(VString key){
        msl_value *p=Find(key);
        if(p)
            return p->val;
        else
            return VString();
    }

void Del(VString key){
        msl_value *p=Find(key);
        if(p){
            OMDel(p); delete p;
        }
        return ;
    }

~msl_value(){ Clear(); }
    void Clear(){ OMClear(); }

};

Добавляем это в msl как msl_value global; и никак иначе. Глобальные переменные есть. Где-то в процессе нужно будет подумать о работе с ветками переменных в случае передачи их в функцию или обратно. А сейчас думаем над передачей самой переменной. Например в случае $hello='Hello World!'; мы должны записать имя первой переменной. Даже не так, мы ее установим, раз в нее устанавливаются данные. Это нужно для того, чтобы на нее можно было ссылаться. Дальше выполняем 'Hello World!', который дожен вернуться как msl_val, где key пустой, а значение 'Hello World!'. Ок. Так же перепишем обработку параметров функций, чтобы передавать не строку, а msl_val.
Вот кстати можно реализовать function()='value', чтобы значение подставлялось как последний пераметр.

Так, вот итоговая мысль, видим переменную - создаем, это нужно для всяких $a[$b]['c'][0xd][e()]; если в нее не устанавливаются данные удалим, ибо у нас линейность, а значит обрабатываем по порядку и не знаем, просто она тут висит или в нее устанавливаются данные.

Теперь по шагам.
Пусть все крутится в DoCode(), он будет раскрывать все скобки, находить переменные и функции. Для того, чтобы он понимал, когда выйти добавляем параметр unsigned char ecode=1, сначала неактивный, ибо ну кто добавит char(1) в код? В принципе подойдет любое другое неиспольземое значение. Надеюсь не будет предложений ecode=0 и if(ecode), что абсолютно лишнее. Добавляем обработчик if(*line==ecode){ return ; }. Ок, всякие (), [] готовы к обработке. Так как в функции может быть и скобка и запятая, добавляем еще один такой же параметр.
Так же надо добавить возвращение результата, добавим параметр msl_value &outval. Порядок.
Переписываю DoCode() под обработку всех возможных вариантов. DoCodeFunctionArgs() больше не нужна, DoCode() прекрасно выполнит ее функцию.
Новая схема работы: Do() -> DoCode(line, to, outval, ';'); Код делится на блоки по ;, пока не дойдет до конца.
DoCodeValues() обрабатывает переменные,
Добавляем SGet() в msl_value, эта функция вернет адрес на переменную, если ее нет, создаст. Это не радует, и обязательно будет удаление таких переменных, если им не присваивается значение. А лучше сделать так сразу. Скажем через тот же SGet(), установив указатель val.sz=0xffffffff; Указатель остается нулевым, и никаких последствий быть не должно, а переменная помечена.

... Много кода спустя.
Есть, работает. Пришлось поработать над DoCode() и DoCodeFunction(), остальное практически без изменений. Код стал сложнее, добавилась работа с переменными, которые у нас одного типа в виде динамических массивов.
Жить стало лучше, жить стало веселее, однако и на данном этапе разработки код особо не поиспользуешь. Вот и остается думать, что делать дальше.
В планах: подключаемые функции, новый класс для хранения переменных, мысли о многопоточности. Но это все не главное. Нам нужны if, while и for, нам нужны операции с переменными, весь набор: !, ||, &&, ., +, /, *, -, .=, ... Одна из этих важных тем и станет нашей следующей целью. Они обе достаточно сложные и вот тут то придется пораскинуть мозгами. Все, что написано до этого сущая ерунда, всего-то 480 строк.

Наслаждайтесь, экспериментируйте, ищите ошибки и баги. Следующий шаг совсем скоро.

msl, opensource, msl-fl, c++, hello world

Previous post Next post
Up